diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 00000000..67f517ed --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,75 @@ +--- +name: CI + +on: + push: + branches: + - master + - 'releases/*' + pull_request: + branches: + - master + +env: + # Use Xcode 15.2 or newer to support VisionOS + DEVELOPER_DIR: /Applications/Xcode_16.4.app + +jobs: + debuggithub: + name: Debug Github + runs-on: macos-latest + steps: + - name: List available simulators (debug) + run: xcrun simctl list devices + - name: List available Runtimes (debug) + run: xcrun simctl list runtimes + - name: List available SDKs (debug) + run: xcodebuild -showsdks + analyze: + name: Analyze + runs-on: macos-latest + strategy: + matrix: + platform: ['iOS Simulator,name=iPhone 16,OS=18.5'] + steps: + - uses: actions/checkout@v2 + - name: Analyze + run: make analyze + test: + name: Test + runs-on: macos-latest + strategy: + matrix: + platform: ['iOS Simulator,name=iPhone 16,OS=18.5'] + steps: + - uses: actions/checkout@v2 + - name: Test + run: make test + cocoapods: + name: CocoaPods + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - name: CocoaPods + run: make cocoapods + carthage: + name: Carthage + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - name: Carthage + run: make carthage + swift-package-manager: + runs-on: macos-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Verify that PINRemoteImage can be build by SPM + run: make spm + example-spm-xcode: + runs-on: macos-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Verify that PINRemoteImage can be build by Xcode's SPM integration + run: make example diff --git a/.github/workflows/publish_release.yml b/.github/workflows/publish_release.yml new file mode 100644 index 00000000..021f4de1 --- /dev/null +++ b/.github/workflows/publish_release.yml @@ -0,0 +1,44 @@ +name: Create Release +on: + workflow_dispatch: + inputs: + release-type: + description: 'The type of release. Must be major, minor or patch' + required: true + +env: + # Use Xcode 15.2 or newer to support VisionOS + DEVELOPER_DIR: /Applications/Xcode_16.4.app + +jobs: + create_release: + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + # Make sure we can lint before creating the release. + - name: Cocoapods lint + run: make cocoapods + - name: Create Release Commit + env: + GITHUB_CHANGELOG_API_KEY: ${{ secrets.GITHUB_TOKEN }} + OSS_PROJECT: PINRemoteImage + run: | + gem install github_changelog_generator + Scripts/release.sh --${{ github.event.inputs.release-type }} + git push origin HEAD + - name: Tag Release + run: Scripts/tag-release-branch.sh + - name: Publish Release + uses: actions/create-release@v1 + env: + GITHUB_CHANGELOG_API_KEY: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ env.RELEASE_TAG }} + release_name: ${{ env.RELEASE_TAG }} + body_path: RELEASE_NOTES.md + draft: false + - name: Push to Cocoapods + env: + COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} + run: pod trunk push --allow-warnings diff --git a/.github_changelog_generator b/.github_changelog_generator new file mode 100644 index 00000000..f21dcf17 --- /dev/null +++ b/.github_changelog_generator @@ -0,0 +1,3 @@ +issues=false +since-tag=3.0.3 +future-release=3.0.4 diff --git a/.gitignore b/.gitignore index 630768cf..86871492 100644 --- a/.gitignore +++ b/.gitignore @@ -42,8 +42,11 @@ xcuserdata # you should judge for yourself, the pros and cons are mentioned at: # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control # -# Pods/ +Pods/ -# Carthage -Carthage/Checkouts Carthage/Build + +## SPM +.swiftpm/ +.build/ +Package.resolved diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 00000000..15a27998 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +3.3.0 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 6ed4ced2..00000000 --- a/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -# reference: http://www.objc.io/issue-6/travis-ci.html - -# whitelist -branches: - only: - - master -language: objective-c -osx_image: xcode7.2 -env: - matrix: - - OS='latest' name='iPhone 6' - -before_install: - - gem install xcpretty -before_script: - - pod --version - - pod repo update - - pod lib lint --allow-warnings -script: - - xcodebuild clean test -destination "platform=iOS Simulator,OS=$OS,name=$name" -workspace Example/PINRemoteImage.xcworkspace -scheme PINRemoteImage ONLY_ACTIVE_ARCH=NO CODE_SIGNING_REQUIRED=NO | xcpretty -t; test ${PIPESTATUS[0]} -eq 0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b1047f7..981e78c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,29 +1,410 @@ -### 2.1.4 -- 2016 Apr 22 ### +# Changelog + +## [releases/p12.19](https://github.com/Pinterest/PINRemoteImage/tree/releases/p12.19) (2024-04-29) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p12.20...releases/p12.19) + +## [releases/p12.20](https://github.com/Pinterest/PINRemoteImage/tree/releases/p12.20) (2024-04-29) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p12.6...releases/p12.20) + + +- Add PrivacyInfo.xcprivacy [\#637](https://github.com/pinterest/PINRemoteImage/pull/637) ([garricn](https://github.com/garricn)) + +## [releases/p12.6](https://github.com/Pinterest/PINRemoteImage/tree/releases/p12.6) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p12.5...releases/p12.6) + +## [releases/p12.5](https://github.com/Pinterest/PINRemoteImage/tree/releases/p12.5) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p12.4...releases/p12.5) + +## [releases/p12.4](https://github.com/Pinterest/PINRemoteImage/tree/releases/p12.4) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.19...releases/p12.4) + +## [releases/p11.19](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.19) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.20...releases/p11.19) + +## [releases/p11.20](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.20) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.21...releases/p11.20) + +## [releases/p11.21](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.21) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.22...releases/p11.21) + +## [releases/p11.22](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.22) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.23...releases/p11.22) + +## [releases/p11.23](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.23) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.24...releases/p11.23) + +## [releases/p11.24](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.24) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.25...releases/p11.24) + +## [releases/p11.25](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.25) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.26...releases/p11.25) + +## [releases/p11.26](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.26) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.27...releases/p11.26) + +## [releases/p11.27](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.27) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.28...releases/p11.27) + +## [releases/p11.28](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.28) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.29...releases/p11.28) + +## [releases/p11.29](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.29) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p12.3...releases/p11.29) + +## [releases/p12.3](https://github.com/Pinterest/PINRemoteImage/tree/releases/p12.3) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p12.2...releases/p12.3) + +## [releases/p12.2](https://github.com/Pinterest/PINRemoteImage/tree/releases/p12.2) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.45...releases/p12.2) + +## [releases/p11.45](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.45) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.44...releases/p11.45) + +## [releases/p11.44](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.44) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.43...releases/p11.44) + +## [releases/p11.43](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.43) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.42...releases/p11.43) + +## [releases/p11.42](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.42) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.41...releases/p11.42) + +## [releases/p11.41](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.41) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.40...releases/p11.41) + +## [releases/p11.40](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.40) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.39...releases/p11.40) + +## [releases/p11.39](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.39) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.38...releases/p11.39) + +## [releases/p11.38](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.38) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.37...releases/p11.38) + +## [releases/p11.37](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.37) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.36...releases/p11.37) + +## [releases/p11.36](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.36) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.35...releases/p11.36) + +## [releases/p11.35](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.35) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.34...releases/p11.35) + +## [releases/p11.34](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.34) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.33...releases/p11.34) + +## [releases/p11.33](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.33) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.32...releases/p11.33) + +## [releases/p11.32](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.32) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.31...releases/p11.32) + +## [releases/p11.31](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.31) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.30...releases/p11.31) + +## [releases/p11.30](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.30) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p12.18...releases/p11.30) + +## [releases/p12.18](https://github.com/Pinterest/PINRemoteImage/tree/releases/p12.18) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p12.9...releases/p12.18) + +## [releases/p12.9](https://github.com/Pinterest/PINRemoteImage/tree/releases/p12.9) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p12.7...releases/p12.9) + +## [releases/p12.7](https://github.com/Pinterest/PINRemoteImage/tree/releases/p12.7) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p12.17...releases/p12.7) + +## [releases/p12.17](https://github.com/Pinterest/PINRemoteImage/tree/releases/p12.17) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p12.16...releases/p12.17) + +## [releases/p12.16](https://github.com/Pinterest/PINRemoteImage/tree/releases/p12.16) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p12.15...releases/p12.16) + +## [releases/p12.15](https://github.com/Pinterest/PINRemoteImage/tree/releases/p12.15) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p12.14...releases/p12.15) + +## [releases/p12.14](https://github.com/Pinterest/PINRemoteImage/tree/releases/p12.14) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p12.13...releases/p12.14) + +## [releases/p12.13](https://github.com/Pinterest/PINRemoteImage/tree/releases/p12.13) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p12.12...releases/p12.13) + +## [releases/p12.12](https://github.com/Pinterest/PINRemoteImage/tree/releases/p12.12) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p12.11...releases/p12.12) + +## [releases/p12.11](https://github.com/Pinterest/PINRemoteImage/tree/releases/p12.11) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p12.10...releases/p12.11) + +## [releases/p12.10](https://github.com/Pinterest/PINRemoteImage/tree/releases/p12.10) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p12.8...releases/p12.10) + +## [releases/p12.8](https://github.com/Pinterest/PINRemoteImage/tree/releases/p12.8) (2023-05-03) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p10.45...releases/p12.8) + + +- Add missing imports to the header [\#627](https://github.com/pinterest/PINRemoteImage/pull/627) ([xGeorge](https://github.com/xGeorge)) + +## [releases/p10.45](https://github.com/Pinterest/PINRemoteImage/tree/releases/p10.45) (2022-03-02) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.1...releases/p10.45) + +## [releases/p11.1](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.1) (2022-03-02) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.3...releases/p11.1) + +## [releases/p11.3](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.3) (2022-03-02) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.4...releases/p11.3) + +## [releases/p11.4](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.4) (2022-03-02) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.5...releases/p11.4) + +## [releases/p11.5](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.5) (2022-03-02) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.6...releases/p11.5) + +## [releases/p11.6](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.6) (2022-03-02) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.7...releases/p11.6) + +## [releases/p11.7](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.7) (2022-03-02) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.8...releases/p11.7) + +## [releases/p11.8](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.8) (2022-03-02) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.9...releases/p11.8) + +## [releases/p11.9](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.9) (2022-03-02) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.12...releases/p11.9) + +## [releases/p11.12](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.12) (2022-03-02) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.13...releases/p11.12) + +## [releases/p11.13](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.13) (2022-03-02) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.14...releases/p11.13) + +## [releases/p11.14](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.14) (2022-03-02) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.15...releases/p11.14) + +## [releases/p11.15](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.15) (2022-03-02) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.16...releases/p11.15) + +## [releases/p11.16](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.16) (2022-03-02) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.17...releases/p11.16) + +## [releases/p11.17](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.17) (2022-03-02) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.18...releases/p11.17) + +## [releases/p11.18](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.18) (2022-03-02) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/releases/p11.2...releases/p11.18) + +## [releases/p11.2](https://github.com/Pinterest/PINRemoteImage/tree/releases/p11.2) (2022-03-02) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/3.0.3...releases/p11.2) + + +- Stability fixes [\#618](https://github.com/pinterest/PINRemoteImage/pull/618) ([RRUIZ5](https://github.com/RRUIZ5)) +- Disable asserts in release builds when using Swift Package Manager [\#615](https://github.com/pinterest/PINRemoteImage/pull/615) ([rcancro](https://github.com/rcancro)) +- Add support for dynamic placeholder images [\#613](https://github.com/pinterest/PINRemoteImage/pull/613) ([bdolman](https://github.com/bdolman)) +- remove property:previousFrame from PINWebPAnimatedImage [\#611](https://github.com/pinterest/PINRemoteImage/pull/611) ([woshimaliang](https://github.com/woshimaliang)) +- unarchiveObjectWithData: and archivedDataWithRootObject: are deprecated [\#610](https://github.com/pinterest/PINRemoteImage/pull/610) ([woshimaliang](https://github.com/woshimaliang)) +- Set cachePolicy accordingly when PINRemoteImageManagerDownloadOptions is provided [\#605](https://github.com/pinterest/PINRemoteImage/pull/605) ([woshimaliang](https://github.com/woshimaliang)) +- Decode WebP images directly into a buffer Core Animation likes [\#600](https://github.com/pinterest/PINRemoteImage/pull/600) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Xcode 12.5 / SPM - Add missing headers to fix build errors [\#597](https://github.com/pinterest/PINRemoteImage/pull/597) ([bpollman](https://github.com/bpollman)) +- Fix PINRemoteImageManager.h Close Comment Formatting [\#594](https://github.com/pinterest/PINRemoteImage/pull/594) ([paulryanclark](https://github.com/paulryanclark)) +- Fix typo in PINRemoteImageManager.html [\#593](https://github.com/pinterest/PINRemoteImage/pull/593) ([HollowMan6](https://github.com/HollowMan6)) +- Fixed spm integration on regular Xcode project [\#586](https://github.com/pinterest/PINRemoteImage/pull/586) ([3a4oT](https://github.com/3a4oT)) +- Carthage is broken on Xcode 12 [\#584](https://github.com/pinterest/PINRemoteImage/pull/584) ([garrettmoon](https://github.com/garrettmoon)) +- Add APNG image support [\#543](https://github.com/pinterest/PINRemoteImage/pull/543) ([SAGESSE-CN](https://github.com/SAGESSE-CN)) + +## [3.0.3](https://github.com/Pinterest/PINRemoteImage/tree/3.0.3) (2020-10-23) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/3.0.2...3.0.3) + + +- Fixes macOS build on newer versions of Xcode [\#581](https://github.com/pinterest/PINRemoteImage/pull/581) ([garrettmoon](https://github.com/garrettmoon)) + +## [3.0.2](https://github.com/Pinterest/PINRemoteImage/tree/3.0.2) (2020-10-22) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/3.0.1...3.0.2) + + +- Add support for automated releases [\#580](https://github.com/pinterest/PINRemoteImage/pull/580) ([garrettmoon](https://github.com/garrettmoon)) +- Fix imports for non-SPM [\#579](https://github.com/pinterest/PINRemoteImage/pull/579) ([garrettmoon](https://github.com/garrettmoon)) +- Moves to an .xcworkspace so we don't imbed subprojects [\#575](https://github.com/pinterest/PINRemoteImage/pull/575) ([garrettmoon](https://github.com/garrettmoon)) +- SPM define [\#574](https://github.com/pinterest/PINRemoteImage/pull/574) ([3a4oT](https://github.com/3a4oT)) +- SPM - Objective-C++ consumers fix [\#573](https://github.com/pinterest/PINRemoteImage/pull/573) ([3a4oT](https://github.com/3a4oT)) +- Use proper units when setting preferredFramesPerSecond [\#572](https://github.com/pinterest/PINRemoteImage/pull/572) ([bdolman](https://github.com/bdolman)) +- SPM support [\#571](https://github.com/pinterest/PINRemoteImage/pull/571) ([3a4oT](https://github.com/3a4oT)) +- fix: build error when using multiproject config [\#569](https://github.com/pinterest/PINRemoteImage/pull/569) ([hendych](https://github.com/hendych)) +- Integrated UIGraphicsImageRenderer for iOS/tvOS 10.0 and above [\#549](https://github.com/pinterest/PINRemoteImage/pull/549) ([IHEARTCOOKIES](https://github.com/IHEARTCOOKIES)) +## [3.0.1](https://github.com/Pinterest/PINRemoteImage/tree/3.0.1) (2020-09-08) + +[Full Changelog](https://github.com/Pinterest/PINRemoteImage/compare/3.0.0...3.0.1) + +**Merged pull requests:** + +- Update PINCache in podspec [\#564](https://github.com/pinterest/PINRemoteImage/pull/564) ([garrettmoon](https://github.com/garrettmoon)) +- Update PINCache and PINOperation [\#562](https://github.com/pinterest/PINRemoteImage/pull/562) ([garrettmoon](https://github.com/garrettmoon)) +- Let's use the same commands we use locally. [\#561](https://github.com/pinterest/PINRemoteImage/pull/561) ([garrettmoon](https://github.com/garrettmoon)) +- Ensure the example defines the macros before referencing them. [\#557](https://github.com/pinterest/PINRemoteImage/pull/557) ([bolsinga](https://github.com/bolsinga)) +- Remove the PCH file and ensure macros are defined before using [\#556](https://github.com/pinterest/PINRemoteImage/pull/556) ([bolsinga](https://github.com/bolsinga)) +- Seems that having the framework and example have the same name confuses cocoapods [\#555](https://github.com/pinterest/PINRemoteImage/pull/555) ([garrettmoon](https://github.com/garrettmoon)) +- Upgrade WebP to 1.1.0 [\#554](https://github.com/pinterest/PINRemoteImage/pull/554) ([garrettmoon](https://github.com/garrettmoon)) +- Conditionally call CADisplayLink method based upon iOS10 availability to remove deprecation warning [\#552](https://github.com/pinterest/PINRemoteImage/pull/552) ([bolsinga](https://github.com/bolsinga)) +- Fix typos [\#548](https://github.com/pinterest/PINRemoteImage/pull/548) ([pgrimaud](https://github.com/pgrimaud)) +- Remove unused CI directory [\#547](https://github.com/pinterest/PINRemoteImage/pull/547) ([jparise](https://github.com/jparise)) +- PINCachedAnimatedImage: Fix retain cycles [\#546](https://github.com/pinterest/PINRemoteImage/pull/546) ([bolsinga](https://github.com/bolsinga)) +- Fix up analyze for new github CI [\#545](https://github.com/pinterest/PINRemoteImage/pull/545) ([garrettmoon](https://github.com/garrettmoon)) +- Switch to GitHub Actions for CI [\#544](https://github.com/pinterest/PINRemoteImage/pull/544) ([jparise](https://github.com/jparise)) +- \#trivial Fix performance issue caused by saving encoded image data to memory cache [\#539](https://github.com/pinterest/PINRemoteImage/pull/539) ([Naituw](https://github.com/Naituw)) +- Update 3.0.0 change log and podspec [\#537](https://github.com/pinterest/PINRemoteImage/pull/537) ([ernestmama](https://github.com/ernestmama)) +- Fix memory cache content in README [\#530](https://github.com/pinterest/PINRemoteImage/pull/530) ([OhKanghoon](https://github.com/OhKanghoon)) +- Refactor remote manager task for uuid method [\#526](https://github.com/pinterest/PINRemoteImage/pull/526) ([zhongwuzw](https://github.com/zhongwuzw)) +- Burst Animated Image speed of frame index search [\#523](https://github.com/pinterest/PINRemoteImage/pull/523) ([zhongwuzw](https://github.com/zhongwuzw)) +- Set HTTPMaximumConnectionsPerHost to PINRemoteImageHTTPMaximumConnectionsPerHost only if user don't provide sessionConfiguration [\#516](https://github.com/pinterest/PINRemoteImage/pull/516) ([zhongwuzw](https://github.com/zhongwuzw)) +- Fixes re-downloading data corrupt for the same url [\#514](https://github.com/pinterest/PINRemoteImage/pull/514) ([zhongwuzw](https://github.com/zhongwuzw)) + +## 3.0.0 -- 2020 Jan 06 +- [new] Add PINRemoteImageManagerConfiguration configuration object. [#492](https://github.com/pinterest/PINRemoteImage/pull/492) [rqueue](https://github.com/rqueue) +- [fixed] Fixes blending in animated WebP images. [#507](https://github.com/pinterest/PINRemoteImage/pull/507) [garrettmoon](https://github.com/garrettmoon) +- [fixed] Fixes support in PINAnimatedImageView for WebP animated images. [#507](https://github.com/pinterest/PINRemoteImage/pull/507) [garrettmoon](https://github.com/garrettmoon) +- [fixed] Fixes re-downloading data corrupt for the same url. [#514](https://github.com/pinterest/PINRemoteImage/pull/514) [zhongwuzw](https://github.com/zhongwuzw) +- [new] Exposure didCompleteTask:withError: delegate method of protocol PINURLSessionManagerDelegate. [#519](https://github.com/pinterest/PINRemoteImage/pull/519) [zhongwuzw](https://github.com/zhongwuzw) +- [fixed] Fixes AnimatedImageView designated initializer not work. [#512](https://github.com/pinterest/PINRemoteImage/pull/512) [zhongwuzw](https://github.com/zhongwuzw) +- [fixed] Set bpp(bits per pixel) to 32 bit for GIF. [#511](https://github.com/pinterest/PINRemoteImage/pull/511) [zhongwuzw](https://github.com/zhongwuzw) +- [new] Add cancel method for PINRemoteImageManager. [#509](https://github.com/pinterest/PINRemoteImage/pull/509) [zhongwuzw](https://github.com/zhongwuzw) +- [fixed] Fixes build error when using Xcode 10.2.1. [#524](https://github.com/pinterest/PINRemoteImage/pull/524) [ANNotunzdY](https://github.com/ANNotunzdY) + +## 3.0.0 Beta 14 +- [fixed] Re-enable warnings check [#506](https://github.com/pinterest/PINRemoteImage/pull/506) [garrettmoon](https://github.com/garrettmoon) +- [new] Allow use of NSURLCache via a custom NSURLSession [#477](https://github.com/pinterest/PINRemoteImage/pull/477) [wiseoldduck](https://github.com/wiseoldduck) +- [new] Respect Cache-Control and Expires headers if the cache supports TTL. [#462](https://github.com/pinterest/PINRemoteImage/pull/462) [wiseoldduck](https://github.com/wiseoldduck) +- [new] Updated to latest PINCache beta 7. [#461](https://github.com/pinterest/PINRemoteImage/pull/461) [wiseoldduck](https://github.com/wiseoldduck) +- [iOS11] Fix warnings [#428](https://github.com/pinterest/PINRemoteImage/pull/428) [Eke](https://github.com/Eke) +- [new / beta] Native Support for GIFs and animated WebP [#453](https://github.com/pinterest/PINRemoteImage/pull/453) [garrettmoon](https://github.com/garrettmoon) +- [new] Add support for getting NSURLSessionMetrics back. [#456](https://github.com/pinterest/PINRemoteImage/pull/456) [garrettmoon](https://github.com/garrettmoon) +- [removed] Removed support for FLAnimatedImage [#453](https://github.com/pinterest/PINRemoteImage/pull/453) [garrettmoon](https://github.com/garrettmoon) +- [new] Add support for higher frame rate devices to animated images. [#417](https://github.com/pinterest/PINRemoteImage/pull/417) [garrettmoon](https://github.com/garrettmoon) +- [fixed] Fixes non-animated GIFs being delivered as an animated image. [#434](https://github.com/pinterest/PINRemoteImage/pull/434) [garrettmoon](https://github.com/garrettmoon) +- [fixed] Fixes a bug where using PINRemoteImageBasicCache would cause images to be decoded on the main thread. [#457](https://github.com/pinterest/PINRemoteImage/pull/457) [kgaidis](https://github.com/kgaidis) +- [cleanup] Remove unused code that supported iOS < 7. [#435](https://github.com/pinterest/PINRemoteImage/pull/435) [Adlai-Holler](https://github.com/Adlai-Holler) +- [cleanup] Use NS_ERROR_ENUM to improve Swift import. [#440](https://github.com/pinterest/PINRemoteImage/pull/440) [Adlai-Holler](https://github.com/Adlai-Holler) +- [fixed] Fixes nil session manager configuration. [#460](https://github.com/pinterest/PINRemoteImage/pull/460) [garrettmoon](https://github.com/garrettmoon) +- [fixed] Fixes deprecated -defaultImageCache not being called if overridden. [479](https://github.com/pinterest/PINRemoteImage/pull/479) [nguyenhuy](https://github.com/nguyenhuy) +- [new] Add a new API that allows a priority to be set when a new download task is scheduled. [#490](https://github.com/pinterest/PINRemoteImage/pull/490) [nguyenhuy](https://github.com/nguyenhuy) + +## 3.0.0 Beta 13 +- [new] Support for webp and improved support for GIFs. [#411](https://github.com/pinterest/PINRemoteImage/pull/411) [garrettmoon](https://github.com/garrettmoon) +- [new] Added back tvOS support through a new target [#408](https://github.com/pinterest/PINRemoteImage/pull/408) [jverdi](https://github.com/jverdi) +- [refactor] Refactor out KVO on NSURLSessionTask to avoid Apple crashes. [#410](https://github.com/pinterest/PINRemoteImage/pull/410) [garrettmoon](https://github.com/garrettmoon) + +## 3.0.0 Beta 12 +- [new] Added a way to specify custom retry logic when network error happens [#386](https://github.com/pinterest/PINRemoteImage/pull/386) +- [new] Improve disk cache migration performance [#391](https://github.com/pinterest/PINRemoteImage/pull/391) [chuganzy](https://github.com/chuganzy), [#394](https://github.com/pinterest/PINRemoteImage/pull/394) [nguyenhuy](https://github.com/nguyenhuy) +- [new] Adds support for using cell vs. wifi in leau of speed for determing which URL to download if speed is unavailable. [garrettmoon](https://github.com/garrettmoon) +- [new] Uses BPS minus time to first byte for deciding which of a set of URLs to download. [garrettmoon](https://github.com/garrettmoon) +- [fixed] Fixes an edge case when image returned with 404 response, we now treat it as image instead of error [#399](https://github.com/pinterest/PINRemoteImage/pull/396) [maxwang](https://github.com/wsdwsd0829) + +## 3.0.0 Beta 11 +- [fixed] Fixes a deadlock with canceling processor tasks [#374](https://github.com/pinterest/PINRemoteImage/pull/374) [zachwaugh](https://github.com/zachwaugh) +- [fixed] Fixes a deadlock in the retry system. [garrettmoon](https://github.com/garrettmoon) +- [fixed] Fixes a threadsafety issue in accessing callbacks. [garrettmoon](https://github.com/garrettmoon) +- [fixed] Fixes a crash with resumed downloads when a key is long. [garrettmoon](https://github.com/garrettmoon) +- [new] PINRemoteImageManager now respects the request timeout value of session configuration. [garrettmoon](https://github.com/garrettmoon) +- [new] Updated to latest PINCache beta 5. [garrettmoon](https://github.com/garrettmoon) +- [new] Added support for getting NSURLResponse from a PINRemoteImageManagerResult object. [garrettmoon](https://github.com/garrettmoon) + +## 3.0.0 Beta 10 +- [new] Added support (in iOS 10) for skipping cancelation if the estimated amount of time to complete the download is less than the average time to first byte for a host. [#364](https://github.com/pinterest/PINRemoteImage/pull/364) [garrettmoon](https://github.com/garrettmoon) +- [fixed] Fixes an issue where PINResume would assert because the server didn't return an expected content length. +- [fixed] Fixed bytes per second on download tasks (which could affect if an image is progressively rendered) [#360](https://github.com/pinterest/PINRemoteImage/pull/360) [garrettmoon](https://github.com/garrettmoon) +- [new] Added request configuration handler to allow customizing HTTP headers per request [#355](https://github.com/pinterest/PINRemoteImage/pull/355) [zachwaugh](https://github.com/zachwaugh) +- [fixed] Moved storage of resume data to disk from memory. [garrettmoon](https://github.com/garrettmoon) +- [fixed] Hopefully fixes crashes occuring in PINURLSessionManager on iOS 9. [garrettmoon](https://github.com/garrettmoon) + +## 2.1.4 -- 2016 Apr 22 - [new] Have PINProgressiveImage pass back the quality of the current progressive image [#185](https://github.com/pinterest/PINRemoteImage/pull/185) -### 2.1.3 -- 2016 Apr 13 ### +## 2.1.3 -- 2016 Apr 13 - [fixed] Images May Be Removed from Disk Cache for Not Being in Memory Cache [#186](https://github.com/pinterest/PINRemoteImage/commit/f15ca03ece954b4712b2c669c849245617e73e08) -### 2.1.2 -- 2016 Mar 25 ### +## 2.1.2 -- 2016 Mar 25 - [fixed] Remove disk cache call potentially on main thread [#167](https://github.com/pinterest/PINRemoteImage/pull/167) - [fixed] Nullability specifiers [#170](https://github.com/pinterest/PINRemoteImage/pull/170) - [fixed] Speling errorrs, unused properties and spacing [#172](https://github.com/pinterest/PINRemoteImage/pull/172) -### 2.1.1 -- 2016 Mar 20 ### +## 2.1.1 -- 2016 Mar 20 - [new] Slightly more performant locking [#165](https://github.com/pinterest/PINRemoteImage/pull/165) - [new] Added support for pulling images synchronously from the cache [#162](https://github.com/pinterest/PINRemoteImage/pull/162) - [fixed] Non-decoded images no longer cached by OS [#161](https://github.com/pinterest/PINRemoteImage/pull/161) - [fixed] OS X and Carthage support [#164](https://github.com/pinterest/PINRemoteImage/pull/164) -### 2.1 -- 2016 Mar 11 ### +## 2.1 -- 2016 Mar 11 - [new] tvOS support: [#131](https://github.com/pinterest/PINRemoteImage/pull/131) - [new] Added method to get image out of cache synchronously: [#162](https://github.com/pinterest/PINRemoteImage/pull/162) - [fixed] Undecoded images are no longer cached by OS: [#161](https://github.com/pinterest/PINRemoteImage/pull/161) - [fixed] Carthage support and OS X example: [#160](https://github.com/pinterest/PINRemoteImage/pull/160) -### 2.0.1 -- 2016 Feb 23 ### +## 2.0.1 -- 2016 Feb 23 - [new] Removed explicit disabling of bitcode: [#136](https://github.com/pinterest/PINRemoteImage/pull/136) - [fixed] Progressive rendering in example apps: [#148](https://github.com/pinterest/PINRemoteImage/pull/148) - [fixed] Carthage compilation: [#141](https://github.com/pinterest/PINRemoteImage/pull/141) - [fixed] Crash on iOS 7 when setting download priority [#137](https://github.com/pinterest/PINRemoteImage/pull/137) -- [fixed] Dumb test bugs! [#144](https://github.com/pinterest/PINRemoteImage/pull/144) \ No newline at end of file +- [fixed] Dumb test bugs! [#144](https://github.com/pinterest/PINRemoteImage/pull/144) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..8b4e45e2 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,40 @@ +# Code of Conduct + +At Pinterest, we work hard to ensure that our work environment is welcoming +and inclusive to as many people as possible. We are committed to creating this +environment for everyone involved in our open source projects as well. We +welcome all participants regardless of ability, age, ethnicity, identified +gender, religion (or lack there of), sexual orientation and socioeconomic +status. + +This code of conduct details our expectations for upholding these values. + +## Good behavior + +We expect members of our community to exhibit good behavior including (but of +course not limited to): + +- Using intentional and empathetic language. +- Focusing on resolving instead of escalating conflict. +- Providing constructive feedback. + +## Unacceptable behavior + +Some examples of unacceptable behavior (again, this is not an exhaustive +list): + +- Harassment, publicly or in private. +- Trolling. +- Sexual advances (this isn’t the place for it). +- Publishing other’s personal information. +- Any behavior which would be deemed unacceptable in a professional environment. + +## Recourse + +If you are witness to or the target of unacceptable behavior, it should be +reported to Pinterest at opensource-policy@pinterest.com. All reporters will +be kept confidential and an appropriate response for each incident will be +evaluated. + +If the maintainers do not uphold and enforce this code of conduct in +good faith, community leadership will hold them accountable. \ No newline at end of file diff --git a/Cartfile b/Cartfile index 580ce89e..e080ef99 100644 --- a/Cartfile +++ b/Cartfile @@ -1 +1,2 @@ -github "pinterest/PINCache" >= 3.0.0 \ No newline at end of file +github "pinterest/PINCache" ~> 3.0.4 +github "pinterest/PINOperation" \ No newline at end of file diff --git a/Cartfile.resolved b/Cartfile.resolved index 4810ec5a..8faa66ef 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1 +1,2 @@ -github "pinterest/PINCache" "3.0.0-beta" +github "pinterest/PINCache" "3.0.4" +github "pinterest/PINOperation" "1.2.3" diff --git a/Carthage/Checkouts/PINCache/.github/workflows/ci.yaml b/Carthage/Checkouts/PINCache/.github/workflows/ci.yaml new file mode 100644 index 00000000..dea8df80 --- /dev/null +++ b/Carthage/Checkouts/PINCache/.github/workflows/ci.yaml @@ -0,0 +1,65 @@ +--- +name: CI + +on: + push: + branches: + - master + - 'releases/*' + pull_request: + branches: + - master + + +env: + # Use Xcode 15.2 or newer to support VisionOS + DEVELOPER_DIR: /Applications/Xcode_15.2.app + +jobs: + test: + name: Test + runs-on: macos-latest + strategy: + matrix: + platform: ['iOS Simulator,name=iPhone 15'] + steps: + - uses: actions/checkout@v2 + - name: Test + run: make test + analyze: + name: Analyze + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - name: analyze + run: make analyze + cocoapods: + name: CocoaPods + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - name: Lint + run: make cocoapods + carthage: + name: Carthage + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - name: carthage + run: make carthage + swift-package-manager: + runs-on: macos-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Verify that PINCache can be built by SPM + run: make spm + xcode-spm-integration: + name: Build iOS example project + runs-on: macos-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Check Xcode's spm integration + run: make example diff --git a/Carthage/Checkouts/PINCache/.github/workflows/publish_release.yml b/Carthage/Checkouts/PINCache/.github/workflows/publish_release.yml new file mode 100644 index 00000000..339c8e18 --- /dev/null +++ b/Carthage/Checkouts/PINCache/.github/workflows/publish_release.yml @@ -0,0 +1,44 @@ +name: Create Release +on: + workflow_dispatch: + inputs: + release-type: + description: 'The type of release. Must be major, minor or patch' + required: true + +env: + # Use Xcode 15.2 or newer to support VisionOS + DEVELOPER_DIR: /Applications/Xcode_15.2.app + +jobs: + create_release: + runs-on: macOS-latest + steps: + - uses: actions/checkout@v2 + # Make sure we can lint before creating the release. + - name: Cocoapods lint + run: make cocoapods + - name: Create Release Branch + env: + GITHUB_CHANGELOG_API_KEY: ${{ secrets.GITHUB_TOKEN }} + OSS_PROJECT: PINCache + run: | + gem install github_changelog_generator + Scripts/release.sh --${{ github.event.inputs.release-type }} + git push origin HEAD + - name: Tag Release + run: Scripts/tag-release-branch.sh + - name: Publish Release + uses: actions/create-release@v1 + env: + GITHUB_CHANGELOG_API_KEY: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ env.RELEASE_TAG }} + release_name: ${{ env.RELEASE_TAG }} + body_path: RELEASE_NOTES.md + draft: false + - name: Push to Cocoapods + env: + COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} + run: pod trunk push diff --git a/Carthage/Checkouts/PINCache/.github_changelog_generator b/Carthage/Checkouts/PINCache/.github_changelog_generator new file mode 100644 index 00000000..1c40d261 --- /dev/null +++ b/Carthage/Checkouts/PINCache/.github_changelog_generator @@ -0,0 +1,3 @@ +issues=false +since-tag=3.0.4 +future-release=3.0.5 diff --git a/Carthage/Checkouts/PINCache/.gitignore b/Carthage/Checkouts/PINCache/.gitignore new file mode 100644 index 00000000..0046cbf2 --- /dev/null +++ b/Carthage/Checkouts/PINCache/.gitignore @@ -0,0 +1,30 @@ +#Ignore the Mac OS X .DS_Store files +.DS_Store + +#Ignore user-specific settings +*.mode1v3 +*.mode2v3 +*.pbxuser +*.perspectivev3 +xcuserdata + +#Ignore textmate build errors +*.tm_build_errors + +#Ignore temp nibs and swap files +*.swp +*~.nib + +.gitattributes + +# Buck +/buck-out +/.buckconfig.local +/.buckd + +Carthage/Build + +# SPM +.swiftpm/ +.build/ +Package.resolved diff --git a/Pod/Assets/.gitkeep b/Carthage/Checkouts/PINCache/.gitmodules similarity index 100% rename from Pod/Assets/.gitkeep rename to Carthage/Checkouts/PINCache/.gitmodules diff --git a/Carthage/Checkouts/PINCache/.ruby-version b/Carthage/Checkouts/PINCache/.ruby-version new file mode 100644 index 00000000..15a27998 --- /dev/null +++ b/Carthage/Checkouts/PINCache/.ruby-version @@ -0,0 +1 @@ +3.3.0 diff --git a/Carthage/Checkouts/PINCache/CHANGELOG.md b/Carthage/Checkouts/PINCache/CHANGELOG.md new file mode 100644 index 00000000..890478c8 --- /dev/null +++ b/Carthage/Checkouts/PINCache/CHANGELOG.md @@ -0,0 +1,198 @@ +# Changelog + +## [3.0.4](https://github.com/Pinterest/PINCache/tree/3.0.4) (2024-05-13) + +[Full Changelog](https://github.com/Pinterest/PINCache/compare/3.0.3...3.0.4) + +- Add ability to configure maxConcurrentOperations [\#329](https://github.com/pinterest/PINCache/pull/329) ([andyfinnell](https://github.com/andyfinnell)) +- Add Least Frequently Used eviction strategy [\#328](https://github.com/pinterest/PINCache/pull/328) ([andyfinnell](https://github.com/andyfinnell)) +- Update project and installation methods \(CocoaPods and Swift Package Manager\) for Xcode 15 [\#327](https://github.com/pinterest/PINCache/pull/327) ([tstump-phunware](https://github.com/tstump-phunware)) + +## [3.0.3](https://github.com/Pinterest/PINCache/tree/3.0.3) (2020-10-22) + +[Full Changelog](https://github.com/Pinterest/PINCache/compare/3.0.2...3.0.3) + + +- Update PINOperation to fix imports [\#293](https://github.com/pinterest/PINCache/pull/293) ([garrettmoon](https://github.com/garrettmoon)) +- Add support for automated releases [\#292](https://github.com/pinterest/PINCache/pull/292) ([garrettmoon](https://github.com/garrettmoon)) +- Fix up imports [\#290](https://github.com/pinterest/PINCache/pull/290) ([garrettmoon](https://github.com/garrettmoon)) +- Fix build issues by removing nested PINOperation.xcodeproj [\#282](https://github.com/pinterest/PINCache/pull/282) ([elliottwilliams](https://github.com/elliottwilliams)) + +## [3.0.2](https://github.com/Pinterest/PINCache/tree/3.0.2) (2020-10-06) + +[Full Changelog](https://github.com/Pinterest/PINCache/compare/3.0.1...3.0.2) + +**Merged pull requests:** + +- Update checkout action [\#287](https://github.com/pinterest/PINCache/pull/287) ([garrettmoon](https://github.com/garrettmoon)) +- Use make commands on the CI so it actually fails [\#286](https://github.com/pinterest/PINCache/pull/286) ([garrettmoon](https://github.com/garrettmoon)) +- Added SPM support [\#283](https://github.com/pinterest/PINCache/pull/283) ([3a4oT](https://github.com/3a4oT)) +- Fix PINCaching compiling in Xcode 12.0b6 \(\#275\) [\#281](https://github.com/pinterest/PINCache/pull/281) ([sagesse-cn](https://github.com/sagesse-cn)) + +## [3.0.1](https://github.com/Pinterest/PINCache/tree/3.0.1) (2020-08-20) + +[Full Changelog](https://github.com/Pinterest/PINCache/compare/3.0.1-beta.8...3.0.1) + +**Implemented enhancements:** + +- Support Catalyst [\#272](https://github.com/pinterest/PINCache/pull/272) ([cgmaier](https://github.com/cgmaier)) + +**Merged pull requests:** + +- Update PINOperation [\#277](https://github.com/pinterest/PINCache/pull/277) ([garrettmoon](https://github.com/garrettmoon)) +- Fix PINCacheTests compiling in Xcode 12.0b4 [\#276](https://github.com/pinterest/PINCache/pull/276) ([arangato](https://github.com/arangato)) +- Remove BUCK files [\#274](https://github.com/pinterest/PINCache/pull/274) ([adlerj](https://github.com/adlerj)) +- Fix compiling in Xcode 12.0b4 [\#273](https://github.com/pinterest/PINCache/pull/273) ([zacwest](https://github.com/zacwest)) +- Fix the grammar in an assertion failure message [\#270](https://github.com/pinterest/PINCache/pull/270) ([jparise](https://github.com/jparise)) +- Add Carthage for watchOS, fix macOS min deployment target version [\#269](https://github.com/pinterest/PINCache/pull/269) ([dreampiggy](https://github.com/dreampiggy)) +- Remove the unused CI directory [\#265](https://github.com/pinterest/PINCache/pull/265) ([jparise](https://github.com/jparise)) +- Fix up analyze for github CI [\#264](https://github.com/pinterest/PINCache/pull/264) ([garrettmoon](https://github.com/garrettmoon)) +- Use correct class name in NSAssert\(\) messages [\#263](https://github.com/pinterest/PINCache/pull/263) ([jparise](https://github.com/jparise)) +- Check fileURL outside of the locked scope [\#262](https://github.com/pinterest/PINCache/pull/262) ([jparise](https://github.com/jparise)) +- Remove Danger from the project [\#261](https://github.com/pinterest/PINCache/pull/261) ([jparise](https://github.com/jparise)) +- Switch to GitHub Actions for CI [\#259](https://github.com/pinterest/PINCache/pull/259) ([jparise](https://github.com/jparise)) +- Test that the "remove object" blocks are called [\#258](https://github.com/pinterest/PINCache/pull/258) ([jparise](https://github.com/jparise)) +- Discrepancy between Header Comment and Implementation \#trivial [\#257](https://github.com/pinterest/PINCache/pull/257) ([jlaws](https://github.com/jlaws)) +- Optimization `PINMemoryCache` trim to date [\#252](https://github.com/pinterest/PINCache/pull/252) ([kinarobin](https://github.com/kinarobin)) +- Optimize `PINMemoryCache` remove objects when receive memory warning notification [\#251](https://github.com/pinterest/PINCache/pull/251) ([kinarobin](https://github.com/kinarobin)) + +## 3.0.1 -- Beta 8 +- [fix] Initing PINCache with TTL enabled should enable TTL on PINMemoryCache. [#246](https://github.com/pinterest/PINCache/pull/246) +- [performance] Return TTL cache objects without waiting for all metadata to be read. [#228](https://github.com/pinterest/PINCache/pull/228) +- [performance] Memory cache now performs some tasks such as trimming and removing experied objects with low priority. [#234](https://github.com/pinterest/PINCache/pull/234) + +## 3.0.1 -- Beta 7 +- [fix] Fix up warnings and upgrade to PINOperation 1.1.1: [#213](https://github.com/pinterest/PINCache/pull/213) +- [performance] Reduce locking churn in cleanup methods. [#212](https://github.com/pinterest/PINCache/pull/212) +- [fix] Don't set file protection unless requested. [#220](https://github.com/pinterest/PINCache/pull/220) +- [new] Add ability to set an object level TTL: [#209](https://github.com/pinterest/PINCache/pull/209) +- [performance] Improve performance of age limit trimming: [#224](https://github.com/pinterest/PINCache/pull/224) + +## 3.0.1 -- Beta 6 +- [fix] Add some sane limits to the disk cache: [#201]https://github.com/pinterest/PINCache/pull/201 +- [new] Update enumeration methods to allow a stop flag to be flipped by caller: [#204](https://github.com/pinterest/PINCache/pull/204) +- [performance] Improves cache miss performance by ~2 orders of magnitude on device: [#202](https://github.com/pinterest/PINCache/pull/202) +- [performance] Significantly improve startup performance: [#203](https://github.com/pinterest/PINCache/pull/203) + +## 3.0.1 -- Beta 5 +- [fix] Respect small byteLimit settings by checking object size in setObject: [#198](https://github.com/pinterest/PINCache/pull/198) +- [new] Added an ability to set custom encoder/decoder for file names: [#192](https://github.com/pinterest/PINCache/pull/192) + +## 2.2.1 -- 2016 Mar 5 +- [new] Removed need for extension macro: [#72](https://github.com/pinterest/PINCache/pull/72) + +## 2.2.1 -- 2016 Feb 15 + +- [fixed] When ttlCache is enabled, skip updating the file modification time when accessing `fileURLForKey:` [#70](https://github.com/pinterest/PINCache/pull/70) + +## 2.2 -- 2016 Feb 10 + +- [new] Allow caches to behave like a TTLCache [#66](https://github.com/pinterest/PINCache/pull/66) + +## 2.1.2 -- 2015 Nov 19 + +- [fix] Fix disk caching bug due to incorrect string encoding [#42](https://github.com/pinterest/PINCache/pull/42) + + +## 2.1.1 -- 2015 Nov 17 + +- [new] Added `tvOS` support +- [fixed] PINDiskCache byteCount tracking bug [#30](https://github.com/pinterest/PINCache/pull/30) + + +## 2.1 -- 2015 Aug 24 + +- [new] Xcode 7 support +- [fixed] Invalid task ID's used for expiration handler on background tasks [#13](https://github.com/pinterest/PINCache/issues/13) +- [fixed] Support for OS X since UIBackgroundTask is only on iOS [#19](https://github.com/pinterest/PINCache/pull/19) + + +## 2.0.1 -- 2015 May 1 + +- [new] Added support for using PINCache in extensions +- [new] Adopting nullability annotations. + + +## 2.0 -- 2015 February 25 + +- [fix] PINCache redesign to avoid deadlocks + + +## 1.2.3 -- 2014 December 13 + +- [fix] TMDiskCache/TMMemoryCache: import `UIKit` to facilitate Swift usage (thanks [digabriel](https://github.com/tumblr/TMCache/pull/57)!) +- [fix] TMDiskCache: add try catch to ensure an exception isn’t thrown if a file on disk is unable to be unarchived (thanks [leonskywalker](https://github.com/tumblr/TMCache/pull/62)!) +- [fix] TMDiskCache: create trash directory asynchronously to avoid race condition (thanks [napoapo77](https://github.com/tumblr/TMCache/pull/68)!) + + +## 1.2.2 -- 2014 October 6 + +- [new] Remove deprecated `documentation` property from Podspec + + +## 1.2.1 -- 2013 July 28 + +- [new] TMDiskCache: introduced concept of "trash" for rapid wipeouts +- [new] TMDiskCache: `nil` checks to prevent crashes +- [new] TMCache/TMDiskCache/TMMemoryCache: import Foundation to facilitate Swift usage + + +## 1.2.0 -- 2013 May 24 + +- [new] TMDiskCache: added method `enumerateObjectsWithBlock:completionBlock:` +- [new] TMDiskCache: added method `enumerateObjectsWithBlock:` +- [new] TMDiskCache: added unit tests for the above +- [new] TMMemoryCache: added method `enumerateObjectsWithBlock:completionBlock:` +- [new] TMMemoryCache: added method `enumerateObjectsWithBlock:` +- [new] TMMemoryCache: added event block `didReceiveMemoryWarningBlock` +- [new] TMMemoryCache: added event block `didEnterBackgroundBlock` +- [new] TMMemoryCache: added boolean property `removeAllObjectsOnMemoryWarning` +- [new] TMMemoryCache: added boolean property `removeAllObjectsOnEnteringBackground` +- [new] TMMemoryCache: added unit tests for memory warning and app background blocks +- [del] TMCache: removed `cost` methods pending a solution for disk-based cost + + +## 1.1.2 -- 2013 May 13 + +- [fix] TMCache: prevent `objectForKey:block:` from hitting the thread ceiling +- [new] TMCache: added a test to make sure we don't deadlock the queue + + +## 1.1.1 -- 2013 May 1 + +- [fix] simplified appledoc arguments in podspec, updated doc script + + +## 1.1.0 -- 2013 April 29 + +- [new] TMCache: added method `setObject:forKey:withCost:` +- [new] TMCache: documentation + + +## 1.0.3 -- 2013 April 27 + +- [new] TMCache: added property `diskByteCount` (for convenience) +- [new] TMMemoryCache: `totalCost` now returned synchronously from queue +- [fix] TMMemoryCache: `totalCost` set to zero immediately after `removeAllObjects:` + + +## 1.0.2 -- 2013 April 26 + +- [fix] TMCache: cache hits from memory will now update access time on disk +- [fix] TMDiskCache: set & remove methods now acquire a `UIBackgroundTaskIdentifier` +- [fix] TMDiskCache: will/didAddObject blocks actually get executed +- [fix] TMDiskCache: `trimToSize:` now correctly removes objects in order of size +- [fix] TMMemoryCache: `trimToCost:` now correctly removes objects in order of cost +- [new] TMDiskCache: added method `trimToSizeByDate:` +- [new] TMMemoryCache: added method `trimToCostByDate:` +- [new] TMDiskCache: added properties `willRemoveAllObjectsBlock` & `didRemoveAllObjectsBlock` +- [new] TMMemoryCache: added properties `willRemoveAllObjectsBlock` & `didRemoveAllObjectsBlock` +- [new] TMCache: added unit tests + + +## 1.0.1 -- 2013 April 23 + +- added an optional "cost limit" to `TMMemoryCache`, including new properties and methods +- calling `[TMDiskCache trimToDate:]` with `[NSDate distantPast]` will now clear the cache +- calling `[TMDiskCache trimDiskToSize:]` will now remove files in order of access date +- setting the byte limit on `TMDiskCache` to 0 will no longer clear the cache (0 means no limit) diff --git a/Carthage/Checkouts/PINCache/CODE_OF_CONDUCT.md b/Carthage/Checkouts/PINCache/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..8b4e45e2 --- /dev/null +++ b/Carthage/Checkouts/PINCache/CODE_OF_CONDUCT.md @@ -0,0 +1,40 @@ +# Code of Conduct + +At Pinterest, we work hard to ensure that our work environment is welcoming +and inclusive to as many people as possible. We are committed to creating this +environment for everyone involved in our open source projects as well. We +welcome all participants regardless of ability, age, ethnicity, identified +gender, religion (or lack there of), sexual orientation and socioeconomic +status. + +This code of conduct details our expectations for upholding these values. + +## Good behavior + +We expect members of our community to exhibit good behavior including (but of +course not limited to): + +- Using intentional and empathetic language. +- Focusing on resolving instead of escalating conflict. +- Providing constructive feedback. + +## Unacceptable behavior + +Some examples of unacceptable behavior (again, this is not an exhaustive +list): + +- Harassment, publicly or in private. +- Trolling. +- Sexual advances (this isn’t the place for it). +- Publishing other’s personal information. +- Any behavior which would be deemed unacceptable in a professional environment. + +## Recourse + +If you are witness to or the target of unacceptable behavior, it should be +reported to Pinterest at opensource-policy@pinterest.com. All reporters will +be kept confidential and an appropriate response for each incident will be +evaluated. + +If the maintainers do not uphold and enforce this code of conduct in +good faith, community leadership will hold them accountable. \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Cartfile b/Carthage/Checkouts/PINCache/Cartfile new file mode 100644 index 00000000..89ffff3f --- /dev/null +++ b/Carthage/Checkouts/PINCache/Cartfile @@ -0,0 +1 @@ +github "pinterest/PINOperation" ~> 1.2.3 \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Cartfile.resolved b/Carthage/Checkouts/PINCache/Cartfile.resolved new file mode 100644 index 00000000..3489bcdc --- /dev/null +++ b/Carthage/Checkouts/PINCache/Cartfile.resolved @@ -0,0 +1 @@ +github "pinterest/PINOperation" "1.2.3" diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/.github/workflows/ci.yml b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/.github/workflows/ci.yml new file mode 100644 index 00000000..053ed706 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/.github/workflows/ci.yml @@ -0,0 +1,54 @@ +--- +name: CI + +on: + push: + branches: + - master + - 'releases/*' + pull_request: + branches: + - master + +env: + # Use Xcode 15.2 or newer to support VisionOS + DEVELOPER_DIR: /Applications/Xcode_15.2.app + +jobs: + test: + name: Test + runs-on: macos-latest + strategy: + matrix: + platform: ['iOS Simulator,name=iPhone 15'] + steps: + - uses: actions/checkout@v2 + - name: Test + run: make test + analyze: + name: Analyze + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - name: analyze + run: make analyze + cocoapods: + name: CocoaPods + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - name: Cocoapods lint + run: make cocoapods + carthage: + name: Carthage + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - name: carthage + run: make carthage + swift-package-manager: + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - name: Verify that PINOperation can be built by SPM + run: make spm diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/.github/workflows/publish_release.yml b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/.github/workflows/publish_release.yml new file mode 100644 index 00000000..c4262e64 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/.github/workflows/publish_release.yml @@ -0,0 +1,44 @@ +name: Create Release +on: + workflow_dispatch: + inputs: + release-type: + description: 'The type of release. Must be major, minor or patch' + required: true + +env: + # Use Xcode 15.2 or newer to support VisionOS + DEVELOPER_DIR: /Applications/Xcode_15.2.app + +jobs: + create_release: + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + # Make sure we can lint before creating the release. + - name: Cocoapods lint + run: make cocoapods + - name: Create Release Commit + env: + GITHUB_CHANGELOG_API_KEY: ${{ secrets.GITHUB_TOKEN }} + OSS_PROJECT: PINOperation + run: | + gem install github_changelog_generator + Scripts/release.sh --${{ github.event.inputs.release-type }} + git push origin HEAD + - name: Tag Release + run: Scripts/tag-release-branch.sh + - name: Publish Release + uses: actions/create-release@v1 + env: + GITHUB_CHANGELOG_API_KEY: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ env.RELEASE_TAG }} + release_name: ${{ env.RELEASE_TAG }} + body_path: RELEASE_NOTES.md + draft: false + - name: Push to Cocoapods + env: + COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} + run: pod trunk push diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/.github_changelog_generator b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/.github_changelog_generator new file mode 100644 index 00000000..3bd27222 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/.github_changelog_generator @@ -0,0 +1,3 @@ +issues=false +since-tag=1.2.1 +future-release=1.2.2 diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/.gitignore b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/.gitignore new file mode 100644 index 00000000..4021767b --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/.gitignore @@ -0,0 +1,57 @@ +.DS_Store + +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData/ + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ + +## Other +*.moved-aside +*.xcuserstate + +## Obj-C/Swift specific +*.hmap +*.ipa +*.dSYM.zip +*.dSYM + +## Docs +docs/docsets/ + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +.build/ + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# Bundler +.bundle +vendor + +# Example project +Example/Pods diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/BUCK b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/BUCK new file mode 100755 index 00000000..c7ade9d1 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/BUCK @@ -0,0 +1,22 @@ +apple_library( + name = 'PINOperation', + modular = True, + exported_headers = glob(['Source/*.h']), + srcs = + glob(['Source/*.m']), + preprocessor_flags = ['-fobjc-arc'], + lang_preprocessor_flags = { + 'C': ['-std=gnu99'], + 'CXX': ['-std=gnu++11', '-stdlib=libc++'], + }, + linker_flags = [ + '-weak_framework', + 'UIKit', + '-weak_framework', + 'AppKit', + ], + frameworks = [ + '$SDKROOT/System/Library/Frameworks/Foundation.framework', + ], + visibility = ['PUBLIC'], +) diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/CHANGELOG.md b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/CHANGELOG.md new file mode 100644 index 00000000..f11e9740 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/CHANGELOG.md @@ -0,0 +1,64 @@ +# Changelog + +## [1.2.3](https://github.com/Pinterest/PINOperation/tree/1.2.3) (TBD) + +[Full Changelog](https://github.com/Pinterest/PINOperation/compare/1.2.2...1.2.3) + + +- Update project to build and run using Xcode 15 +- Update CocoaPods Podspec to include Privacy Manifest file +- Bump minimum deployment targets to iOS 12, tvOS 12, watchOS 4, and macOS 10.13 + +## [1.2.2](https://github.com/Pinterest/PINOperation/tree/1.2.2) (2022-11-28) + +[Full Changelog](https://github.com/Pinterest/PINOperation/compare/1.2.1...1.2.2) + + +- Update CI to modern xcode and fix Carthage [\#47](https://github.com/pinterest/PINOperation/pull/47) ([garrettmoon](https://github.com/garrettmoon)) +- Disable asserts in release builds when using Swift Package Manager [\#44](https://github.com/pinterest/PINOperation/pull/44) ([rcancro](https://github.com/rcancro)) +- Carthage is busted on Xcode 12 [\#41](https://github.com/pinterest/PINOperation/pull/41) ([garrettmoon](https://github.com/garrettmoon)) +- Latest release script [\#40](https://github.com/pinterest/PINOperation/pull/40) ([garrettmoon](https://github.com/garrettmoon)) +- Fixes for automated release process [\#39](https://github.com/pinterest/PINOperation/pull/39) ([garrettmoon](https://github.com/garrettmoon)) + +## [1.2.1](https://github.com/Pinterest/PINOperation/tree/1.2.1) (2020-10-22) + +[Full Changelog](https://github.com/Pinterest/PINOperation/compare/1.2...1.2.1) + + +- Add release script [\#38](https://github.com/pinterest/PINOperation/pull/38) ([garrettmoon](https://github.com/garrettmoon)) +- Only use @import for SPM [\#36](https://github.com/pinterest/PINOperation/pull/36) ([garrettmoon](https://github.com/garrettmoon)) +- Add SPM Test [\#35](https://github.com/pinterest/PINOperation/pull/35) ([garrettmoon](https://github.com/garrettmoon)) +- Remove BUCK target [\#34](https://github.com/pinterest/PINOperation/pull/34) ([adlerj](https://github.com/adlerj)) + +## [1.2](https://github.com/Pinterest/PINOperation/tree/1.2) (2020-06-30) + +[Full Changelog](https://github.com/Pinterest/PINOperation/compare/1.1.2...1.2) + +**Merged pull requests:** + +- Swift Package Manager support [\#32](https://github.com/pinterest/PINOperation/pull/32) ([martinpucik](https://github.com/martinpucik)) +- Add Carthage for watchOS, dependent by PINCache [\#31](https://github.com/pinterest/PINOperation/pull/31) ([dreampiggy](https://github.com/dreampiggy)) +- Fix analyzing [\#30](https://github.com/pinterest/PINOperation/pull/30) ([garrettmoon](https://github.com/garrettmoon)) +- Standardize our GitHub Actions CI workflow [\#29](https://github.com/pinterest/PINOperation/pull/29) ([jparise](https://github.com/jparise)) +- Github CI [\#26](https://github.com/pinterest/PINOperation/pull/26) ([rahul-malik](https://github.com/rahul-malik)) +- Fixes coalesce operation race condition [\#24](https://github.com/pinterest/PINOperation/pull/24) ([zhongwuzw](https://github.com/zhongwuzw)) + +## [1.1.2](https://github.com/Pinterest/PINOperation/tree/1.1.2) (2019-06-11) + +[Full Changelog](https://github.com/Pinterest/PINOperation/compare/1.1.1...1.1.2) + +**Merged pull requests:** + +- Modernizing project [\#21](https://github.com/pinterest/PINOperation/pull/21) ([garrettmoon](https://github.com/garrettmoon)) +- Updates BUCK build file to match source layout. [\#20](https://github.com/pinterest/PINOperation/pull/20) ([RCacheaux](https://github.com/RCacheaux)) +- 1.1.1 release [\#19](https://github.com/pinterest/PINOperation/pull/19) ([garrettmoon](https://github.com/garrettmoon)) + +## 1.1.1 -- 2018 February 3 +* Cleanup warnings [garrett](https://github.com/garrettmoon) + +## 1.1 -- 2017 October 7 +* Deprecate addOperation: in favor of scheduleOperation: [garrett](https://github.com/garrettmoon) + +## 1.0.0 -- 2017 January 10 + +- Initial release! diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/CI/build.sh b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/CI/build.sh new file mode 100755 index 00000000..bbdb8f94 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/CI/build.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -eo pipefail + +make all \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/CI/exclude-from-build.json b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/CI/exclude-from-build.json new file mode 100644 index 00000000..03853aa7 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/CI/exclude-from-build.json @@ -0,0 +1,7 @@ +[ + "^plans/", + "^docs/", + "^CI/exclude-from-build.json$", + "^README.md$", + "^CHANGELOG.md$" +] \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/CODE_OF_CONDUCT.md b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..8b4e45e2 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/CODE_OF_CONDUCT.md @@ -0,0 +1,40 @@ +# Code of Conduct + +At Pinterest, we work hard to ensure that our work environment is welcoming +and inclusive to as many people as possible. We are committed to creating this +environment for everyone involved in our open source projects as well. We +welcome all participants regardless of ability, age, ethnicity, identified +gender, religion (or lack there of), sexual orientation and socioeconomic +status. + +This code of conduct details our expectations for upholding these values. + +## Good behavior + +We expect members of our community to exhibit good behavior including (but of +course not limited to): + +- Using intentional and empathetic language. +- Focusing on resolving instead of escalating conflict. +- Providing constructive feedback. + +## Unacceptable behavior + +Some examples of unacceptable behavior (again, this is not an exhaustive +list): + +- Harassment, publicly or in private. +- Trolling. +- Sexual advances (this isn’t the place for it). +- Publishing other’s personal information. +- Any behavior which would be deemed unacceptable in a professional environment. + +## Recourse + +If you are witness to or the target of unacceptable behavior, it should be +reported to Pinterest at opensource-policy@pinterest.com. All reporters will +be kept confidential and an appropriate response for each incident will be +evaluated. + +If the maintainers do not uphold and enforce this code of conduct in +good faith, community leadership will hold them accountable. \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Dangerfile b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Dangerfile new file mode 100644 index 00000000..d909431b --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Dangerfile @@ -0,0 +1,23 @@ +source_pattern = /(\.m|\.mm|\.h)$/ + +# Sometimes it's a README fix, or something like that - which isn't relevant for +# including in a project's CHANGELOG for example +declared_trivial = github.pr_title.include? "#trivial" +has_changes_in_source_directory = !git.modified_files.grep(/Source/).empty? + +modified_source_files = git.modified_files.grep(source_pattern) +has_modified_source_files = !modified_source_files.empty? +added_source_files = git.added_files.grep(source_pattern) +has_added_source_files = !added_source_files.empty? + +# Make it more obvious that a PR is a work in progress and shouldn't be merged yet +warn("PR is classed as Work in Progress") if github.pr_title.include? "[WIP]" + +# Warn when there is a big PR +warn("This is a big PR, please consider splitting it up to ease code review.") if git.lines_of_code > 500 + +# Changelog entries are required for changes to source files. +no_changelog_entry = !git.modified_files.include?("CHANGELOG.md") +if has_changes_in_source_directory && no_changelog_entry && !declared_trivial + warn("Any source code changes should have an entry in CHANGELOG.md or have #trivial in their title.") +end diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcodeproj/project.pbxproj b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcodeproj/project.pbxproj new file mode 100644 index 00000000..01324ee2 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcodeproj/project.pbxproj @@ -0,0 +1,352 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 60; + objects = { + +/* Begin PBXBuildFile section */ + 1387274F245D5BB500C1F56D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1387274E245D5BB500C1F56D /* AppDelegate.swift */; }; + 13872758245D5BB800C1F56D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13872757245D5BB800C1F56D /* Assets.xcassets */; }; + 1387275B245D5BB800C1F56D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 13872759245D5BB800C1F56D /* LaunchScreen.storyboard */; }; + 13872765245D5D8200C1F56D /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 13872764245D5D8200C1F56D /* MainViewController.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1387274B245D5BB500C1F56D /* PINOperationExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PINOperationExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 1387274E245D5BB500C1F56D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 13872757245D5BB800C1F56D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1387275A245D5BB800C1F56D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 1387275C245D5BB800C1F56D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 13872762245D5D8200C1F56D /* PINOperationExample-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PINOperationExample-Bridging-Header.h"; sourceTree = ""; }; + 13872763245D5D8200C1F56D /* MainViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MainViewController.h; sourceTree = ""; }; + 13872764245D5D8200C1F56D /* MainViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MainViewController.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 13872748245D5BB500C1F56D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 110EBBE34DCD59092AC3306C /* Pods */ = { + isa = PBXGroup; + children = ( + ); + path = Pods; + sourceTree = ""; + }; + 13872742245D5BB500C1F56D = { + isa = PBXGroup; + children = ( + 1387274D245D5BB500C1F56D /* PINOperationExample */, + 1387274C245D5BB500C1F56D /* Products */, + 110EBBE34DCD59092AC3306C /* Pods */, + ); + sourceTree = ""; + }; + 1387274C245D5BB500C1F56D /* Products */ = { + isa = PBXGroup; + children = ( + 1387274B245D5BB500C1F56D /* PINOperationExample.app */, + ); + name = Products; + sourceTree = ""; + }; + 1387274D245D5BB500C1F56D /* PINOperationExample */ = { + isa = PBXGroup; + children = ( + 1387274E245D5BB500C1F56D /* AppDelegate.swift */, + 13872763245D5D8200C1F56D /* MainViewController.h */, + 13872764245D5D8200C1F56D /* MainViewController.m */, + 13872757245D5BB800C1F56D /* Assets.xcassets */, + 13872759245D5BB800C1F56D /* LaunchScreen.storyboard */, + 1387275C245D5BB800C1F56D /* Info.plist */, + 13872762245D5D8200C1F56D /* PINOperationExample-Bridging-Header.h */, + ); + path = PINOperationExample; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1387274A245D5BB500C1F56D /* PINOperationExample */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1387275F245D5BB800C1F56D /* Build configuration list for PBXNativeTarget "PINOperationExample" */; + buildPhases = ( + 13872747245D5BB500C1F56D /* Sources */, + 13872748245D5BB500C1F56D /* Frameworks */, + 13872749245D5BB500C1F56D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PINOperationExample; + productName = PINOperationExample; + productReference = 1387274B245D5BB500C1F56D /* PINOperationExample.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 13872743245D5BB500C1F56D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 1140; + LastUpgradeCheck = 1520; + ORGANIZATIONNAME = Pinterest; + TargetAttributes = { + 1387274A245D5BB500C1F56D = { + CreatedOnToolsVersion = 11.4.1; + LastSwiftMigration = 1140; + }; + }; + }; + buildConfigurationList = 13872746245D5BB500C1F56D /* Build configuration list for PBXProject "PINOperationExample" */; + compatibilityVersion = "Xcode 15.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 13872742245D5BB500C1F56D; + productRefGroup = 1387274C245D5BB500C1F56D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 1387274A245D5BB500C1F56D /* PINOperationExample */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 13872749245D5BB500C1F56D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1387275B245D5BB800C1F56D /* LaunchScreen.storyboard in Resources */, + 13872758245D5BB800C1F56D /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 13872747245D5BB500C1F56D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1387274F245D5BB500C1F56D /* AppDelegate.swift in Sources */, + 13872765245D5D8200C1F56D /* MainViewController.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 13872759245D5BB800C1F56D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 1387275A245D5BB800C1F56D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1387275D245D5BB800C1F56D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 1387275E245D5BB800C1F56D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 13872760245D5BB800C1F56D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = PINOperationExample/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperationExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "PINOperationExample/PINOperationExample-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 13872761245D5BB800C1F56D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = PINOperationExample/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperationExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "PINOperationExample/PINOperationExample-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 13872746245D5BB500C1F56D /* Build configuration list for PBXProject "PINOperationExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1387275D245D5BB800C1F56D /* Debug */, + 1387275E245D5BB800C1F56D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1387275F245D5BB800C1F56D /* Build configuration list for PBXNativeTarget "PINOperationExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 13872760245D5BB800C1F56D /* Debug */, + 13872761245D5BB800C1F56D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 13872743245D5BB500C1F56D /* Project object */; +} diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..b6d9930d --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..4cdc4885 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample/AppDelegate.swift b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample/AppDelegate.swift new file mode 100644 index 00000000..7aa52db8 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample/AppDelegate.swift @@ -0,0 +1,31 @@ +// +// AppDelegate.swift +// PINOperationExample +// +// Created by Martin Púčik on 02/05/2020. +// Copyright © 2020 Pinterest. All rights reserved. +// + +import UIKit + +@UIApplicationMain +final class AppDelegate: UIResponder, UIApplicationDelegate { + private let queue: PINOperationQueue = PINOperationQueue(maxConcurrentOperations: 5) + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + let operationCount = 100 + let group = DispatchGroup() + for _ in 0.. + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample/Info.plist b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample/Info.plist new file mode 100644 index 00000000..75404a26 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample/Info.plist @@ -0,0 +1,41 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample/MainViewController.h b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample/MainViewController.h new file mode 100644 index 00000000..df2e69c3 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample/MainViewController.h @@ -0,0 +1,17 @@ +// +// MainViewController.h +// PINOperationExample +// +// Created by Martin Púčik on 02/05/2020. +// Copyright © 2020 Pinterest. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface MainViewController : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample/MainViewController.m b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample/MainViewController.m new file mode 100644 index 00000000..50d0c95d --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample/MainViewController.m @@ -0,0 +1,41 @@ +// +// MainViewController.m +// PINOperationExample +// +// Created by Martin Púčik on 02/05/2020. +// Copyright © 2020 Pinterest. All rights reserved. +// + +#import "MainViewController.h" +#import +//#import + +@interface MainViewController () +@property (nonatomic, strong) PINOperationQueue *queue; +@end + +@implementation MainViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + self.queue = [[PINOperationQueue alloc] initWithMaxConcurrentOperations:5]; + + const NSUInteger operationCount = 100; + dispatch_group_t group = dispatch_group_create(); + + for (NSUInteger count = 0; count < operationCount; count++) { + dispatch_group_enter(group); + [self.queue scheduleOperation:^{ + dispatch_group_leave(group); + } withPriority:PINOperationQueuePriorityDefault]; + } + + NSUInteger success = dispatch_group_wait(group, [self timeout]); + NSAssert(success == 0, @"Timed out before completing 100 operations"); +} + +- (dispatch_time_t)timeout { + return dispatch_time(DISPATCH_TIME_NOW, (int64_t)(20 * NSEC_PER_SEC)); +} + +@end diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample/PINOperationExample-Bridging-Header.h b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample/PINOperationExample-Bridging-Header.h new file mode 100644 index 00000000..f3b5f384 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/PINOperationExample/PINOperationExample-Bridging-Header.h @@ -0,0 +1 @@ +#import diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/Podfile b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/Podfile new file mode 100644 index 00000000..62ba7b9b --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/Podfile @@ -0,0 +1,6 @@ +source 'https://cdn.cocoapods.org/' +platform :ios, '12.0' + +target 'PINOperationExample' do + pod 'PINOperation', :path => '../' +end diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/Podfile.lock b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/Podfile.lock new file mode 100644 index 00000000..cbbd5f30 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Example/Podfile.lock @@ -0,0 +1,16 @@ +PODS: + - PINOperation (1.2.3) + +DEPENDENCIES: + - PINOperation (from `../`) + +EXTERNAL SOURCES: + PINOperation: + :path: "../" + +SPEC CHECKSUMS: + PINOperation: fb563bcc9c32c26d6c78aaff967d405aa2ee74a7 + +PODFILE CHECKSUM: 590bbecb30df161f3cdb5ab267c95244b0df928f + +COCOAPODS: 1.15.2 diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Gemfile b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Gemfile new file mode 100644 index 00000000..38bfbc8e --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Gemfile @@ -0,0 +1,4 @@ +source 'https://rubygems.org' + +gem 'danger' +gem 'danger-slack' \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/LICENSE.txt b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/LICENSE.txt new file mode 100644 index 00000000..d0381d6d --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/LICENSE.txt @@ -0,0 +1,176 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.podspec b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.podspec new file mode 100644 index 00000000..18d75d46 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.podspec @@ -0,0 +1,25 @@ +Pod::Spec.new do |s| + s.name = 'PINOperation' + s.version = '1.2.3' + s.homepage = 'https://github.com/pinterest/PINOperation' + s.summary = 'Fast, concurrency-limited task queue for iOS and OS X.' + s.authors = { 'Garrett Moon' => 'garrett@pinterest.com' } + s.source = { :git => 'https://github.com/pinterest/PINOperation.git', :tag => "#{s.version}" } + s.license = { :type => 'Apache 2.0', :file => 'LICENSE.txt' } + s.requires_arc = true + s.frameworks = 'Foundation' + s.cocoapods_version = '>= 1.13.0' + s.ios.deployment_target = '12.0' + s.osx.deployment_target = '10.13' + s.tvos.deployment_target = '12.0' + s.visionos.deployment_target = '1.0' + s.watchos.deployment_target = '4.0' + pch_PIN = <<-EOS +#ifndef TARGET_OS_WATCH + #define TARGET_OS_WATCH 0 +#endif +EOS + s.prefix_header_contents = pch_PIN + s.source_files = 'Source/*.{h,m}' + s.resource_bundles = { 'PINOperation' => ['Source/PrivacyInfo.xcprivacy'] } +end diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/project.pbxproj b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/project.pbxproj new file mode 100644 index 00000000..6e8f8563 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/project.pbxproj @@ -0,0 +1,1462 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 60; + objects = { + +/* Begin PBXBuildFile section */ + 3201179424444862004FD783 /* PINOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105801E2711B700890935 /* PINOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3201179524444862004FD783 /* PINOperationGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105811E2711B700890935 /* PINOperationGroup.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3201179624444862004FD783 /* PINOperationMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105831E2711B700890935 /* PINOperationMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3201179724444862004FD783 /* PINOperationQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105841E2711B700890935 /* PINOperationQueue.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3201179824444862004FD783 /* PINOperationTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105861E2711B700890935 /* PINOperationTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3201179924444862004FD783 /* PINOperationGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0105821E2711B700890935 /* PINOperationGroup.m */; }; + 3201179A24444862004FD783 /* PINOperationQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0105851E2711B700890935 /* PINOperationQueue.m */; }; + 68133AEC2BE056A5007627EC /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 68133AEB2BE056A5007627EC /* PrivacyInfo.xcprivacy */; }; + 6817A6442BE46E48007710C1 /* PINOperationGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0105821E2711B700890935 /* PINOperationGroup.m */; }; + 6817A6452BE46E48007710C1 /* PINOperationQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0105851E2711B700890935 /* PINOperationQueue.m */; }; + 6817A6482BE46E48007710C1 /* PINOperationTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105861E2711B700890935 /* PINOperationTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6817A6492BE46E48007710C1 /* PINOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105801E2711B700890935 /* PINOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6817A64A2BE46E48007710C1 /* PINOperationGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105811E2711B700890935 /* PINOperationGroup.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6817A64B2BE46E48007710C1 /* PINOperationMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105831E2711B700890935 /* PINOperationMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6817A64C2BE46E48007710C1 /* PINOperationQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105841E2711B700890935 /* PINOperationQueue.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6817A64E2BE46E48007710C1 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 68133AEB2BE056A5007627EC /* PrivacyInfo.xcprivacy */; }; + 6850F2E62BE471CB00A38144 /* PINOperationQueueTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01059D1E27131B00890935 /* PINOperationQueueTests.m */; }; + 6850F2E72BE471CB00A38144 /* PINOperationGroupTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01059E1E27131B00890935 /* PINOperationGroupTests.m */; }; + 686ECECD2BE4731900634D9F /* PINOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6817A6522BE46E48007710C1 /* PINOperation.framework */; }; + 686ECED62BE474F300634D9F /* PINOperationQueueTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01059D1E27131B00890935 /* PINOperationQueueTests.m */; }; + 686ECED72BE474F300634D9F /* PINOperationGroupTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01059E1E27131B00890935 /* PINOperationGroupTests.m */; }; + 68B3C3072BE475FF00C335B8 /* PINOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3201178C24444859004FD783 /* PINOperation.framework */; }; + 68CEDB9F2BE0E1DF0045CBE7 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 68133AEB2BE056A5007627EC /* PrivacyInfo.xcprivacy */; }; + 68CEDBA02BE0E1E00045CBE7 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 68133AEB2BE056A5007627EC /* PrivacyInfo.xcprivacy */; }; + 68CEDBA12BE0E1E10045CBE7 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 68133AEB2BE056A5007627EC /* PrivacyInfo.xcprivacy */; }; + CC01055B1E27116600890935 /* PINOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC01052D1E27110D00890935 /* PINOperation.framework */; }; + CC01056A1E27117300890935 /* PINOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC01053D1E27113700890935 /* PINOperation.framework */; }; + CC0105791E27117F00890935 /* PINOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC01054A1E27114300890935 /* PINOperation.framework */; }; + CC0105871E2711B700890935 /* PINOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105801E2711B700890935 /* PINOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0105881E2711B700890935 /* PINOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105801E2711B700890935 /* PINOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0105891E2711B700890935 /* PINOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105801E2711B700890935 /* PINOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC01058A1E2711B700890935 /* PINOperationGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105811E2711B700890935 /* PINOperationGroup.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC01058B1E2711B700890935 /* PINOperationGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105811E2711B700890935 /* PINOperationGroup.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC01058C1E2711B700890935 /* PINOperationGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105811E2711B700890935 /* PINOperationGroup.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC01058D1E2711B700890935 /* PINOperationGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0105821E2711B700890935 /* PINOperationGroup.m */; }; + CC01058E1E2711B700890935 /* PINOperationGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0105821E2711B700890935 /* PINOperationGroup.m */; }; + CC01058F1E2711B700890935 /* PINOperationGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0105821E2711B700890935 /* PINOperationGroup.m */; }; + CC0105901E2711B700890935 /* PINOperationMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105831E2711B700890935 /* PINOperationMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0105911E2711B700890935 /* PINOperationMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105831E2711B700890935 /* PINOperationMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0105921E2711B700890935 /* PINOperationMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105831E2711B700890935 /* PINOperationMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0105931E2711B700890935 /* PINOperationQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105841E2711B700890935 /* PINOperationQueue.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0105941E2711B700890935 /* PINOperationQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105841E2711B700890935 /* PINOperationQueue.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0105951E2711B700890935 /* PINOperationQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105841E2711B700890935 /* PINOperationQueue.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0105961E2711B700890935 /* PINOperationQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0105851E2711B700890935 /* PINOperationQueue.m */; }; + CC0105971E2711B700890935 /* PINOperationQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0105851E2711B700890935 /* PINOperationQueue.m */; }; + CC0105981E2711B700890935 /* PINOperationQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0105851E2711B700890935 /* PINOperationQueue.m */; }; + CC0105991E2711B700890935 /* PINOperationTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105861E2711B700890935 /* PINOperationTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC01059A1E2711B700890935 /* PINOperationTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105861E2711B700890935 /* PINOperationTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC01059B1E2711B700890935 /* PINOperationTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105861E2711B700890935 /* PINOperationTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0105A01E27131B00890935 /* PINOperationQueueTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01059D1E27131B00890935 /* PINOperationQueueTests.m */; }; + CC0105A11E27131B00890935 /* PINOperationQueueTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01059D1E27131B00890935 /* PINOperationQueueTests.m */; }; + CC0105A21E27131B00890935 /* PINOperationQueueTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01059D1E27131B00890935 /* PINOperationQueueTests.m */; }; + CC0105A41E27131B00890935 /* PINOperationGroupTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01059E1E27131B00890935 /* PINOperationGroupTests.m */; }; + CC0105A51E27131B00890935 /* PINOperationGroupTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01059E1E27131B00890935 /* PINOperationGroupTests.m */; }; + CC0105A61E27131B00890935 /* PINOperationGroupTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01059E1E27131B00890935 /* PINOperationGroupTests.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 686ECECF2BE4731900634D9F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = CC0105241E27110D00890935 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6817A6422BE46E48007710C1; + remoteInfo = "PINOperation-visionOS"; + }; + 68B3C3092BE475FF00C335B8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = CC0105241E27110D00890935 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 3201178B24444859004FD783; + remoteInfo = "PINOperation-watchOS"; + }; + CC01055C1E27116600890935 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = CC0105241E27110D00890935 /* Project object */; + proxyType = 1; + remoteGlobalIDString = CC01052C1E27110D00890935; + remoteInfo = PINOperation; + }; + CC01056B1E27117300890935 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = CC0105241E27110D00890935 /* Project object */; + proxyType = 1; + remoteGlobalIDString = CC01053C1E27113700890935; + remoteInfo = "PINOperation-tvOS"; + }; + CC01057A1E27117F00890935 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = CC0105241E27110D00890935 /* Project object */; + proxyType = 1; + remoteGlobalIDString = CC0105491E27114300890935; + remoteInfo = "PINOperation-macOS"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 3201178C24444859004FD783 /* PINOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PINOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 68133AEB2BE056A5007627EC /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 6817A6522BE46E48007710C1 /* PINOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PINOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 6850F2EE2BE471CB00A38144 /* PINOperation-visionOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "PINOperation-visionOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 686ECEDE2BE474F300634D9F /* PINOperation-watchOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "PINOperation-watchOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + CC01052D1E27110D00890935 /* PINOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PINOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + CC01053D1E27113700890935 /* PINOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PINOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + CC01054A1E27114300890935 /* PINOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PINOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + CC0105561E27116600890935 /* PINOperationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PINOperationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + CC01055A1E27116600890935 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = ../Tests/Info.plist; sourceTree = ""; }; + CC0105651E27117300890935 /* PINOperation-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "PINOperation-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + CC0105741E27117F00890935 /* PINOperation-macOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "PINOperation-macOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + CC0105801E2711B700890935 /* PINOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINOperation.h; sourceTree = ""; }; + CC0105811E2711B700890935 /* PINOperationGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINOperationGroup.h; sourceTree = ""; }; + CC0105821E2711B700890935 /* PINOperationGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINOperationGroup.m; sourceTree = ""; }; + CC0105831E2711B700890935 /* PINOperationMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINOperationMacros.h; sourceTree = ""; }; + CC0105841E2711B700890935 /* PINOperationQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINOperationQueue.h; sourceTree = ""; }; + CC0105851E2711B700890935 /* PINOperationQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINOperationQueue.m; sourceTree = ""; }; + CC0105861E2711B700890935 /* PINOperationTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINOperationTypes.h; sourceTree = ""; }; + CC01059C1E27129E00890935 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + CC01059D1E27131B00890935 /* PINOperationQueueTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINOperationQueueTests.m; sourceTree = ""; }; + CC01059E1E27131B00890935 /* PINOperationGroupTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINOperationGroupTests.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 3201178924444859004FD783 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6817A6462BE46E48007710C1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6850F2E82BE471CB00A38144 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 686ECECD2BE4731900634D9F /* PINOperation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 686ECED82BE474F300634D9F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 68B3C3072BE475FF00C335B8 /* PINOperation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105291E27110D00890935 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105391E27113700890935 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105461E27114300890935 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105531E27116600890935 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CC01055B1E27116600890935 /* PINOperation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105621E27117300890935 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CC01056A1E27117300890935 /* PINOperation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105711E27117F00890935 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CC0105791E27117F00890935 /* PINOperation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 6850F2F02BE4724000A38144 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; + CC0105231E27110D00890935 = { + isa = PBXGroup; + children = ( + CC01057F1E2711B700890935 /* Source */, + CC0105571E27116600890935 /* Tests */, + CC01052E1E27110D00890935 /* Products */, + 6850F2F02BE4724000A38144 /* Frameworks */, + ); + indentWidth = 2; + sourceTree = ""; + tabWidth = 2; + usesTabs = 0; + }; + CC01052E1E27110D00890935 /* Products */ = { + isa = PBXGroup; + children = ( + CC01052D1E27110D00890935 /* PINOperation.framework */, + CC01053D1E27113700890935 /* PINOperation.framework */, + CC01054A1E27114300890935 /* PINOperation.framework */, + CC0105561E27116600890935 /* PINOperationTests.xctest */, + CC0105651E27117300890935 /* PINOperation-tvOSTests.xctest */, + CC0105741E27117F00890935 /* PINOperation-macOSTests.xctest */, + 3201178C24444859004FD783 /* PINOperation.framework */, + 6817A6522BE46E48007710C1 /* PINOperation.framework */, + 6850F2EE2BE471CB00A38144 /* PINOperation-visionOSTests.xctest */, + 686ECEDE2BE474F300634D9F /* PINOperation-watchOSTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + CC0105571E27116600890935 /* Tests */ = { + isa = PBXGroup; + children = ( + CC01059D1E27131B00890935 /* PINOperationQueueTests.m */, + CC01059E1E27131B00890935 /* PINOperationGroupTests.m */, + CC01055A1E27116600890935 /* Info.plist */, + ); + path = Tests; + sourceTree = ""; + }; + CC01057F1E2711B700890935 /* Source */ = { + isa = PBXGroup; + children = ( + CC0105801E2711B700890935 /* PINOperation.h */, + CC0105811E2711B700890935 /* PINOperationGroup.h */, + CC0105831E2711B700890935 /* PINOperationMacros.h */, + CC0105841E2711B700890935 /* PINOperationQueue.h */, + CC0105861E2711B700890935 /* PINOperationTypes.h */, + CC0105821E2711B700890935 /* PINOperationGroup.m */, + CC0105851E2711B700890935 /* PINOperationQueue.m */, + CC01059C1E27129E00890935 /* Info.plist */, + 68133AEB2BE056A5007627EC /* PrivacyInfo.xcprivacy */, + ); + path = Source; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 3201178724444859004FD783 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 3201179824444862004FD783 /* PINOperationTypes.h in Headers */, + 3201179524444862004FD783 /* PINOperationGroup.h in Headers */, + 3201179424444862004FD783 /* PINOperation.h in Headers */, + 3201179724444862004FD783 /* PINOperationQueue.h in Headers */, + 3201179624444862004FD783 /* PINOperationMacros.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6817A6472BE46E48007710C1 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 6817A6482BE46E48007710C1 /* PINOperationTypes.h in Headers */, + 6817A6492BE46E48007710C1 /* PINOperation.h in Headers */, + 6817A64A2BE46E48007710C1 /* PINOperationGroup.h in Headers */, + 6817A64B2BE46E48007710C1 /* PINOperationMacros.h in Headers */, + 6817A64C2BE46E48007710C1 /* PINOperationQueue.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC01052A1E27110D00890935 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + CC0105991E2711B700890935 /* PINOperationTypes.h in Headers */, + CC0105871E2711B700890935 /* PINOperation.h in Headers */, + CC01058A1E2711B700890935 /* PINOperationGroup.h in Headers */, + CC0105901E2711B700890935 /* PINOperationMacros.h in Headers */, + CC0105931E2711B700890935 /* PINOperationQueue.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC01053A1E27113700890935 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + CC01059A1E2711B700890935 /* PINOperationTypes.h in Headers */, + CC0105881E2711B700890935 /* PINOperation.h in Headers */, + CC01058B1E2711B700890935 /* PINOperationGroup.h in Headers */, + CC0105911E2711B700890935 /* PINOperationMacros.h in Headers */, + CC0105941E2711B700890935 /* PINOperationQueue.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105471E27114300890935 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + CC01059B1E2711B700890935 /* PINOperationTypes.h in Headers */, + CC0105891E2711B700890935 /* PINOperation.h in Headers */, + CC01058C1E2711B700890935 /* PINOperationGroup.h in Headers */, + CC0105921E2711B700890935 /* PINOperationMacros.h in Headers */, + CC0105951E2711B700890935 /* PINOperationQueue.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 3201178B24444859004FD783 /* PINOperation-watchOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3201179324444859004FD783 /* Build configuration list for PBXNativeTarget "PINOperation-watchOS" */; + buildPhases = ( + 3201178824444859004FD783 /* Sources */, + 3201178924444859004FD783 /* Frameworks */, + 3201178724444859004FD783 /* Headers */, + 3201178A24444859004FD783 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "PINOperation-watchOS"; + productName = "PINOperation-watchOS"; + productReference = 3201178C24444859004FD783 /* PINOperation.framework */; + productType = "com.apple.product-type.framework"; + }; + 6817A6422BE46E48007710C1 /* PINOperation-visionOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6817A64F2BE46E48007710C1 /* Build configuration list for PBXNativeTarget "PINOperation-visionOS" */; + buildPhases = ( + 6817A6432BE46E48007710C1 /* Sources */, + 6817A6462BE46E48007710C1 /* Frameworks */, + 6817A6472BE46E48007710C1 /* Headers */, + 6817A64D2BE46E48007710C1 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "PINOperation-visionOS"; + productName = PINOperation; + productReference = 6817A6522BE46E48007710C1 /* PINOperation.framework */; + productType = "com.apple.product-type.framework"; + }; + 6850F2E22BE471CB00A38144 /* PINOperation-visionOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6850F2EB2BE471CB00A38144 /* Build configuration list for PBXNativeTarget "PINOperation-visionOSTests" */; + buildPhases = ( + 6850F2E52BE471CB00A38144 /* Sources */, + 6850F2E82BE471CB00A38144 /* Frameworks */, + 6850F2EA2BE471CB00A38144 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 686ECED02BE4731900634D9F /* PBXTargetDependency */, + ); + name = "PINOperation-visionOSTests"; + productName = PINOperationTests; + productReference = 6850F2EE2BE471CB00A38144 /* PINOperation-visionOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 686ECED22BE474F300634D9F /* PINOperation-watchOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 686ECEDB2BE474F300634D9F /* Build configuration list for PBXNativeTarget "PINOperation-watchOSTests" */; + buildPhases = ( + 686ECED52BE474F300634D9F /* Sources */, + 686ECED82BE474F300634D9F /* Frameworks */, + 686ECEDA2BE474F300634D9F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 68B3C30A2BE475FF00C335B8 /* PBXTargetDependency */, + ); + name = "PINOperation-watchOSTests"; + productName = PINOperationTests; + productReference = 686ECEDE2BE474F300634D9F /* PINOperation-watchOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + CC01052C1E27110D00890935 /* PINOperation */ = { + isa = PBXNativeTarget; + buildConfigurationList = CC0105351E27110D00890935 /* Build configuration list for PBXNativeTarget "PINOperation" */; + buildPhases = ( + CC0105281E27110D00890935 /* Sources */, + CC0105291E27110D00890935 /* Frameworks */, + CC01052A1E27110D00890935 /* Headers */, + CC01052B1E27110D00890935 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PINOperation; + productName = PINOperation; + productReference = CC01052D1E27110D00890935 /* PINOperation.framework */; + productType = "com.apple.product-type.framework"; + }; + CC01053C1E27113700890935 /* PINOperation-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = CC0105421E27113700890935 /* Build configuration list for PBXNativeTarget "PINOperation-tvOS" */; + buildPhases = ( + CC0105381E27113700890935 /* Sources */, + CC0105391E27113700890935 /* Frameworks */, + CC01053A1E27113700890935 /* Headers */, + CC01053B1E27113700890935 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "PINOperation-tvOS"; + productName = "PINOperation-tvOS"; + productReference = CC01053D1E27113700890935 /* PINOperation.framework */; + productType = "com.apple.product-type.framework"; + }; + CC0105491E27114300890935 /* PINOperation-macOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = CC01054F1E27114300890935 /* Build configuration list for PBXNativeTarget "PINOperation-macOS" */; + buildPhases = ( + CC0105451E27114300890935 /* Sources */, + CC0105461E27114300890935 /* Frameworks */, + CC0105471E27114300890935 /* Headers */, + CC0105481E27114300890935 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "PINOperation-macOS"; + productName = "PINOperation-macOS"; + productReference = CC01054A1E27114300890935 /* PINOperation.framework */; + productType = "com.apple.product-type.framework"; + }; + CC0105551E27116600890935 /* PINOperationTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = CC01055E1E27116600890935 /* Build configuration list for PBXNativeTarget "PINOperationTests" */; + buildPhases = ( + CC0105521E27116600890935 /* Sources */, + CC0105531E27116600890935 /* Frameworks */, + CC0105541E27116600890935 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + CC01055D1E27116600890935 /* PBXTargetDependency */, + ); + name = PINOperationTests; + productName = PINOperationTests; + productReference = CC0105561E27116600890935 /* PINOperationTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + CC0105641E27117300890935 /* PINOperation-tvOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = CC01056D1E27117300890935 /* Build configuration list for PBXNativeTarget "PINOperation-tvOSTests" */; + buildPhases = ( + CC0105611E27117300890935 /* Sources */, + CC0105621E27117300890935 /* Frameworks */, + CC0105631E27117300890935 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + CC01056C1E27117300890935 /* PBXTargetDependency */, + ); + name = "PINOperation-tvOSTests"; + productName = "PINOperation-tvOSTests"; + productReference = CC0105651E27117300890935 /* PINOperation-tvOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + CC0105731E27117F00890935 /* PINOperation-macOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = CC01057C1E27117F00890935 /* Build configuration list for PBXNativeTarget "PINOperation-macOSTests" */; + buildPhases = ( + CC0105701E27117F00890935 /* Sources */, + CC0105711E27117F00890935 /* Frameworks */, + CC0105721E27117F00890935 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + CC01057B1E27117F00890935 /* PBXTargetDependency */, + ); + name = "PINOperation-macOSTests"; + productName = "PINOperation-macOSTests"; + productReference = CC0105741E27117F00890935 /* PINOperation-macOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + CC0105241E27110D00890935 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 1520; + LastUpgradeCheck = 1520; + ORGANIZATIONNAME = Pinterest; + TargetAttributes = { + 3201178B24444859004FD783 = { + CreatedOnToolsVersion = 11.4; + ProvisioningStyle = Automatic; + }; + CC01052C1E27110D00890935 = { + CreatedOnToolsVersion = 7.3.1; + }; + CC01053C1E27113700890935 = { + CreatedOnToolsVersion = 7.3.1; + }; + CC0105491E27114300890935 = { + CreatedOnToolsVersion = 7.3.1; + }; + CC0105551E27116600890935 = { + CreatedOnToolsVersion = 7.3.1; + }; + CC0105641E27117300890935 = { + CreatedOnToolsVersion = 7.3.1; + }; + CC0105731E27117F00890935 = { + CreatedOnToolsVersion = 7.3.1; + }; + }; + }; + buildConfigurationList = CC0105271E27110D00890935 /* Build configuration list for PBXProject "PINOperation" */; + compatibilityVersion = "Xcode 15.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + Base, + en, + ); + mainGroup = CC0105231E27110D00890935; + productRefGroup = CC01052E1E27110D00890935 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + CC01052C1E27110D00890935 /* PINOperation */, + CC0105551E27116600890935 /* PINOperationTests */, + CC01053C1E27113700890935 /* PINOperation-tvOS */, + CC0105641E27117300890935 /* PINOperation-tvOSTests */, + CC0105491E27114300890935 /* PINOperation-macOS */, + CC0105731E27117F00890935 /* PINOperation-macOSTests */, + 3201178B24444859004FD783 /* PINOperation-watchOS */, + 686ECED22BE474F300634D9F /* PINOperation-watchOSTests */, + 6817A6422BE46E48007710C1 /* PINOperation-visionOS */, + 6850F2E22BE471CB00A38144 /* PINOperation-visionOSTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 3201178A24444859004FD783 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 68CEDBA12BE0E1E10045CBE7 /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6817A64D2BE46E48007710C1 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6817A64E2BE46E48007710C1 /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6850F2EA2BE471CB00A38144 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 686ECEDA2BE474F300634D9F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC01052B1E27110D00890935 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 68133AEC2BE056A5007627EC /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC01053B1E27113700890935 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 68CEDB9F2BE0E1DF0045CBE7 /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105481E27114300890935 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 68CEDBA02BE0E1E00045CBE7 /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105541E27116600890935 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105631E27117300890935 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105721E27117F00890935 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 3201178824444859004FD783 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3201179924444862004FD783 /* PINOperationGroup.m in Sources */, + 3201179A24444862004FD783 /* PINOperationQueue.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6817A6432BE46E48007710C1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6817A6442BE46E48007710C1 /* PINOperationGroup.m in Sources */, + 6817A6452BE46E48007710C1 /* PINOperationQueue.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6850F2E52BE471CB00A38144 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6850F2E62BE471CB00A38144 /* PINOperationQueueTests.m in Sources */, + 6850F2E72BE471CB00A38144 /* PINOperationGroupTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 686ECED52BE474F300634D9F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 686ECED62BE474F300634D9F /* PINOperationQueueTests.m in Sources */, + 686ECED72BE474F300634D9F /* PINOperationGroupTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105281E27110D00890935 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CC01058D1E2711B700890935 /* PINOperationGroup.m in Sources */, + CC0105961E2711B700890935 /* PINOperationQueue.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105381E27113700890935 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CC01058E1E2711B700890935 /* PINOperationGroup.m in Sources */, + CC0105971E2711B700890935 /* PINOperationQueue.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105451E27114300890935 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CC01058F1E2711B700890935 /* PINOperationGroup.m in Sources */, + CC0105981E2711B700890935 /* PINOperationQueue.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105521E27116600890935 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CC0105A01E27131B00890935 /* PINOperationQueueTests.m in Sources */, + CC0105A41E27131B00890935 /* PINOperationGroupTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105611E27117300890935 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CC0105A11E27131B00890935 /* PINOperationQueueTests.m in Sources */, + CC0105A51E27131B00890935 /* PINOperationGroupTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105701E27117F00890935 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CC0105A21E27131B00890935 /* PINOperationQueueTests.m in Sources */, + CC0105A61E27131B00890935 /* PINOperationGroupTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 686ECED02BE4731900634D9F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 6817A6422BE46E48007710C1 /* PINOperation-visionOS */; + targetProxy = 686ECECF2BE4731900634D9F /* PBXContainerItemProxy */; + }; + 68B3C30A2BE475FF00C335B8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 3201178B24444859004FD783 /* PINOperation-watchOS */; + targetProxy = 68B3C3092BE475FF00C335B8 /* PBXContainerItemProxy */; + }; + CC01055D1E27116600890935 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = CC01052C1E27110D00890935 /* PINOperation */; + targetProxy = CC01055C1E27116600890935 /* PBXContainerItemProxy */; + }; + CC01056C1E27117300890935 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = CC01053C1E27113700890935 /* PINOperation-tvOS */; + targetProxy = CC01056B1E27117300890935 /* PBXContainerItemProxy */; + }; + CC01057B1E27117F00890935 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = CC0105491E27114300890935 /* PINOperation-macOS */; + targetProxy = CC01057A1E27117F00890935 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 3201179124444859004FD783 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperation; + PRODUCT_NAME = PINOperation; + SDKROOT = watchos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 4; + }; + name = Debug; + }; + 3201179224444859004FD783 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperation; + PRODUCT_NAME = PINOperation; + SDKROOT = watchos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 4; + }; + name = Release; + }; + 6817A6502BE46E48007710C1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperation; + PRODUCT_NAME = PINOperation; + RESOURCES_TARGETED_DEVICE_FAMILY = ""; + SDKROOT = xros; + SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + TARGETED_DEVICE_FAMILY = 7; + }; + name = Debug; + }; + 6817A6512BE46E48007710C1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperation; + PRODUCT_NAME = PINOperation; + RESOURCES_TARGETED_DEVICE_FAMILY = ""; + SDKROOT = xros; + SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + TARGETED_DEVICE_FAMILY = 7; + }; + name = Release; + }; + 6850F2EC2BE471CB00A38144 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperationTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = xros; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + TARGETED_DEVICE_FAMILY = 7; + }; + name = Debug; + }; + 6850F2ED2BE471CB00A38144 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperationTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = xros; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + TARGETED_DEVICE_FAMILY = 7; + }; + name = Release; + }; + 686ECEDC2BE474F300634D9F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperationTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + TARGETED_DEVICE_FAMILY = 4; + }; + name = Debug; + }; + 686ECEDD2BE474F300634D9F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperationTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + TARGETED_DEVICE_FAMILY = 4; + }; + name = Release; + }; + CC0105331E27110D00890935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 12.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 4.0; + XROS_DEPLOYMENT_TARGET = 1.0; + }; + name = Debug; + }; + CC0105341E27110D00890935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 4.0; + XROS_DEPLOYMENT_TARGET = 1.0; + }; + name = Release; + }; + CC0105361E27110D00890935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperation; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = YES; + }; + name = Debug; + }; + CC0105371E27110D00890935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperation; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = YES; + }; + name = Release; + }; + CC0105431E27113700890935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperation; + PRODUCT_NAME = PINOperation; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + CC0105441E27113700890935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperation; + PRODUCT_NAME = PINOperation; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + CC0105501E27114300890935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperation; + PRODUCT_NAME = PINOperation; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + CC0105511E27114300890935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperation; + PRODUCT_NAME = PINOperation; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Release; + }; + CC01055F1E27116600890935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperationTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + CC0105601E27116600890935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperationTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + CC01056E1E27117300890935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.pinterest.PINOperation-tvOSTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + CC01056F1E27117300890935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.pinterest.PINOperation-tvOSTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + CC01057D1E27117F00890935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.pinterest.PINOperation-macOSTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + CC01057E1E27117F00890935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.pinterest.PINOperation-macOSTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 3201179324444859004FD783 /* Build configuration list for PBXNativeTarget "PINOperation-watchOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3201179124444859004FD783 /* Debug */, + 3201179224444859004FD783 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6817A64F2BE46E48007710C1 /* Build configuration list for PBXNativeTarget "PINOperation-visionOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6817A6502BE46E48007710C1 /* Debug */, + 6817A6512BE46E48007710C1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6850F2EB2BE471CB00A38144 /* Build configuration list for PBXNativeTarget "PINOperation-visionOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6850F2EC2BE471CB00A38144 /* Debug */, + 6850F2ED2BE471CB00A38144 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 686ECEDB2BE474F300634D9F /* Build configuration list for PBXNativeTarget "PINOperation-watchOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 686ECEDC2BE474F300634D9F /* Debug */, + 686ECEDD2BE474F300634D9F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CC0105271E27110D00890935 /* Build configuration list for PBXProject "PINOperation" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CC0105331E27110D00890935 /* Debug */, + CC0105341E27110D00890935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CC0105351E27110D00890935 /* Build configuration list for PBXNativeTarget "PINOperation" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CC0105361E27110D00890935 /* Debug */, + CC0105371E27110D00890935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CC0105421E27113700890935 /* Build configuration list for PBXNativeTarget "PINOperation-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CC0105431E27113700890935 /* Debug */, + CC0105441E27113700890935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CC01054F1E27114300890935 /* Build configuration list for PBXNativeTarget "PINOperation-macOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CC0105501E27114300890935 /* Debug */, + CC0105511E27114300890935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CC01055E1E27116600890935 /* Build configuration list for PBXNativeTarget "PINOperationTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CC01055F1E27116600890935 /* Debug */, + CC0105601E27116600890935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CC01056D1E27117300890935 /* Build configuration list for PBXNativeTarget "PINOperation-tvOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CC01056E1E27117300890935 /* Debug */, + CC01056F1E27117300890935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CC01057C1E27117F00890935 /* Build configuration list for PBXNativeTarget "PINOperation-macOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CC01057D1E27117F00890935 /* Debug */, + CC01057E1E27117F00890935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = CC0105241E27110D00890935 /* Project object */; +} diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..645415a1 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-macOS.xcscheme b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-macOS.xcscheme new file mode 100644 index 00000000..020b8ba3 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-macOS.xcscheme @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-macOSTests.xcscheme b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-macOSTests.xcscheme new file mode 100644 index 00000000..12133d33 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-macOSTests.xcscheme @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-tvOS.xcscheme b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-tvOS.xcscheme new file mode 100644 index 00000000..d4c1804c --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-tvOS.xcscheme @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-tvOSTests.xcscheme b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-tvOSTests.xcscheme new file mode 100644 index 00000000..95d71307 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-tvOSTests.xcscheme @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-visionOS.xcscheme b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-visionOS.xcscheme new file mode 100644 index 00000000..1fb9fbe6 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-visionOS.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-visionOSTests.xcscheme b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-visionOSTests.xcscheme new file mode 100644 index 00000000..152666b7 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-visionOSTests.xcscheme @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-watchOS.xcscheme b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-watchOS.xcscheme new file mode 100644 index 00000000..1d2f7431 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-watchOS.xcscheme @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-watchOSTests.xcscheme b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-watchOSTests.xcscheme new file mode 100644 index 00000000..d24b717e --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-watchOSTests.xcscheme @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation.xcscheme b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation.xcscheme new file mode 100644 index 00000000..9767c050 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation.xcscheme @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperationTests.xcscheme b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperationTests.xcscheme new file mode 100644 index 00000000..49d28ec8 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperationTests.xcscheme @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Package.swift b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Package.swift new file mode 100644 index 00000000..2be5b4e0 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Package.swift @@ -0,0 +1,34 @@ +// swift-tools-version:5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "PINOperation", + products: [ + // Products define the executables and libraries produced by a package, and make them visible to other packages. + .library( + name: "PINOperation", + targets: ["PINOperation"]), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages which this package depends on. + .target( + name: "PINOperation", + path: "Source", + exclude: ["Info.plist"], + resources: [.process("PrivacyInfo.xcprivacy")], + // Path to public header symlinks (allows for angle bracket imports) + publicHeadersPath: "include", + cSettings: [ + .headerSearchPath("."), + .define("NS_BLOCK_ASSERTIONS", to: "1", .when(configuration: .release)), + ]), + .testTarget( + name: "PINOperationTests", + dependencies: ["PINOperation"], + path: "Tests", + exclude: ["Info.plist"]), + ] +) diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/README.md b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/README.md new file mode 100644 index 00000000..2e29c80f --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/README.md @@ -0,0 +1,47 @@ +# PINOperation + +[![CocoaPods](https://img.shields.io/cocoapods/v/PINOperation.svg)](http://cocoadocs.org/docsets/PINOperation/) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![Build status](https://github.com/pinterest/PINOperation/workflows/CI/badge.svg)](https://github.com/pinterest/PINOperation/actions?query=workflow%3ACI+branch%3Amaster) + +## Fast, concurrency-limited task queue for iOS and macOS. + +## Installation + +### Manually + +[Download the latest tag](https://github.com/pinterest/PINOperation/tags) and drag the `PINOperation` folder into your Xcode project. + +Install the docs by double clicking the `.docset` file under `docs/`, or view them online at [cocoadocs.org](http://cocoadocs.org/docsets/PINOperation/) + +### Git Submodule + + git submodule add https://github.com/pinterest/PINOperation.git + git submodule update --init + +### CocoaPods + +Add [PINOperation](http://cocoapods.org/?q=name%3APINOperation) to your `Podfile` and run `pod install`. + +### Carthage + +Add the following line to your `Cartfile` and run `carthage update --platform ios`. Then follow [this instruction of Carthage](https://github.com/carthage/carthage#adding-frameworks-to-unit-tests-or-a-framework) to embed the framework. + +```github "pinterest/PINOperation"``` + +## Requirements + +__PINOperation__ requires iOS 12.0, tvOS 12.0, macOS 10.13 or watchOS 4.0 and greater. + +## Contact + +[Garrett Moon](mailto:garrett@pinterest.com) + +## License + +Copyright 2013 Tumblr, Inc. +Copyright 2015 Pinterest, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. [See the License](LICENSE.txt) for the specific language governing permissions and limitations under the License. diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/RELEASE.md b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/RELEASE.md new file mode 100644 index 00000000..807cee6a --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/RELEASE.md @@ -0,0 +1,7 @@ +# Release Process +This document describes the process for a public PINOperation release. + +### Process +- Ensure the latest master build is green. +- Run the github action 'Create Release'. +- Check that the release was successfully published to [Github](https://github.com/pinterest/PINOperation/releases) and [Cocoapods](https://cocoapods.org/pods/PINOperation). diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Scripts/release.sh b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Scripts/release.sh new file mode 100755 index 00000000..bd685725 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Scripts/release.sh @@ -0,0 +1,98 @@ +#!/bin/bash +set -e + +if [ -z "$OSS_PROJECT" ]; then + echo "Must set \$OSS_PROJECT envirnonment variable before running." +fi + +PROJECT="$OSS_PROJECT" + +if ! git diff-index --quiet HEAD --; then + echo "Please commit or stash any changes before running." + exit 1 +fi + +if [ -z "$GITHUB_CHANGELOG_API_KEY" ]; then + echo "Must set \$GITHUB_CHANGELOG_API_KEY environment variable" + exit 1 +fi + +case $1 in + "--major") + UPDATE_TYPE="major" + ;; + + "--minor") + UPDATE_TYPE="minor" + ;; + + "--patch") + UPDATE_TYPE="patch" + ;; + + *) + echo "Usage release.sh --patch / --minor / --major" + exit 1 + ;; +esac + +PODSPEC="$PROJECT.podspec" +CURRENT_VERSION=$(grep "version" -m 1 $PODSPEC | sed -E "s/^.*version[ \t]*=[ \t]*['\"]([0-9\.]+)['\"]/\1/") +DOT_COUNT=$(echo "$CURRENT_VERSION" | grep -o '\.' | wc -l) + +if [ "$DOT_COUNT" -eq "0" ]; then + major=$CURRENT_VERSION + minor="0" + patch="0" +elif [ "$DOT_COUNT" -eq "1" ]; then + major=$(echo "$CURRENT_VERSION" | sed -E "s/([0-9])+\.([0-9]+)/\1/") + minor=$(echo "$CURRENT_VERSION" | sed -E "s/([0-9])+\.([0-9]+)/\2/") + patch="0" +elif [ "$DOT_COUNT" -eq "2" ]; then + major=$(echo "$CURRENT_VERSION" | sed -E "s/([0-9])+\.([0-9]+)\.([0-9]+)/\1/") + minor=$(echo "$CURRENT_VERSION" | sed -E "s/([0-9])+\.([0-9]+)\.([0-9]+)/\2/") + patch=$(echo "$CURRENT_VERSION" | sed -E "s/([0-9])+\.([0-9]+)\.([0-9]+)/\3/") +fi + +echo "Current version: $major.$minor.$patch" + +if [ "$UPDATE_TYPE" == "major" ]; then + major=$((major + 1)) + minor=0 + patch=0 +elif [ "$UPDATE_TYPE" == "minor" ]; then + minor=$((minor + 1)) + patch=0 +elif [ "$UPDATE_TYPE" == "patch" ]; then + patch=$((patch + 1)) +fi + +NEW_VERSION="$major.$minor.$patch" +echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV +echo "New version: $NEW_VERSION" + +echo "Updating $PODSPEC" +sed -E "s/^(.*version[ \t]*=[ \t]*)['|\"]$CURRENT_VERSION['|\"]/\1'$NEW_VERSION'/" $PODSPEC > new.podspec +mv new.podspec $PODSPEC + +echo "Updating .github_changelog_generator" +cat << EOF > .github_changelog_generator +issues=false +since-tag=$CURRENT_VERSION +future-release=$NEW_VERSION +EOF + +github_changelog_generator --token $GITHUB_CHANGELOG_API_KEY --user Pinterest --project $PROJECT --output NEW_CHANGES.md + +# Delete # Changelog at the top of the old CHANGELOG +grep -v "# Changelog" CHANGELOG.md > CHANGELOG.tmp && mv CHANGELOG.tmp CHANGELOG.md + +# Delete the last line and first line then use a magic sed command the internet told me +# about to delete trailing newlines (except the last one) +# Then prepend to existing changelog +grep -v "\*" NEW_CHANGES.md | sed -e :a -e '/^\n*$/{$d;N;};/\n$/ba' | cat - CHANGELOG.md > CHANGELOG.tmp +mv CHANGELOG.tmp CHANGELOG.md +rm NEW_CHANGES.md + +git add .github_changelog_generator CHANGELOG.md $PODSPEC +git commit --message "[AUTO] Update CHANGELOG.md and bump for $UPDATE_TYPE update." diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Scripts/tag-release-branch.sh b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Scripts/tag-release-branch.sh new file mode 100755 index 00000000..a66af230 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Scripts/tag-release-branch.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -ex + +echo "Tagging release branch" +TAG=$NEW_VERSION + +echo "RELEASE_TAG=$TAG" >> $GITHUB_ENV +git tag $TAG +git push origin --tags + +echo "Setting Release Notes" +cat CHANGELOG.md | awk '/^#/{f=1} f; /^#/ && ++c==3{exit}' | sed '$ d' > RELEASE_NOTES.md diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/Info.plist b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/Info.plist new file mode 100644 index 00000000..faedaa13 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2017 Pinterest. All rights reserved. + NSPrincipalClass + + + diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PINOperation.h b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PINOperation.h new file mode 100644 index 00000000..1f67472b --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PINOperation.h @@ -0,0 +1,12 @@ +// +// PINOperation.h +// PINOperation +// +// Created by Adlai Holler on 1/10/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import +#import +#import +#import diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PINOperationGroup.h b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PINOperationGroup.h new file mode 100644 index 00000000..989061c3 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PINOperationGroup.h @@ -0,0 +1,38 @@ +// +// PINOperationGroup.h +// PINOperation +// +// Created by Garrett Moon on 10/8/16. +// Copyright © 2016 Pinterest. All rights reserved. +// + +#import +#import +#import + +@class PINOperationQueue; + +NS_ASSUME_NONNULL_BEGIN + +@protocol PINGroupOperationReference; + +PINOP_SUBCLASSING_RESTRICTED +@interface PINOperationGroup : NSObject + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)asyncOperationGroupWithQueue:(PINOperationQueue *)operationQueue; + +- (nullable id )addOperation:(dispatch_block_t)operation; +- (nullable id )addOperation:(dispatch_block_t)operation withPriority:(PINOperationQueuePriority)priority; +- (void)start; +- (void)cancel; +- (void)setCompletion:(dispatch_block_t)completion; +- (void)waitUntilComplete; + +@end + +@protocol PINGroupOperationReference + +@end + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PINOperationGroup.m b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PINOperationGroup.m new file mode 100644 index 00000000..94d09178 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PINOperationGroup.m @@ -0,0 +1,187 @@ +// +// PINOperationGroup.m +// PINOperation +// +// Created by Garrett Moon on 10/8/16. +// Copyright © 2016 Pinterest. All rights reserved. +// + +#import "PINOperationGroup.h" +#import +#import + +@interface NSNumber (PINGroupOperationQueue) +@end + +@interface PINOperationGroup () +{ + pthread_mutex_t _lock; + + PINOperationQueue *_operationQueue; + NSMutableArray *_operations; + NSMutableArray *_operationPriorities; + NSMutableArray > *_operationReferences; + NSMapTable , id > *_groupToOperationReferences; + NSUInteger _operationReferenceCount; + + dispatch_group_t _group; + + dispatch_block_t _completion; + + BOOL _started; + BOOL _canceled; +} + +- (instancetype)initWithOperationQueue:(PINOperationQueue *)operationQueue NS_DESIGNATED_INITIALIZER; + +@end + +@implementation PINOperationGroup + +- (instancetype)initWithOperationQueue:(PINOperationQueue *)operationQueue +{ + if (self = [super init]) { + pthread_mutex_init(&_lock, NULL); + + _operationQueue = operationQueue; + + _operations = [[NSMutableArray alloc] init]; + _operationReferences = [[NSMutableArray alloc] init]; + _operationPriorities = [[NSMutableArray alloc] init]; + + _groupToOperationReferences = [NSMapTable weakToStrongObjectsMapTable]; + _group = dispatch_group_create(); + } + return self; +} + +- (void)dealloc +{ + pthread_mutex_destroy(&_lock); +} + ++ (instancetype)asyncOperationGroupWithQueue:(PINOperationQueue *)operationQueue +{ + return [[self alloc] initWithOperationQueue:operationQueue]; +} + +- (id )locked_nextOperationReference +{ + id reference = [NSNumber numberWithUnsignedInteger:++_operationReferenceCount]; + return reference; +} + +- (void)start +{ + [self lock]; + NSAssert(_canceled == NO, @"Operation group canceled."); + if (_started == NO && _canceled == NO) { + for (NSUInteger idx = 0; idx < _operations.count; idx++) { + dispatch_group_enter(_group); + dispatch_block_t originalOperation = _operations[idx]; + dispatch_block_t groupBlock = ^{ + originalOperation(); + dispatch_group_leave(self->_group); + }; + + id operationReference = [_operationQueue scheduleOperation:groupBlock withPriority:[_operationPriorities[idx] unsignedIntegerValue]]; + [_groupToOperationReferences setObject:operationReference forKey:_operationReferences[idx]]; + } + + if (_completion) { + dispatch_queue_t completionQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + dispatch_group_notify(_group, completionQueue, ^{ + [self runCompletionIfNeeded]; + }); + } + + _operations = nil; + _operationPriorities = nil; + _operationReferences = nil; + } + [self unlock]; +} + +- (void)cancel +{ + [self lock]; + _canceled = YES; + + for (id operationReference in [_groupToOperationReferences objectEnumerator]) { + if ([_operationQueue cancelOperation:operationReference]) { + dispatch_group_leave(_group); + } + } + + //TODO just nil out instead? Does it make sense to support adding operations after cancelation? + [_groupToOperationReferences removeAllObjects]; + [_operations removeAllObjects]; + [_operationPriorities removeAllObjects]; + [_operationReferences removeAllObjects]; + + _completion = nil; + [self unlock]; +} + +- (id )addOperation:(dispatch_block_t)operation +{ + return [self addOperation:operation withPriority:PINOperationQueuePriorityDefault]; +} + +- (id )addOperation:(dispatch_block_t)operation withPriority:(PINOperationQueuePriority)priority +{ + [self lock]; + id reference = nil; + NSAssert(_started == NO && _canceled == NO, @"Operation group already started or canceled."); + if (_started == NO && _canceled == NO) { + reference = [self locked_nextOperationReference]; + [_operations addObject:operation]; + [_operationPriorities addObject:@(priority)]; + [_operationReferences addObject:reference]; + } + [self unlock]; + + return reference; +} + +- (void)setCompletion:(dispatch_block_t)completion +{ + [self lock]; + NSAssert(_started == NO && _canceled == NO, @"Operation group already started or canceled."); + if (_started == NO && _canceled == NO) { + _completion = completion; + } + [self unlock]; +} + +- (void)waitUntilComplete +{ + [self start]; + dispatch_group_wait(_group, DISPATCH_TIME_FOREVER); + [self runCompletionIfNeeded]; +} + +- (void)runCompletionIfNeeded +{ + dispatch_block_t completion; + [self lock]; + completion = _completion; + _completion = nil; + [self unlock]; + + if (completion) { + completion(); + } +} + +- (void)lock +{ + pthread_mutex_lock(&_lock); +} + +- (void)unlock +{ + pthread_mutex_unlock(&_lock); +} + +@end diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PINOperationMacros.h b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PINOperationMacros.h new file mode 100644 index 00000000..5be3a216 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PINOperationMacros.h @@ -0,0 +1,15 @@ +// +// PINOperationMacros.h +// PINOperation +// +// Created by Adlai Holler on 1/10/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#ifndef PINOP_SUBCLASSING_RESTRICTED +#if defined(__has_attribute) && __has_attribute(objc_subclassing_restricted) +#define PINOP_SUBCLASSING_RESTRICTED __attribute__((objc_subclassing_restricted)) +#else +#define PINOP_SUBCLASSING_RESTRICTED +#endif // #if defined(__has_attribute) && __has_attribute(objc_subclassing_restricted) +#endif // #ifndef PINOP_SUBCLASSING_RESTRICTED diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PINOperationQueue.h b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PINOperationQueue.h new file mode 100644 index 00000000..48c30928 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PINOperationQueue.h @@ -0,0 +1,141 @@ +// +// PINOperationQueue.h +// PINOperation +// +// Created by Garrett Moon on 8/23/16. +// +// + +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef void(^PINOperationBlock)(id _Nullable data); +typedef _Nullable id(^PINOperationDataCoalescingBlock)(id _Nullable existingData, id _Nullable newData); + +@protocol PINOperationReference; + +PINOP_SUBCLASSING_RESTRICTED +@interface PINOperationQueue : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +/** + * Initializes and returns a newly allocated operation queue with the specified number of maximum concurrent operations. + * + * @param maxConcurrentOperations The maximum number of queued operations that can execute at the same time. + * + */ +- (instancetype)initWithMaxConcurrentOperations:(NSUInteger)maxConcurrentOperations; + +/** + * Initializes and returns a newly allocated operation queue with the specified number of maximum concurrent operations and the concurrent queue they will be scheduled on. + * + * @param maxConcurrentOperations The maximum number of queued operations that can execute at the same time. + * @param concurrentQueue The operation queue to schedule concurrent operations + * + */ +- (instancetype)initWithMaxConcurrentOperations:(NSUInteger)maxConcurrentOperations concurrentQueue:(dispatch_queue_t)concurrentQueue NS_DESIGNATED_INITIALIZER; + +/** + * Returns the shared instance of the PINOperationQueue class. + */ ++ (instancetype)sharedOperationQueue; + +/** + * Adds the specified operation object to the receiver. + * + * @param operation The operation object to be added to the queue. + * + */ +- (id )scheduleOperation:(dispatch_block_t)operation; + +/** + * Adds the specified operation object to the receiver. + * + * @param operation The operation object to be added to the queue. + * @param priority The execution priority of the operation in an operation queue. + */ +- (id )scheduleOperation:(dispatch_block_t)operation withPriority:(PINOperationQueuePriority)priority; + +/** + * Adds the specified operation object to the receiver. + * + * @param operation The operation object to be added to the queue. + * @param priority The execution priority of the operation in an operation queue. + * @param identifier A string that identifies the operations that can be coalesced. + * @param coalescingData The optional data consumed by this operation that needs to be updated/coalesced with data of a new operation when coalescing the two operations happens. + * @param dataCoalescingBlock The optional block called to update/coalesce the data of this operation with data of a new operation when coalescing the two operations happens. + * @param completion The block to execute after the operation finished. + */ +- (id )scheduleOperation:(PINOperationBlock)operation + withPriority:(PINOperationQueuePriority)priority + identifier:(nullable NSString *)identifier + coalescingData:(nullable id)coalescingData + dataCoalescingBlock:(nullable PINOperationDataCoalescingBlock)dataCoalescingBlock + completion:(nullable dispatch_block_t)completion; + +/** + * The maximum number of queued operations that can execute at the same time. + * + * @discussion The value in this property affects only the operations that the current queue has executing at the same time. Other operation queues can also execute their maximum number of operations in parallel. + * Reducing the number of concurrent operations does not affect any operations that are currently executing. + * + * Setting this value to 1 the operations will not be processed by priority as the operations will processed in a FIFO order to prevent deadlocks if operations depend on certain other operations to run in order. + * + */ +@property (assign) NSUInteger maxConcurrentOperations; + +/** + * Marks the operation as cancelled + */ +- (BOOL)cancelOperation:(id )operationReference; + +/** + * Cancels all queued operations + */ +- (void)cancelAllOperations; + +/** + * Blocks the current thread until all of the receiver’s queued and executing operations finish executing. + * + * @discussion When called, this method blocks the current thread and waits for the receiver’s current and queued + * operations to finish executing. While the current thread is blocked, the receiver continues to launch already + * queued operations and monitor those that are executing. + * + * @warning This should never be called from within an operation submitted to the PINOperationQueue as this will result + * in a deadlock. + */ +- (void)waitUntilAllOperationsAreFinished; + +/** + * Sets the priority for a operation via it's reference + * + * @param priority The new priority for the operation + * @param reference The reference for the operation + * + */ +- (void)setOperationPriority:(PINOperationQueuePriority)priority withReference:(id )reference; + +#pragma mark - Deprecated + +- (id )addOperation:(dispatch_block_t)operation __deprecated_msg("Use scheduleOperation: instead."); + +- (id )addOperation:(dispatch_block_t)operation withPriority:(PINOperationQueuePriority)priority __deprecated_msg("Use scheduleOperation:withPriority: instead."); + +- (id )addOperation:(PINOperationBlock)operation + withPriority:(PINOperationQueuePriority)priority + identifier:(nullable NSString *)identifier + coalescingData:(nullable id)coalescingData + dataCoalescingBlock:(nullable PINOperationDataCoalescingBlock)dataCoalescingBlock + completion:(nullable dispatch_block_t)completion __deprecated_msg("Use scheduleOperation:withPriority:identifier:coalescingData:dataCoalescingBlock:completion: instead."); + +@end + +@protocol PINOperationReference + +@end + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PINOperationQueue.m b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PINOperationQueue.m new file mode 100644 index 00000000..e05451b5 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PINOperationQueue.m @@ -0,0 +1,471 @@ +// +// PINOperationQueue.m +// PINOperation +// +// Created by Garrett Moon on 8/23/16. +// +// + +#import "PINOperationQueue.h" +#import + +@class PINOperation; + +@interface NSNumber (PINOperationQueue) + +@end + +@interface PINOperationQueue () { + pthread_mutex_t _lock; + //increments with every operation to allow cancelation + NSUInteger _operationReferenceCount; + NSUInteger _maxConcurrentOperations; + + dispatch_group_t _group; + + dispatch_queue_t _serialQueue; + BOOL _serialQueueBusy; + + dispatch_semaphore_t _concurrentSemaphore; + dispatch_queue_t _concurrentQueue; + dispatch_queue_t _semaphoreQueue; + + NSMutableOrderedSet *_queuedOperations; + NSMutableOrderedSet *_lowPriorityOperations; + NSMutableOrderedSet *_defaultPriorityOperations; + NSMutableOrderedSet *_highPriorityOperations; + + NSMapTable, PINOperation *> *_referenceToOperations; + NSMapTable *_identifierToOperations; +} + +@end + +@interface PINOperation : NSObject + +@property (nonatomic, strong) PINOperationBlock block; +@property (nonatomic, strong) id reference; +@property (nonatomic, assign) PINOperationQueuePriority priority; +@property (nonatomic, strong) NSMutableArray *completions; +@property (nonatomic, strong) NSString *identifier; +@property (nonatomic, strong) id data; + ++ (instancetype)operationWithBlock:(PINOperationBlock)block reference:(id )reference priority:(PINOperationQueuePriority)priority identifier:(nullable NSString *)identifier data:(nullable id)data completion:(nullable dispatch_block_t)completion; + +- (void)addCompletion:(nullable dispatch_block_t)completion; + +@end + +@implementation PINOperation + ++ (instancetype)operationWithBlock:(PINOperationBlock)block reference:(id)reference priority:(PINOperationQueuePriority)priority identifier:(NSString *)identifier data:(id)data completion:(dispatch_block_t)completion +{ + PINOperation *operation = [[self alloc] init]; + operation.block = block; + operation.reference = reference; + operation.priority = priority; + operation.identifier = identifier; + operation.data = data; + [operation addCompletion:completion]; + + return operation; +} + +- (void)addCompletion:(dispatch_block_t)completion +{ + if (completion == nil) { + return; + } + if (_completions == nil) { + _completions = [NSMutableArray array]; + } + [_completions addObject:completion]; +} + +@end + +@implementation PINOperationQueue + +- (instancetype)initWithMaxConcurrentOperations:(NSUInteger)maxConcurrentOperations +{ + return [self initWithMaxConcurrentOperations:maxConcurrentOperations concurrentQueue:dispatch_queue_create("PINOperationQueue Concurrent Queue", DISPATCH_QUEUE_CONCURRENT)]; +} + +- (instancetype)initWithMaxConcurrentOperations:(NSUInteger)maxConcurrentOperations concurrentQueue:(dispatch_queue_t)concurrentQueue +{ + if (self = [super init]) { + NSAssert(maxConcurrentOperations > 0, @"Max concurrent operations must be greater than 0."); + _maxConcurrentOperations = maxConcurrentOperations; + _operationReferenceCount = 0; + + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + //mutex must be recursive to allow scheduling of operations from within operations + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&_lock, &attr); + + _group = dispatch_group_create(); + + _serialQueue = dispatch_queue_create("PINOperationQueue Serial Queue", DISPATCH_QUEUE_SERIAL); + + _concurrentQueue = concurrentQueue; + + //Create a queue with max - 1 because this plus the serial queue add up to max. + _concurrentSemaphore = dispatch_semaphore_create(_maxConcurrentOperations - 1); + _semaphoreQueue = dispatch_queue_create("PINOperationQueue Serial Semaphore Queue", DISPATCH_QUEUE_SERIAL); + + _queuedOperations = [[NSMutableOrderedSet alloc] init]; + _lowPriorityOperations = [[NSMutableOrderedSet alloc] init]; + _defaultPriorityOperations = [[NSMutableOrderedSet alloc] init]; + _highPriorityOperations = [[NSMutableOrderedSet alloc] init]; + + _referenceToOperations = [NSMapTable weakToWeakObjectsMapTable]; + _identifierToOperations = [NSMapTable weakToWeakObjectsMapTable]; + } + return self; +} + +- (void)dealloc +{ + pthread_mutex_destroy(&_lock); +} + ++ (instancetype)sharedOperationQueue +{ + static PINOperationQueue *sharedOperationQueue = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedOperationQueue = [[PINOperationQueue alloc] initWithMaxConcurrentOperations:MAX([[NSProcessInfo processInfo] activeProcessorCount], 2)]; + }); + return sharedOperationQueue; +} + +- (id )nextOperationReference +{ + [self lock]; + id reference = [NSNumber numberWithUnsignedInteger:++_operationReferenceCount]; + [self unlock]; + return reference; +} + +// Deprecated +- (id )addOperation:(dispatch_block_t)block +{ + return [self scheduleOperation:block]; +} + +- (id )scheduleOperation:(dispatch_block_t)block +{ + return [self scheduleOperation:block withPriority:PINOperationQueuePriorityDefault]; +} + +// Deprecated +- (id )addOperation:(dispatch_block_t)block withPriority:(PINOperationQueuePriority)priority +{ + return [self scheduleOperation:block withPriority:priority]; +} + +- (id )scheduleOperation:(dispatch_block_t)block withPriority:(PINOperationQueuePriority)priority +{ + PINOperation *operation = [PINOperation operationWithBlock:^(id data) { block(); } + reference:[self nextOperationReference] + priority:priority + identifier:nil + data:nil + completion:nil]; + [self lock]; + [self locked_addOperation:operation]; + [self unlock]; + + [self scheduleNextOperations:NO]; + + return operation.reference; +} + +// Deprecated +- (id)addOperation:(PINOperationBlock)block + withPriority:(PINOperationQueuePriority)priority + identifier:(NSString *)identifier + coalescingData:(id)coalescingData + dataCoalescingBlock:(PINOperationDataCoalescingBlock)dataCoalescingBlock + completion:(dispatch_block_t)completion +{ + return [self scheduleOperation:block + withPriority:priority + identifier:identifier + coalescingData:coalescingData + dataCoalescingBlock:dataCoalescingBlock + completion:completion]; +} + +- (id)scheduleOperation:(PINOperationBlock)block + withPriority:(PINOperationQueuePriority)priority + identifier:(NSString *)identifier + coalescingData:(id)coalescingData + dataCoalescingBlock:(PINOperationDataCoalescingBlock)dataCoalescingBlock + completion:(dispatch_block_t)completion +{ + id reference = nil; + BOOL isNewOperation = NO; + + [self lock]; + PINOperation *operation = nil; + if (identifier != nil && (operation = [_identifierToOperations objectForKey:identifier]) != nil) { + // There is an exisiting operation with the provided identifier, let's coalesce these operations + if (dataCoalescingBlock != nil) { + operation.data = dataCoalescingBlock(operation.data, coalescingData); + } + + [operation addCompletion:completion]; + } else { + isNewOperation = YES; + operation = [PINOperation operationWithBlock:block + reference:[self nextOperationReference] + priority:priority + identifier:identifier + data:coalescingData + completion:completion]; + [self locked_addOperation:operation]; + } + reference = operation.reference; + [self unlock]; + + if (isNewOperation) { + [self scheduleNextOperations:NO]; + } + + return reference; +} + +- (void)locked_addOperation:(PINOperation *)operation +{ + NSMutableOrderedSet *queue = [self operationQueueWithPriority:operation.priority]; + + dispatch_group_enter(_group); + [queue addObject:operation]; + [_queuedOperations addObject:operation]; + [_referenceToOperations setObject:operation forKey:operation.reference]; + if (operation.identifier != nil) { + [_identifierToOperations setObject:operation forKey:operation.identifier]; + } +} + +- (void)cancelAllOperations +{ + [self lock]; + for (PINOperation *operation in [[_referenceToOperations copy] objectEnumerator]) { + [self locked_cancelOperation:operation.reference]; + } + [self unlock]; +} + + +- (BOOL)cancelOperation:(id )operationReference +{ + [self lock]; + BOOL success = [self locked_cancelOperation:operationReference]; + [self unlock]; + return success; +} + +- (NSUInteger)maxConcurrentOperations +{ + [self lock]; + NSUInteger maxConcurrentOperations = _maxConcurrentOperations; + [self unlock]; + return maxConcurrentOperations; +} + +- (void)setMaxConcurrentOperations:(NSUInteger)maxConcurrentOperations +{ + NSAssert(maxConcurrentOperations > 0, @"Max concurrent operations must be greater than 0."); + [self lock]; + __block NSInteger difference = maxConcurrentOperations - _maxConcurrentOperations; + _maxConcurrentOperations = maxConcurrentOperations; + [self unlock]; + + if (difference == 0) { + return; + } + + dispatch_async(_semaphoreQueue, ^{ + while (difference != 0) { + if (difference > 0) { + dispatch_semaphore_signal(self->_concurrentSemaphore); + difference--; + } else { + dispatch_semaphore_wait(self->_concurrentSemaphore, DISPATCH_TIME_FOREVER); + difference++; + } + } + }); +} + +#pragma mark - private methods + +- (BOOL)locked_cancelOperation:(id )operationReference +{ + PINOperation *operation = [_referenceToOperations objectForKey:operationReference]; + BOOL success = [self locked_removeOperation:operation]; + if (success) { + dispatch_group_leave(_group); + } + return success; +} + +- (void)setOperationPriority:(PINOperationQueuePriority)priority withReference:(id )operationReference +{ + [self lock]; + PINOperation *operation = [_referenceToOperations objectForKey:operationReference]; + if (operation && operation.priority != priority) { + NSMutableOrderedSet *oldQueue = [self operationQueueWithPriority:operation.priority]; + [oldQueue removeObject:operation]; + + operation.priority = priority; + + NSMutableOrderedSet *queue = [self operationQueueWithPriority:priority]; + [queue addObject:operation]; + } + [self unlock]; +} + +/** + Schedule next operations schedules the next operation by queue order onto the serial queue if + it's available and one operation by priority order onto the concurrent queue. + */ +- (void)scheduleNextOperations:(BOOL)onlyCheckSerial +{ + [self lock]; + + //get next available operation in order, ignoring priority and run it on the serial queue + if (_serialQueueBusy == NO) { + PINOperation *operation = [self locked_nextOperationByQueue]; + if (operation) { + _serialQueueBusy = YES; + dispatch_async(_serialQueue, ^{ + operation.block(operation.data); + for (dispatch_block_t completion in operation.completions) { + completion(); + } + dispatch_group_leave(self->_group); + + [self lock]; + self->_serialQueueBusy = NO; + [self unlock]; + + //see if there are any other operations + [self scheduleNextOperations:YES]; + }); + } + } + + NSInteger maxConcurrentOperations = _maxConcurrentOperations; + + [self unlock]; + + if (onlyCheckSerial) { + return; + } + + //if only one concurrent operation is set, let's just use the serial queue for executing it + if (maxConcurrentOperations < 2) { + return; + } + + dispatch_async(_semaphoreQueue, ^{ + dispatch_semaphore_wait(self->_concurrentSemaphore, DISPATCH_TIME_FOREVER); + [self lock]; + PINOperation *operation = [self locked_nextOperationByPriority]; + [self unlock]; + + if (operation) { + dispatch_async(self->_concurrentQueue, ^{ + operation.block(operation.data); + for (dispatch_block_t completion in operation.completions) { + completion(); + } + dispatch_group_leave(self->_group); + dispatch_semaphore_signal(self->_concurrentSemaphore); + }); + } else { + dispatch_semaphore_signal(self->_concurrentSemaphore); + } + }); +} + +- (NSMutableOrderedSet *)operationQueueWithPriority:(PINOperationQueuePriority)priority +{ + switch (priority) { + case PINOperationQueuePriorityLow: + return _lowPriorityOperations; + + case PINOperationQueuePriorityDefault: + return _defaultPriorityOperations; + + case PINOperationQueuePriorityHigh: + return _highPriorityOperations; + + default: + NSAssert(NO, @"Invalid priority set"); + return _defaultPriorityOperations; + } +} + +//Call with lock held +- (PINOperation *)locked_nextOperationByPriority +{ + PINOperation *operation = [_highPriorityOperations firstObject]; + if (operation == nil) { + operation = [_defaultPriorityOperations firstObject]; + } + if (operation == nil) { + operation = [_lowPriorityOperations firstObject]; + } + if (operation) { + [self locked_removeOperation:operation]; + } + return operation; +} + +//Call with lock held +- (PINOperation *)locked_nextOperationByQueue +{ + PINOperation *operation = [_queuedOperations firstObject]; + [self locked_removeOperation:operation]; + return operation; +} + +- (void)waitUntilAllOperationsAreFinished +{ + [self scheduleNextOperations:NO]; + dispatch_group_wait(_group, DISPATCH_TIME_FOREVER); +} + +//Call with lock held +- (BOOL)locked_removeOperation:(PINOperation *)operation +{ + if (operation) { + NSMutableOrderedSet *priorityQueue = [self operationQueueWithPriority:operation.priority]; + if ([priorityQueue containsObject:operation]) { + [priorityQueue removeObject:operation]; + [_queuedOperations removeObject:operation]; + if (operation.identifier) { + [_identifierToOperations removeObjectForKey:operation.identifier]; + } + return YES; + } + } + return NO; +} + +- (void)lock +{ + pthread_mutex_lock(&_lock); +} + +- (void)unlock +{ + pthread_mutex_unlock(&_lock); +} + +@end diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PINOperationTypes.h b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PINOperationTypes.h new file mode 100644 index 00000000..be7293db --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PINOperationTypes.h @@ -0,0 +1,15 @@ +// +// PINOperationTypes.h +// PINOperation +// +// Created by Adlai Holler on 1/10/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import + +typedef NS_ENUM(NSUInteger, PINOperationQueuePriority) { + PINOperationQueuePriorityLow, + PINOperationQueuePriorityDefault, + PINOperationQueuePriorityHigh, +}; diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PrivacyInfo.xcprivacy b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PrivacyInfo.xcprivacy new file mode 100644 index 00000000..e08a130b --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + NSPrivacyCollectedDataTypes + + NSPrivacyAccessedAPITypes + + + diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperation.h b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperation.h new file mode 120000 index 00000000..0f8eb5e6 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperation.h @@ -0,0 +1 @@ +../../PINOperation.h \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationGroup.h b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationGroup.h new file mode 120000 index 00000000..2fd30a28 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationGroup.h @@ -0,0 +1 @@ +../../PINOperationGroup.h \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationMacros.h b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationMacros.h new file mode 120000 index 00000000..b7be0637 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationMacros.h @@ -0,0 +1 @@ +../../PINOperationMacros.h \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationQueue.h b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationQueue.h new file mode 120000 index 00000000..db4dc22a --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationQueue.h @@ -0,0 +1 @@ +../../PINOperationQueue.h \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationTypes.h b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationTypes.h new file mode 120000 index 00000000..bf9c4040 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationTypes.h @@ -0,0 +1 @@ +../../PINOperationTypes.h \ No newline at end of file diff --git a/Example-Mac/PINRemoteImageTests/Info.plist b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Tests/Info.plist similarity index 100% rename from Example-Mac/PINRemoteImageTests/Info.plist rename to Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Tests/Info.plist diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Tests/PINOperationGroupTests.m b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Tests/PINOperationGroupTests.m new file mode 100644 index 00000000..d42d2e85 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Tests/PINOperationGroupTests.m @@ -0,0 +1,133 @@ +// +// PINOperationGroupTests.m +// PINOperation +// +// Created by Garrett Moon on 10/12/16. +// Copyright © 2016 Pinterest. All rights reserved. +// + +#if SWIFT_PACKAGE +@import PINOperation; +#else +#import +#endif + +#import +#import + +static NSTimeInterval PINOperationGroupTestBlockTimeout = 20; + +@interface PINOperationGroupTests : XCTestCase + +@property PINOperationQueue *queue; + +@end + +@implementation PINOperationGroupTests + +- (dispatch_time_t)timeout +{ + return dispatch_time(DISPATCH_TIME_NOW, (int64_t)(PINOperationGroupTestBlockTimeout * NSEC_PER_SEC)); +} + +- (void)setUp { + [super setUp]; + self.queue = [[PINOperationQueue alloc] initWithMaxConcurrentOperations:5]; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testAllOperationsRunBeforeCompletion +{ + __block NSUInteger operationsRun = 0; + PINOperationGroup *group = [PINOperationGroup asyncOperationGroupWithQueue:self.queue]; + + for (NSUInteger idx = 0; idx < 100; idx++) { + __weak typeof(self) weakSelf = self; + [group addOperation:^{ + typeof(self) strongSelf = weakSelf; + @synchronized (strongSelf) { + operationsRun++; + } + }]; + } + + XCTestExpectation *completionRun = [self expectationWithDescription:@"Completion Run"]; + + __weak typeof(self) weakSelf = self; + [group setCompletion:^{ + typeof(self) strongSelf = weakSelf; + @synchronized (strongSelf) { + XCTAssert(operationsRun == 100, @"Not all operations were run before completion"); + } + [completionRun fulfill]; + }]; + + [group start]; + + [self waitForExpectationsWithTimeout:PINOperationGroupTestBlockTimeout handler:nil]; +} + +- (void)testWaitUntilOperationsComplete +{ + __block NSUInteger operationsRun = 0; + PINOperationGroup *group = [PINOperationGroup asyncOperationGroupWithQueue:self.queue]; + + for (NSUInteger idx = 0; idx < 100; idx++) { + __weak typeof(self) weakSelf = self; + [group addOperation:^{ + typeof(self) strongSelf = weakSelf; + @synchronized (strongSelf) { + operationsRun++; + } + }]; + } + __block BOOL completionBlockCalled = NO; + [group setCompletion:^{ + completionBlockCalled = YES; + }]; + + [group waitUntilComplete]; + XCTAssert(completionBlockCalled, @"Completion block should have been called after waiting."); + + @synchronized (self) { + XCTAssert(operationsRun == 100, @"All operations should be run"); + } +} + +- (void)testCancelation +{ + __block NSUInteger operationsRun = 0; + PINOperationGroup *group = [PINOperationGroup asyncOperationGroupWithQueue:self.queue]; + + const NSUInteger operationsToRun = 100; + + for (NSUInteger idx = 0; idx < operationsToRun; idx++) { + __weak typeof(self) weakSelf = self; + [group addOperation:^{ + usleep(10000); + typeof(self) strongSelf = weakSelf; + @synchronized (strongSelf) { + operationsRun++; + } + }]; + } + + [group setCompletion:^{ + XCTAssert(NO, @"completion should not be run"); + }]; + + [group start]; + [group cancel]; + + usleep(10000 * operationsToRun); + + @synchronized (self) { + XCTAssert(operationsRun < operationsToRun, @"All operations should not be run."); + } +} + +@end diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Tests/PINOperationQueueTests.m b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Tests/PINOperationQueueTests.m new file mode 100644 index 00000000..77f8627d --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/Tests/PINOperationQueueTests.m @@ -0,0 +1,528 @@ +// +// PINOperationQueueTests.m +// PINOperation +// +// Created by Garrett Moon on 8/28/16. +// Copyright © 2016 Pinterest. All rights reserved. +// + +#if SWIFT_PACKAGE +@import PINOperation; +#else +#import +#endif + +#import +#import + +static NSTimeInterval PINOperationQueueTestBlockTimeout = 20; + +@interface PINOperationQueueTests : XCTestCase + +@property (nonatomic, strong) PINOperationQueue *queue; + +@end + +static const NSUInteger PINOperationQueueTestsLowestMaxOperations = 1; +static const NSUInteger PINOperationQueueTestsMaxOperations = 5; + +@implementation PINOperationQueueTests + +- (void)setUp +{ + [super setUp]; + self.queue = [[PINOperationQueue alloc] initWithMaxConcurrentOperations:PINOperationQueueTestsMaxOperations]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown +{ + // Put teardown code here. This method is called after the invocation of each test method in the class. + self.queue = nil; + [super tearDown]; +} + +- (dispatch_time_t)timeout +{ + return dispatch_time(DISPATCH_TIME_NOW, (int64_t)(PINOperationQueueTestBlockTimeout * NSEC_PER_SEC)); +} + +- (void)testAllOperationsRun +{ + const NSUInteger operationCount = 100; + dispatch_group_t group = dispatch_group_create(); + + for (NSUInteger count = 0; count < operationCount; count++) { + dispatch_group_enter(group); + [self.queue scheduleOperation:^{ + dispatch_group_leave(group); + } withPriority:PINOperationQueuePriorityDefault]; + } + + NSUInteger success = dispatch_group_wait(group, [self timeout]); + XCTAssert(success == 0, @"Timed out before completing 100 operations"); +} + +- (void)testAllOperationsReleased +{ + const NSUInteger operationCount = 100; + NSPointerArray *weakOperationPointers = [NSPointerArray weakObjectsPointerArray]; + + for (int i = 0; i < operationCount; i++) { + @autoreleasepool { + dispatch_block_t operation = ^{ + usleep(i); + }; + + [weakOperationPointers addPointer:(__bridge void * _Nullable)(operation)]; + [self.queue scheduleOperation:operation withPriority:PINOperationQueuePriorityDefault]; + } + } + + [self.queue waitUntilAllOperationsAreFinished]; + + // Autorelease pool is drained at the end of each run loop + // Dispatch to the next loop before asserting that all blocks are gone + XCTestExpectation *expectation = [self expectationWithDescription:@"next run loop expectation"]; + dispatch_async(dispatch_get_main_queue(), ^{ + [expectation fulfill]; + }); + + [self waitForExpectationsWithTimeout:10 handler:nil]; + XCTAssertEqual(0, weakOperationPointers.allObjects.count); +} + +- (void)testWaitUntilAllOperationsFinished +{ + const NSUInteger operationCount = 100; + __block NSInteger operationsRun = 0; + + __weak PINOperationQueueTests *weakSelf = self; + for (NSUInteger count = 0; count < operationCount; count++) { + [self.queue scheduleOperation:^{ + __strong PINOperationQueueTests *strongSelf = weakSelf; + @synchronized (strongSelf) { + operationsRun += 1; + } + } withPriority:PINOperationQueuePriorityDefault]; + } + + [self.queue waitUntilAllOperationsAreFinished]; + + XCTAssert(operationCount == operationsRun, @"Timed out before completing 100 operations"); +} + +- (void)testWaitUntilAllOperationsFinishedWithNestedOperations +{ + const NSUInteger operationCount = 100; + + __block NSInteger operationsRun = 0; + for (NSUInteger count = 0; count < operationCount; count++) { + __weak PINOperationQueueTests *weakSelf = self; + [self.queue scheduleOperation:^{ + __strong PINOperationQueueTests *strongSelf = weakSelf; + @synchronized (strongSelf) { + operationsRun += 1; + } + [strongSelf.queue scheduleOperation:^{ + __strong PINOperationQueueTests *strongSelf = weakSelf; + @synchronized (strongSelf) { + operationsRun += 1; + } + } withPriority:PINOperationQueuePriorityHigh]; + } withPriority:PINOperationQueuePriorityDefault]; + } + + [self.queue waitUntilAllOperationsAreFinished]; + + XCTAssert(operationsRun == (operationCount*2), @"Timed out before completing 100 operations"); +} + +- (void)helperConfirmMaxOperations:(NSUInteger)maxOperations queue:(PINOperationQueue *)queue +{ + const NSUInteger operationCount = 100; + dispatch_group_t group = dispatch_group_create(); + + __block NSUInteger runningOperationCount = 0; + __block BOOL operationCountMaxedOut = NO; + + XCTAssert(queue.maxConcurrentOperations == maxOperations, @"Max concurrent operations not correctly set."); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + for (NSUInteger count = 0; count < operationCount; count++) { + dispatch_group_enter(group); + [queue scheduleOperation:^{ + @synchronized (self) { + runningOperationCount++; + if (runningOperationCount == maxOperations) { + operationCountMaxedOut = YES; + } + XCTAssert(runningOperationCount <= maxOperations, @"Running too many operations at once: %lu", (unsigned long)runningOperationCount); + } + + usleep(10000); + + @synchronized (self) { + runningOperationCount--; + XCTAssert(runningOperationCount <= maxOperations, @"Running too many operations at once: %lu", (unsigned long)runningOperationCount); + } + + dispatch_group_leave(group); + } withPriority:PINOperationQueuePriorityDefault]; + } +#pragma clang diagnostic pop + + NSUInteger success = dispatch_group_wait(group, [self timeout]); + XCTAssert(success == 0, @"Timed out before completing 100 operations"); + XCTAssert(operationCountMaxedOut == YES, @"Never reached maximum number of concurrent operations: %lu", (unsigned long)maxOperations); +} + +- (void)testMaximumNumberOfConcurrentOperations +{ + [self helperConfirmMaxOperations:PINOperationQueueTestsMaxOperations queue:self.queue]; +} + +- (void)testMaximumNumberOfConcurrentOperationsIsOne +{ + self.queue = [[PINOperationQueue alloc] initWithMaxConcurrentOperations:PINOperationQueueTestsLowestMaxOperations]; + [self helperConfirmMaxOperations:PINOperationQueueTestsLowestMaxOperations queue:self.queue]; +} + +//We expect operations to run in priority order when added in that order as well +- (void)testPriority +{ + const NSUInteger highOperationCount = 100; + const NSUInteger defaultOperationCount = 100; + const NSUInteger lowOperationCount = 100; + + __block NSUInteger highOperationComplete = 0; + __block NSUInteger defaultOperationComplete = 0; + __block NSUInteger lowOperationComplete = 0; + + dispatch_group_t group = dispatch_group_create(); + + //This is actually a pretty annoying unit test to write. Because multiple operations are allowed to be concurrent, lower priority operations can potentially repeatidly + //obtain the lock while higher priority operations wait… So I'm attempting to make the operations less about lock contention and more about the length of time they take + //to execute and adding a sleep before they obtain the lock to hopefully improve reliability. + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + for (NSUInteger count = 0; count < highOperationCount; count++) { + dispatch_group_enter(group); + [self.queue scheduleOperation:^{ + usleep(10000); + @synchronized (self) { + ++highOperationComplete; + XCTAssert(defaultOperationComplete <= PINOperationQueueTestsMaxOperations, @"Running default operations before high. Default operations complete: %lu", (unsigned long)defaultOperationComplete); + XCTAssert(lowOperationComplete <= PINOperationQueueTestsMaxOperations, @"Running low operations before high. Low operations complete: %lu", (unsigned long)lowOperationComplete); + } + dispatch_group_leave(group); + } withPriority:PINOperationQueuePriorityHigh]; + } + + for (NSUInteger count = 0; count < defaultOperationCount; count++) { + dispatch_group_enter(group); + [self.queue scheduleOperation:^{ + usleep(10000); + @synchronized (self) { + ++defaultOperationComplete; + XCTAssert(lowOperationComplete <= PINOperationQueueTestsMaxOperations, @"Running low operations before default. Low operations complete: %lu", (unsigned long)lowOperationComplete); + XCTAssert(highOperationComplete > highOperationCount - PINOperationQueueTestsMaxOperations, @"Running high operations after default. High operations complete: %lu", (unsigned long)highOperationComplete); + } + dispatch_group_leave(group); + } withPriority:PINOperationQueuePriorityDefault]; + } + + for (NSUInteger count = 0; count < lowOperationCount; count++) { + dispatch_group_enter(group); + [self.queue scheduleOperation:^{ + usleep(10000); + @synchronized (self) { + ++lowOperationComplete; + XCTAssert(defaultOperationComplete > defaultOperationCount - PINOperationQueueTestsMaxOperations, @"Running default operations after low. Default operations complete: %lu", (unsigned long)defaultOperationComplete); + XCTAssert(highOperationComplete > highOperationCount - PINOperationQueueTestsMaxOperations, @"Running high operations after low. High operations complete: %lu", (unsigned long)highOperationComplete); + } + dispatch_group_leave(group); + } withPriority:PINOperationQueuePriorityLow]; + } +#pragma clang diagnostic pop + + NSUInteger success = dispatch_group_wait(group, [self timeout]); + XCTAssert(success == 0, @"Timed out"); +} + +//We expect low priority operations to eventually run even if the queue is continually kept full with higher priority operations +- (void)testOutOfOrderOperations +{ + const NSUInteger operationCount = 100; + dispatch_group_t group = dispatch_group_create(); + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + for (NSUInteger count = 0; count < PINOperationQueueTestsMaxOperations + 1; count++) { + [self.queue scheduleOperation:^{ + [self recursivelyAddOperation]; + } withPriority:PINOperationQueuePriorityHigh]; + } +#pragma clang diagnostic pop + + for (NSUInteger count = 0; count < operationCount; count++) { + dispatch_group_enter(group); + [self.queue scheduleOperation:^{ + dispatch_group_leave(group); + } withPriority:PINOperationQueuePriorityLow]; + } + + NSUInteger success = dispatch_group_wait(group, [self timeout]); + XCTAssert(success == 0, @"Timed out"); +} + +- (void)recursivelyAddOperation +{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + [self.queue scheduleOperation:^{ + [self recursivelyAddOperation]; + } withPriority:PINOperationQueuePriorityHigh]; +#pragma clang diagnostic pop +} + +- (void)testCancelation +{ + const NSUInteger sleepTime = 100000; + for (NSUInteger count = 0; count < PINOperationQueueTestsMaxOperations + 1; count++) { + [self.queue scheduleOperation:^{ + usleep(sleepTime); + } withPriority:PINOperationQueuePriorityDefault]; + } + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + id operation = [self.queue scheduleOperation:^{ + XCTAssertTrue(NO, @"operation should have been canceled"); + } withPriority:PINOperationQueuePriorityDefault]; +#pragma clang diagnostics pop + + [self.queue cancelOperation:operation]; + + usleep(sleepTime * (PINOperationQueueTestsMaxOperations + 1)); +} + +- (void)testChangingPriority +{ + const NSUInteger defaultOperationCount = 100; + + __block NSUInteger defaultOperationComplete = 0; + + dispatch_group_t group = dispatch_group_create(); + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + for (NSUInteger count = 0; count < defaultOperationCount; count++) { + dispatch_group_enter(group); + [self.queue scheduleOperation:^{ + usleep(100); + @synchronized (self) { + ++defaultOperationComplete; + } + dispatch_group_leave(group); + } withPriority:PINOperationQueuePriorityDefault]; + } + + dispatch_group_enter(group); + id operation = [self.queue scheduleOperation:^{ + @synchronized (self) { + //Make sure we're less than defaultOperationCount - PINOperationQueueTestsMaxOperations because this operation could start even while the others are running even + //if started last. + XCTAssert(defaultOperationComplete < defaultOperationCount - PINOperationQueueTestsMaxOperations, @"operation was not completed before default operations even though reprioritized."); + } + dispatch_group_leave(group); + } withPriority:PINOperationQueuePriorityLow]; +#pragma clang diagnostic pop + [self.queue setOperationPriority:PINOperationQueuePriorityHigh withReference:operation]; + + NSUInteger success = dispatch_group_wait(group, [self timeout]); + XCTAssert(success == 0, @"Timed out"); +} + +- (void)testCoalescingOperations +{ + self.queue = [[PINOperationQueue alloc] initWithMaxConcurrentOperations:PINOperationQueueTestsMaxOperations]; + + const NSUInteger totalOperationCount = 100; + dispatch_group_t group = dispatch_group_create(); + + NSString *normalDesc = @"Normal"; + NSString *coallescedDesc = @"Coallesced"; + NSArray *descs = @[normalDesc, coallescedDesc]; + + __block NSMutableDictionary *operationCount = [NSMutableDictionary dictionaryWithObjectsAndKeys:@(0), normalDesc, @(0), coallescedDesc, nil]; + __block NSMutableDictionary *operationRun = [NSMutableDictionary dictionaryWithObjectsAndKeys:@(0), normalDesc, @(0), coallescedDesc, nil]; + __block NSMutableDictionary *operationComplete = [NSMutableDictionary dictionaryWithObjectsAndKeys:@(0), normalDesc, @(0), coallescedDesc, nil]; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + // Fill up the queue with dummy operations so we have time to add real ones without them being unexpectedly executed + for (NSUInteger i = 0; i < PINOperationQueueTestsMaxOperations * 2; i++) { + dispatch_group_enter(group); + [self.queue scheduleOperation:^{ + usleep(1000); + dispatch_group_leave(group); + }]; + } + + for (NSUInteger i = 0; i < totalOperationCount; i++) { + dispatch_group_enter(group); + + NSString *desc = descs[i % descs.count]; + BOOL isNormalOperation = [desc isEqualToString:normalDesc]; + + NSString *identifier = desc; + if (isNormalOperation) { + identifier = [NSString stringWithFormat:@"%@ %tu", desc, i]; + } + + operationCount[desc] = @([operationCount[desc] intValue] + 1); + + PINOperationBlock operation = ^(id _Nullable data) { + @synchronized (self) { + operationRun[desc] = @([operationRun[desc] intValue] + 1); + } + }; + + dispatch_block_t completion = ^{ + @synchronized (self) { + operationComplete[desc] = @([operationComplete[desc] intValue] + 1); + } + dispatch_group_leave(group); + }; + + [self.queue scheduleOperation:operation + withPriority:PINOperationQueuePriorityLow + identifier:identifier + coalescingData:nil + dataCoalescingBlock:nil + completion:completion]; + } +#pragma clang diagnostic pop + + NSUInteger success = dispatch_group_wait(group, [self timeout]); + XCTAssert(success == 0, @"Timed out"); + XCTAssert([operationRun[normalDesc] intValue] == [operationCount[normalDesc] intValue]); + XCTAssert([operationComplete[normalDesc] intValue] == [operationCount[normalDesc] intValue]); + XCTAssert([operationRun[coallescedDesc] intValue] == 1); + XCTAssert([operationComplete[coallescedDesc] intValue] == [operationCount[coallescedDesc] intValue]); +} + +- (void)testCoalescingOperationCompletions +{ + dispatch_group_t group = dispatch_group_create(); + + NSArray *completionFlags = @[@(NO), @(NO), @(YES), @(NO), @(YES)]; + NSIndexSet *expectedCompletedIndexSet = [completionFlags indexesOfObjectsPassingTest:^BOOL(NSNumber * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { return [obj boolValue]; }]; + NSMutableIndexSet *completedIndexSet = [NSMutableIndexSet indexSet]; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + // Fill up the queue with dummy operations so we have time to add real ones without them being unexpectedly executed + for (NSUInteger i = 0; i < PINOperationQueueTestsMaxOperations * 2; i++) { + dispatch_group_enter(group); + [self.queue scheduleOperation:^{ + usleep(1000); + dispatch_group_leave(group); + }]; + } + + for (NSUInteger i = 0; i < completionFlags.count; i++) { + dispatch_group_enter(group); + + PINOperationBlock operation = ^(id _Nullable data) { + for (NSNumber *hasCompletion in completionFlags) { + if ([hasCompletion boolValue] == NO) { + dispatch_group_leave(group); + } + } + }; + + dispatch_block_t completion = [completionFlags[i] boolValue] == NO ? nil : ^{ + XCTAssert([expectedCompletedIndexSet containsIndex:i]); + @synchronized (self) { + [completedIndexSet addIndex:i]; + } + dispatch_group_leave(group); + }; + + [self.queue scheduleOperation:operation + withPriority:PINOperationQueuePriorityLow + identifier:@"Identifier" + coalescingData:nil + dataCoalescingBlock:nil + completion:completion]; + } +#pragma clang diagnostic pop + + NSUInteger success = dispatch_group_wait(group, [self timeout]); + XCTAssert(success == 0, @"Timed out"); + XCTAssert([completedIndexSet isEqual:expectedCompletedIndexSet]); +} + +- (void)testCoalescingOperationData +{ + dispatch_group_t group = dispatch_group_create(); + + NSArray *dataset = @[@(100), @(50), @(50), @(100), @(10)]; + NSNumber *expectedData = [dataset sortedArrayUsingSelector:@selector(compare:)][0]; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + // Fill up the queue with dummy operations so we have time to add real ones without them being unexpectedly executed + for (NSUInteger i = 0; i < PINOperationQueueTestsMaxOperations * 2; i++) { + dispatch_group_enter(group); + [self.queue scheduleOperation:^{ + usleep(1000); + dispatch_group_leave(group); + }]; + } + + for (NSNumber *data in dataset) { + dispatch_group_enter(group); + + PINOperationBlock operation = ^(id _Nullable obj) { + XCTAssert([expectedData compare:obj] == NSOrderedSame); + }; + + PINOperationDataCoalescingBlock dataCoalescingBlock = ^id(id existingData, id newData) { + NSComparisonResult result = [existingData compare:newData]; + return (result == NSOrderedDescending) ? newData : existingData; + }; + + dispatch_block_t completion = ^{ + dispatch_group_leave(group); + }; + + [self.queue scheduleOperation:operation + withPriority:PINOperationQueuePriorityLow + identifier:@"Identifier" + coalescingData:data + dataCoalescingBlock:dataCoalescingBlock + completion:completion]; + } +#pragma clang diagnostic pop + + NSUInteger success = dispatch_group_wait(group, [self timeout]); + XCTAssert(success == 0, @"Timed out"); +} + +- (void)testChangingMaximumNumberOfOperations +{ + PINOperationQueue *queue = [[PINOperationQueue alloc] initWithMaxConcurrentOperations:2]; + [self helperConfirmMaxOperations:2 queue:queue]; + queue.maxConcurrentOperations = 4; + usleep(10000); + [self helperConfirmMaxOperations:4 queue:queue]; + queue.maxConcurrentOperations = 2; + usleep(10000); + [self helperConfirmMaxOperations:2 queue:queue]; +} + +@end diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/build_docs.sh b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/build_docs.sh new file mode 100755 index 00000000..8566ae2e --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/build_docs.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh + +appledoc \ + --company-id com.pinterest \ + --project-name PINOperation \ + --project-company Pinterest \ + --project-version 1.0 \ + --docset-min-xcode-version 4.3 \ + --docset-bundle-id %COMPANYID.%PROJECTID \ + --docset-bundle-name "%PROJECT %VERSION" \ + --docset-bundle-filename %COMPANYID.%PROJECTID-%VERSIONID.docset \ + --ignore "tests" \ + --ignore "docs" \ + --ignore "*.m" \ + --no-repeat-first-par \ + --explicit-crossref \ + --clean-output \ + --keep-intermediate-files \ + --output ./docs \ + . + +mv docs/docset docs/com.pinterest.PINOperation-1.0.docset +rm docs/docset-installed.txt diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/build_tests.sh b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/build_tests.sh new file mode 100755 index 00000000..79b6386a --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/build_tests.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env sh + +# Have to specify destination because http://www.openradar.me/23857648 +xcodebuild ONLY_ACTIVE_ARCH=NO -project tests/PINOperation.xcodeproj -scheme PINOperationTests -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 15,OS=latest' clean build test diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Info.plist b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Info.plist new file mode 100644 index 00000000..3f0c2925 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleIdentifier + com.pinterest.PINOperationQueue + CFBundleName + PINOperationQueue 1.0 + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1.0 + + + + + DocSetFeedName + PINOperationQueue Documentation + + DocSetMinimumXcodeVersion + 4.3 + + DashDocSetFamily + appledoc + DocSetPublisherIdentifier + com.pinterest.documentation + DocSetPublisherName + Pinterest + NSHumanReadableCopyright + Copyright © 2017 Pinterest. All rights reserved. + + diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/Blocks/PINOperationBlock.html b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/Blocks/PINOperationBlock.html new file mode 100644 index 00000000..b7481d79 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/Blocks/PINOperationBlock.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINOperationQueue +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/Constants/PINOperationQueuePriority.html b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/Constants/PINOperationQueuePriority.html new file mode 100644 index 00000000..810f085f --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/Constants/PINOperationQueuePriority.html @@ -0,0 +1,145 @@ + + + + + + + + + + + + +
+
+ +

+ PINOperationQueue +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +

PINOperationQueuePriority

+ +
+ + +

Definition

+ typedef NS_ENUM(NSUInteger, PINOperationQueuePriority ) {
+ +    PINOperationQueuePriorityLow,
+ +    PINOperationQueuePriorityDefault,
+ +    PINOperationQueuePriorityHigh,
+ + };
+ +
+ +
+

Constants

+
+ +
PINOperationQueuePriorityLow
+
+ + +

+ PINOperationQueue.h. +

+ +
+ +
PINOperationQueuePriorityDefault
+
+ + +

+ PINOperationQueue.h. +

+ +
+ +
PINOperationQueuePriorityHigh
+
+ + +

+ PINOperationQueue.h. +

+ +
+ +
+
+ + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/Protocols/PINOperationReference.html b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/Protocols/PINOperationReference.html new file mode 100644 index 00000000..b7481d79 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/Protocols/PINOperationReference.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINOperationQueue +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_index.scss b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_index.scss new file mode 100644 index 00000000..7e98029d --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_index.scss @@ -0,0 +1,13 @@ +.index-container { + display: flex; + flex-direction: row; + flex-wrap: wrap; + + @media (max-width: $mobile-max-width) { + flex-direction: column; + } + + .index-column { + flex: 1 1 33%; + } +} diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_layout.scss b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_layout.scss new file mode 100644 index 00000000..40bd6d4a --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_layout.scss @@ -0,0 +1,303 @@ +* { + box-sizing: border-box; +} + +.clear { + clear: both; +} + +.clearfix { + &:before, &:after { + clear: both; + display: table; + content: ""; + } +} + +.xcode .hide-in-xcode { + display: none; +} + +body { + font: 62.5% $body-font; + background: $body-background; +} + +h1, h2, h3 { + font-weight: 300; + color: #808080; +} + +h1 { + font-size: 2em; + color: #000; +} + +h4 { + font-size: 13px; + line-height: 1.5; + margin: 21px 0 0 0; +} + +a { + color: $tint-color; + text-decoration: none; +} + +pre, code { + font-family: $code-font; + word-wrap: break-word; +} + +pre > code, .method-declaration code { + display: inline-block; + font-size: .85em; + padding: 4px 0 4px 10px; + border-left: 5px solid rgba(0, 155, 51, .2); + + &:before { + content: "Objective-C"; + display: block; + + font: 9px/1 $body-font; + color: #009b33; + text-transform: uppercase; + letter-spacing: 2px; + padding-bottom: 6px; + } +} + +pre > code { + font-size: inherit; +} + +table, th, td { + border: 1px solid #e9e9e9; +} + +table { + width: 100%; +} + +th, td { + padding: 7px; + + > :first-child { + margin-top: 0; + } + + > :last-child { + margin-bottom: 0; + } +} + +.container { + @extend .clearfix; + + max-width: 980px; + padding: 0 10px; + margin: 0 auto; + + @media (max-width: $mobile-max-width) { + padding: 0; + } +} + +header { + position: fixed; + top: 0; + left: 0; + width: 100%; + z-index: 2; + + background: #414141; + color: #fff; + font-size: 1.1em; + line-height: 25px; + letter-spacing: .05em; + + #library-title { + float: left; + } + + #developer-home { + float: right; + } + + h1 { + font-size: inherit; + font-weight: inherit; + margin: 0; + } + + p { + margin: 0; + } + + h1, a { + color: inherit; + } + + @media (max-width: $mobile-max-width) { + position: absolute; + + .container { + padding: 0 10px; + } + } +} + +aside { + position: fixed; + top: 25px; + left: 0; + width: 100%; + height: 25px; + z-index: 2; + + font-size: 1.1em; + + @media (max-width: $mobile-max-width) { + position: absolute; + } + + #header-buttons { + background: rgba(255, 255, 255, .8); + margin: 0 1px; + padding: 0; + list-style: none; + text-align: right; + line-height: 32px; + + li { + display: inline-block; + cursor: pointer; + padding: 0 10px; + } + + label, select { + cursor: inherit; + } + + #on-this-page { + position: relative; + + .chevron { + display: inline-block; + width: 14px; + height: 4px; + position: relative; + + .chevy { + background: #878787; + height: 2px; + position: absolute; + width: 10px; + + &.chevron-left { + left: 0; + transform: rotateZ(45deg) scale(0.6); + } + + &.chevron-right { + right: 0; + transform: rotateZ(-45deg) scale(0.6); + } + } + } + + #jump-to { + opacity: 0; + font-size: 16px; + + position: absolute; + top: 5px; + left: 0; + width: 100%; + height: 100%; + } + } + } +} + +article { + margin-top: 25px; + + #content { + @extend .clearfix; + + background: $content-background; + border: 1px solid $content-border; + padding: 15px 25px 30px 25px; + + font-size: 1.4em; + line-height: 1.45; + + position: relative; + + @media (max-width: $mobile-max-width) { + padding: 15px 10px 20px 10px; + } + + .navigation-top { + position: absolute; + top: 15px; + right: 25px; + } + + .title { + margin: 21px 0 0 0; + padding: 15px 0; + } + + p { + color: #414141; + margin: 0 0 15px 0; + } + + th, td { + p:last-child { + margin-bottom: 0; + } + } + + main { + ul { + list-style: none; + margin-left: 24px; + margin-bottom: 12px; + padding: 0; + + li { + position: relative; + padding-left: 1.3em; + + &:before { + content: "\02022"; + + color: #414141; + font-size: 1.08em; + line-height: 1; + + position: absolute; + left: 0; + padding-top: 2px; + } + } + } + } + + footer { + @extend .clearfix; + + .footer-copyright { + margin: 70px 25px 10px 0; + } + + p { + font-size: .71em; + color: #a0a0a0; + } + } + } +} diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_normalize.scss b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_normalize.scss new file mode 100644 index 00000000..9b8848a5 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_normalize.scss @@ -0,0 +1,581 @@ +/* ========================================================================== + Normalize.scss settings + ========================================================================== */ +/** + * Includes legacy browser support IE6/7 + * + * Set to false if you want to drop support for IE6 and IE7 + */ + +$legacy_browser_support: false !default; + +/* Base + ========================================================================== */ + +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + * 3. Corrects text resizing oddly in IE 6/7 when body `font-size` is set using + * `em` units. + */ + +html { + font-family: sans-serif; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ + @if $legacy_browser_support { + *font-size: 100%; /* 3 */ + } +} + +/** + * Remove default margin. + */ + +body { + margin: 0; +} + +/* HTML5 display definitions + ========================================================================== */ + +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} + +/** + * 1. Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ + +audio, +canvas, +progress, +video { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ + @if $legacy_browser_support { + *display: inline; + *zoom: 1; + } +} + +/** + * Prevents modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ + +[hidden], +template { + display: none; +} + +/* Links + ========================================================================== */ + +/** + * Remove the gray background color from active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ + +a { + &:active, &:hover { + outline: 0; + }; +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +@if $legacy_browser_support { + blockquote { + margin: 1em 40px; + } +} + +/** + * Address styling not present in Safari and Chrome. + */ + +dfn { + font-style: italic; +} + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +@if $legacy_browser_support { + h2 { + font-size: 1.5em; + margin: 0.83em 0; + } + + h3 { + font-size: 1.17em; + margin: 1em 0; + } + + h4 { + font-size: 1em; + margin: 1.33em 0; + } + + h5 { + font-size: 0.83em; + margin: 1.67em 0; + } + + h6 { + font-size: 0.67em; + margin: 2.33em 0; + } +} + +/** + * Addresses styling not present in IE 8/9. + */ + +mark { + background: #ff0; + color: #000; +} + +@if $legacy_browser_support { + + /** + * Addresses margins set differently in IE 6/7. + */ + + p, + pre { + *margin: 1em 0; + } + + /* + * Addresses CSS quotes not supported in IE 6/7. + */ + + q { + *quotes: none; + } + + /* + * Addresses `quotes` property not supported in Safari 4. + */ + + q:before, + q:after { + content: ''; + content: none; + } +} + +/** + * Address inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +@if $legacy_browser_support { + + /* ========================================================================== + Lists + ========================================================================== */ + + /* + * Addresses margins set differently in IE 6/7. + */ + + dl, + menu, + ol, + ul { + *margin: 1em 0; + } + + dd { + *margin: 0 0 0 40px; + } + + /* + * Addresses paddings set differently in IE 6/7. + */ + + menu, + ol, + ul { + *padding: 0 0 0 40px; + } + + /* + * Corrects list images handled incorrectly in IE 7. + */ + + nav ul, + nav ol { + *list-style: none; + *list-style-image: none; + } + +} + +/* Embedded content + ========================================================================== */ + +/** + * 1. Remove border when inside `a` element in IE 8/9/10. + * 2. Improves image quality when scaled in IE 7. + */ + +img { + border: 0; + @if $legacy_browser_support { + *-ms-interpolation-mode: bicubic; /* 2 */ + } +} + +/** + * Correct overflow not hidden in IE 9/10/11. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Grouping content + ========================================================================== */ + +/** + * Address margin not present in IE 8/9 and Safari. + */ + +figure { + margin: 1em 40px; +} + +/** + * Address differences between Firefox and other browsers. + */ + +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +/** + * Contain overflow in all browsers. + */ + +pre { + overflow: auto; +} + +/** + * Address odd `em`-unit font size rendering in all browsers. + * Correct font family set oddly in IE 6, Safari 4/5, and Chrome. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + @if $legacy_browser_support { + _font-family: 'courier new', monospace; + } + font-size: 1em; +} + +/* Forms + ========================================================================== */ + +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ + +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + * 4. Improves appearance and consistency in all browsers. + */ + +button, +input, +optgroup, +select, +textarea { + color: inherit; /* 1 */ + font: inherit; /* 2 */ + margin: 0; /* 3 */ + @if $legacy_browser_support { + vertical-align: baseline; /* 3 */ + *vertical-align: middle; /* 3 */ + } +} + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ + +button { + overflow: visible; +} + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ + +button, +select { + text-transform: none; +} + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + * 4. Removes inner spacing in IE 7 without affecting normal text inputs. + * Known issue: inner spacing remains in IE 6. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ + @if $legacy_browser_support { + *overflow: visible; /* 4 */ + } +} + +/** + * Re-set default cursor for disabled elements. + */ + +button[disabled], +html input[disabled] { + cursor: default; +} + +/** + * Remove inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +input { + line-height: normal; +} + +/** + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + * Known issue: excess padding remains in IE 6. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ + @if $legacy_browser_support { + *height: 13px; /* 3 */ + *width: 13px; /* 3 */ + } +} + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ + +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; /* 2 */ + box-sizing: content-box; +} + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + * 3. Corrects text not wrapping in Firefox 3. + * 4. Corrects alignment displayed oddly in IE 6/7. + */ + +legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ + @if $legacy_browser_support { + white-space: normal; /* 3 */ + *margin-left: -7px; /* 4 */ + } +} + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ + +textarea { + overflow: auto; +} + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ + +optgroup { + font-weight: bold; +} + +/* Tables + ========================================================================== */ + +/** + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} + +td, +th { + padding: 0; +} diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_object.scss b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_object.scss new file mode 100644 index 00000000..22eebd87 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_object.scss @@ -0,0 +1,89 @@ +.section-specification { + table { + width: auto; + + th { + text-align: left; + } + } +} + +.method-title { + margin-left: -15px; + margin-bottom: 8px; + transition: margin-left .3s ease-out; + + .section-method.hide & { + margin-left: 0; + } + + code { + font-weight: 400; + font-size: .85em; + } +} + +.method-info { + background: $object-background; + border-bottom: 1px solid $object-border; + margin: 0 -25px; + padding: 20px 25px 0 25px; + transition: height .3s ease-out; + + position: relative; + + .pointy-thing { + background: $content-background; + height: 10px; + border-bottom: 1px solid $object-border; + margin: -20px -25px 16px -25px; + + &:before { + display: inline-block; + content: ""; + + background: $object-background; + border: 1px solid $object-border; + border-bottom: 0; + border-right: 0; + + position: absolute; + left: 21px; + top: 3px; + width: 12px; + height: 12px; + transform: rotate(45deg); + } + } + + .method-subsection { + margin-bottom: 15px; + + .argument-name { + width: 1px; + text-align: right; + + code { + color: #808080; + font-style: italic; + font-weight: 400; + } + } + } +} + +.section-method { + &.hide .method-info { + height: 0 !important; + overflow: hidden; + display: none; + } + + &.hide.animating .method-info { + display: block; + } + + &.animating .method-info { + overflow: hidden; + } +} diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_print.scss b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_print.scss new file mode 100644 index 00000000..61bdf99f --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_print.scss @@ -0,0 +1,42 @@ +@media print { + body { + background: #fff; + padding: 8px; + } + + header { + position: static; + background: #fff; + color: #000; + } + + aside { + display: none; + } + + .container { + max-width: none; + padding: 0; + } + + article { + margin-top: 0; + + #content { + border: 0; + background: #fff; + padding: 15px 0 0 0; + + .title { + margin-top: 0; + padding-top: 0; + } + } + } + + .method-info { + &, & .pointy-thing { + background: #fff; + } + } +} diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_variables.scss b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_variables.scss new file mode 100644 index 00000000..cbaff3cf --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_variables.scss @@ -0,0 +1,11 @@ +$body-font: -apple-system-font, "Helvetica Neue", Helvetica, sans-serif; +$code-font: "Source Code Pro", Monaco, Menlo, Consolas, monospace; + +$body-background: #f2f2f2; +$content-background: #fff; +$content-border: #e9e9e9; +$tint-color: #08c; +$object-background: #f9f9f9; +$object-border: #e9e9e9; + +$mobile-max-width: 650px; diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_xcode.scss b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_xcode.scss new file mode 100644 index 00000000..340b1f6b --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_xcode.scss @@ -0,0 +1,29 @@ +.xcode { + header, aside { + display: none; + } + + .container { + padding: 0; + } + + article { + margin-top: 0; + + #content { + border: 0; + margin: 0; + } + } + + .method-info { + &, .section-method.hide & { + max-height: auto; + overflow: visible; + + &.hiding { + display: block; + } + } + } +} diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/style.scss b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/style.scss new file mode 100644 index 00000000..648a6086 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/style.scss @@ -0,0 +1 @@ +@import "variables", "normalize", "layout", "index", "object", "print", "xcode"; diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/hierarchy.html b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/hierarchy.html new file mode 100644 index 00000000..9bd0aa1f --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/hierarchy.html @@ -0,0 +1,82 @@ + + + + + + + + + + + + +
+
+ +

+ PINOperationQueue +

+ +

+ Pinterest +

+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/button_bar_background.png b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/button_bar_background.png new file mode 100644 index 00000000..71d1019b Binary files /dev/null and b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/button_bar_background.png differ diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/disclosure.png b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/disclosure.png new file mode 100644 index 00000000..4c5cbf44 Binary files /dev/null and b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/disclosure.png differ diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/disclosure_open.png b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/disclosure_open.png new file mode 100644 index 00000000..82396fed Binary files /dev/null and b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/disclosure_open.png differ diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/library_background.png b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/library_background.png new file mode 100644 index 00000000..3006248a Binary files /dev/null and b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/library_background.png differ diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/title_background.png b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/title_background.png new file mode 100644 index 00000000..846e4968 Binary files /dev/null and b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/title_background.png differ diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/index.html b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/index.html new file mode 100644 index 00000000..fbc5d19d --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/index.html @@ -0,0 +1,90 @@ + + + + + + + + + + + + +
+
+ +

+ PINOperationQueue +

+ +

+ Pinterest +

+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/js/script.js b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/js/script.js new file mode 100644 index 00000000..ca915ee4 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/js/script.js @@ -0,0 +1,58 @@ +function $() { + return document.querySelector.apply(document, arguments); +} + +if (navigator.userAgent.indexOf("Xcode") != -1) { + document.documentElement.classList.add("xcode"); +} + +var jumpTo = $("#jump-to"); + +if (jumpTo) { + jumpTo.addEventListener("change", function(e) { + location.hash = this.options[this.selectedIndex].value; + }); +} + +function hashChanged() { + if (/^#\/\/api\//.test(location.hash)) { + var element = document.querySelector("a[name='" + location.hash.substring(1) + "']"); + + if (!element) { + return; + } + + element = element.parentNode; + + element.classList.remove("hide"); + fixScrollPosition(element); + } +} + +function fixScrollPosition(element) { + var scrollTop = element.offsetTop - 150; + document.documentElement.scrollTop = scrollTop; + document.body.scrollTop = scrollTop; +} + +[].forEach.call(document.querySelectorAll(".section-method"), function(element) { + element.classList.add("hide"); + + element.querySelector(".method-title a").addEventListener("click", function(e) { + var info = element.querySelector(".method-info"), + infoContainer = element.querySelector(".method-info-container"); + + element.classList.add("animating"); + info.style.height = (infoContainer.clientHeight + 40) + "px"; + fixScrollPosition(element); + element.classList.toggle("hide"); + + setTimeout(function() { + element.classList.remove("animating"); + info.style.height = "auto"; + }, 300); + }); +}); + +window.addEventListener("hashchange", hashChanged); +hashChanged(); diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Nodes.xml b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Nodes.xml new file mode 100644 index 00000000..a824d9a5 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Nodes.xml @@ -0,0 +1,67 @@ + + + + + PINOperationQueue + index.html + + + + + + + Protocols + index.html + + + + + + + + + Constants + index.html + + + + + + + + + Blocks + index.html + + + + + + + + + + + + + + + PINOperationReference + Protocols/PINOperationReference.html + + + + + PINOperationQueuePriority + Constants/PINOperationQueuePriority.html + + + + + PINOperationBlock + Blocks/PINOperationBlock.html + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Tokens1.xml b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Tokens1.xml new file mode 100644 index 00000000..03332c47 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Tokens1.xml @@ -0,0 +1,18 @@ + + + + + + //apple_ref/occ/intf/PINOperationReference + Cancels all queued operations + PINOperationQueue.h + + + + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Tokens2.xml b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Tokens2.xml new file mode 100644 index 00000000..b6618281 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Tokens2.xml @@ -0,0 +1,48 @@ + + + + + + //apple_ref/c/tdef/PINOperationQueuePriority + + PINOperationQueue.h + + + + + + + + + //apple_ref/c/econst/PINOperationQueuePriorityLow + + PINOperationQueuePriorityLow + + PINOperationQueue.h + + + + + + //apple_ref/c/econst/PINOperationQueuePriorityDefault + + PINOperationQueuePriorityDefault + + PINOperationQueue.h + + + + + + //apple_ref/c/econst/PINOperationQueuePriorityHigh + + PINOperationQueuePriorityHigh + + PINOperationQueue.h + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Tokens3.xml b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Tokens3.xml new file mode 100644 index 00000000..3fc40bec --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Tokens3.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.dsidx b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.dsidx new file mode 100644 index 00000000..cf3289f0 Binary files /dev/null and b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.dsidx differ diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.dsidx-shm b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.dsidx-shm new file mode 100644 index 00000000..c6022c76 Binary files /dev/null and b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.dsidx-shm differ diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.dsidx-wal b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.dsidx-wal new file mode 100644 index 00000000..4f824904 Binary files /dev/null and b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.dsidx-wal differ diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.mom b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.mom new file mode 100644 index 00000000..0503cfdd Binary files /dev/null and b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.mom differ diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.skidx b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.skidx new file mode 100644 index 00000000..99e1cd2b Binary files /dev/null and b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.skidx differ diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.toc b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.toc new file mode 100644 index 00000000..2088a3ff Binary files /dev/null and b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.toc differ diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.tokencache b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.tokencache new file mode 100644 index 00000000..5118133e Binary files /dev/null and b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.tokencache differ diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/Blocks/PINOperationBlock.html b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/Blocks/PINOperationBlock.html new file mode 100644 index 00000000..b7481d79 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/Blocks/PINOperationBlock.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINOperationQueue +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/Constants/PINOperationQueuePriority.html b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/Constants/PINOperationQueuePriority.html new file mode 100644 index 00000000..810f085f --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/Constants/PINOperationQueuePriority.html @@ -0,0 +1,145 @@ + + + + + + + + + + + + +
+
+ +

+ PINOperationQueue +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +

PINOperationQueuePriority

+ +
+ + +

Definition

+ typedef NS_ENUM(NSUInteger, PINOperationQueuePriority ) {
+ +    PINOperationQueuePriorityLow,
+ +    PINOperationQueuePriorityDefault,
+ +    PINOperationQueuePriorityHigh,
+ + };
+ +
+ +
+

Constants

+
+ +
PINOperationQueuePriorityLow
+
+ + +

+ PINOperationQueue.h. +

+ +
+ +
PINOperationQueuePriorityDefault
+
+ + +

+ PINOperationQueue.h. +

+ +
+ +
PINOperationQueuePriorityHigh
+
+ + +

+ PINOperationQueue.h. +

+ +
+ +
+
+ + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/Protocols/PINOperationReference.html b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/Protocols/PINOperationReference.html new file mode 100644 index 00000000..b7481d79 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/Protocols/PINOperationReference.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINOperationQueue +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/_index.scss b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/_index.scss new file mode 100644 index 00000000..7e98029d --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/_index.scss @@ -0,0 +1,13 @@ +.index-container { + display: flex; + flex-direction: row; + flex-wrap: wrap; + + @media (max-width: $mobile-max-width) { + flex-direction: column; + } + + .index-column { + flex: 1 1 33%; + } +} diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/_layout.scss b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/_layout.scss new file mode 100644 index 00000000..40bd6d4a --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/_layout.scss @@ -0,0 +1,303 @@ +* { + box-sizing: border-box; +} + +.clear { + clear: both; +} + +.clearfix { + &:before, &:after { + clear: both; + display: table; + content: ""; + } +} + +.xcode .hide-in-xcode { + display: none; +} + +body { + font: 62.5% $body-font; + background: $body-background; +} + +h1, h2, h3 { + font-weight: 300; + color: #808080; +} + +h1 { + font-size: 2em; + color: #000; +} + +h4 { + font-size: 13px; + line-height: 1.5; + margin: 21px 0 0 0; +} + +a { + color: $tint-color; + text-decoration: none; +} + +pre, code { + font-family: $code-font; + word-wrap: break-word; +} + +pre > code, .method-declaration code { + display: inline-block; + font-size: .85em; + padding: 4px 0 4px 10px; + border-left: 5px solid rgba(0, 155, 51, .2); + + &:before { + content: "Objective-C"; + display: block; + + font: 9px/1 $body-font; + color: #009b33; + text-transform: uppercase; + letter-spacing: 2px; + padding-bottom: 6px; + } +} + +pre > code { + font-size: inherit; +} + +table, th, td { + border: 1px solid #e9e9e9; +} + +table { + width: 100%; +} + +th, td { + padding: 7px; + + > :first-child { + margin-top: 0; + } + + > :last-child { + margin-bottom: 0; + } +} + +.container { + @extend .clearfix; + + max-width: 980px; + padding: 0 10px; + margin: 0 auto; + + @media (max-width: $mobile-max-width) { + padding: 0; + } +} + +header { + position: fixed; + top: 0; + left: 0; + width: 100%; + z-index: 2; + + background: #414141; + color: #fff; + font-size: 1.1em; + line-height: 25px; + letter-spacing: .05em; + + #library-title { + float: left; + } + + #developer-home { + float: right; + } + + h1 { + font-size: inherit; + font-weight: inherit; + margin: 0; + } + + p { + margin: 0; + } + + h1, a { + color: inherit; + } + + @media (max-width: $mobile-max-width) { + position: absolute; + + .container { + padding: 0 10px; + } + } +} + +aside { + position: fixed; + top: 25px; + left: 0; + width: 100%; + height: 25px; + z-index: 2; + + font-size: 1.1em; + + @media (max-width: $mobile-max-width) { + position: absolute; + } + + #header-buttons { + background: rgba(255, 255, 255, .8); + margin: 0 1px; + padding: 0; + list-style: none; + text-align: right; + line-height: 32px; + + li { + display: inline-block; + cursor: pointer; + padding: 0 10px; + } + + label, select { + cursor: inherit; + } + + #on-this-page { + position: relative; + + .chevron { + display: inline-block; + width: 14px; + height: 4px; + position: relative; + + .chevy { + background: #878787; + height: 2px; + position: absolute; + width: 10px; + + &.chevron-left { + left: 0; + transform: rotateZ(45deg) scale(0.6); + } + + &.chevron-right { + right: 0; + transform: rotateZ(-45deg) scale(0.6); + } + } + } + + #jump-to { + opacity: 0; + font-size: 16px; + + position: absolute; + top: 5px; + left: 0; + width: 100%; + height: 100%; + } + } + } +} + +article { + margin-top: 25px; + + #content { + @extend .clearfix; + + background: $content-background; + border: 1px solid $content-border; + padding: 15px 25px 30px 25px; + + font-size: 1.4em; + line-height: 1.45; + + position: relative; + + @media (max-width: $mobile-max-width) { + padding: 15px 10px 20px 10px; + } + + .navigation-top { + position: absolute; + top: 15px; + right: 25px; + } + + .title { + margin: 21px 0 0 0; + padding: 15px 0; + } + + p { + color: #414141; + margin: 0 0 15px 0; + } + + th, td { + p:last-child { + margin-bottom: 0; + } + } + + main { + ul { + list-style: none; + margin-left: 24px; + margin-bottom: 12px; + padding: 0; + + li { + position: relative; + padding-left: 1.3em; + + &:before { + content: "\02022"; + + color: #414141; + font-size: 1.08em; + line-height: 1; + + position: absolute; + left: 0; + padding-top: 2px; + } + } + } + } + + footer { + @extend .clearfix; + + .footer-copyright { + margin: 70px 25px 10px 0; + } + + p { + font-size: .71em; + color: #a0a0a0; + } + } + } +} diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/_normalize.scss b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/_normalize.scss new file mode 100644 index 00000000..9b8848a5 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/_normalize.scss @@ -0,0 +1,581 @@ +/* ========================================================================== + Normalize.scss settings + ========================================================================== */ +/** + * Includes legacy browser support IE6/7 + * + * Set to false if you want to drop support for IE6 and IE7 + */ + +$legacy_browser_support: false !default; + +/* Base + ========================================================================== */ + +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + * 3. Corrects text resizing oddly in IE 6/7 when body `font-size` is set using + * `em` units. + */ + +html { + font-family: sans-serif; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ + @if $legacy_browser_support { + *font-size: 100%; /* 3 */ + } +} + +/** + * Remove default margin. + */ + +body { + margin: 0; +} + +/* HTML5 display definitions + ========================================================================== */ + +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} + +/** + * 1. Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ + +audio, +canvas, +progress, +video { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ + @if $legacy_browser_support { + *display: inline; + *zoom: 1; + } +} + +/** + * Prevents modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ + +[hidden], +template { + display: none; +} + +/* Links + ========================================================================== */ + +/** + * Remove the gray background color from active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ + +a { + &:active, &:hover { + outline: 0; + }; +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +@if $legacy_browser_support { + blockquote { + margin: 1em 40px; + } +} + +/** + * Address styling not present in Safari and Chrome. + */ + +dfn { + font-style: italic; +} + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +@if $legacy_browser_support { + h2 { + font-size: 1.5em; + margin: 0.83em 0; + } + + h3 { + font-size: 1.17em; + margin: 1em 0; + } + + h4 { + font-size: 1em; + margin: 1.33em 0; + } + + h5 { + font-size: 0.83em; + margin: 1.67em 0; + } + + h6 { + font-size: 0.67em; + margin: 2.33em 0; + } +} + +/** + * Addresses styling not present in IE 8/9. + */ + +mark { + background: #ff0; + color: #000; +} + +@if $legacy_browser_support { + + /** + * Addresses margins set differently in IE 6/7. + */ + + p, + pre { + *margin: 1em 0; + } + + /* + * Addresses CSS quotes not supported in IE 6/7. + */ + + q { + *quotes: none; + } + + /* + * Addresses `quotes` property not supported in Safari 4. + */ + + q:before, + q:after { + content: ''; + content: none; + } +} + +/** + * Address inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +@if $legacy_browser_support { + + /* ========================================================================== + Lists + ========================================================================== */ + + /* + * Addresses margins set differently in IE 6/7. + */ + + dl, + menu, + ol, + ul { + *margin: 1em 0; + } + + dd { + *margin: 0 0 0 40px; + } + + /* + * Addresses paddings set differently in IE 6/7. + */ + + menu, + ol, + ul { + *padding: 0 0 0 40px; + } + + /* + * Corrects list images handled incorrectly in IE 7. + */ + + nav ul, + nav ol { + *list-style: none; + *list-style-image: none; + } + +} + +/* Embedded content + ========================================================================== */ + +/** + * 1. Remove border when inside `a` element in IE 8/9/10. + * 2. Improves image quality when scaled in IE 7. + */ + +img { + border: 0; + @if $legacy_browser_support { + *-ms-interpolation-mode: bicubic; /* 2 */ + } +} + +/** + * Correct overflow not hidden in IE 9/10/11. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Grouping content + ========================================================================== */ + +/** + * Address margin not present in IE 8/9 and Safari. + */ + +figure { + margin: 1em 40px; +} + +/** + * Address differences between Firefox and other browsers. + */ + +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +/** + * Contain overflow in all browsers. + */ + +pre { + overflow: auto; +} + +/** + * Address odd `em`-unit font size rendering in all browsers. + * Correct font family set oddly in IE 6, Safari 4/5, and Chrome. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + @if $legacy_browser_support { + _font-family: 'courier new', monospace; + } + font-size: 1em; +} + +/* Forms + ========================================================================== */ + +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ + +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + * 4. Improves appearance and consistency in all browsers. + */ + +button, +input, +optgroup, +select, +textarea { + color: inherit; /* 1 */ + font: inherit; /* 2 */ + margin: 0; /* 3 */ + @if $legacy_browser_support { + vertical-align: baseline; /* 3 */ + *vertical-align: middle; /* 3 */ + } +} + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ + +button { + overflow: visible; +} + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ + +button, +select { + text-transform: none; +} + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + * 4. Removes inner spacing in IE 7 without affecting normal text inputs. + * Known issue: inner spacing remains in IE 6. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ + @if $legacy_browser_support { + *overflow: visible; /* 4 */ + } +} + +/** + * Re-set default cursor for disabled elements. + */ + +button[disabled], +html input[disabled] { + cursor: default; +} + +/** + * Remove inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +input { + line-height: normal; +} + +/** + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + * Known issue: excess padding remains in IE 6. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ + @if $legacy_browser_support { + *height: 13px; /* 3 */ + *width: 13px; /* 3 */ + } +} + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ + +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; /* 2 */ + box-sizing: content-box; +} + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + * 3. Corrects text not wrapping in Firefox 3. + * 4. Corrects alignment displayed oddly in IE 6/7. + */ + +legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ + @if $legacy_browser_support { + white-space: normal; /* 3 */ + *margin-left: -7px; /* 4 */ + } +} + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ + +textarea { + overflow: auto; +} + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ + +optgroup { + font-weight: bold; +} + +/* Tables + ========================================================================== */ + +/** + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} + +td, +th { + padding: 0; +} diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/_object.scss b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/_object.scss new file mode 100644 index 00000000..22eebd87 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/_object.scss @@ -0,0 +1,89 @@ +.section-specification { + table { + width: auto; + + th { + text-align: left; + } + } +} + +.method-title { + margin-left: -15px; + margin-bottom: 8px; + transition: margin-left .3s ease-out; + + .section-method.hide & { + margin-left: 0; + } + + code { + font-weight: 400; + font-size: .85em; + } +} + +.method-info { + background: $object-background; + border-bottom: 1px solid $object-border; + margin: 0 -25px; + padding: 20px 25px 0 25px; + transition: height .3s ease-out; + + position: relative; + + .pointy-thing { + background: $content-background; + height: 10px; + border-bottom: 1px solid $object-border; + margin: -20px -25px 16px -25px; + + &:before { + display: inline-block; + content: ""; + + background: $object-background; + border: 1px solid $object-border; + border-bottom: 0; + border-right: 0; + + position: absolute; + left: 21px; + top: 3px; + width: 12px; + height: 12px; + transform: rotate(45deg); + } + } + + .method-subsection { + margin-bottom: 15px; + + .argument-name { + width: 1px; + text-align: right; + + code { + color: #808080; + font-style: italic; + font-weight: 400; + } + } + } +} + +.section-method { + &.hide .method-info { + height: 0 !important; + overflow: hidden; + display: none; + } + + &.hide.animating .method-info { + display: block; + } + + &.animating .method-info { + overflow: hidden; + } +} diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/_print.scss b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/_print.scss new file mode 100644 index 00000000..61bdf99f --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/_print.scss @@ -0,0 +1,42 @@ +@media print { + body { + background: #fff; + padding: 8px; + } + + header { + position: static; + background: #fff; + color: #000; + } + + aside { + display: none; + } + + .container { + max-width: none; + padding: 0; + } + + article { + margin-top: 0; + + #content { + border: 0; + background: #fff; + padding: 15px 0 0 0; + + .title { + margin-top: 0; + padding-top: 0; + } + } + } + + .method-info { + &, & .pointy-thing { + background: #fff; + } + } +} diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/_variables.scss b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/_variables.scss new file mode 100644 index 00000000..cbaff3cf --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/_variables.scss @@ -0,0 +1,11 @@ +$body-font: -apple-system-font, "Helvetica Neue", Helvetica, sans-serif; +$code-font: "Source Code Pro", Monaco, Menlo, Consolas, monospace; + +$body-background: #f2f2f2; +$content-background: #fff; +$content-border: #e9e9e9; +$tint-color: #08c; +$object-background: #f9f9f9; +$object-border: #e9e9e9; + +$mobile-max-width: 650px; diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/_xcode.scss b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/_xcode.scss new file mode 100644 index 00000000..340b1f6b --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/_xcode.scss @@ -0,0 +1,29 @@ +.xcode { + header, aside { + display: none; + } + + .container { + padding: 0; + } + + article { + margin-top: 0; + + #content { + border: 0; + margin: 0; + } + } + + .method-info { + &, .section-method.hide & { + max-height: auto; + overflow: visible; + + &.hiding { + display: block; + } + } + } +} diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/style.scss b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/style.scss new file mode 100644 index 00000000..648a6086 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/css/scss/style.scss @@ -0,0 +1 @@ +@import "variables", "normalize", "layout", "index", "object", "print", "xcode"; diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/hierarchy.html b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/hierarchy.html new file mode 100644 index 00000000..9bd0aa1f --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/hierarchy.html @@ -0,0 +1,82 @@ + + + + + + + + + + + + +
+
+ +

+ PINOperationQueue +

+ +

+ Pinterest +

+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/img/button_bar_background.png b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/img/button_bar_background.png new file mode 100644 index 00000000..71d1019b Binary files /dev/null and b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/img/button_bar_background.png differ diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/img/disclosure.png b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/img/disclosure.png new file mode 100644 index 00000000..4c5cbf44 Binary files /dev/null and b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/img/disclosure.png differ diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/img/disclosure_open.png b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/img/disclosure_open.png new file mode 100644 index 00000000..82396fed Binary files /dev/null and b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/img/disclosure_open.png differ diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/img/library_background.png b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/img/library_background.png new file mode 100644 index 00000000..3006248a Binary files /dev/null and b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/img/library_background.png differ diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/img/title_background.png b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/img/title_background.png new file mode 100644 index 00000000..846e4968 Binary files /dev/null and b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/img/title_background.png differ diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/index.html b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/index.html new file mode 100644 index 00000000..fbc5d19d --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/index.html @@ -0,0 +1,90 @@ + + + + + + + + + + + + +
+
+ +

+ PINOperationQueue +

+ +

+ Pinterest +

+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/js/script.js b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/js/script.js new file mode 100644 index 00000000..ca915ee4 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/docs/html/js/script.js @@ -0,0 +1,58 @@ +function $() { + return document.querySelector.apply(document, arguments); +} + +if (navigator.userAgent.indexOf("Xcode") != -1) { + document.documentElement.classList.add("xcode"); +} + +var jumpTo = $("#jump-to"); + +if (jumpTo) { + jumpTo.addEventListener("change", function(e) { + location.hash = this.options[this.selectedIndex].value; + }); +} + +function hashChanged() { + if (/^#\/\/api\//.test(location.hash)) { + var element = document.querySelector("a[name='" + location.hash.substring(1) + "']"); + + if (!element) { + return; + } + + element = element.parentNode; + + element.classList.remove("hide"); + fixScrollPosition(element); + } +} + +function fixScrollPosition(element) { + var scrollTop = element.offsetTop - 150; + document.documentElement.scrollTop = scrollTop; + document.body.scrollTop = scrollTop; +} + +[].forEach.call(document.querySelectorAll(".section-method"), function(element) { + element.classList.add("hide"); + + element.querySelector(".method-title a").addEventListener("click", function(e) { + var info = element.querySelector(".method-info"), + infoContainer = element.querySelector(".method-info-container"); + + element.classList.add("animating"); + info.style.height = (infoContainer.clientHeight + 40) + "px"; + fixScrollPosition(element); + element.classList.toggle("hide"); + + setTimeout(function() { + element.classList.remove("animating"); + info.style.height = "auto"; + }, 300); + }); +}); + +window.addEventListener("hashchange", hashChanged); +hashChanged(); diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/makefile b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/makefile new file mode 100644 index 00000000..4e24e342 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/makefile @@ -0,0 +1,43 @@ +PLATFORM="platform=iOS Simulator,name=iPhone 15" +SDK="iphonesimulator" +SHELL=/bin/bash -o pipefail +XCODE_MAJOR_VERSION=$(shell xcodebuild -version | HEAD -n 1 | sed -E 's/Xcode ([0-9]+).*/\1/') + +.PHONY: all cocoapods test analyze carthage spm install_xcbeautify + +carthage: + carthage build --no-skip-current --use-xcframeworks + +cocoapods: + pod lib lint + +install_xcbeautify: + if ! command -v xcbeautify &> /dev/null; then brew install xcbeautify; fi + +analyze: install_xcbeautify + xcodebuild clean analyze -destination ${PLATFORM} -sdk ${SDK} -project PINOperation.xcodeproj -scheme PINOperation \ + ONLY_ACTIVE_ARCH=NO \ + CODE_SIGNING_REQUIRED=NO \ + CLANG_ANALYZER_OUTPUT=plist-html \ + CLANG_ANALYZER_OUTPUT_DIR="$(shell pwd)/clang" | xcbeautify + if [[ -n `find $(shell pwd)/clang -name "*.html"` ]] ; then rm -rf `pwd`/clang; exit 1; fi + rm -rf $(shell pwd)/clang + +test: install_xcbeautify + # TODO: Fix data races and enable thread sanitizer with '-enableThreadSanitizer YES' + xcodebuild clean test -destination ${PLATFORM} -sdk ${SDK} -project PINOperation.xcodeproj -scheme PINOperation \ + ONLY_ACTIVE_ARCH=NO \ + CODE_SIGNING_REQUIRED=NO | xcbeautify + +spm: + # TODO: Fix data races and enable thread sanitizer with '--sanitize thread' + swift test + +release-major: + +release-minor: + +release-patch: + + +all: carthage cocoapods test analyze spm diff --git a/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/run_tests_update_status.sh b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/run_tests_update_status.sh new file mode 100755 index 00000000..5d7e4bd6 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/run_tests_update_status.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +set -eo pipefail + +UPDATE_STATUS_PATH=$1 +BUILDKITE_PULL_REQUEST=$2 +BUILDKITE_BUILD_URL=$3 + +function updateStatus() { + if [ "${BUILDKITE_PULL_REQUEST}" != "false" ] ; then + ${UPDATE_STATUS_PATH} "pinterest" "PINOperation" ${BUILDKITE_PULL_REQUEST} "$1" ${BUILDKITE_BUILD_URL} "$2" "CI/Pinterest" + fi +} + +if [[ -z "${UPDATE_STATUS_PATH}" || -z "${BUILDKITE_PULL_REQUEST}" || -z "${BUILDKITE_BUILD_URL}" ]] ; then + echo "Update status path (${UPDATE_STATUS_PATH}), pull request (${BUILDKITE_BUILD_URL}) or build url (${BUILDKITE_PULL_REQUEST}) unset." + trap - EXIT + exit 255 +fi + +trapped="false" +function trap_handler() { + if [[ "$trapped" = "false" ]]; then + updateStatus failure "Tests failed…" + echo "Tests failed, updated status to failure" + fi + trapped="true" +} +trap trap_handler INT TERM EXIT + +updateStatus pending "Starting build…" + +make all + +updateStatus success "Tests passed" + +echo "All tests succeeded, updated status to success" +trap - EXIT +exit 0 \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration.xcodeproj/project.pbxproj b/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration.xcodeproj/project.pbxproj new file mode 100644 index 00000000..962314b7 --- /dev/null +++ b/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration.xcodeproj/project.pbxproj @@ -0,0 +1,358 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 60; + objects = { + +/* Begin PBXBuildFile section */ + E03DEAC225671BA900ACCAFC /* PINCache_SPM_IntegrationApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = E03DEAC125671BA900ACCAFC /* PINCache_SPM_IntegrationApp.swift */; }; + E03DEAC425671BA900ACCAFC /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E03DEAC325671BA900ACCAFC /* ContentView.swift */; }; + E03DEAC625671BAE00ACCAFC /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E03DEAC525671BAE00ACCAFC /* Assets.xcassets */; }; + E03DEAC925671BAE00ACCAFC /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E03DEAC825671BAE00ACCAFC /* Preview Assets.xcassets */; }; + E03DEB1B256BD0CB00ACCAFC /* PINCache in Frameworks */ = {isa = PBXBuildFile; productRef = E03DEB1A256BD0CB00ACCAFC /* PINCache */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + E03DEABE25671BA900ACCAFC /* PINCache-SPM-Integration.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "PINCache-SPM-Integration.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + E03DEAC125671BA900ACCAFC /* PINCache_SPM_IntegrationApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PINCache_SPM_IntegrationApp.swift; sourceTree = ""; }; + E03DEAC325671BA900ACCAFC /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + E03DEAC525671BAE00ACCAFC /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + E03DEAC825671BAE00ACCAFC /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + E03DEACA25671BAE00ACCAFC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + E03DEB18256BD05A00ACCAFC /* PINCache */ = {isa = PBXFileReference; lastKnownFileType = folder; name = PINCache; path = ../../..; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + E03DEABB25671BA900ACCAFC /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E03DEB1B256BD0CB00ACCAFC /* PINCache in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + E03DEAB525671BA900ACCAFC = { + isa = PBXGroup; + children = ( + E03DEAC025671BA900ACCAFC /* PINCache-SPM-Integration */, + E03DEABF25671BA900ACCAFC /* Products */, + E03DEAD325671F1100ACCAFC /* Frameworks */, + ); + sourceTree = ""; + }; + E03DEABF25671BA900ACCAFC /* Products */ = { + isa = PBXGroup; + children = ( + E03DEABE25671BA900ACCAFC /* PINCache-SPM-Integration.app */, + ); + name = Products; + sourceTree = ""; + }; + E03DEAC025671BA900ACCAFC /* PINCache-SPM-Integration */ = { + isa = PBXGroup; + children = ( + E03DEB18256BD05A00ACCAFC /* PINCache */, + E03DEAC125671BA900ACCAFC /* PINCache_SPM_IntegrationApp.swift */, + E03DEAC325671BA900ACCAFC /* ContentView.swift */, + E03DEAC525671BAE00ACCAFC /* Assets.xcassets */, + E03DEACA25671BAE00ACCAFC /* Info.plist */, + E03DEAC725671BAE00ACCAFC /* Preview Content */, + ); + path = "PINCache-SPM-Integration"; + sourceTree = ""; + }; + E03DEAC725671BAE00ACCAFC /* Preview Content */ = { + isa = PBXGroup; + children = ( + E03DEAC825671BAE00ACCAFC /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + E03DEAD325671F1100ACCAFC /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + E03DEABD25671BA900ACCAFC /* PINCache-SPM-Integration */ = { + isa = PBXNativeTarget; + buildConfigurationList = E03DEACD25671BAE00ACCAFC /* Build configuration list for PBXNativeTarget "PINCache-SPM-Integration" */; + buildPhases = ( + E03DEABA25671BA900ACCAFC /* Sources */, + E03DEABB25671BA900ACCAFC /* Frameworks */, + E03DEABC25671BA900ACCAFC /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "PINCache-SPM-Integration"; + packageProductDependencies = ( + E03DEB1A256BD0CB00ACCAFC /* PINCache */, + ); + productName = "PINCache-SPM-Integration"; + productReference = E03DEABE25671BA900ACCAFC /* PINCache-SPM-Integration.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + E03DEAB625671BA900ACCAFC /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 1210; + LastUpgradeCheck = 1520; + TargetAttributes = { + E03DEABD25671BA900ACCAFC = { + CreatedOnToolsVersion = 12.1; + }; + }; + }; + buildConfigurationList = E03DEAB925671BA900ACCAFC /* Build configuration list for PBXProject "PINCache-SPM-Integration" */; + compatibilityVersion = "Xcode 15.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = E03DEAB525671BA900ACCAFC; + packageReferences = ( + ); + productRefGroup = E03DEABF25671BA900ACCAFC /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + E03DEABD25671BA900ACCAFC /* PINCache-SPM-Integration */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + E03DEABC25671BA900ACCAFC /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E03DEAC925671BAE00ACCAFC /* Preview Assets.xcassets in Resources */, + E03DEAC625671BAE00ACCAFC /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + E03DEABA25671BA900ACCAFC /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E03DEAC425671BA900ACCAFC /* ContentView.swift in Sources */, + E03DEAC225671BA900ACCAFC /* PINCache_SPM_IntegrationApp.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + E03DEACB25671BAE00ACCAFC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.1; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + E03DEACC25671BAE00ACCAFC /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.1; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + E03DEACE25671BAE00ACCAFC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_ASSET_PATHS = "\"PINCache-SPM-Integration/Preview Content\""; + ENABLE_PREVIEWS = YES; + INFOPLIST_FILE = "PINCache-SPM-Integration/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "pintrest.PINCache-SPM-Integration"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + E03DEACF25671BAE00ACCAFC /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_ASSET_PATHS = "\"PINCache-SPM-Integration/Preview Content\""; + ENABLE_PREVIEWS = YES; + INFOPLIST_FILE = "PINCache-SPM-Integration/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "pintrest.PINCache-SPM-Integration"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + E03DEAB925671BA900ACCAFC /* Build configuration list for PBXProject "PINCache-SPM-Integration" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E03DEACB25671BAE00ACCAFC /* Debug */, + E03DEACC25671BAE00ACCAFC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E03DEACD25671BAE00ACCAFC /* Build configuration list for PBXNativeTarget "PINCache-SPM-Integration" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E03DEACE25671BAE00ACCAFC /* Debug */, + E03DEACF25671BAE00ACCAFC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCSwiftPackageProductDependency section */ + E03DEB1A256BD0CB00ACCAFC /* PINCache */ = { + isa = XCSwiftPackageProductDependency; + productName = PINCache; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = E03DEAB625671BA900ACCAFC /* Project object */; +} diff --git a/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration.xcodeproj/xcshareddata/xcschemes/PINCache-SPM-Integration.xcscheme b/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration.xcodeproj/xcshareddata/xcschemes/PINCache-SPM-Integration.xcscheme new file mode 100644 index 00000000..24ba2e3d --- /dev/null +++ b/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration.xcodeproj/xcshareddata/xcschemes/PINCache-SPM-Integration.xcscheme @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration/Assets.xcassets/AccentColor.colorset/Contents.json b/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration/Assets.xcassets/AppIcon.appiconset/Contents.json b/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..9221b9bb --- /dev/null +++ b/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration/Assets.xcassets/Contents.json b/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration/ContentView.swift b/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration/ContentView.swift new file mode 100644 index 00000000..0aca95cb --- /dev/null +++ b/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration/ContentView.swift @@ -0,0 +1,35 @@ +// +// ContentView.swift +// PINCache-SPM-Integration +// +// Created by Petro Rovenskyy on 19.11.2020. +// + +import SwiftUI +import PINCache + +struct ContentView: View { + let cacheKey: String + @State + private var cachedValue: String = "loading..." + var body: some View { + Text(cachedValue) + .onAppear(perform: loadValue) + .padding() + } + private func loadValue() { + PINCache.shared.object(forKeyAsync: self.cacheKey, completion: { (_, _, object) in + if let object: String = object as? String { + self.cachedValue = object + return + } + self.cachedValue = "Failed to load value from cache" + }) + } +} + +struct ContentView_Previews: PreviewProvider { + static var previews: some View { + ContentView(cacheKey: AppDelegate.cacheKey) + } +} diff --git a/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration/Info.plist b/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration/Info.plist new file mode 100644 index 00000000..efc211a0 --- /dev/null +++ b/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration/Info.plist @@ -0,0 +1,50 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + + UIApplicationSupportsIndirectInputEvents + + UILaunchScreen + + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration/PINCache_SPM_IntegrationApp.swift b/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration/PINCache_SPM_IntegrationApp.swift new file mode 100644 index 00000000..577a53ab --- /dev/null +++ b/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration/PINCache_SPM_IntegrationApp.swift @@ -0,0 +1,29 @@ +// +// PINCache_SPM_IntegrationApp.swift +// PINCache-SPM-Integration +// +// Created by Petro Rovenskyy on 19.11.2020. +// + +import SwiftUI +import PINCache + +final class AppDelegate: UIResponder, UIApplicationDelegate { + static let cacheKey: String = "pinCache" + func application(_ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { + PINCache.shared.setObject("Hello! I'm cached string", + forKey: Self.cacheKey) + return true + } +} + +@main +struct PINCache_SPM_IntegrationApp: App { + @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate + var body: some Scene { + WindowGroup { + ContentView(cacheKey: AppDelegate.cacheKey) + } + } +} diff --git a/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration/Preview Content/Preview Assets.xcassets/Contents.json b/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/Carthage/Checkouts/PINCache/IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Example-Mac/Pods/PINCache/LICENSE.txt b/Carthage/Checkouts/PINCache/LICENSE.txt similarity index 100% rename from Example-Mac/Pods/PINCache/LICENSE.txt rename to Carthage/Checkouts/PINCache/LICENSE.txt diff --git a/Carthage/Checkouts/PINCache/Makefile b/Carthage/Checkouts/PINCache/Makefile new file mode 100644 index 00000000..9caccffc --- /dev/null +++ b/Carthage/Checkouts/PINCache/Makefile @@ -0,0 +1,46 @@ +PLATFORM="platform=iOS Simulator,name=iPhone 15" +SDK="iphonesimulator" +SHELL=/bin/bash -o pipefail +XCODE_MAJOR_VERSION=$(shell xcodebuild -version | HEAD -n 1 | sed -E 's/Xcode ([0-9]+).*/\1/') +IOS_EXAMPLE_PROJECT="IntegrationTests/PINCache-SPM-Integration/PINCache-SPM-Integration.xcodeproj" +EXAMPLE_SCHEME="PINCache-SPM-Integration" + +.PHONY: all cocoapods test carthage analyze spm example + +cocoapods: + pod lib lint + +analyze: + # TODO: Fix data races and enable thread sanitizer with '-enableThreadSanitizer YES' + xcodebuild clean analyze -destination ${PLATFORM} -sdk ${SDK} -workspace PINCache.xcworkspace -scheme PINCache \ + ONLY_ACTIVE_ARCH=NO \ + CODE_SIGNING_REQUIRED=NO \ + CLANG_ANALYZER_OUTPUT=plist-html \ + CLANG_ANALYZER_OUTPUT_DIR="$(shell pwd)/clang" | xcpretty + if [[ -n `find $(shell pwd)/clang -name "*.html"` ]] ; then rm -rf `pwd`/clang; exit 1; fi + rm -rf $(shell pwd)/clang + +test: + xcodebuild clean test -destination ${PLATFORM} -sdk ${SDK} -workspace PINCache.xcworkspace -scheme PINCache \ + ONLY_ACTIVE_ARCH=NO \ + CODE_SIGNING_REQUIRED=NO | xcpretty + +carthage: + carthage update --no-use-binaries --no-build + carthage build --no-skip-current --use-xcframeworks + +spm: + # TODO: Fix data races and enable thread sanitizer with '--sanitize thread' + swift test + + +example: + if [ ${XCODE_MAJOR_VERSION} -lt 15 ] ; then \ + echo "Xcode 15 and Swift 5.9 required to build example project"; \ + exit 1; \ + fi + xcodebuild clean build -project ${IOS_EXAMPLE_PROJECT} -scheme ${EXAMPLE_SCHEME} -destination ${PLATFORM} -sdk ${SDK} \ + ONLY_ACTIVE_ARCH=NO \ + CODE_SIGNING_REQUIRED=NO | xcpretty + +all: carthage cocoapods test analyze spm example diff --git a/Carthage/Checkouts/PINCache/PINCache.podspec b/Carthage/Checkouts/PINCache/PINCache.podspec new file mode 100644 index 00000000..cb6879ac --- /dev/null +++ b/Carthage/Checkouts/PINCache/PINCache.podspec @@ -0,0 +1,35 @@ +Pod::Spec.new do |s| + s.name = 'PINCache' + s.version = '3.0.4' + s.homepage = 'https://github.com/pinterest/PINCache' + s.summary = 'Fast, thread safe, parallel object cache for iOS and OS X.' + s.authors = { 'Garrett Moon' => 'garrett@pinterest.com', 'Justin Ouellette' => 'jstn@tumblr.com' } + s.source = { :git => 'https://github.com/pinterest/PINCache.git', :tag => "#{s.version}" } + s.license = { :type => 'Apache 2.0', :file => 'LICENSE.txt' } + s.requires_arc = true + s.frameworks = 'Foundation' + s.ios.weak_frameworks = 'UIKit' + s.osx.weak_frameworks = 'AppKit' + s.cocoapods_version = '>= 1.13.0' + s.ios.deployment_target = '12.0' + s.osx.deployment_target = '10.13' + s.tvos.deployment_target = '12.0' + s.visionos.deployment_target = '1.0' + s.watchos.deployment_target = '4.0' + pch_PIN = <<-EOS +#ifndef TARGET_OS_WATCH + #define TARGET_OS_WATCH 0 +#endif +EOS + s.prefix_header_contents = pch_PIN + s.subspec 'Core' do |sp| + sp.source_files = 'Source/*.{h,m}' + sp.dependency 'PINOperation', '~> 1.2.3' + end + s.subspec 'Arc-exception-safe' do |sp| + sp.dependency 'PINCache/Core' + sp.source_files = 'Source/PINDiskCache.m' + sp.compiler_flags = '-fobjc-arc-exceptions' + end + s.resource_bundles = { 'PINCache' => ['Source/PrivacyInfo.xcprivacy'] } +end diff --git a/Carthage/Checkouts/PINCache/PINCache.xcodeproj/project.pbxproj b/Carthage/Checkouts/PINCache/PINCache.xcodeproj/project.pbxproj new file mode 100644 index 00000000..aa7386c1 --- /dev/null +++ b/Carthage/Checkouts/PINCache/PINCache.xcodeproj/project.pbxproj @@ -0,0 +1,1597 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 60; + objects = { + +/* Begin PBXBuildFile section */ + 320117C524444E3C004FD783 /* PINCaching.h in Headers */ = {isa = PBXBuildFile; fileRef = 6928EED21E4160EE00B5D975 /* PINCaching.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 320117C624444E3D004FD783 /* PINCache.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0106051E271A9000890935 /* PINCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 320117C724444E3D004FD783 /* PINCache.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0106061E271A9000890935 /* PINCache.m */; }; + 320117C824444E3D004FD783 /* PINCacheObjectSubscripting.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0106071E271A9000890935 /* PINCacheObjectSubscripting.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 320117C924444E3D004FD783 /* PINDiskCache.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0106081E271A9000890935 /* PINDiskCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 320117CA24444E3D004FD783 /* PINDiskCache.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0106091E271A9000890935 /* PINDiskCache.m */; }; + 320117CB24444E3D004FD783 /* PINMemoryCache.h in Headers */ = {isa = PBXBuildFile; fileRef = CC01060A1E271A9000890935 /* PINMemoryCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 320117CC24444E3D004FD783 /* PINMemoryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01060B1E271A9000890935 /* PINMemoryCache.m */; }; + 320117CD24444E3D004FD783 /* PINCacheMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 68A0FBFF1E4D3282000B552D /* PINCacheMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 68133AE32BE01D15007627EC /* PINDiskCache+PINCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C38F01A920A32E0200F47F0E /* PINDiskCache+PINCacheTests.m */; }; + 68133AE42BE01D16007627EC /* PINDiskCache+PINCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C38F01A920A32E0200F47F0E /* PINDiskCache+PINCacheTests.m */; }; + 68133AE52BE020DA007627EC /* PINDiskCache+PINCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C38F01A920A32E0200F47F0E /* PINDiskCache+PINCacheTests.m */; }; + 68133AE72BE02E98007627EC /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 68133AE62BE02E97007627EC /* PrivacyInfo.xcprivacy */; }; + 68133AE82BE02E98007627EC /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 68133AE62BE02E97007627EC /* PrivacyInfo.xcprivacy */; }; + 68133AE92BE02E98007627EC /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 68133AE62BE02E97007627EC /* PrivacyInfo.xcprivacy */; }; + 68133AEA2BE02E98007627EC /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 68133AE62BE02E97007627EC /* PrivacyInfo.xcprivacy */; }; + 6818C1491E55020400875DB7 /* PINCache.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC0105CE1E271A4900890935 /* PINCache.framework */; }; + 683188D82BE56C5C00031329 /* PINCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01060D1E271A9000890935 /* PINCacheTests.m */; }; + 683188D92BE56C5C00031329 /* PINDiskCache+PINCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C38F01A920A32E0200F47F0E /* PINDiskCache+PINCacheTests.m */; }; + 683188DA2BE56C5C00031329 /* NSDate+PINCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C30EE1EA203717DE00D78CB9 /* NSDate+PINCacheTests.m */; }; + 683188DF2BE56C5C00031329 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = CC0106CA1E28248800890935 /* Default-568h@2x.png */; }; + 683188E52BE56CFE00031329 /* PINCache.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 320117A124444DF7004FD783 /* PINCache.framework */; }; + 683188EB2BE56D1000031329 /* PINOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 683188EA2BE56D1000031329 /* PINOperation.framework */; }; + 683188EE2BE56D2200031329 /* PINCache.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 68F2102B2BE55BDE00CFE762 /* PINCache.framework */; }; + 683188F42BE56D2900031329 /* PINOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 683188F32BE56D2900031329 /* PINOperation.framework */; }; + 683188F82BE56D4700031329 /* PINOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 683188F72BE56D4700031329 /* PINOperation.framework */; }; + 687BB0AA1E52706B005D70C6 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = CC0106CA1E28248800890935 /* Default-568h@2x.png */; }; + 68A0FC001E4D32C4000B552D /* PINCacheMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 68A0FBFF1E4D3282000B552D /* PINCacheMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 68A0FC011E4D32C6000B552D /* PINCacheMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 68A0FBFF1E4D3282000B552D /* PINCacheMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 68A0FC021E4D32C7000B552D /* PINCacheMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 68A0FBFF1E4D3282000B552D /* PINCacheMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 68CEDBA32BE17B580045CBE7 /* PINOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 68CEDBA22BE17B580045CBE7 /* PINOperation.framework */; }; + 68CEDBA72BE17B750045CBE7 /* PINOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 68CEDBA62BE17B750045CBE7 /* PINOperation.framework */; }; + 68CEDBAA2BE17B8F0045CBE7 /* PINOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 68CEDBA92BE17B8F0045CBE7 /* PINOperation.framework */; }; + 68CEDBAE2BE17BB30045CBE7 /* PINOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 68CEDBAD2BE17BB30045CBE7 /* PINOperation.framework */; }; + 68CEDBB12BE17BC70045CBE7 /* PINOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 68CEDBB02BE17BC70045CBE7 /* PINOperation.framework */; }; + 68CEDBB52BE17BD50045CBE7 /* PINOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 68CEDBB42BE17BD50045CBE7 /* PINOperation.framework */; }; + 68CEDBB82BE17BE40045CBE7 /* PINOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 68CEDBB72BE17BE40045CBE7 /* PINOperation.framework */; }; + 68F2101A2BE55BDE00CFE762 /* PINCache.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0106061E271A9000890935 /* PINCache.m */; }; + 68F2101B2BE55BDE00CFE762 /* PINMemoryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01060B1E271A9000890935 /* PINMemoryCache.m */; }; + 68F2101C2BE55BDE00CFE762 /* PINDiskCache.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0106091E271A9000890935 /* PINDiskCache.m */; }; + 68F210202BE55BDE00CFE762 /* PINMemoryCache.h in Headers */ = {isa = PBXBuildFile; fileRef = CC01060A1E271A9000890935 /* PINMemoryCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 68F210212BE55BDE00CFE762 /* PINCache.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0106051E271A9000890935 /* PINCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 68F210222BE55BDE00CFE762 /* PINCacheObjectSubscripting.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0106071E271A9000890935 /* PINCacheObjectSubscripting.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 68F210232BE55BDE00CFE762 /* PINCacheMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 68A0FBFF1E4D3282000B552D /* PINCacheMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 68F210242BE55BDE00CFE762 /* PINDiskCache.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0106081E271A9000890935 /* PINDiskCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 68F210252BE55BDE00CFE762 /* PINCaching.h in Headers */ = {isa = PBXBuildFile; fileRef = 6928EED21E4160EE00B5D975 /* PINCaching.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 68F210272BE55BDE00CFE762 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 68133AE62BE02E97007627EC /* PrivacyInfo.xcprivacy */; }; + 68F210312BE55C6C00CFE762 /* PINCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01060D1E271A9000890935 /* PINCacheTests.m */; }; + 68F210322BE55C6C00CFE762 /* PINDiskCache+PINCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C38F01A920A32E0200F47F0E /* PINDiskCache+PINCacheTests.m */; }; + 68F210332BE55C6C00CFE762 /* NSDate+PINCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C30EE1EA203717DE00D78CB9 /* NSDate+PINCacheTests.m */; }; + 68F210382BE55C6C00CFE762 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = CC0106CA1E28248800890935 /* Default-568h@2x.png */; }; + 6928EED31E4160EE00B5D975 /* PINCaching.h in Headers */ = {isa = PBXBuildFile; fileRef = 6928EED21E4160EE00B5D975 /* PINCaching.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6928EED41E4160FE00B5D975 /* PINCaching.h in Headers */ = {isa = PBXBuildFile; fileRef = 6928EED21E4160EE00B5D975 /* PINCaching.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6928EED51E41610700B5D975 /* PINCaching.h in Headers */ = {isa = PBXBuildFile; fileRef = 6928EED21E4160EE00B5D975 /* PINCaching.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C30EE1F520373D1900D78CB9 /* NSDate+PINCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C30EE1EA203717DE00D78CB9 /* NSDate+PINCacheTests.m */; }; + C30EE1F620373D1A00D78CB9 /* NSDate+PINCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C30EE1EA203717DE00D78CB9 /* NSDate+PINCacheTests.m */; }; + C30EE1F720373D1B00D78CB9 /* NSDate+PINCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C30EE1EA203717DE00D78CB9 /* NSDate+PINCacheTests.m */; }; + CC0105DF1E271A5C00890935 /* PINCache.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC0105B11E271A1600890935 /* PINCache.framework */; }; + CC0105EE1E271A6400890935 /* PINCache.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC0105C11E271A4000890935 /* PINCache.framework */; }; + CC01060E1E271A9500890935 /* PINCache.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0106061E271A9000890935 /* PINCache.m */; }; + CC01060F1E271A9500890935 /* PINDiskCache.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0106091E271A9000890935 /* PINDiskCache.m */; }; + CC0106101E271A9500890935 /* PINMemoryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01060B1E271A9000890935 /* PINMemoryCache.m */; }; + CC0106111E271A9600890935 /* PINCache.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0106061E271A9000890935 /* PINCache.m */; }; + CC0106121E271A9600890935 /* PINDiskCache.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0106091E271A9000890935 /* PINDiskCache.m */; }; + CC0106131E271A9600890935 /* PINMemoryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01060B1E271A9000890935 /* PINMemoryCache.m */; }; + CC0106141E271A9700890935 /* PINCache.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0106061E271A9000890935 /* PINCache.m */; }; + CC0106151E271A9700890935 /* PINDiskCache.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0106091E271A9000890935 /* PINDiskCache.m */; }; + CC0106161E271A9700890935 /* PINMemoryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01060B1E271A9000890935 /* PINMemoryCache.m */; }; + CC0106171E271AAF00890935 /* PINCache.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0106051E271A9000890935 /* PINCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0106181E271AAF00890935 /* PINCacheObjectSubscripting.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0106071E271A9000890935 /* PINCacheObjectSubscripting.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0106191E271AAF00890935 /* PINDiskCache.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0106081E271A9000890935 /* PINDiskCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC01061A1E271AAF00890935 /* PINMemoryCache.h in Headers */ = {isa = PBXBuildFile; fileRef = CC01060A1E271A9000890935 /* PINMemoryCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC01061B1E271AB000890935 /* PINCache.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0106051E271A9000890935 /* PINCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC01061C1E271AB000890935 /* PINCacheObjectSubscripting.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0106071E271A9000890935 /* PINCacheObjectSubscripting.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC01061D1E271AB000890935 /* PINDiskCache.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0106081E271A9000890935 /* PINDiskCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC01061E1E271AB000890935 /* PINMemoryCache.h in Headers */ = {isa = PBXBuildFile; fileRef = CC01060A1E271A9000890935 /* PINMemoryCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC01061F1E271AB000890935 /* PINCache.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0106051E271A9000890935 /* PINCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0106201E271AB000890935 /* PINCacheObjectSubscripting.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0106071E271A9000890935 /* PINCacheObjectSubscripting.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0106211E271AB000890935 /* PINDiskCache.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0106081E271A9000890935 /* PINDiskCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0106221E271AB000890935 /* PINMemoryCache.h in Headers */ = {isa = PBXBuildFile; fileRef = CC01060A1E271A9000890935 /* PINMemoryCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0106C61E28226900890935 /* PINCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01060D1E271A9000890935 /* PINCacheTests.m */; }; + CC0106C71E28226A00890935 /* PINCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01060D1E271A9000890935 /* PINCacheTests.m */; }; + CC0106C81E28226A00890935 /* PINCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01060D1E271A9000890935 /* PINCacheTests.m */; }; + CC0106CD1E28249C00890935 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = CC0106CA1E28248800890935 /* Default-568h@2x.png */; }; + CC0106CE1E28249D00890935 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = CC0106CA1E28248800890935 /* Default-568h@2x.png */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 683188E72BE56CFE00031329 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = CC0105A81E271A1600890935 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 320117A024444DF7004FD783; + remoteInfo = "PINCache-watchOS"; + }; + 683188F02BE56D2200031329 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = CC0105A81E271A1600890935 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 68F210182BE55BDE00CFE762; + remoteInfo = "PINCache-visionOS"; + }; + CC0105E01E271A5C00890935 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = CC0105A81E271A1600890935 /* Project object */; + proxyType = 1; + remoteGlobalIDString = CC0105B01E271A1600890935; + remoteInfo = PINCache; + }; + CC0105EF1E271A6400890935 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = CC0105A81E271A1600890935 /* Project object */; + proxyType = 1; + remoteGlobalIDString = CC0105C01E271A4000890935; + remoteInfo = "PINCache-tvOS"; + }; + CC0105FE1E271A7300890935 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = CC0105A81E271A1600890935 /* Project object */; + proxyType = 1; + remoteGlobalIDString = CC0105CD1E271A4900890935; + remoteInfo = "PINCache-macOS"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 320117A124444DF7004FD783 /* PINCache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PINCache.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 68133AE62BE02E97007627EC /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 683188E32BE56C5C00031329 /* PINCache-watchOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "PINCache-watchOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 683188EA2BE56D1000031329 /* PINOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PINOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 683188F32BE56D2900031329 /* PINOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PINOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 683188F72BE56D4700031329 /* PINOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PINOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 68A0FBFF1E4D3282000B552D /* PINCacheMacros.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PINCacheMacros.h; sourceTree = ""; }; + 68CEDBA22BE17B580045CBE7 /* PINOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PINOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 68CEDBA62BE17B750045CBE7 /* PINOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PINOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 68CEDBA92BE17B8F0045CBE7 /* PINOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PINOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 68CEDBAD2BE17BB30045CBE7 /* PINOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PINOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 68CEDBB02BE17BC70045CBE7 /* PINOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PINOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 68CEDBB42BE17BD50045CBE7 /* PINOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PINOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 68CEDBB72BE17BE40045CBE7 /* PINOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PINOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 68F2102B2BE55BDE00CFE762 /* PINCache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PINCache.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 68F2103C2BE55C6C00CFE762 /* PINCache-visionOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "PINCache-visionOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6928EED21E4160EE00B5D975 /* PINCaching.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINCaching.h; sourceTree = ""; }; + C30EE1E9203717DE00D78CB9 /* NSDate+PINCacheTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSDate+PINCacheTests.h"; sourceTree = ""; }; + C30EE1EA203717DE00D78CB9 /* NSDate+PINCacheTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSDate+PINCacheTests.m"; sourceTree = ""; }; + C38F01A820A32E0200F47F0E /* PINDiskCache+PINCacheTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PINDiskCache+PINCacheTests.h"; sourceTree = ""; }; + C38F01A920A32E0200F47F0E /* PINDiskCache+PINCacheTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "PINDiskCache+PINCacheTests.m"; sourceTree = ""; }; + CC0105B11E271A1600890935 /* PINCache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PINCache.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + CC0105C11E271A4000890935 /* PINCache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PINCache.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + CC0105CE1E271A4900890935 /* PINCache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PINCache.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + CC0105DA1E271A5C00890935 /* PINCacheTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PINCacheTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + CC0105E91E271A6400890935 /* PINCache-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "PINCache-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + CC0105F81E271A7300890935 /* PINCache-macOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "PINCache-macOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + CC0106051E271A9000890935 /* PINCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PINCache.h; sourceTree = ""; }; + CC0106061E271A9000890935 /* PINCache.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PINCache.m; sourceTree = ""; }; + CC0106071E271A9000890935 /* PINCacheObjectSubscripting.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PINCacheObjectSubscripting.h; sourceTree = ""; }; + CC0106081E271A9000890935 /* PINDiskCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PINDiskCache.h; sourceTree = ""; }; + CC0106091E271A9000890935 /* PINDiskCache.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PINDiskCache.m; sourceTree = ""; }; + CC01060A1E271A9000890935 /* PINMemoryCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PINMemoryCache.h; sourceTree = ""; }; + CC01060B1E271A9000890935 /* PINMemoryCache.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PINMemoryCache.m; sourceTree = ""; }; + CC01060D1E271A9000890935 /* PINCacheTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PINCacheTests.m; sourceTree = ""; }; + CC0106441E281B0E00890935 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + CC0106C51E281D6900890935 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + CC0106C91E28228300890935 /* PINCacheTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PINCacheTests.h; sourceTree = ""; }; + CC0106CA1E28248800890935 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 3201179E24444DF7004FD783 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 68CEDBB82BE17BE40045CBE7 /* PINOperation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 683188DB2BE56C5C00031329 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 683188EB2BE56D1000031329 /* PINOperation.framework in Frameworks */, + 683188E52BE56CFE00031329 /* PINCache.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 68F2101D2BE55BDE00CFE762 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 683188F82BE56D4700031329 /* PINOperation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 68F210342BE55C6C00CFE762 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 683188F42BE56D2900031329 /* PINOperation.framework in Frameworks */, + 683188EE2BE56D2200031329 /* PINCache.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105AD1E271A1600890935 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 68CEDBA32BE17B580045CBE7 /* PINOperation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105BD1E271A4000890935 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 68CEDBAA2BE17B8F0045CBE7 /* PINOperation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105CA1E271A4900890935 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 68CEDBB12BE17BC70045CBE7 /* PINOperation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105D71E271A5C00890935 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 68CEDBA72BE17B750045CBE7 /* PINOperation.framework in Frameworks */, + CC0105DF1E271A5C00890935 /* PINCache.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105E61E271A6400890935 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 68CEDBAE2BE17BB30045CBE7 /* PINOperation.framework in Frameworks */, + CC0105EE1E271A6400890935 /* PINCache.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105F51E271A7300890935 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 68CEDBB52BE17BD50045CBE7 /* PINOperation.framework in Frameworks */, + 6818C1491E55020400875DB7 /* PINCache.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 6818C2861E55217D00875DB7 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 683188EA2BE56D1000031329 /* PINOperation.framework */, + 68CEDBB72BE17BE40045CBE7 /* PINOperation.framework */, + 683188F72BE56D4700031329 /* PINOperation.framework */, + 683188F32BE56D2900031329 /* PINOperation.framework */, + 68CEDBB42BE17BD50045CBE7 /* PINOperation.framework */, + 68CEDBB02BE17BC70045CBE7 /* PINOperation.framework */, + 68CEDBAD2BE17BB30045CBE7 /* PINOperation.framework */, + 68CEDBA92BE17B8F0045CBE7 /* PINOperation.framework */, + 68CEDBA62BE17B750045CBE7 /* PINOperation.framework */, + 68CEDBA22BE17B580045CBE7 /* PINOperation.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + CC0105A71E271A1600890935 = { + isa = PBXGroup; + children = ( + CC0106031E271A9000890935 /* Source */, + CC01060C1E271A9000890935 /* Tests */, + CC0105B21E271A1600890935 /* Products */, + 6818C2861E55217D00875DB7 /* Frameworks */, + ); + sourceTree = ""; + }; + CC0105B21E271A1600890935 /* Products */ = { + isa = PBXGroup; + children = ( + CC0105B11E271A1600890935 /* PINCache.framework */, + CC0105C11E271A4000890935 /* PINCache.framework */, + CC0105CE1E271A4900890935 /* PINCache.framework */, + CC0105DA1E271A5C00890935 /* PINCacheTests.xctest */, + CC0105E91E271A6400890935 /* PINCache-tvOSTests.xctest */, + CC0105F81E271A7300890935 /* PINCache-macOSTests.xctest */, + 320117A124444DF7004FD783 /* PINCache.framework */, + 68F2102B2BE55BDE00CFE762 /* PINCache.framework */, + 68F2103C2BE55C6C00CFE762 /* PINCache-visionOSTests.xctest */, + 683188E32BE56C5C00031329 /* PINCache-watchOSTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + CC0106031E271A9000890935 /* Source */ = { + isa = PBXGroup; + children = ( + CC0106441E281B0E00890935 /* Info.plist */, + 68133AE62BE02E97007627EC /* PrivacyInfo.xcprivacy */, + 6928EED21E4160EE00B5D975 /* PINCaching.h */, + CC0106051E271A9000890935 /* PINCache.h */, + CC0106061E271A9000890935 /* PINCache.m */, + CC0106071E271A9000890935 /* PINCacheObjectSubscripting.h */, + CC0106081E271A9000890935 /* PINDiskCache.h */, + CC0106091E271A9000890935 /* PINDiskCache.m */, + CC01060A1E271A9000890935 /* PINMemoryCache.h */, + CC01060B1E271A9000890935 /* PINMemoryCache.m */, + 68A0FBFF1E4D3282000B552D /* PINCacheMacros.h */, + ); + path = Source; + sourceTree = ""; + }; + CC01060C1E271A9000890935 /* Tests */ = { + isa = PBXGroup; + children = ( + CC0106CB1E28248A00890935 /* Assets */, + CC0106C51E281D6900890935 /* Info.plist */, + C30EE1E9203717DE00D78CB9 /* NSDate+PINCacheTests.h */, + C30EE1EA203717DE00D78CB9 /* NSDate+PINCacheTests.m */, + CC0106C91E28228300890935 /* PINCacheTests.h */, + CC01060D1E271A9000890935 /* PINCacheTests.m */, + C38F01A820A32E0200F47F0E /* PINDiskCache+PINCacheTests.h */, + C38F01A920A32E0200F47F0E /* PINDiskCache+PINCacheTests.m */, + ); + path = Tests; + sourceTree = ""; + }; + CC0106CB1E28248A00890935 /* Assets */ = { + isa = PBXGroup; + children = ( + CC0106CA1E28248800890935 /* Default-568h@2x.png */, + ); + name = Assets; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 3201179C24444DF7004FD783 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 320117CB24444E3D004FD783 /* PINMemoryCache.h in Headers */, + 320117C624444E3D004FD783 /* PINCache.h in Headers */, + 320117C824444E3D004FD783 /* PINCacheObjectSubscripting.h in Headers */, + 320117CD24444E3D004FD783 /* PINCacheMacros.h in Headers */, + 320117C924444E3D004FD783 /* PINDiskCache.h in Headers */, + 320117C524444E3C004FD783 /* PINCaching.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 68F2101F2BE55BDE00CFE762 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 68F210202BE55BDE00CFE762 /* PINMemoryCache.h in Headers */, + 68F210212BE55BDE00CFE762 /* PINCache.h in Headers */, + 68F210222BE55BDE00CFE762 /* PINCacheObjectSubscripting.h in Headers */, + 68F210232BE55BDE00CFE762 /* PINCacheMacros.h in Headers */, + 68F210242BE55BDE00CFE762 /* PINDiskCache.h in Headers */, + 68F210252BE55BDE00CFE762 /* PINCaching.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105AE1E271A1600890935 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 6928EED31E4160EE00B5D975 /* PINCaching.h in Headers */, + CC0106171E271AAF00890935 /* PINCache.h in Headers */, + 68A0FC001E4D32C4000B552D /* PINCacheMacros.h in Headers */, + CC0106181E271AAF00890935 /* PINCacheObjectSubscripting.h in Headers */, + CC01061A1E271AAF00890935 /* PINMemoryCache.h in Headers */, + CC0106191E271AAF00890935 /* PINDiskCache.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105BE1E271A4000890935 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 6928EED41E4160FE00B5D975 /* PINCaching.h in Headers */, + CC01061B1E271AB000890935 /* PINCache.h in Headers */, + 68A0FC011E4D32C6000B552D /* PINCacheMacros.h in Headers */, + CC01061C1E271AB000890935 /* PINCacheObjectSubscripting.h in Headers */, + CC01061E1E271AB000890935 /* PINMemoryCache.h in Headers */, + CC01061D1E271AB000890935 /* PINDiskCache.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105CB1E271A4900890935 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 6928EED51E41610700B5D975 /* PINCaching.h in Headers */, + CC01061F1E271AB000890935 /* PINCache.h in Headers */, + 68A0FC021E4D32C7000B552D /* PINCacheMacros.h in Headers */, + CC0106201E271AB000890935 /* PINCacheObjectSubscripting.h in Headers */, + CC0106221E271AB000890935 /* PINMemoryCache.h in Headers */, + CC0106211E271AB000890935 /* PINDiskCache.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 320117A024444DF7004FD783 /* PINCache-watchOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 320117AE24444DF7004FD783 /* Build configuration list for PBXNativeTarget "PINCache-watchOS" */; + buildPhases = ( + 3201179D24444DF7004FD783 /* Sources */, + 3201179E24444DF7004FD783 /* Frameworks */, + 3201179C24444DF7004FD783 /* Headers */, + 3201179F24444DF7004FD783 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "PINCache-watchOS"; + productName = "PINCache-watchOS"; + productReference = 320117A124444DF7004FD783 /* PINCache.framework */; + productType = "com.apple.product-type.framework"; + }; + 683188D42BE56C5C00031329 /* PINCache-watchOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 683188E02BE56C5C00031329 /* Build configuration list for PBXNativeTarget "PINCache-watchOSTests" */; + buildPhases = ( + 683188D72BE56C5C00031329 /* Sources */, + 683188DB2BE56C5C00031329 /* Frameworks */, + 683188DE2BE56C5C00031329 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 683188E82BE56CFE00031329 /* PBXTargetDependency */, + ); + name = "PINCache-watchOSTests"; + productName = "PINCache-tvOSTests"; + productReference = 683188E32BE56C5C00031329 /* PINCache-watchOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 68F210182BE55BDE00CFE762 /* PINCache-visionOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 68F210282BE55BDE00CFE762 /* Build configuration list for PBXNativeTarget "PINCache-visionOS" */; + buildPhases = ( + 68F210192BE55BDE00CFE762 /* Sources */, + 68F2101D2BE55BDE00CFE762 /* Frameworks */, + 68F2101F2BE55BDE00CFE762 /* Headers */, + 68F210262BE55BDE00CFE762 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "PINCache-visionOS"; + productName = "PINCache-watchOS"; + productReference = 68F2102B2BE55BDE00CFE762 /* PINCache.framework */; + productType = "com.apple.product-type.framework"; + }; + 68F2102D2BE55C6C00CFE762 /* PINCache-visionOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 68F210392BE55C6C00CFE762 /* Build configuration list for PBXNativeTarget "PINCache-visionOSTests" */; + buildPhases = ( + 68F210302BE55C6C00CFE762 /* Sources */, + 68F210342BE55C6C00CFE762 /* Frameworks */, + 68F210372BE55C6C00CFE762 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 683188F12BE56D2200031329 /* PBXTargetDependency */, + ); + name = "PINCache-visionOSTests"; + productName = "PINCache-tvOSTests"; + productReference = 68F2103C2BE55C6C00CFE762 /* PINCache-visionOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + CC0105B01E271A1600890935 /* PINCache */ = { + isa = PBXNativeTarget; + buildConfigurationList = CC0105B91E271A1600890935 /* Build configuration list for PBXNativeTarget "PINCache" */; + buildPhases = ( + CC0105AC1E271A1600890935 /* Sources */, + CC0105AD1E271A1600890935 /* Frameworks */, + CC0105AE1E271A1600890935 /* Headers */, + CC0105AF1E271A1600890935 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PINCache; + productName = PINCache; + productReference = CC0105B11E271A1600890935 /* PINCache.framework */; + productType = "com.apple.product-type.framework"; + }; + CC0105C01E271A4000890935 /* PINCache-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = CC0105C61E271A4000890935 /* Build configuration list for PBXNativeTarget "PINCache-tvOS" */; + buildPhases = ( + CC0105BC1E271A4000890935 /* Sources */, + CC0105BD1E271A4000890935 /* Frameworks */, + CC0105BE1E271A4000890935 /* Headers */, + CC0105BF1E271A4000890935 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "PINCache-tvOS"; + productName = "PINCache-tvOS"; + productReference = CC0105C11E271A4000890935 /* PINCache.framework */; + productType = "com.apple.product-type.framework"; + }; + CC0105CD1E271A4900890935 /* PINCache-macOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = CC0105D31E271A4900890935 /* Build configuration list for PBXNativeTarget "PINCache-macOS" */; + buildPhases = ( + CC0105C91E271A4900890935 /* Sources */, + CC0105CA1E271A4900890935 /* Frameworks */, + CC0105CB1E271A4900890935 /* Headers */, + CC0105CC1E271A4900890935 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "PINCache-macOS"; + productName = "PINCache-macOS"; + productReference = CC0105CE1E271A4900890935 /* PINCache.framework */; + productType = "com.apple.product-type.framework"; + }; + CC0105D91E271A5C00890935 /* PINCacheTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = CC0105E21E271A5C00890935 /* Build configuration list for PBXNativeTarget "PINCacheTests" */; + buildPhases = ( + CC0105D61E271A5C00890935 /* Sources */, + CC0105D71E271A5C00890935 /* Frameworks */, + CC0105D81E271A5C00890935 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + CC0105E11E271A5C00890935 /* PBXTargetDependency */, + ); + name = PINCacheTests; + productName = PINCacheTests; + productReference = CC0105DA1E271A5C00890935 /* PINCacheTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + CC0105E81E271A6400890935 /* PINCache-tvOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = CC0105F11E271A6400890935 /* Build configuration list for PBXNativeTarget "PINCache-tvOSTests" */; + buildPhases = ( + CC0105E51E271A6400890935 /* Sources */, + CC0105E61E271A6400890935 /* Frameworks */, + CC0105E71E271A6400890935 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + CC0105F01E271A6400890935 /* PBXTargetDependency */, + ); + name = "PINCache-tvOSTests"; + productName = "PINCache-tvOSTests"; + productReference = CC0105E91E271A6400890935 /* PINCache-tvOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + CC0105F71E271A7300890935 /* PINCache-macOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = CC0106001E271A7300890935 /* Build configuration list for PBXNativeTarget "PINCache-macOSTests" */; + buildPhases = ( + CC0105F41E271A7300890935 /* Sources */, + CC0105F51E271A7300890935 /* Frameworks */, + CC0105F61E271A7300890935 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + CC0105FF1E271A7300890935 /* PBXTargetDependency */, + ); + name = "PINCache-macOSTests"; + productName = "PINCache-macOSTests"; + productReference = CC0105F81E271A7300890935 /* PINCache-macOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + CC0105A81E271A1600890935 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1520; + ORGANIZATIONNAME = Pinterest; + TargetAttributes = { + 320117A024444DF7004FD783 = { + CreatedOnToolsVersion = 11.4; + ProvisioningStyle = Automatic; + }; + CC0105B01E271A1600890935 = { + CreatedOnToolsVersion = 7.3.1; + }; + CC0105C01E271A4000890935 = { + CreatedOnToolsVersion = 7.3.1; + }; + CC0105CD1E271A4900890935 = { + CreatedOnToolsVersion = 7.3.1; + }; + CC0105D91E271A5C00890935 = { + CreatedOnToolsVersion = 7.3.1; + }; + CC0105E81E271A6400890935 = { + CreatedOnToolsVersion = 7.3.1; + }; + CC0105F71E271A7300890935 = { + CreatedOnToolsVersion = 7.3.1; + }; + }; + }; + buildConfigurationList = CC0105AB1E271A1600890935 /* Build configuration list for PBXProject "PINCache" */; + compatibilityVersion = "Xcode 15.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = CC0105A71E271A1600890935; + productRefGroup = CC0105B21E271A1600890935 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + CC0105B01E271A1600890935 /* PINCache */, + CC0105D91E271A5C00890935 /* PINCacheTests */, + CC0105C01E271A4000890935 /* PINCache-tvOS */, + CC0105E81E271A6400890935 /* PINCache-tvOSTests */, + CC0105CD1E271A4900890935 /* PINCache-macOS */, + CC0105F71E271A7300890935 /* PINCache-macOSTests */, + 68F210182BE55BDE00CFE762 /* PINCache-visionOS */, + 68F2102D2BE55C6C00CFE762 /* PINCache-visionOSTests */, + 320117A024444DF7004FD783 /* PINCache-watchOS */, + 683188D42BE56C5C00031329 /* PINCache-watchOSTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 3201179F24444DF7004FD783 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 68133AEA2BE02E98007627EC /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 683188DE2BE56C5C00031329 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 683188DF2BE56C5C00031329 /* Default-568h@2x.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 68F210262BE55BDE00CFE762 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 68F210272BE55BDE00CFE762 /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 68F210372BE55C6C00CFE762 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 68F210382BE55C6C00CFE762 /* Default-568h@2x.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105AF1E271A1600890935 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 68133AE72BE02E98007627EC /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105BF1E271A4000890935 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 68133AE82BE02E98007627EC /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105CC1E271A4900890935 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 68133AE92BE02E98007627EC /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105D81E271A5C00890935 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 687BB0AA1E52706B005D70C6 /* Default-568h@2x.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105E71E271A6400890935 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CC0106CD1E28249C00890935 /* Default-568h@2x.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105F61E271A7300890935 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CC0106CE1E28249D00890935 /* Default-568h@2x.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 3201179D24444DF7004FD783 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 320117C724444E3D004FD783 /* PINCache.m in Sources */, + 320117CC24444E3D004FD783 /* PINMemoryCache.m in Sources */, + 320117CA24444E3D004FD783 /* PINDiskCache.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 683188D72BE56C5C00031329 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 683188D82BE56C5C00031329 /* PINCacheTests.m in Sources */, + 683188D92BE56C5C00031329 /* PINDiskCache+PINCacheTests.m in Sources */, + 683188DA2BE56C5C00031329 /* NSDate+PINCacheTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 68F210192BE55BDE00CFE762 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 68F2101A2BE55BDE00CFE762 /* PINCache.m in Sources */, + 68F2101B2BE55BDE00CFE762 /* PINMemoryCache.m in Sources */, + 68F2101C2BE55BDE00CFE762 /* PINDiskCache.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 68F210302BE55C6C00CFE762 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 68F210312BE55C6C00CFE762 /* PINCacheTests.m in Sources */, + 68F210322BE55C6C00CFE762 /* PINDiskCache+PINCacheTests.m in Sources */, + 68F210332BE55C6C00CFE762 /* NSDate+PINCacheTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105AC1E271A1600890935 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CC01060E1E271A9500890935 /* PINCache.m in Sources */, + CC0106101E271A9500890935 /* PINMemoryCache.m in Sources */, + CC01060F1E271A9500890935 /* PINDiskCache.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105BC1E271A4000890935 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CC0106111E271A9600890935 /* PINCache.m in Sources */, + CC0106131E271A9600890935 /* PINMemoryCache.m in Sources */, + CC0106121E271A9600890935 /* PINDiskCache.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105C91E271A4900890935 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CC0106141E271A9700890935 /* PINCache.m in Sources */, + CC0106161E271A9700890935 /* PINMemoryCache.m in Sources */, + CC0106151E271A9700890935 /* PINDiskCache.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105D61E271A5C00890935 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CC0106C61E28226900890935 /* PINCacheTests.m in Sources */, + 68133AE52BE020DA007627EC /* PINDiskCache+PINCacheTests.m in Sources */, + C30EE1F520373D1900D78CB9 /* NSDate+PINCacheTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105E51E271A6400890935 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CC0106C71E28226A00890935 /* PINCacheTests.m in Sources */, + 68133AE32BE01D15007627EC /* PINDiskCache+PINCacheTests.m in Sources */, + C30EE1F620373D1A00D78CB9 /* NSDate+PINCacheTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105F41E271A7300890935 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CC0106C81E28226A00890935 /* PINCacheTests.m in Sources */, + 68133AE42BE01D16007627EC /* PINDiskCache+PINCacheTests.m in Sources */, + C30EE1F720373D1B00D78CB9 /* NSDate+PINCacheTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 683188E82BE56CFE00031329 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 320117A024444DF7004FD783 /* PINCache-watchOS */; + targetProxy = 683188E72BE56CFE00031329 /* PBXContainerItemProxy */; + }; + 683188F12BE56D2200031329 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 68F210182BE55BDE00CFE762 /* PINCache-visionOS */; + targetProxy = 683188F02BE56D2200031329 /* PBXContainerItemProxy */; + }; + CC0105E11E271A5C00890935 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = CC0105B01E271A1600890935 /* PINCache */; + targetProxy = CC0105E01E271A5C00890935 /* PBXContainerItemProxy */; + }; + CC0105F01E271A6400890935 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = CC0105C01E271A4000890935 /* PINCache-tvOS */; + targetProxy = CC0105EF1E271A6400890935 /* PBXContainerItemProxy */; + }; + CC0105FF1E271A7300890935 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = CC0105CD1E271A4900890935 /* PINCache-macOS */; + targetProxy = CC0105FE1E271A7300890935 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 320117A624444DF7004FD783 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/watchOS"; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINCache; + PRODUCT_NAME = PINCache; + SDKROOT = watchos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 4; + }; + name = Debug; + }; + 320117A724444DF7004FD783 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/watchOS"; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINCache; + PRODUCT_NAME = PINCache; + SDKROOT = watchos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 4; + }; + name = Release; + }; + 683188E12BE56C5C00031329 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.pinterest.PINCache-watchOSTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + TARGETED_DEVICE_FAMILY = 4; + }; + name = Debug; + }; + 683188E22BE56C5C00031329 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.pinterest.PINCache-watchOSTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + TARGETED_DEVICE_FAMILY = 4; + }; + name = Release; + }; + 68F210292BE55BDE00CFE762 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/visionOS"; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINCache; + PRODUCT_NAME = PINCache; + SDKROOT = xros; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 7; + }; + name = Debug; + }; + 68F2102A2BE55BDE00CFE762 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/visionOS"; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINCache; + PRODUCT_NAME = PINCache; + SDKROOT = xros; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 7; + }; + name = Release; + }; + 68F2103A2BE55C6C00CFE762 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.pinterest.PINCache-visionOSTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = xros; + TARGETED_DEVICE_FAMILY = 7; + }; + name = Debug; + }; + 68F2103B2BE55C6C00CFE762 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.pinterest.PINCache-visionOSTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = xros; + TARGETED_DEVICE_FAMILY = 7; + }; + name = Release; + }; + CC0105B71E271A1600890935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 12.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 4.0; + XROS_DEPLOYMENT_TARGET = 1.0; + }; + name = Debug; + }; + CC0105B81E271A1600890935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 4.0; + XROS_DEPLOYMENT_TARGET = 1.0; + }; + name = Release; + }; + CC0105BA1E271A1600890935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINCache; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = YES; + }; + name = Debug; + }; + CC0105BB1E271A1600890935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINCache; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = YES; + }; + name = Release; + }; + CC0105C71E271A4000890935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/tvOS", + ); + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINCache; + PRODUCT_NAME = PINCache; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + CC0105C81E271A4000890935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/tvOS", + ); + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINCache; + PRODUCT_NAME = PINCache; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + CC0105D41E271A4900890935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/Mac", + ); + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINCache; + PRODUCT_NAME = PINCache; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + CC0105D51E271A4900890935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/Mac", + ); + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINCache; + PRODUCT_NAME = PINCache; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Release; + }; + CC0105E31E271A5C00890935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINCacheTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + CC0105E41E271A5C00890935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINCacheTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + CC0105F21E271A6400890935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.pinterest.PINCache-tvOSTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + CC0105F31E271A6400890935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.pinterest.PINCache-tvOSTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + CC0106011E271A7300890935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.pinterest.PINCache-macOSTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + CC0106021E271A7300890935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.pinterest.PINCache-macOSTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 320117AE24444DF7004FD783 /* Build configuration list for PBXNativeTarget "PINCache-watchOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 320117A624444DF7004FD783 /* Debug */, + 320117A724444DF7004FD783 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 683188E02BE56C5C00031329 /* Build configuration list for PBXNativeTarget "PINCache-watchOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 683188E12BE56C5C00031329 /* Debug */, + 683188E22BE56C5C00031329 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 68F210282BE55BDE00CFE762 /* Build configuration list for PBXNativeTarget "PINCache-visionOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 68F210292BE55BDE00CFE762 /* Debug */, + 68F2102A2BE55BDE00CFE762 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 68F210392BE55C6C00CFE762 /* Build configuration list for PBXNativeTarget "PINCache-visionOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 68F2103A2BE55C6C00CFE762 /* Debug */, + 68F2103B2BE55C6C00CFE762 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CC0105AB1E271A1600890935 /* Build configuration list for PBXProject "PINCache" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CC0105B71E271A1600890935 /* Debug */, + CC0105B81E271A1600890935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CC0105B91E271A1600890935 /* Build configuration list for PBXNativeTarget "PINCache" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CC0105BA1E271A1600890935 /* Debug */, + CC0105BB1E271A1600890935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CC0105C61E271A4000890935 /* Build configuration list for PBXNativeTarget "PINCache-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CC0105C71E271A4000890935 /* Debug */, + CC0105C81E271A4000890935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CC0105D31E271A4900890935 /* Build configuration list for PBXNativeTarget "PINCache-macOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CC0105D41E271A4900890935 /* Debug */, + CC0105D51E271A4900890935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CC0105E21E271A5C00890935 /* Build configuration list for PBXNativeTarget "PINCacheTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CC0105E31E271A5C00890935 /* Debug */, + CC0105E41E271A5C00890935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CC0105F11E271A6400890935 /* Build configuration list for PBXNativeTarget "PINCache-tvOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CC0105F21E271A6400890935 /* Debug */, + CC0105F31E271A6400890935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CC0106001E271A7300890935 /* Build configuration list for PBXNativeTarget "PINCache-macOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CC0106011E271A7300890935 /* Debug */, + CC0106021E271A7300890935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = CC0105A81E271A1600890935 /* Project object */; +} diff --git a/Carthage/Checkouts/PINCache/PINCache.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/PINCache/PINCache.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/Carthage/Checkouts/PINCache/PINCache.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Carthage/Checkouts/PINCache/PINCache.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Carthage/Checkouts/PINCache/PINCache.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Carthage/Checkouts/PINCache/PINCache.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Carthage/Checkouts/PINCache/PINCache.xcodeproj/xcshareddata/xcschemes/PINCache-macOS.xcscheme b/Carthage/Checkouts/PINCache/PINCache.xcodeproj/xcshareddata/xcschemes/PINCache-macOS.xcscheme new file mode 100644 index 00000000..ee6943bd --- /dev/null +++ b/Carthage/Checkouts/PINCache/PINCache.xcodeproj/xcshareddata/xcschemes/PINCache-macOS.xcscheme @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINCache/PINCache.xcodeproj/xcshareddata/xcschemes/PINCache-tvOS.xcscheme b/Carthage/Checkouts/PINCache/PINCache.xcodeproj/xcshareddata/xcschemes/PINCache-tvOS.xcscheme new file mode 100644 index 00000000..bdf96603 --- /dev/null +++ b/Carthage/Checkouts/PINCache/PINCache.xcodeproj/xcshareddata/xcschemes/PINCache-tvOS.xcscheme @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINCache/PINCache.xcodeproj/xcshareddata/xcschemes/PINCache-visionOS.xcscheme b/Carthage/Checkouts/PINCache/PINCache.xcodeproj/xcshareddata/xcschemes/PINCache-visionOS.xcscheme new file mode 100644 index 00000000..421f7ec6 --- /dev/null +++ b/Carthage/Checkouts/PINCache/PINCache.xcodeproj/xcshareddata/xcschemes/PINCache-visionOS.xcscheme @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINCache/PINCache.xcodeproj/xcshareddata/xcschemes/PINCache-watchOS.xcscheme b/Carthage/Checkouts/PINCache/PINCache.xcodeproj/xcshareddata/xcschemes/PINCache-watchOS.xcscheme new file mode 100644 index 00000000..f65c1629 --- /dev/null +++ b/Carthage/Checkouts/PINCache/PINCache.xcodeproj/xcshareddata/xcschemes/PINCache-watchOS.xcscheme @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINCache/PINCache.xcodeproj/xcshareddata/xcschemes/PINCache.xcscheme b/Carthage/Checkouts/PINCache/PINCache.xcodeproj/xcshareddata/xcschemes/PINCache.xcscheme new file mode 100644 index 00000000..a1e90ee9 --- /dev/null +++ b/Carthage/Checkouts/PINCache/PINCache.xcodeproj/xcshareddata/xcschemes/PINCache.xcscheme @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINCache/PINCache.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/PINCache/PINCache.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..4e95af76 --- /dev/null +++ b/Carthage/Checkouts/PINCache/PINCache.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Carthage/Checkouts/PINCache/PINCache.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Carthage/Checkouts/PINCache/PINCache.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Carthage/Checkouts/PINCache/PINCache.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Carthage/Checkouts/PINCache/Package.swift b/Carthage/Checkouts/PINCache/Package.swift new file mode 100644 index 00000000..811bbdd0 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Package.swift @@ -0,0 +1,54 @@ +// swift-tools-version:5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "PINCache", + platforms: [ + .iOS(.v12), + .macOS(.v10_13), + .tvOS(.v12), + .visionOS(.v1), + .watchOS(.v4), + ], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "PINCache", + targets: ["PINCache"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + .package( + url: "https://github.com/pinterest/PINOperation.git", + from: "1.2.3"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "PINCache", + dependencies: ["PINOperation"], + path: "Source", + exclude: ["Info.plist"], + resources: [.process("PrivacyInfo.xcprivacy")], + // Path to public header symlinks (allows for angle bracket imports) + publicHeadersPath: "include", + cSettings: [ + .headerSearchPath("."), + .define("NS_BLOCK_ASSERTIONS", to: "1", .when(configuration: .release)), + ]), + .testTarget( + name: "PINCacheTests", + dependencies: ["PINCache"], + path: "Tests", + exclude: ["Info.plist"], + resources: [.process("Default-568h@2x.png")], + cSettings: [ + .define("TEST_AS_SPM"), + .define("NS_BLOCK_ASSERTIONS", to: "1", .when(configuration: .release)), + ]), + ] +) diff --git a/Carthage/Checkouts/PINCache/README.md b/Carthage/Checkouts/PINCache/README.md new file mode 100644 index 00000000..e8ca01d4 --- /dev/null +++ b/Carthage/Checkouts/PINCache/README.md @@ -0,0 +1,98 @@ +# PINCache + +[![CocoaPods](https://img.shields.io/cocoapods/v/PINCache.svg)](http://cocoadocs.org/docsets/PINCache/) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![Build status](https://github.com/pinterest/PINCache/workflows/CI/badge.svg)](https://github.com/pinterest/PINCache/actions?query=workflow%3ACI+branch%3Amaster) + +## Fast, non-deadlocking parallel object cache for iOS and OS X. + +[PINCache](Source/PINCache.h) is a fork of [TMCache](https://github.com/tumblr/TMCache) re-architected to fix issues with deadlocking caused by heavy use. It is a key/value store designed for persisting temporary objects that are expensive to reproduce, such as downloaded data or the results of slow processing. It is comprised of two self-similar stores, one in memory ([PINMemoryCache](Source/PINMemoryCache.h)) and one on disk ([PINDiskCache](Source/PINDiskCache.h)), all backed by GCD and safe to access from multiple threads simultaneously. On iOS, `PINMemoryCache` will clear itself when the app receives a memory warning or goes into the background. Objects stored in `PINDiskCache` remain until you trim the cache yourself, either manually or by setting a byte or age limit. + +`PINCache` and `PINDiskCache` accept any object conforming to [NSCoding](https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Protocols/NSCoding_Protocol/Reference/Reference.html). Put things in like this: + +**Objective-C** +```objective-c +UIImage *img = [[UIImage alloc] initWithData:data scale:[[UIScreen mainScreen] scale]]; +[[PINCache sharedCache] setObject:img forKey:@"image" block:nil]; // returns immediately +``` +**Swift** +```swift +let img = UIImage(data: data, scale:UIScreen.main.scale) +PINCache.shared().setObject(img, forKey: "img") +``` + +Get them back out like this: + +**Objective-C** +```objc +[[PINCache sharedCache] objectForKeyAsync:@"image" block:^(PINCache *cache, NSString *key, id object) { + UIImage *image = (UIImage *)object; + NSLog(@"image scale: %f", image.scale); +}]; +``` +**Swift** +```swift +PINCache.shared().object(forKey: "image") { (cache, key, object) in + if let image = object as? UIImage { + print("image scale: %f", image.scale) + } +} +``` + +Both `PINMemoryCache` and `PINDiskCache` use locks to protect reads and writes. `PINCache` coordinates them so that objects added to memory are available immediately to other threads while being written to disk safely in the background. Both caches are public properties of `PINCache`, so it's easy to manipulate one or the other separately if necessary. + +Collections work too. Thanks to the magic of `NSKeyedArchiver`, objects repeated in a collection only occupy the space of one on disk: + +**Objective-C** +```objective-c +NSArray *images = @[ image, image, image ]; +[[PINCache sharedCache] setObject:images forKey:@"images"]; +NSLog(@"3 for the price of 1: %d", [[[PINCache sharedCache] diskCache] byteCount]); +``` +**Swift** +```swift +// In Swift, Array, String, and Dictionary are all value types. +let images = [image, image, image] as NSArray // Cast to NSArray +PINCache.shared.setObject(images, forKey: "images") +print("3 for the prices of 1: %d", PINCache.shared.diskCache.byteCount) +``` + +## Installation + +### Manually + +[Download the latest tag](https://github.com/pinterest/PINCache/tags) and drag the `PINCache` folder into your Xcode project. + +Install the docs by double clicking the `.docset` file under `docs/`, or view them online at [cocoadocs.org](http://cocoadocs.org/docsets/PINCache/) + +### Git Submodule + + git submodule add https://github.com/pinterest/PINCache.git + git submodule update --init + +### CocoaPods + +Add [PINCache](http://cocoapods.org/?q=name%3APINCache) to your `Podfile` and run `pod install`. + +### Carthage + +Add the following line to your `Cartfile` and run `carthage update --platform ios`. Then follow [this instruction of Carthage](https://github.com/carthage/carthage#adding-frameworks-to-unit-tests-or-a-framework) to embed the framework. + +```github "pinterest/PINCache"``` + +## Requirements + +__PINCache__ requires iOS 12.0, tvOS 12.0, watchOS 4.0 or macOS 10.13 and greater. + +## Contact + +[Garrett Moon](mailto:garrett@pinterest.com) + +## License + +Copyright 2013 Tumblr, Inc. +Copyright 2015 Pinterest, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. [See the License](LICENSE.txt) for the specific language governing permissions and limitations under the License. diff --git a/Carthage/Checkouts/PINCache/RELEASE.md b/Carthage/Checkouts/PINCache/RELEASE.md new file mode 100644 index 00000000..6e86b11c --- /dev/null +++ b/Carthage/Checkouts/PINCache/RELEASE.md @@ -0,0 +1,13 @@ +# Release Process +This document describes the process for a public PINCache release. + +### Preparation +- Install [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator): `sudo gem install github_changelog_generator` +- Generate a GitHub Personal Access Token to prevent running into public GitHub API rate limits: https://github.com/github-changelog-generator/github-changelog-generator#github-token + +### Process +- Run `github_changelog_generator` in PINCache project directory: `github_changelog_generator --token --user Pinterest --project PINCache`. To avoid hitting rate limit, the generator will replace the entire file with just the changes from this version – revert that giant deletion to get the entire new changelog. +- Update `spec.version` within `PINCache.podspec` and the `since-tag` and `future-release` fields in `.github_changelog_generator`. +- Create a new PR with the updated `PINCache.podspec` and the newly generated changelog, add `#changelog` to the PR message so the CI will not prevent merging it. +- After merging in the PR, [create a new GitHub release](https://github.com/Pinterest/PINCache/releases/new). Use the generated changelog for the new release. +- Push to Cocoapods with `pod trunk push` diff --git a/Carthage/Checkouts/PINCache/Scripts/release.sh b/Carthage/Checkouts/PINCache/Scripts/release.sh new file mode 100755 index 00000000..fd094a6b --- /dev/null +++ b/Carthage/Checkouts/PINCache/Scripts/release.sh @@ -0,0 +1,98 @@ +#!/bin/bash +set -e + +if [ -z "$OSS_PROJECT" ]; then + echo "Must set \$OSS_PROJECT envirnonment variable before running." +fi + +PROJECT="$OSS_PROJECT" + +if ! git diff-index --quiet HEAD --; then + echo "Please commit or stash any changes before running." + exit 1 +fi + +if [ -z "$GITHUB_CHANGELOG_API_KEY" ]; then + echo "Must set \$GITHUB_CHANGELOG_API_KEY environment variable" + exit 1 +fi + +case $1 in + "--major") + UPDATE_TYPE="major" + ;; + + "--minor") + UPDATE_TYPE="minor" + ;; + + "--patch") + UPDATE_TYPE="patch" + ;; + + *) + echo "Usage release.sh --patch / --minor / --major" + exit 1 + ;; +esac + +PODSPEC="$PROJECT.podspec" +CURRENT_VERSION=`grep "version" -m 1 $PODSPEC | sed -E "s/^.*version[ \t]*=[ \t]*'([0-9\.]+)'/\1/"` +DOT_COUNT=`echo "$CURRENT_VERSION" | grep -o '\.' | wc -l` + +if [ "$DOT_COUNT" -eq "0" ]; then + major=$CURRENT_VERSION + minor="0" + patch="0" +elif [ "$DOT_COUNT" -eq "1" ]; then + major=`echo "$CURRENT_VERSION" | sed -E "s/([0-9])+\.([0-9]+)/\1/"` + minor=`echo "$CURRENT_VERSION" | sed -E "s/([0-9])+\.([0-9]+)/\2/"` + patch="0" +elif [ "$DOT_COUNT" -eq "2" ]; then + major=`echo "$CURRENT_VERSION" | sed -E "s/([0-9])+\.([0-9]+)\.([0-9]+)/\1/"` + minor=`echo "$CURRENT_VERSION" | sed -E "s/([0-9])+\.([0-9]+)\.([0-9]+)/\2/"` + patch=`echo "$CURRENT_VERSION" | sed -E "s/([0-9])+\.([0-9]+)\.([0-9]+)/\3/"` +fi + +echo "Current version: $major.$minor.$patch" + +if [ "$UPDATE_TYPE" == "major" ]; then + major=$((major + 1)) + minor=0 + patch=0 +elif [ "$UPDATE_TYPE" == "minor" ]; then + minor=$((minor + 1)) + patch=0 +elif [ "$UPDATE_TYPE" == "patch" ]; then + patch=$((patch + 1)) +fi + +NEW_VERSION="$major.$minor.$patch" +echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV +echo "New version: $NEW_VERSION" + +echo "Updating $PODSPEC" +sed -E "s/^(.*version[ \t]*=[ \t]*)'$CURRENT_VERSION'/\1'$NEW_VERSION'/" $PODSPEC > new.podspec +mv new.podspec $PODSPEC + +echo "Updating .github_changelog_generator" +cat << EOF > .github_changelog_generator +issues=false +since-tag=$CURRENT_VERSION +future-release=$NEW_VERSION +EOF + +github_changelog_generator --token $GITHUB_CHANGELOG_API_KEY --user Pinterest --project $PROJECT --output NEW_CHANGES.md + +# Delete # Changelog at the top of the old CHANGELOG +grep -v "# Changelog" CHANGELOG.md > CHANGELOG.tmp && mv CHANGELOG.tmp CHANGELOG.md + +# Delete the last line and first line then use a magic sed command the internet told me +# about to delete trailing newlines (except the last one) +# Then prepend to existing changelog +grep -v "\*" NEW_CHANGES.md | sed -e :a -e '/^\n*$/{$d;N;};/\n$/ba' | cat - CHANGELOG.md > CHANGELOG.tmp +mv CHANGELOG.tmp CHANGELOG.md +rm NEW_CHANGES.md + +git add .github_changelog_generator CHANGELOG.md $PODSPEC +git commit --message "[AUTO] Update CHANGELOG.md and bump for $UPDATE_TYPE update." diff --git a/Carthage/Checkouts/PINCache/Scripts/tag-release-branch.sh b/Carthage/Checkouts/PINCache/Scripts/tag-release-branch.sh new file mode 100755 index 00000000..a66af230 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Scripts/tag-release-branch.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -ex + +echo "Tagging release branch" +TAG=$NEW_VERSION + +echo "RELEASE_TAG=$TAG" >> $GITHUB_ENV +git tag $TAG +git push origin --tags + +echo "Setting Release Notes" +cat CHANGELOG.md | awk '/^#/{f=1} f; /^#/ && ++c==3{exit}' | sed '$ d' > RELEASE_NOTES.md diff --git a/Carthage/Checkouts/PINCache/Source/Info.plist b/Carthage/Checkouts/PINCache/Source/Info.plist new file mode 100644 index 00000000..faedaa13 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Source/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2017 Pinterest. All rights reserved. + NSPrincipalClass + + + diff --git a/Carthage/Checkouts/PINCache/Source/PINCache.h b/Carthage/Checkouts/PINCache/Source/PINCache.h new file mode 100644 index 00000000..80782eca --- /dev/null +++ b/Carthage/Checkouts/PINCache/Source/PINCache.h @@ -0,0 +1,195 @@ +// PINCache is a modified version of TMCache +// Modifications by Garrett Moon +// Copyright (c) 2015 Pinterest. All rights reserved. + +#import + +#import +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@class PINCache; + + +/** + `PINCache` is a thread safe key/value store designed for persisting temporary objects that are expensive to + reproduce, such as downloaded data or the results of slow processing. It is comprised of two self-similar + stores, one in memory () and one on disk (). + + `PINCache` itself actually does very little; its main function is providing a front end for a common use case: + a small, fast memory cache that asynchronously persists itself to a large, slow disk cache. When objects are + removed from the memory cache in response to an "apocalyptic" event they remain in the disk cache and are + repopulated in memory the next time they are accessed. `PINCache` also does the tedious work of creating a + dispatch group to wait for both caches to finish their operations without blocking each other. + + The parallel caches are accessible as public properties ( and ) and can be manipulated + separately if necessary. See the docs for and for more details. + + @warning when using in extension or watch extension, define PIN_APP_EXTENSIONS=1 + */ + +PIN_SUBCLASSING_RESTRICTED +@interface PINCache : NSObject + +#pragma mark - +/// @name Core + +/** + Synchronously retrieves the total byte count of the on the shared disk queue. + */ +@property (readonly) NSUInteger diskByteCount; + +/** + Sets/gets the maximum number of concurrent operations when handling async requests. + */ +@property (nonatomic) NSUInteger maxConcurrentOperations; + +/** + The underlying disk cache, see for additional configuration and trimming options. + */ +@property (readonly) PINDiskCache *diskCache; + +/** + The underlying memory cache, see for additional configuration and trimming options. + */ +@property (readonly) PINMemoryCache *memoryCache; + +#pragma mark - Lifecycle +/// @name Initialization + +/** + A shared cache. + + @result The shared singleton cache instance. + */ +@property (class, strong, readonly) PINCache *sharedCache; + +- (instancetype)init NS_UNAVAILABLE; + +/** + Multiple instances with the same name are *not* allowed and can *not* safely + access the same data on disk. Also used to create the . + + @see name + @param name The name of the cache. + @result A new cache with the specified name. + */ +- (instancetype)initWithName:(nonnull NSString *)name; + +/** + Multiple instances with the same name are *not* allowed and can *not* safely + access the same data on disk. Also used to create the . + + @see name + @param name The name of the cache. + @param rootPath The path of the cache on disk. + @result A new cache with the specified name. + */ +- (instancetype)initWithName:(nonnull NSString *)name rootPath:(nonnull NSString *)rootPath; + +/** + Multiple instances with the same name are *not* allowed and can *not* safely + access the same data on disk.. Also used to create the . + Initializer allows you to override default NSKeyedArchiver/NSKeyedUnarchiver serialization for . + You must provide both serializer and deserializer, or opt-out to default implementation providing nil values. + + @see name + @param name The name of the cache. + @param rootPath The path of the cache on disk. + @param serializer A block used to serialize object before writing to disk. If nil provided, default NSKeyedArchiver serialized will be used. + @param deserializer A block used to deserialize object read from disk. If nil provided, default NSKeyedUnarchiver serialized will be used. + @result A new cache with the specified name. + */ +- (instancetype)initWithName:(NSString *)name + rootPath:(NSString *)rootPath + serializer:(nullable PINDiskCacheSerializerBlock)serializer + deserializer:(nullable PINDiskCacheDeserializerBlock)deserializer; + +/** + Multiple instances with the same name are *not* allowed and can *not* safely + access the same data on disk. Also used to create the . + Initializer allows you to override default NSKeyedArchiver/NSKeyedUnarchiver serialization for . + You must provide both serializer and deserializer, or opt-out to default implementation providing nil values. + + @see name + @param name The name of the cache. + @param rootPath The path of the cache on disk. + @param serializer A block used to serialize object before writing to disk. If nil provided, default NSKeyedArchiver serialized will be used. + @param deserializer A block used to deserialize object read from disk. If nil provided, default NSKeyedUnarchiver serialized will be used. + @param keyEncoder A block used to encode key(filename). If nil provided, default url encoder will be used + @param keyDecoder A block used to decode key(filename). If nil provided, default url decoder will be used + @result A new cache with the specified name. + */ +- (instancetype)initWithName:(nonnull NSString *)name + rootPath:(nonnull NSString *)rootPath + serializer:(nullable PINDiskCacheSerializerBlock)serializer + deserializer:(nullable PINDiskCacheDeserializerBlock)deserializer + keyEncoder:(nullable PINDiskCacheKeyEncoderBlock)keyEncoder + keyDecoder:(nullable PINDiskCacheKeyDecoderBlock)keyDecoder; + +/** + Multiple instances with the same name are *not* allowed and can *not* safely + access the same data on disk. Also used to create the . + Initializer allows you to override default NSKeyedArchiver/NSKeyedUnarchiver serialization for . + You must provide both serializer and deserializer, or opt-out to default implementation providing nil values. + + @see name + @param name The name of the cache. + @param rootPath The path of the cache on disk. + @param serializer A block used to serialize object before writing to disk. If nil provided, default NSKeyedArchiver serialized will be used. + @param deserializer A block used to deserialize object read from disk. If nil provided, default NSKeyedUnarchiver serialized will be used. + @param keyEncoder A block used to encode key(filename). If nil provided, default url encoder will be used + @param keyDecoder A block used to decode key(filename). If nil provided, default url decoder will be used + @param ttlCache Whether or not the cache should behave as a TTL cache. + @result A new cache with the specified name. + */ +- (instancetype)initWithName:(nonnull NSString *)name + rootPath:(nonnull NSString *)rootPath + serializer:(nullable PINDiskCacheSerializerBlock)serializer + deserializer:(nullable PINDiskCacheDeserializerBlock)deserializer + keyEncoder:(nullable PINDiskCacheKeyEncoderBlock)keyEncoder + keyDecoder:(nullable PINDiskCacheKeyDecoderBlock)keyDecoder + ttlCache:(BOOL)ttlCache; + +/** + Multiple instances with the same name are *not* allowed and can *not* safely + access the same data on disk. Also used to create the . + Initializer allows you to override default NSKeyedArchiver/NSKeyedUnarchiver serialization for . + You must provide both serializer and deserializer, or opt-out to default implementation providing nil values. + + @see name + @param name The name of the cache. + @param rootPath The path of the cache on disk. + @param serializer A block used to serialize object before writing to disk. If nil provided, default NSKeyedArchiver serialized will be used. + @param deserializer A block used to deserialize object read from disk. If nil provided, default NSKeyedUnarchiver serialized will be used. + @param keyEncoder A block used to encode key(filename). If nil provided, default url encoder will be used + @param keyDecoder A block used to decode key(filename). If nil provided, default url decoder will be used + @param ttlCache Whether or not the cache should behave as a TTL cache. + @param evictionStrategy How the cache decide to evict objects when over cost. + @result A new cache with the specified name. + */ +- (instancetype)initWithName:(nonnull NSString *)name + rootPath:(nonnull NSString *)rootPath + serializer:(nullable PINDiskCacheSerializerBlock)serializer + deserializer:(nullable PINDiskCacheDeserializerBlock)deserializer + keyEncoder:(nullable PINDiskCacheKeyEncoderBlock)keyEncoder + keyDecoder:(nullable PINDiskCacheKeyDecoderBlock)keyDecoder + ttlCache:(BOOL)ttlCache + evictionStrategy:(PINCacheEvictionStrategy)evictionStrategy NS_DESIGNATED_INITIALIZER; + +@end + +@interface PINCache (Deprecated) +- (void)containsObjectForKey:(NSString *)key block:(PINCacheObjectContainmentBlock)block __attribute__((deprecated)); +- (void)objectForKey:(NSString *)key block:(PINCacheObjectBlock)block __attribute__((deprecated)); +- (void)setObject:(id )object forKey:(NSString *)key block:(nullable PINCacheObjectBlock)block __attribute__((deprecated)); +- (void)setObject:(id )object forKey:(NSString *)key withCost:(NSUInteger)cost block:(nullable PINCacheObjectBlock)block __attribute__((deprecated)); +- (void)removeObjectForKey:(NSString *)key block:(nullable PINCacheObjectBlock)block __attribute__((deprecated)); +- (void)trimToDate:(NSDate *)date block:(nullable PINCacheBlock)block __attribute__((deprecated)); +- (void)removeAllObjects:(nullable PINCacheBlock)block __attribute__((deprecated)); +@end + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/PINCache/Source/PINCache.m b/Carthage/Checkouts/PINCache/Source/PINCache.m new file mode 100644 index 00000000..5666e85d --- /dev/null +++ b/Carthage/Checkouts/PINCache/Source/PINCache.m @@ -0,0 +1,441 @@ +// PINCache is a modified version of TMCache +// Modifications by Garrett Moon +// Copyright (c) 2015 Pinterest. All rights reserved. + +#import "PINCache.h" + +#import + +static NSString * const PINCachePrefix = @"com.pinterest.PINCache"; +static NSString * const PINCacheSharedName = @"PINCacheShared"; + +@interface PINCache () +@property (copy, nonatomic) NSString *name; +@property (strong, nonatomic) PINOperationQueue *operationQueue; +@end + +@implementation PINCache + +#pragma mark - Initialization - + +- (instancetype)init +{ + @throw [NSException exceptionWithName:@"Must initialize with a name" reason:@"PINCache must be initialized with a name. Call initWithName: instead." userInfo:nil]; + return [self initWithName:@""]; +} + +- (instancetype)initWithName:(NSString *)name +{ + return [self initWithName:name rootPath:[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]]; +} + +- (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath +{ + return [self initWithName:name rootPath:rootPath serializer:nil deserializer:nil]; +} + +- (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath serializer:(PINDiskCacheSerializerBlock)serializer deserializer:(PINDiskCacheDeserializerBlock)deserializer { + return [self initWithName:name rootPath:rootPath serializer:serializer deserializer:deserializer keyEncoder:nil keyDecoder:nil]; +} + +- (instancetype)initWithName:(NSString *)name + rootPath:(NSString *)rootPath + serializer:(PINDiskCacheSerializerBlock)serializer + deserializer:(PINDiskCacheDeserializerBlock)deserializer + keyEncoder:(PINDiskCacheKeyEncoderBlock)keyEncoder + keyDecoder:(PINDiskCacheKeyDecoderBlock)keyDecoder +{ + return [self initWithName:name rootPath:rootPath serializer:serializer deserializer:deserializer keyEncoder:keyEncoder keyDecoder:keyDecoder ttlCache:NO]; +} + +- (instancetype)initWithName:(nonnull NSString *)name + rootPath:(nonnull NSString *)rootPath + serializer:(nullable PINDiskCacheSerializerBlock)serializer + deserializer:(nullable PINDiskCacheDeserializerBlock)deserializer + keyEncoder:(nullable PINDiskCacheKeyEncoderBlock)keyEncoder + keyDecoder:(nullable PINDiskCacheKeyDecoderBlock)keyDecoder + ttlCache:(BOOL)ttlCache +{ + return [self initWithName:name rootPath:rootPath serializer:serializer deserializer:deserializer keyEncoder:keyEncoder keyDecoder:keyDecoder ttlCache:ttlCache evictionStrategy:PINCacheEvictionStrategyLeastRecentlyUsed]; +} + +- (instancetype)initWithName:(NSString *)name + rootPath:(NSString *)rootPath + serializer:(PINDiskCacheSerializerBlock)serializer + deserializer:(PINDiskCacheDeserializerBlock)deserializer + keyEncoder:(PINDiskCacheKeyEncoderBlock)keyEncoder + keyDecoder:(PINDiskCacheKeyDecoderBlock)keyDecoder + ttlCache:(BOOL)ttlCache + evictionStrategy:(PINCacheEvictionStrategy)evictionStrategy +{ + if (!name) + return nil; + + if (self = [super init]) { + _name = [name copy]; + + //10 may actually be a bit high, but currently much of our threads are blocked on empyting the trash. Until we can resolve that, lets bump this up. + _operationQueue = [[PINOperationQueue alloc] initWithMaxConcurrentOperations:10]; + _diskCache = [[PINDiskCache alloc] initWithName:_name + prefix:PINDiskCachePrefix + rootPath:rootPath + serializer:serializer + deserializer:deserializer + keyEncoder:keyEncoder + keyDecoder:keyDecoder + operationQueue:_operationQueue + ttlCache:ttlCache + byteLimit:PINDiskCacheDefaultByteLimit + ageLimit:PINDiskCacheDefaultAgeLimit + evictionStrategy:evictionStrategy]; + _memoryCache = [[PINMemoryCache alloc] initWithName:_name operationQueue:_operationQueue ttlCache:ttlCache evictionStrategy:evictionStrategy]; + } + return self; +} + +- (NSString *)description +{ + return [[NSString alloc] initWithFormat:@"%@.%@.%p", PINCachePrefix, _name, (void *)self]; +} + ++ (PINCache *)sharedCache +{ + static PINCache *cache; + static dispatch_once_t predicate; + + dispatch_once(&predicate, ^{ + cache = [[PINCache alloc] initWithName:PINCacheSharedName]; + }); + + return cache; +} + +#pragma mark - Public Asynchronous Methods - + +- (void)containsObjectForKeyAsync:(NSString *)key completion:(PINCacheObjectContainmentBlock)block +{ + if (!key || !block) { + return; + } + + [self.operationQueue scheduleOperation:^{ + BOOL containsObject = [self containsObjectForKey:key]; + block(containsObject); + }]; +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wshadow" + +- (void)objectForKeyAsync:(NSString *)key completion:(PINCacheObjectBlock)block +{ + if (!key || !block) + return; + + [self.operationQueue scheduleOperation:^{ + [self->_memoryCache objectForKeyAsync:key completion:^(id memoryCache, NSString *memoryCacheKey, id memoryCacheObject) { + if (memoryCacheObject) { + // Update file modification date. TODO: make this a separate method? + [self->_diskCache fileURLForKeyAsync:memoryCacheKey completion:^(NSString * _Nonnull key, NSURL * _Nullable fileURL) {}]; + [self->_operationQueue scheduleOperation:^{ + block(self, memoryCacheKey, memoryCacheObject); + }]; + } else { + [self->_diskCache objectForKeyAsync:memoryCacheKey completion:^(PINDiskCache *diskCache, NSString *diskCacheKey, id diskCacheObject) { + + [self->_memoryCache setObjectAsync:diskCacheObject forKey:diskCacheKey completion:nil]; + + [self->_operationQueue scheduleOperation:^{ + block(self, diskCacheKey, diskCacheObject); + }]; + }]; + } + }]; + }]; +} + +#pragma clang diagnostic pop + +- (void)setObjectAsync:(id )object forKey:(NSString *)key completion:(PINCacheObjectBlock)block +{ + [self setObjectAsync:object forKey:key withCost:0 completion:block]; +} + +- (void)setObjectAsync:(id )object forKey:(NSString *)key withAgeLimit:(NSTimeInterval)ageLimit completion:(PINCacheObjectBlock)block +{ + [self setObjectAsync:object forKey:key withCost:0 ageLimit:ageLimit completion:block]; +} + +- (void)setObjectAsync:(id )object forKey:(NSString *)key withCost:(NSUInteger)cost completion:(PINCacheObjectBlock)block +{ + [self setObjectAsync:object forKey:key withCost:cost ageLimit:0.0 completion:block]; +} + +- (void)setObjectAsync:(nonnull id)object forKey:(nonnull NSString *)key withCost:(NSUInteger)cost ageLimit:(NSTimeInterval)ageLimit completion:(nullable PINCacheObjectBlock)block +{ + if (!key || !object) + return; + + PINOperationGroup *group = [PINOperationGroup asyncOperationGroupWithQueue:_operationQueue]; + + [group addOperation:^{ + [self->_memoryCache setObject:object forKey:key withCost:cost ageLimit:ageLimit]; + }]; + [group addOperation:^{ + [self->_diskCache setObject:object forKey:key withAgeLimit:ageLimit]; + }]; + + if (block) { + [group setCompletion:^{ + block(self, key, object); + }]; + } + + [group start]; +} + +- (void)removeObjectForKeyAsync:(NSString *)key completion:(PINCacheObjectBlock)block +{ + if (!key) + return; + + PINOperationGroup *group = [PINOperationGroup asyncOperationGroupWithQueue:_operationQueue]; + + [group addOperation:^{ + [self->_memoryCache removeObjectForKey:key]; + }]; + [group addOperation:^{ + [self->_diskCache removeObjectForKey:key]; + }]; + + if (block) { + [group setCompletion:^{ + block(self, key, nil); + }]; + } + + [group start]; +} + +- (void)removeAllObjectsAsync:(PINCacheBlock)block +{ + PINOperationGroup *group = [PINOperationGroup asyncOperationGroupWithQueue:_operationQueue]; + + [group addOperation:^{ + [self->_memoryCache removeAllObjects]; + }]; + [group addOperation:^{ + [self->_diskCache removeAllObjects]; + }]; + + if (block) { + [group setCompletion:^{ + block(self); + }]; + } + + [group start]; +} + +- (void)trimToDateAsync:(NSDate *)date completion:(PINCacheBlock)block +{ + if (!date) + return; + + PINOperationGroup *group = [PINOperationGroup asyncOperationGroupWithQueue:_operationQueue]; + + [group addOperation:^{ + [self->_memoryCache trimToDate:date]; + }]; + [group addOperation:^{ + [self->_diskCache trimToDate:date]; + }]; + + if (block) { + [group setCompletion:^{ + block(self); + }]; + } + + [group start]; +} + +- (void)removeExpiredObjectsAsync:(PINCacheBlock)block +{ + PINOperationGroup *group = [PINOperationGroup asyncOperationGroupWithQueue:_operationQueue]; + + [group addOperation:^{ + [self->_memoryCache removeExpiredObjects]; + }]; + [group addOperation:^{ + [self->_diskCache removeExpiredObjects]; + }]; + + if (block) { + [group setCompletion:^{ + block(self); + }]; + } + + [group start]; +} + +#pragma mark - Public Synchronous Accessors - + +- (NSUInteger)diskByteCount +{ + __block NSUInteger byteCount = 0; + + [_diskCache synchronouslyLockFileAccessWhileExecutingBlock:^(id diskCache) { + byteCount = ((PINDiskCache *)diskCache).byteCount; + }]; + + return byteCount; +} + +- (BOOL)containsObjectForKey:(NSString *)key +{ + if (!key) + return NO; + + return [_memoryCache containsObjectForKey:key] || [_diskCache containsObjectForKey:key]; +} + +- (nullable id)objectForKey:(NSString *)key +{ + if (!key) + return nil; + + __block id object = nil; + + object = [_memoryCache objectForKey:key]; + + if (object) { + // Update file modification date. TODO: make this a separate method? + [_diskCache fileURLForKeyAsync:key completion:^(NSString * _Nonnull key, NSURL * _Nullable fileURL) {}]; + } else { + object = [_diskCache objectForKey:key]; + [_memoryCache setObject:object forKey:key]; + } + + return object; +} + +- (void)setObject:(id )object forKey:(NSString *)key +{ + [self setObject:object forKey:key withCost:0]; +} + +- (void)setObject:(id )object forKey:(NSString *)key withAgeLimit:(NSTimeInterval)ageLimit +{ + [self setObject:object forKey:key withCost:0 ageLimit:ageLimit]; +} + +- (void)setObject:(id )object forKey:(NSString *)key withCost:(NSUInteger)cost +{ + [self setObject:object forKey:key withCost:cost ageLimit:0.0]; +} + +- (void)setObject:(nullable id)object forKey:(nonnull NSString *)key withCost:(NSUInteger)cost ageLimit:(NSTimeInterval)ageLimit +{ + if (!key || !object) + return; + + [_memoryCache setObject:object forKey:key withCost:cost ageLimit:ageLimit]; + [_diskCache setObject:object forKey:key withAgeLimit:ageLimit]; +} + +- (nullable id)objectForKeyedSubscript:(NSString *)key +{ + return [self objectForKey:key]; +} + +- (void)setObject:(nullable id)obj forKeyedSubscript:(NSString *)key +{ + if (obj == nil) { + [self removeObjectForKey:key]; + } else { + [self setObject:obj forKey:key]; + } +} + +- (void)removeObjectForKey:(NSString *)key +{ + if (!key) + return; + + [_memoryCache removeObjectForKey:key]; + [_diskCache removeObjectForKey:key]; +} + +- (void)trimToDate:(NSDate *)date +{ + if (!date) + return; + + [_memoryCache trimToDate:date]; + [_diskCache trimToDate:date]; +} + +- (void)removeExpiredObjects +{ + [_memoryCache removeExpiredObjects]; + [_diskCache removeExpiredObjects]; +} + +- (void)removeAllObjects +{ + [_memoryCache removeAllObjects]; + [_diskCache removeAllObjects]; +} + +- (NSUInteger)maxConcurrentOperations +{ + return _operationQueue.maxConcurrentOperations; +} + +- (void)setMaxConcurrentOperations:(NSUInteger)maxOperations +{ + _operationQueue.maxConcurrentOperations = maxOperations; +} + +@end + +@implementation PINCache (Deprecated) + +- (void)containsObjectForKey:(NSString *)key block:(PINCacheObjectContainmentBlock)block +{ + [self containsObjectForKeyAsync:key completion:block]; +} + +- (void)objectForKey:(NSString *)key block:(PINCacheObjectBlock)block +{ + [self objectForKeyAsync:key completion:block]; +} + +- (void)setObject:(id )object forKey:(NSString *)key block:(nullable PINCacheObjectBlock)block +{ + [self setObjectAsync:object forKey:key completion:block]; +} + +- (void)setObject:(id )object forKey:(NSString *)key withCost:(NSUInteger)cost block:(nullable PINCacheObjectBlock)block +{ + [self setObjectAsync:object forKey:key withCost:cost completion:block]; +} + +- (void)removeObjectForKey:(NSString *)key block:(nullable PINCacheObjectBlock)block +{ + [self removeObjectForKeyAsync:key completion:block]; +} + +- (void)trimToDate:(NSDate *)date block:(nullable PINCacheBlock)block +{ + [self trimToDateAsync:date completion:block]; +} + +- (void)removeAllObjects:(nullable PINCacheBlock)block +{ + [self removeAllObjectsAsync:block]; +} + +@end diff --git a/Carthage/Checkouts/PINCache/Source/PINCacheMacros.h b/Carthage/Checkouts/PINCache/Source/PINCacheMacros.h new file mode 100644 index 00000000..e7179a17 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Source/PINCacheMacros.h @@ -0,0 +1,23 @@ +// +// PINCacheMacros.h +// PINCache +// +// Created by Adlai Holler on 1/31/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#ifndef PIN_SUBCLASSING_RESTRICTED +#if defined(__has_attribute) && __has_attribute(objc_subclassing_restricted) +#define PIN_SUBCLASSING_RESTRICTED __attribute__((objc_subclassing_restricted)) +#else +#define PIN_SUBCLASSING_RESTRICTED +#endif // #if defined(__has_attribute) && __has_attribute(objc_subclassing_restricted) +#endif // #ifndef PIN_SUBCLASSING_RESTRICTED + +#ifndef PIN_NOESCAPE +#if defined(__has_attribute) && __has_attribute(noescape) +#define PIN_NOESCAPE __attribute__((noescape)) +#else +#define PIN_NOESCAPE +#endif // #if defined(__has_attribute) && __has_attribute(noescape) +#endif // #ifndef PIN_NOESCAPE diff --git a/Carthage/Checkouts/PINCache/Source/PINCacheObjectSubscripting.h b/Carthage/Checkouts/PINCache/Source/PINCacheObjectSubscripting.h new file mode 100644 index 00000000..a7bd20b4 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Source/PINCacheObjectSubscripting.h @@ -0,0 +1,35 @@ +// +// PINCacheObjectSubscripting.h +// PINCache +// +// Created by Rocir Marcos Leite Santiago on 4/2/16. +// Copyright © 2016 Pinterest. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol PINCacheObjectSubscripting + +@required + +/** + This method enables using literals on the receiving object, such as `id object = cache[@"key"];`. + + @param key The key associated with the object. + @result The object for the specified key. + */ +- (nullable id)objectForKeyedSubscript:(NSString *)key; + +/** + This method enables using literals on the receiving object, such as `cache[@"key"] = object;`. + + @param object An object to be assigned for the key. Pass `nil` to remove the existing object for this key. + @param key A key to associate with the object. This string will be copied. + */ +- (void)setObject:(nullable id)object forKeyedSubscript:(NSString *)key; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/PINCache/Source/PINCaching.h b/Carthage/Checkouts/PINCache/Source/PINCaching.h new file mode 100644 index 00000000..79ecad5e --- /dev/null +++ b/Carthage/Checkouts/PINCache/Source/PINCaching.h @@ -0,0 +1,268 @@ +// +// PINCaching.h +// PINCache +// +// Created by Michael Schneider on 1/31/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@protocol PINCaching; + +/** + A callback block which provides only the cache as an argument + */ +typedef void (^PINCacheBlock)(__kindof id cache); + +/** + A callback block which provides the cache, key and object as arguments + */ +typedef void (^PINCacheObjectBlock)(__kindof id cache, NSString *key, id _Nullable object); + +/** + A callback block used for enumeration which provides the cache, key and object as arguments plus a stop flag that + may be flipped by the caller. + */ +typedef void (^PINCacheObjectEnumerationBlock)(__kindof id cache, NSString *key, id _Nullable object, BOOL *stop); + +/** + A callback block which provides a BOOL value as argument + */ +typedef void (^PINCacheObjectContainmentBlock)(BOOL containsObject); + +typedef NS_ENUM(NSInteger, PINCacheEvictionStrategy) { + PINCacheEvictionStrategyLeastRecentlyUsed, + PINCacheEvictionStrategyLeastFrequentlyUsed, +}; + +@protocol PINCaching + +#pragma mark - Core + +/** + The name of this cache, used to create a directory under Library/Caches and also appearing in stack traces. + */ +@property (readonly) NSString *name; + +#pragma mark - Asynchronous Methods + +/// @name Asynchronous Methods + +/** + This method determines whether an object is present for the given key in the cache. This method returns immediately + and executes the passed block after the object is available, potentially in parallel with other blocks on the + . + + @see containsObjectForKey: + @param key The key associated with the object. + @param block A block to be executed concurrently after the containment check happened + */ +- (void)containsObjectForKeyAsync:(NSString *)key completion:(PINCacheObjectContainmentBlock)block; + +/** + Retrieves the object for the specified key. This method returns immediately and executes the passed + block after the object is available, potentially in parallel with other blocks on the . + + @param key The key associated with the requested object. + @param block A block to be executed concurrently when the object is available. + */ +- (void)objectForKeyAsync:(NSString *)key completion:(PINCacheObjectBlock)block; + +/** + Stores an object in the cache for the specified key. This method returns immediately and executes the + passed block after the object has been stored, potentially in parallel with other blocks on the . + + @param object An object to store in the cache. + @param key A key to associate with the object. This string will be copied. + @param block A block to be executed concurrently after the object has been stored, or nil. + */ +- (void)setObjectAsync:(id)object forKey:(NSString *)key completion:(nullable PINCacheObjectBlock)block; + +/** + Stores an object in the cache for the specified key and the specified age limit. This method returns immediately + and executes the passed block after the object has been stored, potentially in parallel with other blocks + on the . + + @param object An object to store in the cache. + @param key A key to associate with the object. This string will be copied. + @param ageLimit The age limit (in seconds) to associate with the object. An age limit <= 0 means there is no object-level age limit and the + cache-level TTL will be used for this object. + @param block A block to be executed concurrently after the object has been stored, or nil. + */ +- (void)setObjectAsync:(id)object forKey:(NSString *)key withAgeLimit:(NSTimeInterval)ageLimit completion:(nullable PINCacheObjectBlock)block; + +/** + Stores an object in the cache for the specified key and the specified memory cost. If the cost causes the total + to go over the the cache is trimmed (oldest objects first). This method returns immediately + and executes the passed block after the object has been stored, potentially in parallel with other blocks + on the . + + @param object An object to store in the cache. + @param key A key to associate with the object. This string will be copied. + @param cost An amount to add to the . + @param block A block to be executed concurrently after the object has been stored, or nil. + */ +- (void)setObjectAsync:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost completion:(nullable PINCacheObjectBlock)block; + +/** + Stores an object in the cache for the specified key and the specified memory cost and age limit. If the cost causes the total + to go over the the cache is trimmed (oldest objects first). This method returns immediately + and executes the passed block after the object has been stored, potentially in parallel with other blocks + on the . + + @param object An object to store in the cache. + @param key A key to associate with the object. This string will be copied. + @param cost An amount to add to the . + @param ageLimit The age limit (in seconds) to associate with the object. An age limit <= 0 means there is no object-level age limit and the cache-level TTL will be + used for this object. + @param block A block to be executed concurrently after the object has been stored, or nil. + */ +- (void)setObjectAsync:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost ageLimit:(NSTimeInterval)ageLimit completion:(nullable PINCacheObjectBlock)block; + +/** + Removes the object for the specified key. This method returns immediately and executes the passed + block after the object has been removed, potentially in parallel with other blocks on the . + + @param key The key associated with the object to be removed. + @param block A block to be executed concurrently after the object has been removed, or nil. + */ +- (void)removeObjectForKeyAsync:(NSString *)key completion:(nullable PINCacheObjectBlock)block; + +/** + Removes all objects from the cache that have not been used since the specified date. This method returns immediately and + executes the passed block after the cache has been trimmed, potentially in parallel with other blocks on the . + + @param date Objects that haven't been accessed since this date are removed from the cache. + @param block A block to be executed concurrently after the cache has been trimmed, or nil. + */ +- (void)trimToDateAsync:(NSDate *)date completion:(nullable PINCacheBlock)block; + +/** + Removes all expired objects from the cache. This includes objects that are considered expired due to the cache-level ageLimit + as well as object-level ageLimits. This method returns immediately and executes the passed block after the objects have been removed, + potentially in parallel with other blocks on the . + + @param block A block to be executed concurrently after the objects have been removed, or nil. + */ +- (void)removeExpiredObjectsAsync:(nullable PINCacheBlock)block; + +/** + Removes all objects from the cache.This method returns immediately and executes the passed block after the + cache has been cleared, potentially in parallel with other blocks on the . + + @param block A block to be executed concurrently after the cache has been cleared, or nil. + */ +- (void)removeAllObjectsAsync:(nullable PINCacheBlock)block; + + +#pragma mark - Synchronous Methods +/// @name Synchronous Methods + +/** + This method determines whether an object is present for the given key in the cache. + + @see containsObjectForKeyAsync:completion: + @param key The key associated with the object. + @result YES if an object is present for the given key in the cache, otherwise NO. + */ +- (BOOL)containsObjectForKey:(NSString *)key; + +/** + Retrieves the object for the specified key. This method blocks the calling thread until the object is available. + Uses a lock to achieve synchronicity on the disk cache. + + @see objectForKeyAsync:completion: + @param key The key associated with the object. + @result The object for the specified key. + */ +- (nullable id)objectForKey:(NSString *)key; + +/** + Stores an object in the cache for the specified key. This method blocks the calling thread until the object has been set. + Uses a lock to achieve synchronicity on the disk cache. + + @see setObjectAsync:forKey:completion: + @param object An object to store in the cache. + @param key A key to associate with the object. This string will be copied. + */ +- (void)setObject:(nullable id)object forKey:(NSString *)key; + +/** + Stores an object in the cache for the specified key and age limit. This method blocks the calling thread until the + object has been set. Uses a lock to achieve synchronicity on the disk cache. + + @see setObjectAsync:forKey:completion: + @param object An object to store in the cache. + @param key A key to associate with the object. This string will be copied. + @param ageLimit The age limit (in seconds) to associate with the object. An age limit <= 0 means there is no + object-level age limit and the cache-level TTL will be used for this object. + */ +- (void)setObject:(nullable id)object forKey:(NSString *)key withAgeLimit:(NSTimeInterval)ageLimit; + +/** + Stores an object in the cache for the specified key and the specified memory cost. If the cost causes the total + to go over the the cache is trimmed (oldest objects first). This method blocks the calling thread + until the object has been stored. + + @param object An object to store in the cache. + @param key A key to associate with the object. This string will be copied. + @param cost An amount to add to the . + */ +- (void)setObject:(nullable id)object forKey:(NSString *)key withCost:(NSUInteger)cost; + +/** + Stores an object in the cache for the specified key and the specified memory cost and age limit. If the cost causes the total + to go over the the cache is trimmed (oldest objects first). This method blocks the calling thread + until the object has been stored. + + @param object An object to store in the cache. + @param key A key to associate with the object. This string will be copied. + @param cost An amount to add to the . + @param ageLimit The age limit (in seconds) to associate with the object. An age limit <= 0 means there is no object-level age + limit and the cache-level TTL will be used for this object. + */ +- (void)setObject:(nullable id)object forKey:(NSString *)key withCost:(NSUInteger)cost ageLimit:(NSTimeInterval)ageLimit; + +/** + Removes the object for the specified key. This method blocks the calling thread until the object + has been removed. + Uses a lock to achieve synchronicity on the disk cache. + + @see removeObjectForKeyAsync:completion: + @param key The key associated with the object to be removed. + */ +- (void)removeObjectForKey:(NSString *)key; + +/** + Removes all objects from the cache that have not been used since the specified date. + This method blocks the calling thread until the cache has been trimmed. + Uses a lock to achieve synchronicity on the disk cache. + + @see trimToDateAsync:completion: + @param date Objects that haven't been accessed since this date are removed from the cache. + */ +- (void)trimToDate:(NSDate *)date; + +/** + Removes all expired objects from the cache. This includes objects that are considered expired due to the cache-level ageLimit + as well as object-level ageLimits. This method blocks the calling thread until the objects have been removed. + Uses a lock to achieve synchronicity on the disk cache. + */ +- (void)removeExpiredObjects; + +/** + Removes all objects from the cache. This method blocks the calling thread until the cache has been cleared. + Uses a lock to achieve synchronicity on the disk cache. + + @see removeAllObjectsAsync: + */ +- (void)removeAllObjects; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/Carthage/Checkouts/PINCache/Source/PINDiskCache.h b/Carthage/Checkouts/PINCache/Source/PINDiskCache.h new file mode 100644 index 00000000..075d4c4d --- /dev/null +++ b/Carthage/Checkouts/PINCache/Source/PINDiskCache.h @@ -0,0 +1,660 @@ +// PINCache is a modified version of TMCache +// Modifications by Garrett Moon +// Copyright (c) 2015 Pinterest. All rights reserved. + +#import + +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@class PINDiskCache; +@class PINOperationQueue; + +extern NSString * const PINDiskCacheErrorDomain; +extern NSErrorUserInfoKey const PINDiskCacheErrorReadFailureCodeKey; +extern NSErrorUserInfoKey const PINDiskCacheErrorWriteFailureCodeKey; +extern NSString * const PINDiskCachePrefix; + +extern NSUInteger PINDiskCacheDefaultByteLimit; +extern NSTimeInterval PINDiskCacheDefaultAgeLimit; + +typedef NS_ENUM(NSInteger, PINDiskCacheError) { + PINDiskCacheErrorReadFailure = -1000, + PINDiskCacheErrorWriteFailure = -1001, +}; + +/** + A callback block which provides the cache, key and object as arguments + */ +typedef void (^PINDiskCacheObjectBlock)(PINDiskCache *cache, NSString *key, id _Nullable object); + +/** + A callback block which provides the key and fileURL of the object + */ +typedef void (^PINDiskCacheFileURLBlock)(NSString *key, NSURL * _Nullable fileURL); + +/** + A callback block used for enumeration which provides the key and fileURL of the object plus a stop flag that + may be flipped by the caller. + */ +typedef void (^PINDiskCacheFileURLEnumerationBlock)(NSString *key, NSURL * _Nullable fileURL, BOOL *stop); + +/** + A callback block which provides a BOOL value as argument + */ +typedef void (^PINDiskCacheContainsBlock)(BOOL containsObject); + +/** + * A block used to serialize object before writing to disk + * + * @param object Object to serialize + * @param key The key associated with the object + * + * @return Serialized object representation + */ +typedef NSData* _Nonnull(^PINDiskCacheSerializerBlock)(id object, NSString *key); + +/** + * A block used to deserialize objects + * + * @param data Serialized object data + * @param key The key associated with the object + * + * @return Deserialized object + */ +typedef id _Nonnull(^PINDiskCacheDeserializerBlock)(NSData* data, NSString *key); + +/** + * A block used to encode keys + * + * @param decodedKey Original/decoded key + * + * @return encoded key + */ +typedef NSString *_Nonnull(^PINDiskCacheKeyEncoderBlock)(NSString *decodedKey); + +/** + * A block used to decode keys + * + * @param encodedKey An encoded key + * + * @return decoded key + */ +typedef NSString *_Nonnull(^PINDiskCacheKeyDecoderBlock)(NSString *encodedKey); + + +/** + `PINDiskCache` is a thread safe key/value store backed by the file system. It accepts any object conforming + to the `NSCoding` protocol, which includes the basic Foundation data types and collection classes and also + many UIKit classes, notably `UIImage`. All work is performed on a serial queue shared by all instances in + the app, and archiving is handled by `NSKeyedArchiver`. This is a particular advantage for `UIImage` because + it skips `UIImagePNGRepresentation()` and retains information like scale and orientation. + + The designated initializer for `PINDiskCache` is . The string is used to create a directory + under Library/Caches that scopes disk access for this instance. Multiple instances with the same name are *not* + allowed as they would conflict with each other. + + Unless otherwise noted, all properties and methods are safe to access from any thread at any time. All blocks + will cause the queue to wait, making it safe to access and manipulate the actual cache files on disk for the + duration of the block. + + Because this cache is bound by disk I/O it can be much slower than , although values stored in + `PINDiskCache` persist after application relaunch. Using is recommended over using `PINDiskCache` + by itself, as it adds a fast layer of additional memory caching while still writing to disk. + + All access to the cache is dated so the that the least-used objects can be trimmed first. Setting an optional + will trigger a GCD timer to periodically to trim the cache with . + */ + +PIN_SUBCLASSING_RESTRICTED +@interface PINDiskCache : NSObject + +#pragma mark - Class + +/** + @param rootPath The path for where the cache should be stored. + @param prefix The prefix for the cache name. + @param name The name of the cache. + @result The full URL of the cache. + */ ++ (NSURL *)cacheURLWithRootPath:(NSString *)rootPath prefix:(NSString *)prefix name:(NSString *)name; + +#pragma mark - Properties +/// @name Core + +/** + The prefix to the name of this cache, used to create a directory under Library/Caches and also appearing in stack traces. + */ +@property (readonly) NSString *prefix; + +/** + The URL of the directory used by this cache, usually `Library/Caches/com.pinterest.PINDiskCache.(name)` + + @warning Do not interact with files under this URL except in or + . + */ +@property (readonly) NSURL *cacheURL; + +/** + The total number of bytes used on disk, as reported by `NSURLTotalFileAllocatedSizeKey`. + + @warning This property should only be read from a call to or + its asynchronous equivalent + + For example: + + // some background thread + + __block NSUInteger byteCount = 0; + + [_diskCache synchronouslyLockFileAccessWhileExecutingBlock:^(PINDiskCache *diskCache) { + byteCount = diskCache.byteCount; + }]; + */ +@property (readonly) NSUInteger byteCount; + +/** + The maximum number of bytes allowed on disk. This value is checked every time an object is set, if the written + size exceeds the limit a trim call is queued. Defaults to 50MB. + + */ +@property (assign) NSUInteger byteLimit; + +/** + The maximum number of seconds an object is allowed to exist in the cache. Setting this to a value + greater than `0.0` will start a recurring GCD timer with the same period that calls . + Setting it back to `0.0` will stop the timer. Defaults to 30 days. + + */ +@property (assign) NSTimeInterval ageLimit; + +/** + The eviction strategy when trimming the cache. + */ +@property (atomic, assign) PINCacheEvictionStrategy evictionStrategy; + +/** + The writing protection option used when writing a file on disk. This value is used every time an object is set. + NSDataWritingAtomic and NSDataWritingWithoutOverwriting are ignored if set + Defaults to NSDataWritingFileProtectionNone. + + @warning Only new files are affected by the new writing protection. If you need all files to be affected, + you'll have to purge and set the objects back to the cache + + Only available on iOS + */ +#if TARGET_OS_IPHONE +@property (assign) NSDataWritingOptions writingProtectionOption; +#endif + +/** + If ttlCache is YES, the cache behaves like a ttlCache. This means that once an object enters the + cache, it only lives as long as self.ageLimit. This has the following implications: + - Accessing an object in the cache does not extend that object's lifetime in the cache + - When attempting to access an object in the cache that has lived longer than self.ageLimit, + the cache will behave as if the object does not exist + + @note If an object-level age limit is set via one of the @c -setObject:forKey:withAgeLimit methods, + that age limit overrides self.ageLimit. The overridden object age limit could be greater or less + than self.agelimit but must be greater than zero. + + */ +@property (nonatomic, readonly, getter=isTTLCache) BOOL ttlCache; + +#pragma mark - Event Blocks +/// @name Event Blocks + +/** + A block to be executed just before an object is added to the cache. The queue waits during execution. + */ +@property (nullable, copy) PINDiskCacheObjectBlock willAddObjectBlock; + +/** + A block to be executed just before an object is removed from the cache. The queue waits during execution. + */ +@property (nullable, copy) PINDiskCacheObjectBlock willRemoveObjectBlock; + +/** + A block to be executed just before all objects are removed from the cache as a result of . + The queue waits during execution. + */ +@property (nullable, copy) PINCacheBlock willRemoveAllObjectsBlock; + +/** + A block to be executed just after an object is added to the cache. The queue waits during execution. + */ +@property (nullable, copy) PINDiskCacheObjectBlock didAddObjectBlock; + +/** + A block to be executed just after an object is removed from the cache. The queue waits during execution. + */ +@property (nullable, copy) PINDiskCacheObjectBlock didRemoveObjectBlock; + +/** + A block to be executed just after all objects are removed from the cache as a result of . + The queue waits during execution. + */ +@property (nullable, copy) PINCacheBlock didRemoveAllObjectsBlock; + +#pragma mark - Lifecycle +/// @name Initialization + +/** + A shared cache. + + @result The shared singleton cache instance. + */ +@property (class, readonly, strong) PINDiskCache *sharedCache; + +/** + Empties the trash with `DISPATCH_QUEUE_PRIORITY_BACKGROUND`. Does not use lock. + */ ++ (void)emptyTrash; + +- (instancetype)init NS_UNAVAILABLE; + +/** + Multiple instances with the same name are *not* allowed as they would conflict + with each other. + + @see name + @param name The name of the cache. + @result A new cache with the specified name. + */ +- (instancetype)initWithName:(nonnull NSString *)name; + +/** + Multiple instances with the same name are *not* allowed as they would conflict + with each other. + + @see name + @param name The name of the cache. + @param rootPath The path of the cache. + @result A new cache with the specified name. + */ +- (instancetype)initWithName:(nonnull NSString *)name rootPath:(nonnull NSString *)rootPath; + +/** + @see name + @param name The name of the cache. + @param rootPath The path of the cache. + @param serializer A block used to serialize object. If nil provided, default NSKeyedArchiver serialized will be used. + @param deserializer A block used to deserialize object. If nil provided, default NSKeyedUnarchiver serialized will be used. + @result A new cache with the specified name. + */ +- (instancetype)initWithName:(nonnull NSString *)name rootPath:(nonnull NSString *)rootPath serializer:(nullable PINDiskCacheSerializerBlock)serializer deserializer:(nullable PINDiskCacheDeserializerBlock)deserializer; + +/** + @see name + @param name The name of the cache. + @param rootPath The path of the cache. + @param serializer A block used to serialize object. If nil provided, default NSKeyedArchiver serialized will be used. + @param deserializer A block used to deserialize object. If nil provided, default NSKeyedUnarchiver serialized will be used. + @param operationQueue A PINOperationQueue to run asynchronous operations + @result A new cache with the specified name. + */ +- (instancetype)initWithName:(nonnull NSString *)name rootPath:(nonnull NSString *)rootPath serializer:(nullable PINDiskCacheSerializerBlock)serializer deserializer:(nullable PINDiskCacheDeserializerBlock)deserializer operationQueue:(nonnull PINOperationQueue *)operationQueue __attribute__((deprecated)); + +/** + @see name + @param name The name of the cache. + @param prefix The prefix for the cache name. Defaults to com.pinterest.PINDiskCache + @param rootPath The path of the cache. + @param serializer A block used to serialize object. If nil provided, default NSKeyedArchiver serialized will be used. + @param deserializer A block used to deserialize object. If nil provided, default NSKeyedUnarchiver serialized will be used. + @param keyEncoder A block used to encode key(filename). If nil provided, default url encoder will be used + @param keyDecoder A block used to decode key(filename). If nil provided, default url decoder will be used + @param operationQueue A PINOperationQueue to run asynchronous operations + @result A new cache with the specified name. + */ +- (instancetype)initWithName:(nonnull NSString *)name + prefix:(nonnull NSString *)prefix + rootPath:(nonnull NSString *)rootPath + serializer:(nullable PINDiskCacheSerializerBlock)serializer + deserializer:(nullable PINDiskCacheDeserializerBlock)deserializer + keyEncoder:(nullable PINDiskCacheKeyEncoderBlock)keyEncoder + keyDecoder:(nullable PINDiskCacheKeyDecoderBlock)keyDecoder + operationQueue:(nonnull PINOperationQueue *)operationQueue; + +/** + The designated initializer allowing you to override default NSKeyedArchiver/NSKeyedUnarchiver serialization. + + @see name + @param name The name of the cache. + @param prefix The prefix for the cache name. Defaults to com.pinterest.PINDiskCache + @param rootPath The path of the cache. + @param serializer A block used to serialize object. If nil provided, default NSKeyedArchiver serialized will be used. + @param deserializer A block used to deserialize object. If nil provided, default NSKeyedUnarchiver serialized will be used. + @param keyEncoder A block used to encode key(filename). If nil provided, default url encoder will be used + @param keyDecoder A block used to decode key(filename). If nil provided, default url decoder will be used + @param operationQueue A PINOperationQueue to run asynchronous operations + @param ttlCache Whether or not the cache should behave as a TTL cache. + @result A new cache with the specified name. + */ +- (instancetype)initWithName:(nonnull NSString *)name + prefix:(nonnull NSString *)prefix + rootPath:(nonnull NSString *)rootPath + serializer:(nullable PINDiskCacheSerializerBlock)serializer + deserializer:(nullable PINDiskCacheDeserializerBlock)deserializer + keyEncoder:(nullable PINDiskCacheKeyEncoderBlock)keyEncoder + keyDecoder:(nullable PINDiskCacheKeyDecoderBlock)keyDecoder + operationQueue:(nonnull PINOperationQueue *)operationQueue + ttlCache:(BOOL)ttlCache; + +/** + @see name + @param name The name of the cache. + @param prefix The prefix for the cache name. Defaults to com.pinterest.PINDiskCache + @param rootPath The path of the cache. + @param serializer A block used to serialize object. If nil provided, default NSKeyedArchiver serialized will be used. + @param deserializer A block used to deserialize object. If nil provided, default NSKeyedUnarchiver serialized will be used. + @param keyEncoder A block used to encode key(filename). If nil provided, default url encoder will be used + @param keyDecoder A block used to decode key(filename). If nil provided, default url decoder will be used + @param operationQueue A PINOperationQueue to run asynchronous operations + @param ttlCache Whether or not the cache should behave as a TTL cache. + @param byteLimit The maximum number of bytes allowed on disk. Defaults to 50MB. + @param ageLimit The maximum number of seconds an object is allowed to exist in the cache. Defaults to 30 days. + @result A new cache with the specified name. + */ +- (instancetype)initWithName:(nonnull NSString *)name + prefix:(nonnull NSString *)prefix + rootPath:(nonnull NSString *)rootPath + serializer:(nullable PINDiskCacheSerializerBlock)serializer + deserializer:(nullable PINDiskCacheDeserializerBlock)deserializer + keyEncoder:(nullable PINDiskCacheKeyEncoderBlock)keyEncoder + keyDecoder:(nullable PINDiskCacheKeyDecoderBlock)keyDecoder + operationQueue:(nonnull PINOperationQueue *)operationQueue + ttlCache:(BOOL)ttlCache + byteLimit:(NSUInteger)byteLimit + ageLimit:(NSTimeInterval)ageLimit; + +/** + The designated initializer allowing you to override default NSKeyedArchiver/NSKeyedUnarchiver serialization. + + @see name + @param name The name of the cache. + @param prefix The prefix for the cache name. Defaults to com.pinterest.PINDiskCache + @param rootPath The path of the cache. + @param serializer A block used to serialize object. If nil provided, default NSKeyedArchiver serialized will be used. + @param deserializer A block used to deserialize object. If nil provided, default NSKeyedUnarchiver serialized will be used. + @param keyEncoder A block used to encode key(filename). If nil provided, default url encoder will be used + @param keyDecoder A block used to decode key(filename). If nil provided, default url decoder will be used + @param operationQueue A PINOperationQueue to run asynchronous operations + @param ttlCache Whether or not the cache should behave as a TTL cache. + @param byteLimit The maximum number of bytes allowed on disk. Defaults to 50MB. + @param ageLimit The maximum number of seconds an object is allowed to exist in the cache. Defaults to 30 days. + @param evictionStrategy How the cache decides to evict objects + @result A new cache with the specified name. + */ +- (instancetype)initWithName:(nonnull NSString *)name + prefix:(nonnull NSString *)prefix + rootPath:(nonnull NSString *)rootPath + serializer:(nullable PINDiskCacheSerializerBlock)serializer + deserializer:(nullable PINDiskCacheDeserializerBlock)deserializer + keyEncoder:(nullable PINDiskCacheKeyEncoderBlock)keyEncoder + keyDecoder:(nullable PINDiskCacheKeyDecoderBlock)keyDecoder + operationQueue:(nonnull PINOperationQueue *)operationQueue + ttlCache:(BOOL)ttlCache + byteLimit:(NSUInteger)byteLimit + ageLimit:(NSTimeInterval)ageLimit + evictionStrategy:(PINCacheEvictionStrategy)evictionStrategy NS_DESIGNATED_INITIALIZER; + +#pragma mark - Asynchronous Methods +/// @name Asynchronous Methods +/** + Locks access to ivars and allows safe interaction with files on disk. This method returns immediately. + + @warning Calling synchronous methods on the diskCache inside this block will likely cause a deadlock. + + @param block A block to be executed when a lock is available. + */ +- (void)lockFileAccessWhileExecutingBlockAsync:(PINCacheBlock)block; + +/** + Retrieves the object for the specified key. This method returns immediately and executes the passed + block as soon as the object is available. + + @param key The key associated with the requested object. + @param block A block to be executed serially when the object is available. + */ +- (void)objectForKeyAsync:(NSString *)key completion:(nullable PINDiskCacheObjectBlock)block; + +/** + Retrieves the fileURL for the specified key without actually reading the data from disk. This method + returns immediately and executes the passed block as soon as the object is available. + + @warning Access is protected for the duration of the block, but to maintain safe disk access do not + access this fileURL after the block has ended. + + @warning The PINDiskCache lock is held while block is executed. Any synchronous calls to the diskcache + or a cache which owns the instance of the disk cache are likely to cause a deadlock. This is why the block is + *not* passed the instance of the disk cache. You should also avoid doing extensive work while this + lock is held. + + @param key The key associated with the requested object. + @param block A block to be executed serially when the file URL is available. + */ +- (void)fileURLForKeyAsync:(NSString *)key completion:(PINDiskCacheFileURLBlock)block; + +/** + Stores an object in the cache for the specified key. This method returns immediately and executes the + passed block as soon as the object has been stored. + + @param object An object to store in the cache. + @param key A key to associate with the object. This string will be copied. + @param block A block to be executed serially after the object has been stored, or nil. + */ +- (void)setObjectAsync:(id )object forKey:(NSString *)key completion:(nullable PINDiskCacheObjectBlock)block; + +/** + Stores an object in the cache for the specified key and age limit. This method returns immediately and executes the + passed block as soon as the object has been stored. + + @param object An object to store in the cache. + @param key A key to associate with the object. This string will be copied. + @param ageLimit The age limit (in seconds) to associate with the object. An age limit <= 0 means there is no object-level age limit and the cache-level TTL + will be used for this object. + @param block A block to be executed serially after the object has been stored, or nil. + */ +- (void)setObjectAsync:(id )object forKey:(NSString *)key withAgeLimit:(NSTimeInterval)ageLimit completion:(nullable PINDiskCacheObjectBlock)block; + +/** + Stores an object in the cache for the specified key and the specified memory cost. If the cost causes the total + to go over the the cache is trimmed (oldest objects first). This method returns immediately + and executes the passed block after the object has been stored, potentially in parallel with other blocks + on the . + + @param object An object to store in the cache. + @param key A key to associate with the object. This string will be copied. + @param cost An amount to add to the . + @param block A block to be executed concurrently after the object has been stored, or nil. + */ +- (void)setObjectAsync:(id )object forKey:(NSString *)key withCost:(NSUInteger)cost completion:(nullable PINCacheObjectBlock)block; + +/** + Stores an object in the cache for the specified key and the specified memory cost and age limit. If the cost causes the total + to go over the the cache is trimmed (oldest objects first). This method returns immediately + and executes the passed block after the object has been stored, potentially in parallel with other blocks + on the . + + @param object An object to store in the cache. + @param key A key to associate with the object. This string will be copied. + @param cost An amount to add to the . + @param ageLimit The age limit (in seconds) to associate with the object. An age limit <= 0 means there is no object-level age limit and the cache-level TTL will be used for + this object. + @param block A block to be executed concurrently after the object has been stored, or nil. + */ +- (void)setObjectAsync:(id )object forKey:(NSString *)key withCost:(NSUInteger)cost ageLimit:(NSTimeInterval)ageLimit completion:(nullable PINCacheObjectBlock)block; + +/** + Removes the object for the specified key. This method returns immediately and executes the passed block + as soon as the object has been removed. + + @param key The key associated with the object to be removed. + @param block A block to be executed serially after the object has been removed, or nil. + */ +- (void)removeObjectForKeyAsync:(NSString *)key completion:(nullable PINDiskCacheObjectBlock)block; + +/** + Removes objects from the cache, largest first, until the cache is equal to or smaller than the specified byteCount. + This method returns immediately and executes the passed block as soon as the cache has been trimmed. + + @param byteCount The cache will be trimmed equal to or smaller than this size. + @param block A block to be executed serially after the cache has been trimmed, or nil. + */ +- (void)trimToSizeAsync:(NSUInteger)byteCount completion:(nullable PINCacheBlock)block; + +/** + Removes objects from the cache, using the eviction strategy, until the cache is equal to or smaller + than the specified byteCount. This method returns immediately and executes the passed block as soon as the cache has + been trimmed. + + @param byteCount The cache will be trimmed equal to or smaller than this size. + @param block A block to be executed serially after the cache has been trimmed, or nil. + + @note This will not remove objects that have been added via one of the @c -setObject:forKey:withAgeLimit methods. + */ +- (void)trimToSizeByEvictionStrategyAsync:(NSUInteger)byteCount completion:(nullable PINCacheBlock)block; + +/** + Loops through all objects in the cache (reads and writes are suspended during the enumeration). Data is not actually + read from disk, the `object` parameter of the block will be `nil` but the `fileURL` will be available. + This method returns immediately. + + @param block A block to be executed for every object in the cache. + @param completionBlock An optional block to be executed after the enumeration is complete. + + @warning The PINDiskCache lock is held while block is executed. Any synchronous calls to the diskcache + or a cache which owns the instance of the disk cache are likely to cause a deadlock. This is why the block is + *not* passed the instance of the disk cache. You should also avoid doing extensive work while this + lock is held. + + */ +- (void)enumerateObjectsWithBlockAsync:(PINDiskCacheFileURLEnumerationBlock)block completionBlock:(nullable PINCacheBlock)completionBlock; + +#pragma mark - Synchronous Methods +/// @name Synchronous Methods + +/** + Locks access to ivars and allows safe interaction with files on disk. This method only returns once the block + has been run. + + @warning Calling synchronous methods on the diskCache inside this block will likely cause a deadlock. + + @param block A block to be executed when a lock is available. + */ +- (void)synchronouslyLockFileAccessWhileExecutingBlock:(PIN_NOESCAPE PINCacheBlock)block; + +/** + Retrieves the object for the specified key. This method blocks the calling thread until the + object is available. + + @see objectForKeyAsync:completion: + @param key The key associated with the object. + @result The object for the specified key. + */ +- (nullable id )objectForKey:(NSString *)key; + +/** + Retrieves the file URL for the specified key. This method blocks the calling thread until the + url is available. Do not use this URL anywhere except with . This method probably + shouldn't even exist, just use the asynchronous one. + + @see fileURLForKeyAsync:completion: + @param key The key associated with the object. + @result The file URL for the specified key. + */ +- (nullable NSURL *)fileURLForKey:(nullable NSString *)key; + +/** + Stores an object in the cache for the specified key. This method blocks the calling thread until + the object has been stored. + + @see setObjectAsync:forKey:completion: + @param object An object to store in the cache. + @param key A key to associate with the object. This string will be copied. + */ +- (void)setObject:(nullable id )object forKey:(NSString *)key; + +/** + Stores an object in the cache for the specified key and age limit. This method blocks the calling thread until + the object has been stored. + + @see setObjectAsync:forKey:completion: + @param object An object to store in the cache. + @param key A key to associate with the object. This string will be copied. + @param ageLimit The age limit (in seconds) to associate with the object. An age limit <= 0 means there is + no object-level age limit and the cache-level TTL will be used for this object. + */ +- (void)setObject:(nullable id )object forKey:(NSString *)key withAgeLimit:(NSTimeInterval)ageLimit; + +/** + Removes objects from the cache, largest first, until the cache is equal to or smaller than the + specified byteCount. This method blocks the calling thread until the cache has been trimmed. + + @see trimToSizeAsync: + @param byteCount The cache will be trimmed equal to or smaller than this size. + */ +- (void)trimToSize:(NSUInteger)byteCount; + +/** + Removes objects from the cache, using the defined evictionStrategy, until the cache is equal to or + smaller than the specified byteCount. This method blocks the calling thread until the cache has been trimmed. + + @see trimToSizeByEvictionStrategyAsync: + @param byteCount The cache will be trimmed equal to or smaller than this size. + + @note This will not remove objects that have been added via one of the @c -setObject:forKey:withAgeLimit methods. + */ +- (void)trimToSizeByEvictionStrategy:(NSUInteger)byteCount; + +/** + Loops through all objects in the cache (reads and writes are suspended during the enumeration). Data is not actually + read from disk, the `object` parameter of the block will be `nil` but the `fileURL` will be available. + This method blocks the calling thread until all objects have been enumerated. + + @see enumerateObjectsWithBlockAsync:completionBlock + @param block A block to be executed for every object in the cache. + + @warning Do not call this method within the event blocks (, etc.) + Instead use the asynchronous version, . + + @warning The PINDiskCache lock is held while block is executed. Any synchronous calls to the diskcache + or a cache which owns the instance of the disk cache are likely to cause a deadlock. This is why the block is + *not* passed the instance of the disk cache. You should also avoid doing extensive work while this + lock is held. + + */ +- (void)enumerateObjectsWithBlock:(PIN_NOESCAPE PINDiskCacheFileURLEnumerationBlock)block; + +@end + + +#pragma mark - Deprecated + +/** + A callback block which provides only the cache as an argument + */ +typedef void (^PINDiskCacheBlock)(PINDiskCache *cache); + +@interface PINDiskCache (Deprecated) +- (void)lockFileAccessWhileExecutingBlock:(nullable PINCacheBlock)block __attribute__((deprecated)); +- (void)containsObjectForKey:(NSString *)key block:(PINDiskCacheContainsBlock)block __attribute__((deprecated)); +- (void)objectForKey:(NSString *)key block:(nullable PINDiskCacheObjectBlock)block __attribute__((deprecated)); +- (void)fileURLForKey:(NSString *)key block:(nullable PINDiskCacheFileURLBlock)block __attribute__((deprecated)); +- (void)setObject:(id )object forKey:(NSString *)key block:(nullable PINDiskCacheObjectBlock)block __attribute__((deprecated)); +- (void)removeObjectForKey:(NSString *)key block:(nullable PINDiskCacheObjectBlock)block __attribute__((deprecated)); +- (void)trimToDate:(NSDate *)date block:(nullable PINDiskCacheBlock)block __attribute__((deprecated)); +- (void)trimToSize:(NSUInteger)byteCount block:(nullable PINDiskCacheBlock)block __attribute__((deprecated)); +- (void)trimToSizeByDate:(NSUInteger)byteCount block:(nullable PINDiskCacheBlock)block __attribute__((deprecated)); +- (void)removeAllObjects:(nullable PINDiskCacheBlock)block __attribute__((deprecated)); +- (void)enumerateObjectsWithBlock:(PINDiskCacheFileURLBlock)block completionBlock:(nullable PINDiskCacheBlock)completionBlock __attribute__((deprecated)); +- (void)setTtlCache:(BOOL)ttlCache DEPRECATED_MSG_ATTRIBUTE("ttlCache is no longer a settable property and must now be set via initializer."); +- (void)trimToSizeByDate:(NSUInteger)byteCount DEPRECATED_MSG_ATTRIBUTE("Use trimToSizeByEvictionStrategy: instead"); +- (void)trimToSizeByDateAsync:(NSUInteger)byteCount completion:(nullable PINCacheBlock)block DEPRECATED_MSG_ATTRIBUTE("Use trimToSizeByEvictionStrategyAsync:completion: instead"); +@end + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/PINCache/Source/PINDiskCache.m b/Carthage/Checkouts/PINCache/Source/PINDiskCache.m new file mode 100644 index 00000000..fc6b0c81 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Source/PINDiskCache.m @@ -0,0 +1,1858 @@ +// PINCache is a modified version of TMCache +// Modifications by Garrett Moon +// Copyright (c) 2015 Pinterest. All rights reserved. + +#import "PINDiskCache.h" + +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 +#import +#endif + +#import +#import + +#import + +#define PINDiskCacheError(error) if (error) { NSLog(@"%@ (%d) ERROR: %@", \ +[[NSString stringWithUTF8String:__FILE__] lastPathComponent], \ +__LINE__, [error localizedDescription]); } + +#define PINDiskCacheException(exception) if (exception) { NSAssert(NO, [exception reason]); } + +const char * PINDiskCacheAgeLimitAttributeName = "com.pinterest.PINDiskCache.ageLimit"; +const char * PINDiskCacheAccessCountAttributeName = "com.pinterest.PINDiskCache.accessCount"; +NSString * const PINDiskCacheErrorDomain = @"com.pinterest.PINDiskCache"; +NSErrorUserInfoKey const PINDiskCacheErrorReadFailureCodeKey = @"PINDiskCacheErrorReadFailureCodeKey"; +NSErrorUserInfoKey const PINDiskCacheErrorWriteFailureCodeKey = @"PINDiskCacheErrorWriteFailureCodeKey"; +NSString * const PINDiskCachePrefix = @"com.pinterest.PINDiskCache"; +static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared"; + +NSUInteger PINDiskCacheDefaultByteLimit = 50 * 1024 * 1024; // 50 MB by default +NSTimeInterval PINDiskCacheDefaultAgeLimit = 60 * 60 * 24 * 30; // 30 days by default + +static NSString * const PINDiskCacheOperationIdentifierTrimToDate = @"PINDiskCacheOperationIdentifierTrimToDate"; +static NSString * const PINDiskCacheOperationIdentifierTrimToSize = @"PINDiskCacheOperationIdentifierTrimToSize"; +static NSString * const PINDiskCacheOperationIdentifierTrimToSizeByDate = @"PINDiskCacheOperationIdentifierTrimToSizeByDate"; + +typedef NS_ENUM(NSUInteger, PINDiskCacheCondition) { + PINDiskCacheConditionNotReady = 0, + PINDiskCacheConditionReady = 1, +}; + +static PINOperationDataCoalescingBlock PINDiskTrimmingSizeCoalescingBlock = ^id(NSNumber *existingSize, NSNumber *newSize) { + NSComparisonResult result = [existingSize compare:newSize]; + return (result == NSOrderedDescending) ? newSize : existingSize; +}; + +static PINOperationDataCoalescingBlock PINDiskTrimmingDateCoalescingBlock = ^id(NSDate *existingDate, NSDate *newDate) { + NSComparisonResult result = [existingDate compare:newDate]; + return (result == NSOrderedDescending) ? newDate : existingDate; +}; + +const char * PINDiskCacheFileSystemRepresentation(NSURL *url) +{ + return url.fileSystemRepresentation; +} + +@interface PINDiskCacheMetadata : NSObject +// When the object was added to the disk cache +@property (nonatomic, strong) NSDate *createdDate; +// Last time the object was accessed +@property (nonatomic, strong) NSDate *lastModifiedDate; +@property (nonatomic, strong) NSNumber *size; +// Age limit is used in conjuction with ttl +@property (nonatomic) NSTimeInterval ageLimit; +// Access count is how many times this object has been fetched. Used with the LFU +@property (nonatomic) NSInteger accessCount; +@end + +@interface PINDiskCache () { + PINDiskCacheSerializerBlock _serializer; + PINDiskCacheDeserializerBlock _deserializer; + + PINDiskCacheKeyEncoderBlock _keyEncoder; + PINDiskCacheKeyDecoderBlock _keyDecoder; +} + +@property (assign, nonatomic) pthread_mutex_t mutex; +@property (copy, nonatomic) NSString *name; +@property (assign) NSUInteger byteCount; +@property (strong, nonatomic) NSURL *cacheURL; +@property (strong, nonatomic) PINOperationQueue *operationQueue; +@property (strong, nonatomic) NSMutableDictionary *metadata; +@property (assign, nonatomic) pthread_cond_t diskWritableCondition; +@property (assign, nonatomic) BOOL diskWritable; +@property (assign, nonatomic) pthread_cond_t diskStateKnownCondition; +@property (assign, nonatomic) BOOL diskStateKnown; +@property (assign, nonatomic) BOOL writingProtectionOptionSet; +@end + +@implementation PINDiskCache + +static NSURL *_sharedTrashURL; + +@synthesize willAddObjectBlock = _willAddObjectBlock; +@synthesize willRemoveObjectBlock = _willRemoveObjectBlock; +@synthesize willRemoveAllObjectsBlock = _willRemoveAllObjectsBlock; +@synthesize didAddObjectBlock = _didAddObjectBlock; +@synthesize didRemoveObjectBlock = _didRemoveObjectBlock; +@synthesize didRemoveAllObjectsBlock = _didRemoveAllObjectsBlock; +@synthesize byteLimit = _byteLimit; +@synthesize ageLimit = _ageLimit; +@synthesize ttlCache = _ttlCache; + +#if TARGET_OS_IPHONE +@synthesize writingProtectionOption = _writingProtectionOption; +@synthesize writingProtectionOptionSet = _writingProtectionOptionSet; +#endif + +#pragma mark - Initialization - + +- (void)dealloc +{ + __unused int result = pthread_mutex_destroy(&_mutex); + NSCAssert(result == 0, @"Failed to destroy lock in PINDiskCache %p. Code: %d", (void *)self, result); + pthread_cond_destroy(&_diskWritableCondition); + pthread_cond_destroy(&_diskStateKnownCondition); +} + +- (instancetype)init +{ + @throw [NSException exceptionWithName:@"Must initialize with a name" reason:@"PINDiskCache must be initialized with a name. Call initWithName: instead." userInfo:nil]; + return [self initWithName:@""]; +} + +- (instancetype)initWithName:(NSString *)name +{ + return [self initWithName:name rootPath:[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0]]; +} + +- (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath +{ + return [self initWithName:name rootPath:rootPath serializer:nil deserializer:nil]; +} + +- (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath serializer:(PINDiskCacheSerializerBlock)serializer deserializer:(PINDiskCacheDeserializerBlock)deserializer +{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + return [self initWithName:name rootPath:rootPath serializer:serializer deserializer:deserializer operationQueue:[PINOperationQueue sharedOperationQueue]]; +#pragma clang diagnostic pop +} + +- (instancetype)initWithName:(NSString *)name + rootPath:(NSString *)rootPath + serializer:(PINDiskCacheSerializerBlock)serializer + deserializer:(PINDiskCacheDeserializerBlock)deserializer + operationQueue:(PINOperationQueue *)operationQueue +{ + return [self initWithName:name + prefix:PINDiskCachePrefix + rootPath:rootPath + serializer:serializer + deserializer:deserializer + keyEncoder:nil + keyDecoder:nil + operationQueue:operationQueue]; +} + +- (instancetype)initWithName:(NSString *)name + prefix:(NSString *)prefix + rootPath:(NSString *)rootPath + serializer:(PINDiskCacheSerializerBlock)serializer + deserializer:(PINDiskCacheDeserializerBlock)deserializer + keyEncoder:(PINDiskCacheKeyEncoderBlock)keyEncoder + keyDecoder:(PINDiskCacheKeyDecoderBlock)keyDecoder + operationQueue:(PINOperationQueue *)operationQueue +{ + return [self initWithName:name prefix:prefix + rootPath:rootPath + serializer:serializer + deserializer:deserializer + keyEncoder:keyEncoder + keyDecoder:keyDecoder + operationQueue:operationQueue + ttlCache:NO]; +} + +- (instancetype)initWithName:(NSString *)name + prefix:(NSString *)prefix + rootPath:(NSString *)rootPath + serializer:(PINDiskCacheSerializerBlock)serializer + deserializer:(PINDiskCacheDeserializerBlock)deserializer + keyEncoder:(PINDiskCacheKeyEncoderBlock)keyEncoder + keyDecoder:(PINDiskCacheKeyDecoderBlock)keyDecoder + operationQueue:(PINOperationQueue *)operationQueue + ttlCache:(BOOL)ttlCache +{ + return [self initWithName:name prefix:prefix + rootPath:rootPath + serializer:serializer + deserializer:deserializer + keyEncoder:keyEncoder + keyDecoder:keyDecoder + operationQueue:operationQueue + ttlCache:ttlCache + byteLimit:PINDiskCacheDefaultByteLimit + ageLimit:PINDiskCacheDefaultAgeLimit]; +} + +- (instancetype)initWithName:(nonnull NSString *)name + prefix:(nonnull NSString *)prefix + rootPath:(nonnull NSString *)rootPath + serializer:(nullable PINDiskCacheSerializerBlock)serializer + deserializer:(nullable PINDiskCacheDeserializerBlock)deserializer + keyEncoder:(nullable PINDiskCacheKeyEncoderBlock)keyEncoder + keyDecoder:(nullable PINDiskCacheKeyDecoderBlock)keyDecoder + operationQueue:(nonnull PINOperationQueue *)operationQueue + ttlCache:(BOOL)ttlCache + byteLimit:(NSUInteger)byteLimit + ageLimit:(NSTimeInterval)ageLimit +{ + return [self initWithName:name + prefix:prefix + rootPath:rootPath + serializer:serializer + deserializer:deserializer + keyEncoder:keyEncoder + keyDecoder:keyDecoder + operationQueue:operationQueue + ttlCache:ttlCache + byteLimit:byteLimit + ageLimit:ageLimit + evictionStrategy:PINCacheEvictionStrategyLeastRecentlyUsed]; + +} + +- (instancetype)initWithName:(NSString *)name + prefix:(NSString *)prefix + rootPath:(NSString *)rootPath + serializer:(PINDiskCacheSerializerBlock)serializer + deserializer:(PINDiskCacheDeserializerBlock)deserializer + keyEncoder:(PINDiskCacheKeyEncoderBlock)keyEncoder + keyDecoder:(PINDiskCacheKeyDecoderBlock)keyDecoder + operationQueue:(PINOperationQueue *)operationQueue + ttlCache:(BOOL)ttlCache + byteLimit:(NSUInteger)byteLimit + ageLimit:(NSTimeInterval)ageLimit + evictionStrategy:(PINCacheEvictionStrategy)evictionStrategy +{ + if (!name) { + return nil; + } + + NSAssert(((!serializer && !deserializer) || (serializer && deserializer)), + @"PINDiskCache must be initialized with a serializer AND deserializer."); + + NSAssert(((!keyEncoder && !keyDecoder) || (keyEncoder && keyDecoder)), + @"PINDiskCache must be initialized with an encoder AND decoder."); + + if (self = [super init]) { + __unused int result = pthread_mutex_init(&_mutex, NULL); + NSAssert(result == 0, @"Failed to init lock in PINDiskCache %@. Code: %d", self, result); + + _name = [name copy]; + _prefix = [prefix copy]; + _operationQueue = operationQueue; + _ttlCache = ttlCache; + _willAddObjectBlock = nil; + _willRemoveObjectBlock = nil; + _willRemoveAllObjectsBlock = nil; + _didAddObjectBlock = nil; + _didRemoveObjectBlock = nil; + _didRemoveAllObjectsBlock = nil; + + _byteCount = 0; + _byteLimit = byteLimit; + _ageLimit = ageLimit; + _evictionStrategy = evictionStrategy; + +#if TARGET_OS_IPHONE + _writingProtectionOptionSet = NO; + // This is currently the default for files, but we'd rather not write it if it's unspecified. + _writingProtectionOption = NSDataWritingFileProtectionCompleteUntilFirstUserAuthentication; +#endif + + _metadata = [[NSMutableDictionary alloc] init]; + _diskStateKnown = NO; + + _cacheURL = [[self class] cacheURLWithRootPath:rootPath prefix:_prefix name:_name]; + + //setup serializers + if(serializer) { + _serializer = [serializer copy]; + } else { + _serializer = self.defaultSerializer; + } + + if(deserializer) { + _deserializer = [deserializer copy]; + } else { + _deserializer = self.defaultDeserializer; + } + + //setup key encoder/decoder + if(keyEncoder) { + _keyEncoder = [keyEncoder copy]; + } else { + _keyEncoder = self.defaultKeyEncoder; + } + + if(keyDecoder) { + _keyDecoder = [keyDecoder copy]; + } else { + _keyDecoder = self.defaultKeyDecoder; + } + + pthread_cond_init(&_diskWritableCondition, NULL); + pthread_cond_init(&_diskStateKnownCondition, NULL); + + //we don't want to do anything without setting up the disk cache, but we also don't want to block init, it can take a while to initialize. This must *not* be done on _operationQueue because other operations added may hold the lock and fill up the queue. + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [self lock]; + [self _locked_createCacheDirectory]; + [self unlock]; + [self initializeDiskProperties]; + }); + } + return self; +} + +- (NSString *)description +{ + return [[NSString alloc] initWithFormat:@"%@.%@.%p", PINDiskCachePrefix, _name, (__bridge void *)self]; +} + ++ (PINDiskCache *)sharedCache +{ + static PINDiskCache *cache; + static dispatch_once_t predicate; + + dispatch_once(&predicate, ^{ + cache = [[PINDiskCache alloc] initWithName:PINDiskCacheSharedName]; + }); + + return cache; +} + ++ (NSURL *)cacheURLWithRootPath:(NSString *)rootPath prefix:(NSString *)prefix name:(NSString *)name +{ + NSString *pathComponent = [[NSString alloc] initWithFormat:@"%@.%@", prefix, name]; + return [NSURL fileURLWithPathComponents:@[ rootPath, pathComponent ]]; +} + +#pragma mark - Private Methods - + +- (NSURL *)encodedFileURLForKey:(NSString *)key +{ + if (![key length]) + return nil; + + //Significantly improve performance by indicating that the URL will *not* result in a directory. + //Also note that accessing _cacheURL is safe without the lock because it is only set on init. + return [_cacheURL URLByAppendingPathComponent:[self encodedString:key] isDirectory:NO]; +} + +- (NSString *)keyForEncodedFileURL:(NSURL *)url +{ + NSString *fileName = [url lastPathComponent]; + if (!fileName) + return nil; + + return [self decodedString:fileName]; +} + +- (NSString *)encodedString:(NSString *)string +{ + return _keyEncoder(string); +} + +- (NSString *)decodedString:(NSString *)string +{ + return _keyDecoder(string); +} + +- (PINDiskCacheSerializerBlock)defaultSerializer +{ + return ^NSData*(id object, NSString *key){ + NSError *error = nil; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:object requiringSecureCoding:NO error:&error]; + PINDiskCacheError(error); + return data; + }; +} + +- (PINDiskCacheDeserializerBlock)defaultDeserializer +{ + return ^id(NSData * data, NSString *key){ + NSError *error = nil; + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data error:&error]; + NSAssert(!error, @"unarchiver init failed with error"); + unarchiver.requiresSecureCoding = NO; + return [unarchiver decodeObjectForKey:NSKeyedArchiveRootObjectKey]; + }; +} + +- (PINDiskCacheKeyEncoderBlock)defaultKeyEncoder +{ + return ^NSString *(NSString *decodedKey) { + if (![decodedKey length]) { + return @""; + } + + NSString *encodedString = [decodedKey stringByAddingPercentEncodingWithAllowedCharacters:[[NSCharacterSet characterSetWithCharactersInString:@".:/%"] invertedSet]]; + return encodedString; + }; +} + +- (PINDiskCacheKeyEncoderBlock)defaultKeyDecoder +{ + return ^NSString *(NSString *encodedKey) { + if (![encodedKey length]) { + return @""; + } + + return [encodedKey stringByRemovingPercentEncoding]; + }; +} + + +#pragma mark - Private Trash Methods - + ++ (dispatch_queue_t)sharedTrashQueue +{ + static dispatch_queue_t trashQueue; + static dispatch_once_t predicate; + + dispatch_once(&predicate, ^{ + NSString *queueName = [[NSString alloc] initWithFormat:@"%@.trash", PINDiskCachePrefix]; + trashQueue = dispatch_queue_create([queueName UTF8String], DISPATCH_QUEUE_SERIAL); + dispatch_set_target_queue(trashQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)); + }); + + return trashQueue; +} + ++ (NSLock *)sharedLock +{ + static NSLock *sharedLock; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedLock = [NSLock new]; + }); + return sharedLock; +} + ++ (NSURL *)sharedTrashURL +{ + NSAssert(![[PINDiskCache sharedLock] tryLock] || ([[PINDiskCache sharedLock] unlock], NO), + @"+[sharedTrashURL] must be called with +[sharedLock] held."); + if (_sharedTrashURL == nil) { + NSString *uniqueString = [[NSProcessInfo processInfo] globallyUniqueString]; + _sharedTrashURL = [[[NSURL alloc] initFileURLWithPath:NSTemporaryDirectory()] URLByAppendingPathComponent:uniqueString isDirectory:YES]; + + NSError *error = nil; + [[NSFileManager defaultManager] createDirectoryAtURL:_sharedTrashURL + withIntermediateDirectories:YES + attributes:nil + error:&error]; + PINDiskCacheError(error); + } + return _sharedTrashURL; +} + ++ (BOOL)moveItemAtURLToTrashOrRemove:(NSURL *)itemURL +{ + if (![[NSFileManager defaultManager] fileExistsAtPath:[itemURL path]]) + return NO; + + NSError *error = nil; + NSString *uniqueString = [[NSProcessInfo processInfo] globallyUniqueString]; + + [[PINDiskCache sharedLock] lock]; + NSURL *uniqueTrashURL = [[PINDiskCache sharedTrashURL] URLByAppendingPathComponent:uniqueString + isDirectory:NO]; + BOOL moved = [[NSFileManager defaultManager] moveItemAtURL:itemURL toURL:uniqueTrashURL error:&error]; + [[PINDiskCache sharedLock] unlock]; + PINDiskCacheError(error); + BOOL removed = NO; + if (!moved) { + // Delete the item synchronously as a fallback. + removed = [[NSFileManager defaultManager] removeItemAtURL:itemURL error:&error]; + PINDiskCacheError(error); + } + return moved || removed; +} + ++ (void)emptyTrash +{ + dispatch_async([PINDiskCache sharedTrashQueue], ^{ + NSURL *trashURL = nil; + + // If _sharedTrashURL is unset, there's nothing left to do because it hasn't been accessed and therefore items haven't been added to it. + // If it is set, we can just remove it. + // We also need to nil out _sharedTrashURL so that a new one will be created if there's an attempt to move a new file to the trash. + [[PINDiskCache sharedLock] lock]; + if (_sharedTrashURL != nil) { + trashURL = _sharedTrashURL; + _sharedTrashURL = nil; + } + [[PINDiskCache sharedLock] unlock]; + + if (trashURL != nil) { + NSError *removeTrashedItemError = nil; + [[NSFileManager defaultManager] removeItemAtURL:trashURL error:&removeTrashedItemError]; + PINDiskCacheError(removeTrashedItemError); + } + }); +} + +#pragma mark - Private Queue Methods - + +- (BOOL)_locked_createCacheDirectory +{ + BOOL created = NO; + if ([[NSFileManager defaultManager] fileExistsAtPath:[_cacheURL path]] == NO) { + NSError *error = nil; + created = [[NSFileManager defaultManager] createDirectoryAtURL:_cacheURL + withIntermediateDirectories:YES + attributes:nil + error:&error]; + PINDiskCacheError(error); + } + + + + // while this may not be true if success is false, it's better than deadlocking later. + _diskWritable = YES; + pthread_cond_broadcast(&_diskWritableCondition); + + return created; +} + ++ (NSArray *)resourceKeys +{ + static NSArray *resourceKeys = nil; + static dispatch_once_t predicate; + + dispatch_once(&predicate, ^{ + resourceKeys = @[ NSURLCreationDateKey, NSURLContentModificationDateKey, NSURLTotalFileAllocatedSizeKey ]; + }); + + return resourceKeys; +} + +/** + * @return File size in bytes. + */ +- (NSUInteger)_locked_initializeDiskPropertiesForFile:(NSURL *)fileURL fileKey:(NSString *)fileKey +{ + NSError *error = nil; + + NSDictionary *dictionary = [fileURL resourceValuesForKeys:[PINDiskCache resourceKeys] error:&error]; + PINDiskCacheError(error); + + if (_metadata[fileKey] == nil) { + _metadata[fileKey] = [[PINDiskCacheMetadata alloc] init]; + } + + NSDate *createdDate = dictionary[NSURLCreationDateKey]; + if (createdDate && fileKey) + _metadata[fileKey].createdDate = createdDate; + + NSDate *lastModifiedDate = dictionary[NSURLContentModificationDateKey]; + if (lastModifiedDate && fileKey) + _metadata[fileKey].lastModifiedDate = lastModifiedDate; + + NSNumber *fileSize = dictionary[NSURLTotalFileAllocatedSizeKey]; + if (fileSize) { + _metadata[fileKey].size = fileSize; + } + + if (_ttlCache) { + NSTimeInterval ageLimit; + ssize_t res = getxattr(PINDiskCacheFileSystemRepresentation(fileURL), PINDiskCacheAgeLimitAttributeName, &ageLimit, sizeof(NSTimeInterval), 0, 0); + if(res > 0) { + _metadata[fileKey].ageLimit = ageLimit; + } else if (res == -1) { + // Ignore if the extended attribute was never recorded for this file. + if (errno != ENOATTR) { + NSDictionary *userInfo = @{ PINDiskCacheErrorReadFailureCodeKey : @(errno)}; + error = [NSError errorWithDomain:PINDiskCacheErrorDomain code:PINDiskCacheErrorReadFailure userInfo:userInfo]; + PINDiskCacheError(error); + } + } + } + + NSInteger accessCount = 0; + ssize_t accessCountResult = getxattr(PINDiskCacheFileSystemRepresentation(fileURL), PINDiskCacheAccessCountAttributeName, &accessCount, sizeof(NSInteger), 0, 0); + if(accessCountResult > 0) { + _metadata[fileKey].accessCount = accessCount; + } else if (accessCountResult == -1) { + // Ignore if the extended attribute was never recorded for this file. + if (errno != ENOATTR) { + NSDictionary *userInfo = @{ PINDiskCacheErrorReadFailureCodeKey : @(errno)}; + error = [NSError errorWithDomain:PINDiskCacheErrorDomain code:PINDiskCacheErrorReadFailure userInfo:userInfo]; + PINDiskCacheError(error); + } + } + + return [fileSize unsignedIntegerValue]; +} + +- (void)initializeDiskProperties +{ + NSUInteger byteCount = 0; + + NSError *error = nil; + + [self lock]; + NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:_cacheURL + includingPropertiesForKeys:[PINDiskCache resourceKeys] + options:NSDirectoryEnumerationSkipsHiddenFiles + error:&error]; + [self unlock]; + + PINDiskCacheError(error); + + for (NSURL *fileURL in files) { + NSString *fileKey = [self keyForEncodedFileURL:fileURL]; + // Continually grab and release lock while processing files to avoid contention + [self lock]; + if (_metadata[fileKey] == nil) { + byteCount += [self _locked_initializeDiskPropertiesForFile:fileURL fileKey:fileKey]; + } + [self unlock]; + } + + [self lock]; + if (byteCount > 0) + _byteCount = byteCount; + + if (self->_byteLimit > 0 && self->_byteCount > self->_byteLimit) + [self trimToSizeByEvictionStrategyAsync:self->_byteLimit completion:nil]; + + if (self->_ttlCache) + [self removeExpiredObjectsAsync:nil]; + + _diskStateKnown = YES; + pthread_cond_broadcast(&_diskStateKnownCondition); + [self unlock]; +} + +- (void)asynchronouslySetFileModificationDate:(NSDate *)date forURL:(NSURL *)fileURL +{ + [self.operationQueue scheduleOperation:^{ + [self lockForWriting]; + [self _locked_setFileModificationDate:date forURL:fileURL]; + [self unlock]; + } withPriority:PINOperationQueuePriorityLow]; +} + +- (BOOL)_locked_setFileModificationDate:(NSDate *)date forURL:(NSURL *)fileURL +{ + if (!date || !fileURL) { + return NO; + } + + NSError *error = nil; + BOOL success = [[NSFileManager defaultManager] setAttributes:@{ NSFileModificationDate: date } + ofItemAtPath:[fileURL path] + error:&error]; + PINDiskCacheError(error); + + return success; +} + +- (void)asynchronouslySetAgeLimit:(NSTimeInterval)ageLimit forURL:(NSURL *)fileURL +{ + [self.operationQueue scheduleOperation:^{ + [self lockForWriting]; + [self _locked_setAgeLimit:ageLimit forURL:fileURL]; + [self unlock]; + } withPriority:PINOperationQueuePriorityLow]; +} + +- (BOOL)_locked_setAgeLimit:(NSTimeInterval)ageLimit forURL:(NSURL *)fileURL +{ + if (!fileURL) { + return NO; + } + + NSError *error = nil; + if (ageLimit <= 0.0) { + if (removexattr(PINDiskCacheFileSystemRepresentation(fileURL), PINDiskCacheAgeLimitAttributeName, 0) != 0) { + // Ignore if the extended attribute was never recorded for this file. + if (errno != ENOATTR) { + NSDictionary *userInfo = @{ PINDiskCacheErrorWriteFailureCodeKey : @(errno)}; + error = [NSError errorWithDomain:PINDiskCacheErrorDomain code:PINDiskCacheErrorWriteFailure userInfo:userInfo]; + PINDiskCacheError(error); + } + } + } else { + if (setxattr(PINDiskCacheFileSystemRepresentation(fileURL), PINDiskCacheAgeLimitAttributeName, &ageLimit, sizeof(NSTimeInterval), 0, 0) != 0) { + NSDictionary *userInfo = @{ PINDiskCacheErrorWriteFailureCodeKey : @(errno)}; + error = [NSError errorWithDomain:PINDiskCacheErrorDomain code:PINDiskCacheErrorWriteFailure userInfo:userInfo]; + PINDiskCacheError(error); + } + } + + if (!error) { + NSString *key = [self keyForEncodedFileURL:fileURL]; + if (key) { + _metadata[key].ageLimit = ageLimit; + } + } + + return !error; +} + +- (void)asynchronouslySetAccessCount:(NSInteger)accessCount forURL:(NSURL *)fileURL +{ + [self.operationQueue scheduleOperation:^{ + [self lockForWriting]; + [self _locked_setAcessCount:accessCount forURL:fileURL]; + [self unlock]; + } withPriority:PINOperationQueuePriorityLow]; +} + +- (BOOL)_locked_setAcessCount:(NSInteger)accessCount forURL:(NSURL *)fileURL +{ + if (!fileURL) { + return NO; + } + + NSError *error = nil; + if (accessCount <= 0) { + if (removexattr(PINDiskCacheFileSystemRepresentation(fileURL), PINDiskCacheAccessCountAttributeName, 0) != 0) { + // Ignore if the extended attribute was never recorded for this file. + if (errno != ENOATTR) { + NSDictionary *userInfo = @{ PINDiskCacheErrorWriteFailureCodeKey : @(errno)}; + error = [NSError errorWithDomain:PINDiskCacheErrorDomain code:PINDiskCacheErrorWriteFailure userInfo:userInfo]; + PINDiskCacheError(error); + } + } + } else { + if (setxattr(PINDiskCacheFileSystemRepresentation(fileURL), PINDiskCacheAccessCountAttributeName, &accessCount, sizeof(NSInteger), 0, 0) != 0) { + NSDictionary *userInfo = @{ PINDiskCacheErrorWriteFailureCodeKey : @(errno)}; + error = [NSError errorWithDomain:PINDiskCacheErrorDomain code:PINDiskCacheErrorWriteFailure userInfo:userInfo]; + PINDiskCacheError(error); + } + } + + if (!error) { + NSString *key = [self keyForEncodedFileURL:fileURL]; + if (key) { + _metadata[key].accessCount = accessCount; + } + } + + return !error; +} + +- (BOOL)removeFileAndExecuteBlocksForKey:(NSString *)key +{ + NSURL *fileURL = [self encodedFileURLForKey:key]; + if (!fileURL) { + return NO; + } + + // We only need to lock until writable at the top because once writable, always writable + [self lockForWriting]; + if (![[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]]) { + [self unlock]; + return NO; + } + + PINDiskCacheObjectBlock willRemoveObjectBlock = _willRemoveObjectBlock; + if (willRemoveObjectBlock) { + [self unlock]; + willRemoveObjectBlock(self, key, nil); + [self lock]; + } + + BOOL trashed = [PINDiskCache moveItemAtURLToTrashOrRemove:fileURL]; + if (!trashed) { + [self unlock]; + return NO; + } + + [PINDiskCache emptyTrash]; + + NSNumber *byteSize = _metadata[key].size; + if (byteSize) + self.byteCount = _byteCount - [byteSize unsignedIntegerValue]; // atomic + + [_metadata removeObjectForKey:key]; + + PINDiskCacheObjectBlock didRemoveObjectBlock = _didRemoveObjectBlock; + if (didRemoveObjectBlock) { + [self unlock]; + _didRemoveObjectBlock(self, key, nil); + [self lock]; + } + + [self unlock]; + + return YES; +} + +- (void)trimDiskToSize:(NSUInteger)trimByteCount +{ + NSMutableArray *keysToRemove = nil; + + [self lockForWriting]; + if (_byteCount > trimByteCount) { + keysToRemove = [[NSMutableArray alloc] init]; + + NSArray *keysSortedBySize = [_metadata keysSortedByValueUsingComparator:^NSComparisonResult(PINDiskCacheMetadata * _Nonnull obj1, PINDiskCacheMetadata * _Nonnull obj2) { + return [obj1.size compare:obj2.size]; + }]; + + NSUInteger bytesSaved = 0; + for (NSString *key in [keysSortedBySize reverseObjectEnumerator]) { // largest objects first + [keysToRemove addObject:key]; + NSNumber *byteSize = _metadata[key].size; + if (byteSize) { + bytesSaved += [byteSize unsignedIntegerValue]; + } + if (_byteCount - bytesSaved <= trimByteCount) { + break; + } + } + } + [self unlock]; + + for (NSString *key in keysToRemove) { + [self removeFileAndExecuteBlocksForKey:key]; + } +} + +// This is the default trimming method which happens automatically +- (void)trimDiskToSizeByEvictionStrategy:(NSUInteger)trimByteCount +{ + if (self.isTTLCache) { + [self removeExpiredObjects]; + } + + NSMutableArray *keysToRemove = nil; + + [self lockForWriting]; + if (_byteCount > trimByteCount) { + PINCacheEvictionStrategy strategy = self->_evictionStrategy; + keysToRemove = [[NSMutableArray alloc] init]; + + // last modified represents last access. + NSArray *keysSortedByEvictionStrategy = nil; + switch (strategy) { + case PINCacheEvictionStrategyLeastRecentlyUsed: + keysSortedByEvictionStrategy = [_metadata keysSortedByValueUsingComparator:^NSComparisonResult(PINDiskCacheMetadata * _Nonnull obj1, PINDiskCacheMetadata * _Nonnull obj2) { + return [obj1.lastModifiedDate compare:obj2.lastModifiedDate]; + }]; + break; + + case PINCacheEvictionStrategyLeastFrequentlyUsed: + keysSortedByEvictionStrategy = [_metadata keysSortedByValueUsingComparator:^NSComparisonResult(PINDiskCacheMetadata * _Nonnull obj1, PINDiskCacheMetadata * _Nonnull obj2) { + if (obj1.accessCount < obj2.accessCount) { + return NSOrderedAscending; + } else if (obj1.accessCount > obj2.accessCount) { + return NSOrderedDescending; + } else { + return [obj1.lastModifiedDate compare:obj2.lastModifiedDate]; + } + }]; + break; + } + + NSUInteger bytesSaved = 0; + // objects accessed last first. + for (NSString *key in keysSortedByEvictionStrategy) { + [keysToRemove addObject:key]; + NSNumber *byteSize = _metadata[key].size; + if (byteSize) { + bytesSaved += [byteSize unsignedIntegerValue]; + } + if (_byteCount - bytesSaved <= trimByteCount) { + break; + } + } + } + [self unlock]; + + for (NSString *key in keysToRemove) { + [self removeFileAndExecuteBlocksForKey:key]; + } +} + +- (void)trimDiskToDate:(NSDate *)trimDate +{ + [self lockForWriting]; + NSArray *keysSortedByCreatedDate = [_metadata keysSortedByValueUsingComparator:^NSComparisonResult(PINDiskCacheMetadata * _Nonnull obj1, PINDiskCacheMetadata * _Nonnull obj2) { + return [obj1.createdDate compare:obj2.createdDate]; + }]; + + NSMutableArray *keysToRemove = [[NSMutableArray alloc] init]; + + for (NSString *key in keysSortedByCreatedDate) { // oldest files first + NSDate *createdDate = _metadata[key].createdDate; + if (!createdDate || _metadata[key].ageLimit > 0.0) + continue; + + if ([createdDate compare:trimDate] == NSOrderedAscending) { // older than trim date + [keysToRemove addObject:key]; + } else { + break; + } + } + [self unlock]; + + for (NSString *key in keysToRemove) { + [self removeFileAndExecuteBlocksForKey:key]; + } +} + +- (void)trimToAgeLimitRecursively +{ + [self lock]; + NSTimeInterval ageLimit = _ageLimit; + [self unlock]; + if (ageLimit == 0.0) + return; + + NSDate *date = [[NSDate alloc] initWithTimeIntervalSinceNow:-ageLimit]; + [self trimToDateAsync:date completion:nil]; + + dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(ageLimit * NSEC_PER_SEC)); + dispatch_after(time, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { + // Ensure that ageLimit is the same as when we were scheduled, otherwise, we've been + // rescheduled (another dispatch_after was issued) and should cancel. + BOOL shouldReschedule = YES; + [self lock]; + if (ageLimit != self->_ageLimit) { + shouldReschedule = NO; + } + [self unlock]; + + if (shouldReschedule) { + [self.operationQueue scheduleOperation:^{ + [self trimToAgeLimitRecursively]; + } withPriority:PINOperationQueuePriorityLow]; + } + }); +} + +#pragma mark - Public Asynchronous Methods - + +- (void)lockFileAccessWhileExecutingBlockAsync:(PINCacheBlock)block +{ + if (block == nil) { + return; + } + + [self.operationQueue scheduleOperation:^{ + [self lockForWriting]; + block(self); + [self unlock]; + } withPriority:PINOperationQueuePriorityLow]; +} + +- (void)containsObjectForKeyAsync:(NSString *)key completion:(PINDiskCacheContainsBlock)block +{ + if (!key || !block) + return; + + [self.operationQueue scheduleOperation:^{ + block([self containsObjectForKey:key]); + } withPriority:PINOperationQueuePriorityLow]; +} + +- (void)objectForKeyAsync:(NSString *)key completion:(PINDiskCacheObjectBlock)block +{ + [self.operationQueue scheduleOperation:^{ + NSURL *fileURL = nil; + id object = [self objectForKey:key fileURL:&fileURL]; + + block(self, key, object); + } withPriority:PINOperationQueuePriorityLow]; +} + +- (void)fileURLForKeyAsync:(NSString *)key completion:(PINDiskCacheFileURLBlock)block +{ + if (block == nil) { + return; + } + + [self.operationQueue scheduleOperation:^{ + NSURL *fileURL = [self fileURLForKey:key]; + + [self lockForWriting]; + block(key, fileURL); + [self unlock]; + } withPriority:PINOperationQueuePriorityLow]; +} + +- (void)setObjectAsync:(id )object forKey:(NSString *)key completion:(PINDiskCacheObjectBlock)block +{ + [self setObjectAsync:object forKey:key withAgeLimit:0.0 completion:(PINDiskCacheObjectBlock)block]; +} + +- (void)setObjectAsync:(id )object forKey:(NSString *)key withAgeLimit:(NSTimeInterval)ageLimit completion:(nullable PINDiskCacheObjectBlock)block +{ + [self.operationQueue scheduleOperation:^{ + NSURL *fileURL = nil; + [self setObject:object forKey:key withAgeLimit:ageLimit fileURL:&fileURL]; + + if (block) { + block(self, key, object); + } + } withPriority:PINOperationQueuePriorityLow]; +} + +- (void)setObjectAsync:(id )object forKey:(NSString *)key withCost:(NSUInteger)cost completion:(nullable PINCacheObjectBlock)block +{ + [self setObjectAsync:object forKey:key completion:(PINDiskCacheObjectBlock)block]; +} + +- (void)setObjectAsync:(id )object forKey:(NSString *)key withCost:(NSUInteger)cost ageLimit:(NSTimeInterval)ageLimit completion:(nullable PINCacheObjectBlock)block +{ + [self setObjectAsync:object forKey:key withAgeLimit:ageLimit completion:(PINDiskCacheObjectBlock)block]; +} + +- (void)removeObjectForKeyAsync:(NSString *)key completion:(PINDiskCacheObjectBlock)block +{ + [self.operationQueue scheduleOperation:^{ + NSURL *fileURL = nil; + [self removeObjectForKey:key fileURL:&fileURL]; + + if (block) { + block(self, key, nil); + } + } withPriority:PINOperationQueuePriorityLow]; +} + +- (void)trimToSizeAsync:(NSUInteger)trimByteCount completion:(PINCacheBlock)block +{ + PINOperationBlock operation = ^(id data) { + [self trimToSize:((NSNumber *)data).unsignedIntegerValue]; + }; + + dispatch_block_t completion = nil; + if (block) { + completion = ^{ + block(self); + }; + } + + [self.operationQueue scheduleOperation:operation + withPriority:PINOperationQueuePriorityLow + identifier:PINDiskCacheOperationIdentifierTrimToSize + coalescingData:[NSNumber numberWithUnsignedInteger:trimByteCount] + dataCoalescingBlock:PINDiskTrimmingSizeCoalescingBlock + completion:completion]; +} + +- (void)trimToDateAsync:(NSDate *)trimDate completion:(PINCacheBlock)block +{ + PINOperationBlock operation = ^(id data){ + [self trimToDate:(NSDate *)data]; + }; + + dispatch_block_t completion = nil; + if (block) { + completion = ^{ + block(self); + }; + } + + [self.operationQueue scheduleOperation:operation + withPriority:PINOperationQueuePriorityLow + identifier:PINDiskCacheOperationIdentifierTrimToDate + coalescingData:trimDate + dataCoalescingBlock:PINDiskTrimmingDateCoalescingBlock + completion:completion]; +} + +- (void)trimToSizeByEvictionStrategyAsync:(NSUInteger)trimByteCount completion:(PINCacheBlock)block +{ + PINOperationBlock operation = ^(id data){ + [self trimToSizeByEvictionStrategy:((NSNumber *)data).unsignedIntegerValue]; + }; + + dispatch_block_t completion = nil; + if (block) { + completion = ^{ + block(self); + }; + } + + [self.operationQueue scheduleOperation:operation + withPriority:PINOperationQueuePriorityLow + identifier:PINDiskCacheOperationIdentifierTrimToSizeByDate + coalescingData:[NSNumber numberWithUnsignedInteger:trimByteCount] + dataCoalescingBlock:PINDiskTrimmingSizeCoalescingBlock + completion:completion]; +} + +- (void)removeExpiredObjectsAsync:(PINCacheBlock)block +{ + [self.operationQueue scheduleOperation:^{ + [self removeExpiredObjects]; + + if (block) { + block(self); + } + } withPriority:PINOperationQueuePriorityLow]; +} + +- (void)removeAllObjectsAsync:(PINCacheBlock)block +{ + [self.operationQueue scheduleOperation:^{ + [self removeAllObjects]; + + if (block) { + block(self); + } + } withPriority:PINOperationQueuePriorityLow]; +} + +- (void)enumerateObjectsWithBlockAsync:(PINDiskCacheFileURLEnumerationBlock)block completionBlock:(PINCacheBlock)completionBlock +{ + [self.operationQueue scheduleOperation:^{ + [self enumerateObjectsWithBlock:block]; + + if (completionBlock) { + completionBlock(self); + } + } withPriority:PINOperationQueuePriorityLow]; +} + +#pragma mark - Public Synchronous Methods - + +- (void)synchronouslyLockFileAccessWhileExecutingBlock:(PIN_NOESCAPE PINCacheBlock)block +{ + if (block) { + [self lockForWriting]; + block(self); + [self unlock]; + } +} + +- (BOOL)containsObjectForKey:(NSString *)key +{ + [self lock]; + if (_metadata[key] != nil || _diskStateKnown == NO) { + BOOL objectExpired = NO; + if (self->_ttlCache && _metadata[key].createdDate != nil) { + NSTimeInterval ageLimit = _metadata[key].ageLimit > 0.0 ? _metadata[key].ageLimit : self->_ageLimit; + objectExpired = ageLimit > 0 && fabs([_metadata[key].createdDate timeIntervalSinceDate:[NSDate date]]) > ageLimit; + } + [self unlock]; + return (!objectExpired && [self fileURLForKey:key updateFileModificationDate:NO] != nil); + } + [self unlock]; + return NO; +} + +- (nullable id)objectForKey:(NSString *)key +{ + return [self objectForKey:key fileURL:nil]; +} + +- (id)objectForKeyedSubscript:(NSString *)key +{ + return [self objectForKey:key]; +} + +- (nullable id )objectForKey:(NSString *)key fileURL:(NSURL **)outFileURL +{ + [self lock]; + BOOL containsKey = _metadata[key] != nil || _diskStateKnown == NO; + [self unlock]; + + if (!key || !containsKey) + return nil; + + id object = nil; + NSURL *fileURL = [self encodedFileURLForKey:key]; + + NSDate *now = [NSDate date]; + [self lock]; + if (self->_ttlCache) { + if (!_diskStateKnown) { + if (_metadata[key] == nil) { + NSString *fileKey = [self keyForEncodedFileURL:fileURL]; + [self _locked_initializeDiskPropertiesForFile:fileURL fileKey:fileKey]; + } + } + } + + NSTimeInterval ageLimit = _metadata[key].ageLimit > 0.0 ? _metadata[key].ageLimit : self->_ageLimit; + if (!self->_ttlCache || ageLimit <= 0 || fabs([_metadata[key].createdDate timeIntervalSinceDate:now]) < ageLimit) { + // If the cache should behave like a TTL cache, then only fetch the object if there's a valid ageLimit and the object is still alive + + NSData *objectData = [[NSData alloc] initWithContentsOfFile:[fileURL path]]; + + if (objectData) { + //Be careful with locking below. We unlock here so that we're not locked while deserializing, we re-lock after. + [self unlock]; + @try { + object = _deserializer(objectData, key); + } + @catch (NSException *exception) { + NSError *error = nil; + [self lock]; + [[NSFileManager defaultManager] removeItemAtPath:[fileURL path] error:&error]; + [self unlock]; + PINDiskCacheError(error) + PINDiskCacheException(exception); + } + [self lock]; + } + if (object) { + _metadata[key].lastModifiedDate = now; + [self asynchronouslySetFileModificationDate:now forURL:fileURL]; + NSInteger accessCount = _metadata[key].accessCount; + if (accessCount < NSIntegerMax) { + accessCount += 1; + _metadata[key].accessCount = accessCount; + [self asynchronouslySetAccessCount:accessCount forURL:fileURL]; + } + } + } + [self unlock]; + + if (outFileURL) { + *outFileURL = fileURL; + } + + return object; +} + +/// Helper function to call fileURLForKey:updateFileModificationDate: +- (NSURL *)fileURLForKey:(NSString *)key +{ + // Don't update the file modification time, if self is a ttlCache + return [self fileURLForKey:key updateFileModificationDate:!self->_ttlCache]; +} + +- (NSURL *)fileURLForKey:(NSString *)key updateFileModificationDate:(BOOL)updateFileModificationDate +{ + if (!key) { + return nil; + } + + NSDate *now = [NSDate date]; + NSURL *fileURL = [self encodedFileURLForKey:key]; + + [self lockForWriting]; + if (fileURL.path && [[NSFileManager defaultManager] fileExistsAtPath:fileURL.path]) { + if (updateFileModificationDate) { + _metadata[key].lastModifiedDate = now; + [self asynchronouslySetFileModificationDate:now forURL:fileURL]; + + NSInteger accessCount = _metadata[key].accessCount; + if (accessCount < NSIntegerMax) { + accessCount += 1; + _metadata[key].accessCount = accessCount; + [self asynchronouslySetAccessCount:accessCount forURL:fileURL]; + } + } + } else { + fileURL = nil; + } + [self unlock]; + return fileURL; +} + +- (void)setObject:(id )object forKey:(NSString *)key +{ + [self setObject:object forKey:key withAgeLimit:0.0]; +} + +- (void)setObject:(id )object forKey:(NSString *)key withAgeLimit:(NSTimeInterval)ageLimit +{ + [self setObject:object forKey:key withAgeLimit:ageLimit fileURL:nil]; +} + +- (void)setObject:(id )object forKey:(NSString *)key withCost:(NSUInteger)cost ageLimit:(NSTimeInterval)ageLimit +{ + [self setObject:object forKey:key withAgeLimit:ageLimit]; +} + +- (void)setObject:(id )object forKey:(NSString *)key withCost:(NSUInteger)cost +{ + [self setObject:object forKey:key]; +} + +- (void)setObject:(id)object forKeyedSubscript:(NSString *)key +{ + if (object == nil) { + [self removeObjectForKey:key]; + } else { + [self setObject:object forKey:key]; + } +} + +- (void)setObject:(id )object forKey:(NSString *)key withAgeLimit:(NSTimeInterval)ageLimit fileURL:(NSURL **)outFileURL +{ + NSAssert(ageLimit <= 0.0 || (ageLimit > 0.0 && _ttlCache), @"ttlCache must be set to YES if setting an object-level age limit."); + + if (!key || !object) + return; + + NSDataWritingOptions writeOptions = NSDataWritingAtomic; + #if TARGET_OS_IPHONE + if (self.writingProtectionOptionSet) { + writeOptions |= self.writingProtectionOption; + } + #endif + + // Remain unlocked here so that we're not locked while serializing. + NSData *data = _serializer(object, key); + NSURL *fileURL = nil; + + NSUInteger byteLimit = self.byteLimit; + if (data.length <= byteLimit || byteLimit == 0) { + // The cache is large enough to fit this object (although we may need to evict others). + fileURL = [self encodedFileURLForKey:key]; + } else { + // The cache isn't large enough to fit this object (even if all others were evicted). + // We should not write it to disk because it will be deleted immediately after. + if (outFileURL) { + *outFileURL = nil; + } + return; + } + + [self lockForWriting]; + PINDiskCacheObjectBlock willAddObjectBlock = self->_willAddObjectBlock; + if (willAddObjectBlock) { + [self unlock]; + willAddObjectBlock(self, key, object); + [self lock]; + } + + NSError *writeError = nil; + BOOL written = [data writeToURL:fileURL options:writeOptions error:&writeError]; + PINDiskCacheError(writeError); + + if (written) { + if (_metadata[key] == nil) { + _metadata[key] = [[PINDiskCacheMetadata alloc] init]; + } + + NSError *error = nil; + NSDictionary *values = [fileURL resourceValuesForKeys:@[ NSURLCreationDateKey, NSURLContentModificationDateKey, NSURLTotalFileAllocatedSizeKey ] error:&error]; + PINDiskCacheError(error); + + NSNumber *diskFileSize = [values objectForKey:NSURLTotalFileAllocatedSizeKey]; + if (diskFileSize) { + NSNumber *prevDiskFileSize = self->_metadata[key].size; + if (prevDiskFileSize) { + self.byteCount = self->_byteCount - [prevDiskFileSize unsignedIntegerValue]; + } + self->_metadata[key].size = diskFileSize; + self.byteCount = self->_byteCount + [diskFileSize unsignedIntegerValue]; // atomic + } + NSDate *createdDate = [values objectForKey:NSURLCreationDateKey]; + if (createdDate) { + self->_metadata[key].createdDate = createdDate; + } + NSDate *lastModifiedDate = [values objectForKey:NSURLContentModificationDateKey]; + if (lastModifiedDate) { + self->_metadata[key].lastModifiedDate = lastModifiedDate; + } + [self asynchronouslySetAgeLimit:ageLimit forURL:fileURL]; + NSInteger accessCount = self->_metadata[key].accessCount; + if (accessCount < NSIntegerMax) { + accessCount += 1; + self->_metadata[key].accessCount = accessCount; + [self asynchronouslySetAccessCount:accessCount forURL:fileURL]; + } + + if (self->_byteLimit > 0 && self->_byteCount > self->_byteLimit) + [self trimToSizeByEvictionStrategyAsync:self->_byteLimit completion:nil]; + } else { + fileURL = nil; + } + + PINDiskCacheObjectBlock didAddObjectBlock = self->_didAddObjectBlock; + if (didAddObjectBlock) { + [self unlock]; + didAddObjectBlock(self, key, object); + [self lock]; + } + [self unlock]; + + if (outFileURL) { + *outFileURL = fileURL; + } +} + +- (void)removeObjectForKey:(NSString *)key +{ + [self removeObjectForKey:key fileURL:nil]; +} + +- (void)removeObjectForKey:(NSString *)key fileURL:(NSURL **)outFileURL +{ + if (!key) + return; + + NSURL *fileURL = nil; + + fileURL = [self encodedFileURLForKey:key]; + + [self removeFileAndExecuteBlocksForKey:key]; + + if (outFileURL) { + *outFileURL = fileURL; + } +} + +- (void)trimToSize:(NSUInteger)trimByteCount +{ + if (trimByteCount == 0) { + [self removeAllObjects]; + return; + } + + [self trimDiskToSize:trimByteCount]; +} + +- (void)trimToDate:(NSDate *)trimDate +{ + if (!trimDate) + return; + + if ([trimDate isEqualToDate:[NSDate distantPast]]) { + [self removeAllObjects]; + return; + } + + [self trimDiskToDate:trimDate]; +} + +- (void)trimToSizeByEvictionStrategy:(NSUInteger)trimByteCount +{ + if (trimByteCount == 0) { + [self removeAllObjects]; + return; + } + + [self trimDiskToSizeByEvictionStrategy:trimByteCount]; +} + +- (void)removeExpiredObjects +{ + [self lockForWriting]; + NSDate *now = [NSDate date]; + NSMutableArray *expiredObjectKeys = [NSMutableArray array]; + [_metadata enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, PINDiskCacheMetadata * _Nonnull obj, BOOL * _Nonnull stop) { + NSTimeInterval ageLimit = obj.ageLimit > 0.0 ? obj.ageLimit : self->_ageLimit; + NSDate *expirationDate = [obj.createdDate dateByAddingTimeInterval:ageLimit]; + if ([expirationDate compare:now] == NSOrderedAscending) { // Expiration date has passed + [expiredObjectKeys addObject:key]; + } + }]; + [self unlock]; + + for (NSString *key in expiredObjectKeys) { + //unlock, removeFileAndExecuteBlocksForKey handles locking itself + [self removeFileAndExecuteBlocksForKey:key]; + } +} + +- (void)removeAllObjects +{ + // We don't need to know the disk state since we're just going to remove everything. + [self lockForWriting]; + PINCacheBlock willRemoveAllObjectsBlock = self->_willRemoveAllObjectsBlock; + if (willRemoveAllObjectsBlock) { + [self unlock]; + willRemoveAllObjectsBlock(self); + [self lock]; + } + + [PINDiskCache moveItemAtURLToTrashOrRemove:self->_cacheURL]; + [PINDiskCache emptyTrash]; + + [self _locked_createCacheDirectory]; + + [self->_metadata removeAllObjects]; + self.byteCount = 0; // atomic + + PINCacheBlock didRemoveAllObjectsBlock = self->_didRemoveAllObjectsBlock; + if (didRemoveAllObjectsBlock) { + [self unlock]; + didRemoveAllObjectsBlock(self); + [self lock]; + } + + [self unlock]; +} + +- (void)enumerateObjectsWithBlock:(PIN_NOESCAPE PINDiskCacheFileURLEnumerationBlock)block +{ + if (!block) + return; + + [self lockAndWaitForKnownState]; + NSDate *now = [NSDate date]; + + for (NSString *key in _metadata) { + NSURL *fileURL = [self encodedFileURLForKey:key]; + // If the cache should behave like a TTL cache, then only fetch the object if there's a valid ageLimit and the object is still alive + NSDate *createdDate = _metadata[key].createdDate; + NSTimeInterval ageLimit = _metadata[key].ageLimit > 0.0 ? _metadata[key].ageLimit : self->_ageLimit; + if (!self->_ttlCache || ageLimit <= 0 || (createdDate && fabs([createdDate timeIntervalSinceDate:now]) < ageLimit)) { + BOOL stop = NO; + block(key, fileURL, &stop); + if (stop) + break; + } + } + [self unlock]; +} + +#pragma mark - Public Thread Safe Accessors - + +- (PINDiskCacheObjectBlock)willAddObjectBlock +{ + PINDiskCacheObjectBlock block = nil; + + [self lock]; + block = _willAddObjectBlock; + [self unlock]; + + return block; +} + +- (void)setWillAddObjectBlock:(PINDiskCacheObjectBlock)block +{ + [self.operationQueue scheduleOperation:^{ + [self lock]; + self->_willAddObjectBlock = [block copy]; + [self unlock]; + } withPriority:PINOperationQueuePriorityHigh]; +} + +- (PINDiskCacheObjectBlock)willRemoveObjectBlock +{ + PINDiskCacheObjectBlock block = nil; + + [self lock]; + block = _willRemoveObjectBlock; + [self unlock]; + + return block; +} + +- (void)setWillRemoveObjectBlock:(PINDiskCacheObjectBlock)block +{ + [self.operationQueue scheduleOperation:^{ + [self lock]; + self->_willRemoveObjectBlock = [block copy]; + [self unlock]; + } withPriority:PINOperationQueuePriorityHigh]; +} + +- (PINCacheBlock)willRemoveAllObjectsBlock +{ + PINCacheBlock block = nil; + + [self lock]; + block = _willRemoveAllObjectsBlock; + [self unlock]; + + return block; +} + +- (void)setWillRemoveAllObjectsBlock:(PINCacheBlock)block +{ + [self.operationQueue scheduleOperation:^{ + [self lock]; + self->_willRemoveAllObjectsBlock = [block copy]; + [self unlock]; + } withPriority:PINOperationQueuePriorityHigh]; +} + +- (PINDiskCacheObjectBlock)didAddObjectBlock +{ + PINDiskCacheObjectBlock block = nil; + + [self lock]; + block = _didAddObjectBlock; + [self unlock]; + + return block; +} + +- (void)setDidAddObjectBlock:(PINDiskCacheObjectBlock)block +{ + [self.operationQueue scheduleOperation:^{ + [self lock]; + self->_didAddObjectBlock = [block copy]; + [self unlock]; + } withPriority:PINOperationQueuePriorityHigh]; +} + +- (PINDiskCacheObjectBlock)didRemoveObjectBlock +{ + PINDiskCacheObjectBlock block = nil; + + [self lock]; + block = _didRemoveObjectBlock; + [self unlock]; + + return block; +} + +- (void)setDidRemoveObjectBlock:(PINDiskCacheObjectBlock)block +{ + [self.operationQueue scheduleOperation:^{ + [self lock]; + self->_didRemoveObjectBlock = [block copy]; + [self unlock]; + } withPriority:PINOperationQueuePriorityHigh]; +} + +- (PINCacheBlock)didRemoveAllObjectsBlock +{ + PINCacheBlock block = nil; + + [self lock]; + block = _didRemoveAllObjectsBlock; + [self unlock]; + + return block; +} + +- (void)setDidRemoveAllObjectsBlock:(PINCacheBlock)block +{ + [self.operationQueue scheduleOperation:^{ + [self lock]; + self->_didRemoveAllObjectsBlock = [block copy]; + [self unlock]; + } withPriority:PINOperationQueuePriorityHigh]; +} + +- (NSUInteger)byteLimit +{ + NSUInteger byteLimit; + + [self lock]; + byteLimit = _byteLimit; + [self unlock]; + + return byteLimit; +} + +- (void)setByteLimit:(NSUInteger)byteLimit +{ + [self.operationQueue scheduleOperation:^{ + [self lock]; + self->_byteLimit = byteLimit; + [self unlock]; + + if (byteLimit > 0) + [self trimDiskToSizeByEvictionStrategy:byteLimit]; + } withPriority:PINOperationQueuePriorityHigh]; +} + +- (NSTimeInterval)ageLimit +{ + NSTimeInterval ageLimit; + + [self lock]; + ageLimit = _ageLimit; + [self unlock]; + + return ageLimit; +} + +- (void)setAgeLimit:(NSTimeInterval)ageLimit +{ + [self.operationQueue scheduleOperation:^{ + [self lock]; + self->_ageLimit = ageLimit; + [self unlock]; + + [self.operationQueue scheduleOperation:^{ + [self trimToAgeLimitRecursively]; + } withPriority:PINOperationQueuePriorityLow]; + } withPriority:PINOperationQueuePriorityHigh]; +} + +- (BOOL)isTTLCache +{ + BOOL isTTLCache; + + [self lock]; + isTTLCache = _ttlCache; + [self unlock]; + + return isTTLCache; +} + +#if TARGET_OS_IPHONE +- (NSDataWritingOptions)writingProtectionOption +{ + NSDataWritingOptions option; + + [self lock]; + option = _writingProtectionOption; + [self unlock]; + + return option; +} + +- (void)setWritingProtectionOption:(NSDataWritingOptions)writingProtectionOption +{ + [self.operationQueue scheduleOperation:^{ + NSDataWritingOptions option = NSDataWritingFileProtectionMask & writingProtectionOption; + + [self lock]; + self->_writingProtectionOptionSet = YES; + self->_writingProtectionOption = option; + [self unlock]; + } withPriority:PINOperationQueuePriorityHigh]; +} +#endif + +- (void)lockForWriting +{ + [self lock]; + + // Lock if the disk isn't writable. + if (_diskWritable == NO) { + pthread_cond_wait(&_diskWritableCondition, &_mutex); + } +} + +- (void)lockAndWaitForKnownState +{ + [self lock]; + + // Lock if the disk state isn't known. + if (_diskStateKnown == NO) { + pthread_cond_wait(&_diskStateKnownCondition, &_mutex); + } +} + +- (void)lock +{ + __unused int result = pthread_mutex_lock(&_mutex); + NSAssert(result == 0, @"Failed to lock PINDiskCache %@. Code: %d", self, result); +} + +- (void)unlock +{ + __unused int result = pthread_mutex_unlock(&_mutex); + NSAssert(result == 0, @"Failed to unlock PINDiskCache %@. Code: %d", self, result); +} + +@end + +@implementation PINDiskCache (Deprecated) + +- (void)lockFileAccessWhileExecutingBlock:(nullable PINCacheBlock)block +{ + [self lockFileAccessWhileExecutingBlockAsync:block]; +} + +- (void)containsObjectForKey:(NSString *)key block:(PINDiskCacheContainsBlock)block +{ + [self containsObjectForKeyAsync:key completion:block]; +} + +- (void)objectForKey:(NSString *)key block:(nullable PINDiskCacheObjectBlock)block +{ + [self objectForKeyAsync:key completion:block]; +} + +- (void)fileURLForKey:(NSString *)key block:(nullable PINDiskCacheFileURLBlock)block +{ + [self fileURLForKeyAsync:key completion:block]; +} + +- (void)setObject:(id )object forKey:(NSString *)key block:(nullable PINDiskCacheObjectBlock)block +{ + [self setObjectAsync:object forKey:key completion:block]; +} + +- (void)removeObjectForKey:(NSString *)key block:(nullable PINDiskCacheObjectBlock)block +{ + [self removeObjectForKeyAsync:key completion:block]; +} + +- (void)trimToDate:(NSDate *)date block:(nullable PINDiskCacheBlock)block +{ + [self trimToDateAsync:date completion:^(id diskCache) { + if (block) { + block((PINDiskCache *)diskCache); + } + }]; +} + +- (void)trimToSize:(NSUInteger)byteCount block:(nullable PINDiskCacheBlock)block +{ + [self trimToSizeAsync:byteCount completion:^(id diskCache) { + if (block) { + block((PINDiskCache *)diskCache); + } + }]; +} + +- (void)trimToSizeByDate:(NSUInteger)byteCount block:(nullable PINDiskCacheBlock)block +{ + [self trimToSizeAsync:byteCount completion:^(id diskCache) { + if (block) { + block((PINDiskCache *)diskCache); + } + }]; +} + +- (void)removeAllObjects:(nullable PINDiskCacheBlock)block +{ + [self removeAllObjectsAsync:^(id diskCache) { + if (block) { + block((PINDiskCache *)diskCache); + } + }]; +} + +- (void)enumerateObjectsWithBlock:(PINDiskCacheFileURLBlock)block completionBlock:(nullable PINDiskCacheBlock)completionBlock +{ + [self enumerateObjectsWithBlockAsync:^(NSString * _Nonnull key, NSURL * _Nullable fileURL, BOOL * _Nonnull stop) { + block(key, fileURL); + } completionBlock:^(id diskCache) { + if (completionBlock) { + completionBlock((PINDiskCache *)diskCache); + } + }]; +} + +- (void)setTtlCache:(BOOL)ttlCache +{ + [self.operationQueue scheduleOperation:^{ + [self lock]; + self->_ttlCache = ttlCache; + [self unlock]; + } withPriority:PINOperationQueuePriorityHigh]; +} + +- (void)trimToSizeByDate:(NSUInteger)byteCount +{ + [self trimToSizeByEvictionStrategy:byteCount]; +} + +- (void)trimToSizeByDateAsync:(NSUInteger)byteCount completion:(nullable PINCacheBlock)block +{ + [self trimToSizeByEvictionStrategyAsync:byteCount completion:block]; +} + +@end + +@implementation PINDiskCacheMetadata +@end diff --git a/Carthage/Checkouts/PINCache/Source/PINMemoryCache.h b/Carthage/Checkouts/PINCache/Source/PINMemoryCache.h new file mode 100644 index 00000000..5bb78e11 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Source/PINMemoryCache.h @@ -0,0 +1,254 @@ +// PINCache is a modified version of TMCache +// Modifications by Garrett Moon +// Copyright (c) 2015 Pinterest. All rights reserved. + +#import + +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@class PINMemoryCache; +@class PINOperationQueue; + + +/** + `PINMemoryCache` is a fast, thread safe key/value store similar to `NSCache`. On iOS it will clear itself + automatically to reduce memory usage when the app receives a memory warning or goes into the background. + + Access is natively synchronous. Asynchronous variations are provided. Every asynchronous method accepts a + callback block that runs on a concurrent , with cache reads and writes protected by a lock. + + All access to the cache is dated so the that the least-used objects can be trimmed first. Setting an + optional will trigger a GCD timer to periodically to trim the cache to that age. + + Objects can optionally be set with a "cost", which could be a byte count or any other meaningful integer. + Setting a will automatically keep the cache below that value with . + + Values will not persist after application relaunch or returning from the background. See for + a memory cache backed by a disk cache. + */ + +PIN_SUBCLASSING_RESTRICTED +@interface PINMemoryCache : NSObject + +#pragma mark - Properties +/// @name Core + +/** + The total accumulated cost. + */ +@property (readonly) NSUInteger totalCost; + +/** + The maximum cost allowed to accumulate before objects begin to be removed with . + */ +@property (assign) NSUInteger costLimit; + +/** + The maximum number of seconds an object is allowed to exist in the cache. Setting this to a value + greater than `0.0` will start a recurring GCD timer with the same period that calls . + Setting it back to `0.0` will stop the timer. Defaults to `0.0`. + */ +@property (assign) NSTimeInterval ageLimit; + +/** + If ttlCache is YES, the cache behaves like a ttlCache. This means that once an object enters the + cache, it only lives as long as self.ageLimit. This has the following implications: + - Accessing an object in the cache does not extend that object's lifetime in the cache + - When attempting to access an object in the cache that has lived longer than self.ageLimit, + the cache will behave as if the object does not exist + + @note If an object-level age limit is set via one of the @c -setObject:forKey:withAgeLimit methods, + that age limit overrides self.ageLimit. The overridden object age limit could be greater or + less than self.agelimit but must be greater than zero. + */ +@property (nonatomic, readonly, getter=isTTLCache) BOOL ttlCache; + +/** + The eviction strategy when trimming the cache. + */ +@property (atomic, assign) PINCacheEvictionStrategy evictionStrategy; + +/** + When `YES` on iOS the cache will remove all objects when the app receives a memory warning. + Defaults to `YES`. + */ +@property (assign) BOOL removeAllObjectsOnMemoryWarning; + +/** + When `YES` on iOS the cache will remove all objects when the app enters the background. + Defaults to `YES`. + */ +@property (assign) BOOL removeAllObjectsOnEnteringBackground; + +#pragma mark - Event Blocks +/// @name Event Blocks + +/** + A block to be executed just before an object is added to the cache. This block will be excuted within + a lock, i.e. all reads and writes are suspended for the duration of the block. + Calling synchronous methods on the cache within this callback will likely cause a deadlock. + */ +@property (nullable, copy) PINCacheObjectBlock willAddObjectBlock; + +/** + A block to be executed just before an object is removed from the cache. This block will be excuted + within a lock, i.e. all reads and writes are suspended for the duration of the block. + Calling synchronous methods on the cache within this callback will likely cause a deadlock. + */ +@property (nullable, copy) PINCacheObjectBlock willRemoveObjectBlock; + +/** + A block to be executed just before all objects are removed from the cache as a result of . + This block will be excuted within a lock, i.e. all reads and writes are suspended for the duration of the block. + Calling synchronous methods on the cache within this callback will likely cause a deadlock. + */ +@property (nullable, copy) PINCacheBlock willRemoveAllObjectsBlock; + +/** + A block to be executed just after an object is added to the cache. This block will be excuted within + a lock, i.e. all reads and writes are suspended for the duration of the block. + Calling synchronous methods on the cache within this callback will likely cause a deadlock. + */ +@property (nullable, copy) PINCacheObjectBlock didAddObjectBlock; + +/** + A block to be executed just after an object is removed from the cache. This block will be excuted + within a lock, i.e. all reads and writes are suspended for the duration of the block. + Calling synchronous methods on the cache within this callback will likely cause a deadlock. + */ +@property (nullable, copy) PINCacheObjectBlock didRemoveObjectBlock; + +/** + A block to be executed just after all objects are removed from the cache as a result of . + This block will be excuted within a lock, i.e. all reads and writes are suspended for the duration of the block. + Calling synchronous methods on the cache within this callback will likely cause a deadlock. + */ +@property (nullable, copy) PINCacheBlock didRemoveAllObjectsBlock; + +/** + A block to be executed upon receiving a memory warning (iOS only) potentially in parallel with other blocks on the . + This block will be executed regardless of the value of . Defaults to `nil`. + */ +@property (nullable, copy) PINCacheBlock didReceiveMemoryWarningBlock; + +/** + A block to be executed when the app enters the background (iOS only) potentially in parallel with other blocks on the . + This block will be executed regardless of the value of . Defaults to `nil`. + */ +@property (nullable, copy) PINCacheBlock didEnterBackgroundBlock; + +#pragma mark - Lifecycle +/// @name Shared Cache + +/** + A shared cache. + + @result The shared singleton cache instance. + */ +@property (class, strong, readonly) PINMemoryCache *sharedCache; + +- (instancetype)initWithOperationQueue:(PINOperationQueue *)operationQueue; + +- (instancetype)initWithName:(NSString *)name operationQueue:(PINOperationQueue *)operationQueue; + +- (instancetype)initWithName:(NSString *)name operationQueue:(PINOperationQueue *)operationQueue ttlCache:(BOOL)ttlCache; + +- (instancetype)initWithName:(NSString *)name operationQueue:(PINOperationQueue *)operationQueue ttlCache:(BOOL)ttlCache evictionStrategy:(PINCacheEvictionStrategy)evictionStrategy NS_DESIGNATED_INITIALIZER; + +#pragma mark - Asynchronous Methods +/// @name Asynchronous Methods + +/** + Removes objects from the cache, costliest objects first, until the is below the specified + value. This method returns immediately and executes the passed block after the cache has been trimmed, + potentially in parallel with other blocks on the . + + @param cost The total accumulation allowed to remain after the cache has been trimmed. + @param block A block to be executed concurrently after the cache has been trimmed, or nil. + */ +- (void)trimToCostAsync:(NSUInteger)cost completion:(nullable PINCacheBlock)block; + +/** + Removes objects from the cache, ordered by date (least recently used first), until the is below + the specified value. This method returns immediately and executes the passed block after the cache has been + trimmed, potentially in parallel with other blocks on the . + + @param cost The total accumulation allowed to remain after the cache has been trimmed. + @param block A block to be executed concurrently after the cache has been trimmed, or nil. + */ +- (void)trimToCostByEvictionStrategyAsync:(NSUInteger)cost completion:(nullable PINCacheBlock)block; + +/** + Loops through all objects in the cache with reads and writes suspended. Calling serial methods which + write to the cache inside block may be unsafe and may result in a deadlock. This method returns immediately. + + @param block A block to be executed for every object in the cache. + @param completionBlock An optional block to be executed concurrently when the enumeration is complete. + */ +- (void)enumerateObjectsWithBlockAsync:(PINCacheObjectEnumerationBlock)block completionBlock:(nullable PINCacheBlock)completionBlock; + +#pragma mark - Synchronous Methods +/// @name Synchronous Methods + +/** + Removes objects from the cache, costliest objects first, until the is below the specified + value. This method blocks the calling thread until the cache has been trimmed. + + @see trimToCostAsync: + @param cost The total accumulation allowed to remain after the cache has been trimmed. + */ +- (void)trimToCost:(NSUInteger)cost; + +/** + Removes objects from the cache, ordered by date (least recently used first), until the is below + the specified value. This method blocks the calling thread until the cache has been trimmed. + + @see trimToCostByEvictionStrategyAsync: + @param cost The total accumulation allowed to remain after the cache has been trimmed. + */ +- (void)trimToCostByEvictionStrategy:(NSUInteger)cost; + +/** + Loops through all objects in the cache within a memory lock (reads and writes are suspended during the enumeration). + This method blocks the calling thread until all objects have been enumerated. + Calling synchronous methods on the cache within this callback will likely cause a deadlock. + + @see enumerateObjectsWithBlockAsync:completionBlock: + @param block A block to be executed for every object in the cache. + + @warning Do not call this method within the event blocks (, etc.) + Instead use the asynchronous version, . + + */ +- (void)enumerateObjectsWithBlock:(PIN_NOESCAPE PINCacheObjectEnumerationBlock)block; + +@end + + +#pragma mark - Deprecated + +typedef void (^PINMemoryCacheBlock)(PINMemoryCache *cache); +typedef void (^PINMemoryCacheObjectBlock)(PINMemoryCache *cache, NSString *key, id _Nullable object); +typedef void (^PINMemoryCacheContainmentBlock)(BOOL containsObject); + +@interface PINMemoryCache (Deprecated) +- (void)containsObjectForKey:(NSString *)key block:(PINMemoryCacheContainmentBlock)block __attribute__((deprecated)); +- (void)objectForKey:(NSString *)key block:(nullable PINMemoryCacheObjectBlock)block __attribute__((deprecated)); +- (void)setObject:(id)object forKey:(NSString *)key block:(nullable PINMemoryCacheObjectBlock)block __attribute__((deprecated)); +- (void)setObject:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost block:(nullable PINMemoryCacheObjectBlock)block __attribute__((deprecated)); +- (void)removeObjectForKey:(NSString *)key block:(nullable PINMemoryCacheObjectBlock)block __attribute__((deprecated)); +- (void)trimToDate:(NSDate *)date block:(nullable PINMemoryCacheBlock)block __attribute__((deprecated)); +- (void)trimToCost:(NSUInteger)cost block:(nullable PINMemoryCacheBlock)block __attribute__((deprecated)); +- (void)trimToCostByDate:(NSUInteger)cost block:(nullable PINMemoryCacheBlock)block __attribute__((deprecated)); +- (void)removeAllObjects:(nullable PINMemoryCacheBlock)block __attribute__((deprecated)); +- (void)enumerateObjectsWithBlock:(PINMemoryCacheObjectBlock)block completionBlock:(nullable PINMemoryCacheBlock)completionBlock __attribute__((deprecated)); +- (void)setTtlCache:(BOOL)ttlCache DEPRECATED_MSG_ATTRIBUTE("ttlCache is no longer a settable property and must now be set via initializer."); +- (void)trimToCostByDate:(NSUInteger)cost DEPRECATED_MSG_ATTRIBUTE("Use trimToCostByEvictionStrategy: instead"); +- (void)trimToCostByDateAsync:(NSUInteger)cost completion:(nullable PINCacheBlock)block DEPRECATED_MSG_ATTRIBUTE("Use trimToCostByEvictionStrategyAsync:completion: instead."); +@end + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/PINCache/Source/PINMemoryCache.m b/Carthage/Checkouts/PINCache/Source/PINMemoryCache.m new file mode 100644 index 00000000..48f017df --- /dev/null +++ b/Carthage/Checkouts/PINCache/Source/PINMemoryCache.m @@ -0,0 +1,992 @@ +// PINCache is a modified version of TMCache +// Modifications by Garrett Moon +// Copyright (c) 2015 Pinterest. All rights reserved. + +#import "PINMemoryCache.h" + +#import + +#import + +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 +#import +#endif + +static NSString * const PINMemoryCachePrefix = @"com.pinterest.PINMemoryCache"; +static NSString * const PINMemoryCacheSharedName = @"PINMemoryCacheSharedName"; + +@interface PINMemoryCache () +@property (copy, nonatomic) NSString *name; +@property (strong, nonatomic) PINOperationQueue *operationQueue; +@property (assign, nonatomic) pthread_mutex_t mutex; +@property (strong, nonatomic) NSMutableDictionary *dictionary; +@property (strong, nonatomic) NSMutableDictionary *createdDates; +@property (strong, nonatomic) NSMutableDictionary *accessDates; +@property (strong, nonatomic) NSMutableDictionary *costs; +@property (strong, nonatomic) NSMutableDictionary *ageLimits; +@property (strong, nonatomic) NSMutableDictionary *accessCounts; +@end + +@implementation PINMemoryCache + +@synthesize name = _name; +@synthesize ageLimit = _ageLimit; +@synthesize costLimit = _costLimit; +@synthesize totalCost = _totalCost; +@synthesize ttlCache = _ttlCache; +@synthesize willAddObjectBlock = _willAddObjectBlock; +@synthesize willRemoveObjectBlock = _willRemoveObjectBlock; +@synthesize willRemoveAllObjectsBlock = _willRemoveAllObjectsBlock; +@synthesize didAddObjectBlock = _didAddObjectBlock; +@synthesize didRemoveObjectBlock = _didRemoveObjectBlock; +@synthesize didRemoveAllObjectsBlock = _didRemoveAllObjectsBlock; +@synthesize didReceiveMemoryWarningBlock = _didReceiveMemoryWarningBlock; +@synthesize didEnterBackgroundBlock = _didEnterBackgroundBlock; + +#pragma mark - Initialization - + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + __unused int result = pthread_mutex_destroy(&_mutex); + NSCAssert(result == 0, @"Failed to destroy lock in PINMemoryCache %p. Code: %d", (void *)self, result); +} + +- (instancetype)init +{ + return [self initWithOperationQueue:[PINOperationQueue sharedOperationQueue]]; +} + +- (instancetype)initWithOperationQueue:(PINOperationQueue *)operationQueue +{ + return [self initWithName:PINMemoryCacheSharedName operationQueue:operationQueue]; +} + +- (instancetype)initWithName:(NSString *)name operationQueue:(PINOperationQueue *)operationQueue +{ + return [self initWithName:name operationQueue:operationQueue ttlCache:NO]; +} + +- (instancetype)initWithName:(NSString *)name operationQueue:(PINOperationQueue *)operationQueue ttlCache:(BOOL)ttlCache +{ + return [self initWithName:name operationQueue:operationQueue ttlCache:ttlCache evictionStrategy:PINCacheEvictionStrategyLeastRecentlyUsed]; +} + +- (instancetype)initWithName:(NSString *)name operationQueue:(PINOperationQueue *)operationQueue ttlCache:(BOOL)ttlCache evictionStrategy:(PINCacheEvictionStrategy)evictionStrategy +{ + if (self = [super init]) { + __unused int result = pthread_mutex_init(&_mutex, NULL); + NSAssert(result == 0, @"Failed to init lock in PINMemoryCache %@. Code: %d", self, result); + + _name = [name copy]; + _operationQueue = operationQueue; + _ttlCache = ttlCache; + + _dictionary = [[NSMutableDictionary alloc] init]; + _createdDates = [[NSMutableDictionary alloc] init]; + _accessDates = [[NSMutableDictionary alloc] init]; + _costs = [[NSMutableDictionary alloc] init]; + _ageLimits = [[NSMutableDictionary alloc] init]; + _accessCounts = [[NSMutableDictionary alloc] init]; + + _willAddObjectBlock = nil; + _willRemoveObjectBlock = nil; + _willRemoveAllObjectsBlock = nil; + + _didAddObjectBlock = nil; + _didRemoveObjectBlock = nil; + _didRemoveAllObjectsBlock = nil; + + _didReceiveMemoryWarningBlock = nil; + _didEnterBackgroundBlock = nil; + + _ageLimit = 0.0; + _costLimit = 0; + _totalCost = 0; + _evictionStrategy = evictionStrategy; + + _removeAllObjectsOnMemoryWarning = YES; + _removeAllObjectsOnEnteringBackground = YES; + +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 && !TARGET_OS_WATCH + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didReceiveEnterBackgroundNotification:) + name:UIApplicationDidEnterBackgroundNotification + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didReceiveMemoryWarningNotification:) + name:UIApplicationDidReceiveMemoryWarningNotification + object:nil]; + +#endif + } + return self; +} + ++ (PINMemoryCache *)sharedCache +{ + static PINMemoryCache *cache; + static dispatch_once_t predicate; + + dispatch_once(&predicate, ^{ + cache = [[PINMemoryCache alloc] init]; + }); + + return cache; +} + +#pragma mark - Private Methods - + +- (void)didReceiveMemoryWarningNotification:(NSNotification *)notification { + if (self.removeAllObjectsOnMemoryWarning) { + [self removeAllObjectsAsync:nil]; + } else { + [self removeExpiredObjects]; + } + + [self.operationQueue scheduleOperation:^{ + [self lock]; + PINCacheBlock didReceiveMemoryWarningBlock = self->_didReceiveMemoryWarningBlock; + [self unlock]; + + if (didReceiveMemoryWarningBlock) + didReceiveMemoryWarningBlock(self); + } withPriority:PINOperationQueuePriorityHigh]; +} + +- (void)didReceiveEnterBackgroundNotification:(NSNotification *)notification +{ + if (self.removeAllObjectsOnEnteringBackground) + [self removeAllObjectsAsync:nil]; + + [self.operationQueue scheduleOperation:^{ + [self lock]; + PINCacheBlock didEnterBackgroundBlock = self->_didEnterBackgroundBlock; + [self unlock]; + + if (didEnterBackgroundBlock) + didEnterBackgroundBlock(self); + } withPriority:PINOperationQueuePriorityHigh]; +} + +- (void)removeObjectAndExecuteBlocksForKey:(NSString *)key +{ + [self lock]; + id object = _dictionary[key]; + NSNumber *cost = _costs[key]; + PINCacheObjectBlock willRemoveObjectBlock = _willRemoveObjectBlock; + PINCacheObjectBlock didRemoveObjectBlock = _didRemoveObjectBlock; + [self unlock]; + + if (object == nil) { + return; + } + + if (willRemoveObjectBlock) + willRemoveObjectBlock(self, key, object); + + [self lock]; + if (cost) + _totalCost -= [cost unsignedIntegerValue]; + + [_dictionary removeObjectForKey:key]; + [_createdDates removeObjectForKey:key]; + [_accessDates removeObjectForKey:key]; + [_costs removeObjectForKey:key]; + [_ageLimits removeObjectForKey:key]; + [_accessCounts removeObjectForKey:key]; + [self unlock]; + + if (didRemoveObjectBlock) + didRemoveObjectBlock(self, key, nil); +} + +- (void)trimMemoryToDate:(NSDate *)trimDate +{ + [self lock]; + NSDictionary *createdDates = [_createdDates copy]; + NSDictionary *ageLimits = [_ageLimits copy]; + [self unlock]; + + [createdDates enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSDate * _Nonnull createdDate, BOOL * _Nonnull stop) { + NSTimeInterval ageLimit = [ageLimits[key] doubleValue]; + if (!createdDate || ageLimit > 0.0) { + return; + } + if ([createdDate compare:trimDate] == NSOrderedAscending) { // older than trim date + [self removeObjectAndExecuteBlocksForKey:key]; + } + }]; +} + +- (void)removeExpiredObjects +{ + [self lock]; + NSDictionary *createdDates = [_createdDates copy]; + NSDictionary *ageLimits = [_ageLimits copy]; + NSTimeInterval globalAgeLimit = self->_ageLimit; + [self unlock]; + + NSDate *now = [NSDate date]; + for (NSString *key in ageLimits) { + NSDate *createdDate = createdDates[key]; + NSTimeInterval ageLimit = [ageLimits[key] doubleValue] ?: globalAgeLimit; + if (!createdDate) + continue; + + NSDate *expirationDate = [createdDate dateByAddingTimeInterval:ageLimit]; + if ([expirationDate compare:now] == NSOrderedAscending) { // Expiration date has passed + [self removeObjectAndExecuteBlocksForKey:key]; + } + } +} + +- (void)trimToCostLimit:(NSUInteger)limit +{ + NSUInteger totalCost = 0; + + [self lock]; + totalCost = _totalCost; + [self unlock]; + + if (totalCost <= limit) { + return; + } + + [self lock]; + NSDictionary *costs = [_costs copy]; + [self unlock]; + + NSArray *keysSortedByCost = [costs keysSortedByValueUsingSelector:@selector(compare:)]; + + for (NSString *key in [keysSortedByCost reverseObjectEnumerator]) { // costliest objects first + [self removeObjectAndExecuteBlocksForKey:key]; + + [self lock]; + totalCost = _totalCost; + [self unlock]; + + if (totalCost <= limit) + break; + } +} + +- (void)trimToCostLimitByEvictionStrategy:(NSUInteger)limit +{ + if (self.isTTLCache) { + [self removeExpiredObjects]; + } + + [self lock]; + NSUInteger totalCost = _totalCost; + [self unlock]; + + if (totalCost <= limit) + return; + + [self lock]; + NSDictionary *accessDates = [_accessDates copy]; + NSDictionary *accessCounts = [_accessCounts copy]; + PINCacheEvictionStrategy strategy = _evictionStrategy; + [self unlock]; + + NSArray *keysSortedByEvictionStrategy = nil; + switch (strategy) { + case PINCacheEvictionStrategyLeastRecentlyUsed: + keysSortedByEvictionStrategy = [accessDates keysSortedByValueUsingSelector:@selector(compare:)]; + break; + + case PINCacheEvictionStrategyLeastFrequentlyUsed: + keysSortedByEvictionStrategy = [[accessCounts allKeys] sortedArrayUsingComparator:^NSComparisonResult(NSString * _Nonnull key1, NSString * _Nonnull key2) { + NSInteger count1 = [accessCounts[key1] integerValue]; + NSInteger count2 = [accessCounts[key2] integerValue]; + if (count1 < count2) { + return NSOrderedAscending; + } else if (count1 > count2) { + return NSOrderedDescending; + } else { + NSDate *date1 = accessDates[key1]; + NSDate *date2 = accessDates[key2]; + return [date1 compare:date2]; + } + }]; + break; + } + + for (NSString *key in keysSortedByEvictionStrategy) { // oldest objects first + [self removeObjectAndExecuteBlocksForKey:key]; + + [self lock]; + totalCost = _totalCost; + [self unlock]; + if (totalCost <= limit) + break; + } +} + +- (void)trimToAgeLimitRecursively +{ + [self lock]; + NSTimeInterval ageLimit = _ageLimit; + [self unlock]; + + if (ageLimit == 0.0) + return; + + NSDate *date = [[NSDate alloc] initWithTimeIntervalSinceNow:-ageLimit]; + + [self trimMemoryToDate:date]; + + dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(ageLimit * NSEC_PER_SEC)); + dispatch_after(time, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){ + // Ensure that ageLimit is the same as when we were scheduled, otherwise, we've been + // rescheduled (another dispatch_after was issued) and should cancel. + BOOL shouldReschedule = YES; + [self lock]; + if (ageLimit != self->_ageLimit) { + shouldReschedule = NO; + } + [self unlock]; + + if (shouldReschedule) { + [self.operationQueue scheduleOperation:^{ + [self trimToAgeLimitRecursively]; + } withPriority:PINOperationQueuePriorityLow]; + } + }); +} + +#pragma mark - Public Asynchronous Methods - + +- (void)containsObjectForKeyAsync:(NSString *)key completion:(PINCacheObjectContainmentBlock)block +{ + if (!key || !block) + return; + + [self.operationQueue scheduleOperation:^{ + BOOL containsObject = [self containsObjectForKey:key]; + + block(containsObject); + } withPriority:PINOperationQueuePriorityHigh]; +} + +- (void)objectForKeyAsync:(NSString *)key completion:(PINCacheObjectBlock)block +{ + if (block == nil) { + return; + } + + [self.operationQueue scheduleOperation:^{ + id object = [self objectForKey:key]; + + block(self, key, object); + } withPriority:PINOperationQueuePriorityHigh]; +} + +- (void)setObjectAsync:(id)object forKey:(NSString *)key completion:(PINCacheObjectBlock)block +{ + [self setObjectAsync:object forKey:key withCost:0 completion:block]; +} + +- (void)setObjectAsync:(id)object forKey:(NSString *)key withAgeLimit:(NSTimeInterval)ageLimit completion:(PINCacheObjectBlock)block +{ + [self setObjectAsync:object forKey:key withCost:0 ageLimit:ageLimit completion:block]; +} + +- (void)setObjectAsync:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost completion:(PINCacheObjectBlock)block +{ + [self setObjectAsync:object forKey:key withCost:cost ageLimit:0.0 completion:block]; +} + +- (void)setObjectAsync:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost ageLimit:(NSTimeInterval)ageLimit completion:(PINCacheObjectBlock)block +{ + [self.operationQueue scheduleOperation:^{ + [self setObject:object forKey:key withCost:cost ageLimit:ageLimit]; + + if (block) + block(self, key, object); + } withPriority:PINOperationQueuePriorityHigh]; +} + +- (void)removeObjectForKeyAsync:(NSString *)key completion:(PINCacheObjectBlock)block +{ + [self.operationQueue scheduleOperation:^{ + [self removeObjectForKey:key]; + + if (block) + block(self, key, nil); + } withPriority:PINOperationQueuePriorityLow]; +} + +- (void)trimToDateAsync:(NSDate *)trimDate completion:(PINCacheBlock)block +{ + [self.operationQueue scheduleOperation:^{ + [self trimToDate:trimDate]; + + if (block) + block(self); + } withPriority:PINOperationQueuePriorityLow]; +} + +- (void)trimToCostAsync:(NSUInteger)cost completion:(PINCacheBlock)block +{ + [self.operationQueue scheduleOperation:^{ + [self trimToCost:cost]; + + if (block) + block(self); + } withPriority:PINOperationQueuePriorityLow]; +} + +- (void)trimToCostByEvictionStrategyAsync:(NSUInteger)cost completion:(PINCacheBlock)block +{ + [self.operationQueue scheduleOperation:^{ + [self trimToCostByEvictionStrategy:cost]; + + if (block) + block(self); + } withPriority:PINOperationQueuePriorityLow]; +} + +- (void)removeExpiredObjectsAsync:(PINCacheBlock)block +{ + [self.operationQueue scheduleOperation:^{ + [self removeExpiredObjects]; + + if (block) + block(self); + } withPriority:PINOperationQueuePriorityLow]; +} + +- (void)removeAllObjectsAsync:(PINCacheBlock)block +{ + [self.operationQueue scheduleOperation:^{ + [self removeAllObjects]; + + if (block) + block(self); + } withPriority:PINOperationQueuePriorityLow]; +} + +- (void)enumerateObjectsWithBlockAsync:(PINCacheObjectEnumerationBlock)block completionBlock:(PINCacheBlock)completionBlock +{ + [self.operationQueue scheduleOperation:^{ + [self enumerateObjectsWithBlock:block]; + + if (completionBlock) + completionBlock(self); + } withPriority:PINOperationQueuePriorityLow]; +} + +#pragma mark - Public Synchronous Methods - + +- (BOOL)containsObjectForKey:(NSString *)key +{ + if (!key) + return NO; + + [self lock]; + BOOL containsObject = (_dictionary[key] != nil); + [self unlock]; + return containsObject; +} + +- (nullable id)objectForKey:(NSString *)key +{ + if (!key) + return nil; + + NSDate *now = [NSDate date]; + [self lock]; + id object = nil; + // If the cache should behave like a TTL cache, then only fetch the object if there's a valid ageLimit and the object is still alive + NSTimeInterval ageLimit = [_ageLimits[key] doubleValue] ?: self->_ageLimit; + if (!self->_ttlCache || ageLimit <= 0 || fabs([[_createdDates objectForKey:key] timeIntervalSinceDate:now]) < ageLimit) { + object = _dictionary[key]; + } + [self unlock]; + + if (object) { + [self lock]; + _accessDates[key] = now; + NSInteger accessCount = [_accessCounts[key] integerValue]; + if (accessCount < NSIntegerMax) { + _accessCounts[key] = @(accessCount + 1); + } + [self unlock]; + } + + return object; +} + +- (id)objectForKeyedSubscript:(NSString *)key +{ + return [self objectForKey:key]; +} + +- (void)setObject:(id)object forKey:(NSString *)key +{ + [self setObject:object forKey:key withCost:0]; +} + +- (void)setObject:(id)object forKey:(NSString *)key withAgeLimit:(NSTimeInterval)ageLimit +{ + [self setObject:object forKey:key withCost:0 ageLimit:ageLimit]; +} + +- (void)setObject:(id)object forKeyedSubscript:(NSString *)key +{ + if (object == nil) { + [self removeObjectForKey:key]; + } else { + [self setObject:object forKey:key]; + } +} + +- (void)setObject:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost +{ + [self setObject:object forKey:key withCost:cost ageLimit:0.0]; +} + +- (void)setObject:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost ageLimit:(NSTimeInterval)ageLimit +{ + NSAssert(ageLimit <= 0.0 || (ageLimit > 0.0 && _ttlCache), @"ttlCache must be set to YES if setting an object-level age limit."); + + if (!key || !object) + return; + + [self lock]; + PINCacheObjectBlock willAddObjectBlock = _willAddObjectBlock; + PINCacheObjectBlock didAddObjectBlock = _didAddObjectBlock; + NSUInteger costLimit = _costLimit; + [self unlock]; + + if (willAddObjectBlock) + willAddObjectBlock(self, key, object); + + [self lock]; + NSNumber* oldCost = _costs[key]; + if (oldCost) + _totalCost -= [oldCost unsignedIntegerValue]; + + NSDate *now = [NSDate date]; + _dictionary[key] = object; + _createdDates[key] = now; + _accessDates[key] = now; + NSInteger accessCount = [_accessCounts[key] integerValue]; + if (accessCount < NSIntegerMax) { + _accessCounts[key] = @(accessCount + 1); + } + + _costs[key] = @(cost); + + if (ageLimit > 0.0) { + _ageLimits[key] = @(ageLimit); + } else { + [_ageLimits removeObjectForKey:key]; + } + + _totalCost += cost; + [self unlock]; + + if (didAddObjectBlock) + didAddObjectBlock(self, key, object); + + if (costLimit > 0) + [self trimToCostByEvictionStrategy:costLimit]; +} + +- (void)removeObjectForKey:(NSString *)key +{ + if (!key) + return; + + [self removeObjectAndExecuteBlocksForKey:key]; +} + +- (void)trimToDate:(NSDate *)trimDate +{ + if (!trimDate) + return; + + if ([trimDate isEqualToDate:[NSDate distantPast]]) { + [self removeAllObjects]; + return; + } + + [self trimMemoryToDate:trimDate]; +} + +- (void)trimToCost:(NSUInteger)cost +{ + [self trimToCostLimit:cost]; +} + +- (void)trimToCostByEvictionStrategy:(NSUInteger)cost +{ + [self trimToCostLimitByEvictionStrategy:cost]; +} + +- (void)removeAllObjects +{ + [self lock]; + PINCacheBlock willRemoveAllObjectsBlock = _willRemoveAllObjectsBlock; + PINCacheBlock didRemoveAllObjectsBlock = _didRemoveAllObjectsBlock; + [self unlock]; + + if (willRemoveAllObjectsBlock) + willRemoveAllObjectsBlock(self); + + [self lock]; + [_dictionary removeAllObjects]; + [_createdDates removeAllObjects]; + [_accessDates removeAllObjects]; + [_accessCounts removeAllObjects]; + [_costs removeAllObjects]; + [_ageLimits removeAllObjects]; + + _totalCost = 0; + [self unlock]; + + if (didRemoveAllObjectsBlock) + didRemoveAllObjectsBlock(self); + +} + +- (void)enumerateObjectsWithBlock:(PIN_NOESCAPE PINCacheObjectEnumerationBlock)block +{ + if (!block) + return; + + [self lock]; + NSDate *now = [NSDate date]; + NSArray *keysSortedByCreatedDate = [_createdDates keysSortedByValueUsingSelector:@selector(compare:)]; + + for (NSString *key in keysSortedByCreatedDate) { + // If the cache should behave like a TTL cache, then only fetch the object if there's a valid ageLimit and the object is still alive + NSTimeInterval ageLimit = [_ageLimits[key] doubleValue] ?: self->_ageLimit; + if (!self->_ttlCache || ageLimit <= 0 || fabs([[_createdDates objectForKey:key] timeIntervalSinceDate:now]) < ageLimit) { + BOOL stop = NO; + block(self, key, _dictionary[key], &stop); + if (stop) + break; + } + } + [self unlock]; +} + +#pragma mark - Public Thread Safe Accessors - + +- (PINCacheObjectBlock)willAddObjectBlock +{ + [self lock]; + PINCacheObjectBlock block = _willAddObjectBlock; + [self unlock]; + + return block; +} + +- (void)setWillAddObjectBlock:(PINCacheObjectBlock)block +{ + [self lock]; + _willAddObjectBlock = [block copy]; + [self unlock]; +} + +- (PINCacheObjectBlock)willRemoveObjectBlock +{ + [self lock]; + PINCacheObjectBlock block = _willRemoveObjectBlock; + [self unlock]; + + return block; +} + +- (void)setWillRemoveObjectBlock:(PINCacheObjectBlock)block +{ + [self lock]; + _willRemoveObjectBlock = [block copy]; + [self unlock]; +} + +- (PINCacheBlock)willRemoveAllObjectsBlock +{ + [self lock]; + PINCacheBlock block = _willRemoveAllObjectsBlock; + [self unlock]; + + return block; +} + +- (void)setWillRemoveAllObjectsBlock:(PINCacheBlock)block +{ + [self lock]; + _willRemoveAllObjectsBlock = [block copy]; + [self unlock]; +} + +- (PINCacheObjectBlock)didAddObjectBlock +{ + [self lock]; + PINCacheObjectBlock block = _didAddObjectBlock; + [self unlock]; + + return block; +} + +- (void)setDidAddObjectBlock:(PINCacheObjectBlock)block +{ + [self lock]; + _didAddObjectBlock = [block copy]; + [self unlock]; +} + +- (PINCacheObjectBlock)didRemoveObjectBlock +{ + [self lock]; + PINCacheObjectBlock block = _didRemoveObjectBlock; + [self unlock]; + + return block; +} + +- (void)setDidRemoveObjectBlock:(PINCacheObjectBlock)block +{ + [self lock]; + _didRemoveObjectBlock = [block copy]; + [self unlock]; +} + +- (PINCacheBlock)didRemoveAllObjectsBlock +{ + [self lock]; + PINCacheBlock block = _didRemoveAllObjectsBlock; + [self unlock]; + + return block; +} + +- (void)setDidRemoveAllObjectsBlock:(PINCacheBlock)block +{ + [self lock]; + _didRemoveAllObjectsBlock = [block copy]; + [self unlock]; +} + +- (PINCacheBlock)didReceiveMemoryWarningBlock +{ + [self lock]; + PINCacheBlock block = _didReceiveMemoryWarningBlock; + [self unlock]; + + return block; +} + +- (void)setDidReceiveMemoryWarningBlock:(PINCacheBlock)block +{ + [self lock]; + _didReceiveMemoryWarningBlock = [block copy]; + [self unlock]; +} + +- (PINCacheBlock)didEnterBackgroundBlock +{ + [self lock]; + PINCacheBlock block = _didEnterBackgroundBlock; + [self unlock]; + + return block; +} + +- (void)setDidEnterBackgroundBlock:(PINCacheBlock)block +{ + [self lock]; + _didEnterBackgroundBlock = [block copy]; + [self unlock]; +} + +- (NSTimeInterval)ageLimit +{ + [self lock]; + NSTimeInterval ageLimit = _ageLimit; + [self unlock]; + + return ageLimit; +} + +- (void)setAgeLimit:(NSTimeInterval)ageLimit +{ + [self lock]; + _ageLimit = ageLimit; + [self unlock]; + + [self trimToAgeLimitRecursively]; +} + +- (NSUInteger)costLimit +{ + [self lock]; + NSUInteger costLimit = _costLimit; + [self unlock]; + + return costLimit; +} + +- (void)setCostLimit:(NSUInteger)costLimit +{ + [self lock]; + _costLimit = costLimit; + [self unlock]; + + if (costLimit > 0) + [self trimToCostLimitByEvictionStrategy:costLimit]; +} + +- (NSUInteger)totalCost +{ + [self lock]; + NSUInteger cost = _totalCost; + [self unlock]; + + return cost; +} + +- (BOOL)isTTLCache { + BOOL isTTLCache; + + [self lock]; + isTTLCache = _ttlCache; + [self unlock]; + + return isTTLCache; +} + +- (void)lock +{ + __unused int result = pthread_mutex_lock(&_mutex); + NSAssert(result == 0, @"Failed to lock PINMemoryCache %@. Code: %d", self, result); +} + +- (void)unlock +{ + __unused int result = pthread_mutex_unlock(&_mutex); + NSAssert(result == 0, @"Failed to unlock PINMemoryCache %@. Code: %d", self, result); +} + +@end + + +#pragma mark - Deprecated + +@implementation PINMemoryCache (Deprecated) + +- (void)containsObjectForKey:(NSString *)key block:(PINMemoryCacheContainmentBlock)block +{ + [self containsObjectForKeyAsync:key completion:block]; +} + +- (void)objectForKey:(NSString *)key block:(nullable PINMemoryCacheObjectBlock)block +{ + [self objectForKeyAsync:key completion:^(id memoryCache, NSString *memoryCacheKey, id memoryCacheObject) { + if (block) { + block((PINMemoryCache *)memoryCache, memoryCacheKey, memoryCacheObject); + } + }]; +} + +- (void)setObject:(id)object forKey:(NSString *)key block:(nullable PINMemoryCacheObjectBlock)block +{ + [self setObjectAsync:object forKey:key completion:^(id memoryCache, NSString *memoryCacheKey, id memoryCacheObject) { + if (block) { + block((PINMemoryCache *)memoryCache, memoryCacheKey, memoryCacheObject); + } + }]; +} + +- (void)setObject:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost block:(nullable PINMemoryCacheObjectBlock)block +{ + [self setObjectAsync:object forKey:key withCost:cost completion:^(id memoryCache, NSString *memoryCacheKey, id memoryCacheObject) { + if (block) { + block((PINMemoryCache *)memoryCache, memoryCacheKey, memoryCacheObject); + } + }]; +} + +- (void)removeObjectForKey:(NSString *)key block:(nullable PINMemoryCacheObjectBlock)block +{ + [self removeObjectForKeyAsync:key completion:^(id memoryCache, NSString *memoryCacheKey, id memoryCacheObject) { + if (block) { + block((PINMemoryCache *)memoryCache, memoryCacheKey, memoryCacheObject); + } + }]; +} + +- (void)trimToDate:(NSDate *)date block:(nullable PINMemoryCacheBlock)block +{ + [self trimToDateAsync:date completion:^(id memoryCache) { + if (block) { + block((PINMemoryCache *)memoryCache); + } + }]; +} + +- (void)trimToCost:(NSUInteger)cost block:(nullable PINMemoryCacheBlock)block +{ + [self trimToCostAsync:cost completion:^(id memoryCache) { + if (block) { + block((PINMemoryCache *)memoryCache); + } + }]; +} + +- (void)trimToCostByDate:(NSUInteger)cost block:(nullable PINMemoryCacheBlock)block +{ + [self trimToCostByEvictionStrategyAsync:cost completion:^(id memoryCache) { + if (block) { + block((PINMemoryCache *)memoryCache); + } + }]; +} + +- (void)removeAllObjects:(nullable PINMemoryCacheBlock)block +{ + [self removeAllObjectsAsync:^(id memoryCache) { + if (block) { + block((PINMemoryCache *)memoryCache); + } + }]; +} + +- (void)enumerateObjectsWithBlock:(PINMemoryCacheObjectBlock)block completionBlock:(nullable PINMemoryCacheBlock)completionBlock +{ + [self enumerateObjectsWithBlockAsync:^(id _Nonnull cache, NSString * _Nonnull key, id _Nullable object, BOOL * _Nonnull stop) { + if ([cache isKindOfClass:[PINMemoryCache class]]) { + PINMemoryCache *memoryCache = (PINMemoryCache *)cache; + block(memoryCache, key, object); + } + } completionBlock:^(id memoryCache) { + if (completionBlock) { + completionBlock((PINMemoryCache *)memoryCache); + } + }]; +} + +- (void)setTtlCache:(BOOL)ttlCache +{ + [self lock]; + _ttlCache = ttlCache; + [self unlock]; +} + +- (void)trimToCostByDate:(NSUInteger)cost +{ + [self trimToCostByEvictionStrategy:cost]; +} + +- (void)trimToCostByDateAsync:(NSUInteger)cost completion:(nullable PINCacheBlock)block +{ + [self trimToCostByEvictionStrategyAsync:cost completion:block]; +} + +@end diff --git a/Carthage/Checkouts/PINCache/Source/PrivacyInfo.xcprivacy b/Carthage/Checkouts/PINCache/Source/PrivacyInfo.xcprivacy new file mode 100644 index 00000000..3d1e6f5b --- /dev/null +++ b/Carthage/Checkouts/PINCache/Source/PrivacyInfo.xcprivacy @@ -0,0 +1,23 @@ + + + + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + NSPrivacyCollectedDataTypes + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryFileTimestamp + NSPrivacyAccessedAPITypeReasons + + 0A2A.1 + + + + + diff --git a/Carthage/Checkouts/PINCache/Source/include/PINCache/PINCache.h b/Carthage/Checkouts/PINCache/Source/include/PINCache/PINCache.h new file mode 120000 index 00000000..76a60a50 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Source/include/PINCache/PINCache.h @@ -0,0 +1 @@ +../../PINCache.h \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Source/include/PINCache/PINCacheMacros.h b/Carthage/Checkouts/PINCache/Source/include/PINCache/PINCacheMacros.h new file mode 120000 index 00000000..80168b7b --- /dev/null +++ b/Carthage/Checkouts/PINCache/Source/include/PINCache/PINCacheMacros.h @@ -0,0 +1 @@ +../../PINCacheMacros.h \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Source/include/PINCache/PINCacheObjectSubscripting.h b/Carthage/Checkouts/PINCache/Source/include/PINCache/PINCacheObjectSubscripting.h new file mode 120000 index 00000000..ceeb3108 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Source/include/PINCache/PINCacheObjectSubscripting.h @@ -0,0 +1 @@ +../../PINCacheObjectSubscripting.h \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Source/include/PINCache/PINCaching.h b/Carthage/Checkouts/PINCache/Source/include/PINCache/PINCaching.h new file mode 120000 index 00000000..7bdfe5c4 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Source/include/PINCache/PINCaching.h @@ -0,0 +1 @@ +../../PINCaching.h \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Source/include/PINCache/PINDiskCache.h b/Carthage/Checkouts/PINCache/Source/include/PINCache/PINDiskCache.h new file mode 120000 index 00000000..323ef6a2 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Source/include/PINCache/PINDiskCache.h @@ -0,0 +1 @@ +../../PINDiskCache.h \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Source/include/PINCache/PINMemoryCache.h b/Carthage/Checkouts/PINCache/Source/include/PINCache/PINMemoryCache.h new file mode 120000 index 00000000..68e77631 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Source/include/PINCache/PINMemoryCache.h @@ -0,0 +1 @@ +../../PINMemoryCache.h \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/Tests/Default-568h@2x.png b/Carthage/Checkouts/PINCache/Tests/Default-568h@2x.png new file mode 100644 index 00000000..9fe62db8 Binary files /dev/null and b/Carthage/Checkouts/PINCache/Tests/Default-568h@2x.png differ diff --git a/Carthage/Checkouts/PINCache/Tests/Info.plist b/Carthage/Checkouts/PINCache/Tests/Info.plist new file mode 100644 index 00000000..ba72822e --- /dev/null +++ b/Carthage/Checkouts/PINCache/Tests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Carthage/Checkouts/PINCache/Tests/NSDate+PINCacheTests.h b/Carthage/Checkouts/PINCache/Tests/NSDate+PINCacheTests.h new file mode 100644 index 00000000..e11033d0 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Tests/NSDate+PINCacheTests.h @@ -0,0 +1,15 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSDate (PINCacheTests) + +/** Swizzles +[NSDate date] to always return the specified date. */ ++ (void)startMockingDateWithDate:(NSDate *)date; + +/** Stops swizzling +[NSDate date] and returns to original implementation */ ++ (void)stopMockingDate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/PINCache/Tests/NSDate+PINCacheTests.m b/Carthage/Checkouts/PINCache/Tests/NSDate+PINCacheTests.m new file mode 100644 index 00000000..1133c2b0 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Tests/NSDate+PINCacheTests.m @@ -0,0 +1,50 @@ +#import "NSDate+PINCacheTests.h" + +#import + +static NSDate *PINCacheTestsSwizzedDate = nil; + +@implementation NSDate (PINCacheTests) + ++ (void)startMockingDateWithDate:(NSDate *)date +{ + // If already swizzled, just replace the static date. + BOOL alreadySwizzled = (PINCacheTestsSwizzedDate != nil); + PINCacheTestsSwizzedDate = date; + if (alreadySwizzled) { return; } + + SEL originalSelector = @selector(date); + SEL swizzledSelector = @selector(swizzled_date); + + Method originalMethod = class_getClassMethod(self, originalSelector); + Method swizzledMethod = class_getClassMethod(self, swizzledSelector); + + Class class = object_getClass((id)self); + + if (class_addMethod(class, + originalSelector, + method_getImplementation(swizzledMethod), + method_getTypeEncoding(swizzledMethod))) { + class_replaceMethod(class, + swizzledSelector, + method_getImplementation(originalMethod), + method_getTypeEncoding(originalMethod)); + } else { + method_exchangeImplementations(originalMethod, swizzledMethod); + } +} + ++ (void)stopMockingDate +{ + Method originalMethod = class_getClassMethod(self, @selector(date)); + Method swizzledMethod = class_getClassMethod(self, @selector(swizzled_date)); + method_exchangeImplementations(swizzledMethod, originalMethod); + PINCacheTestsSwizzedDate = nil; +} + ++ (instancetype)swizzled_date +{ + return PINCacheTestsSwizzedDate; +} + +@end diff --git a/Carthage/Checkouts/PINCache/Tests/PINCacheTests.h b/Carthage/Checkouts/PINCache/Tests/PINCacheTests.h new file mode 100644 index 00000000..0d46b14d --- /dev/null +++ b/Carthage/Checkouts/PINCache/Tests/PINCacheTests.h @@ -0,0 +1,11 @@ +// PINCache is a modified version of TMCache +// Modifications by Garrett Moon +// Copyright (c) 2015 Pinterest. All rights reserved. + +#import + +extern const NSTimeInterval PINCacheTestBlockTimeout; + +@interface PINCacheTests : XCTestCase + +@end diff --git a/Carthage/Checkouts/PINCache/Tests/PINCacheTests.m b/Carthage/Checkouts/PINCache/Tests/PINCacheTests.m new file mode 100644 index 00000000..c154a127 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Tests/PINCacheTests.m @@ -0,0 +1,1530 @@ +// PINCache is a modified version of TMCache +// Modifications by Garrett Moon +// Copyright (c) 2015 Pinterest. All rights reserved. + +#import +#import + +#import "PINCacheTests.h" +#import "NSDate+PINCacheTests.h" +#import "PINDiskCache+PINCacheTests.h" + + +#if TARGET_OS_IPHONE + typedef UIImage PINImage; +#else + typedef NSImage PINImage; +#endif + +static NSString * const PINCacheTestName = @"PINCacheTest"; +const NSTimeInterval PINCacheTestBlockTimeout = 20.0; + +@interface PINDiskCache() + +@property (assign, nonatomic) BOOL diskStateKnown; +@property (strong, nonatomic) NSDictionary *metadata; +@property (readonly) PINOperationQueue *operationQueue; + ++ (dispatch_queue_t)sharedTrashQueue; ++ (NSLock *)sharedLock; ++ (NSURL *)sharedTrashURL; +- (NSString *)encodedString:(NSString *)string; + +@end + +@interface PINMemoryCache () + +- (void)didReceiveEnterBackgroundNotification:(NSNotification *)notification; +- (void)setTtlCache:(BOOL)ttlCache; + +@end + +@interface PINCacheTests () +@property (strong, nonatomic) PINCache *cache; +@end + +@implementation PINCacheTests + +#pragma mark - XCTestCase - + +- (void)setUp +{ + [super setUp]; + self.cache = [[PINCache alloc] initWithName:[[NSUUID UUID] UUIDString]]; + + XCTAssertNotNil(self.cache, @"test cache does not exist"); +} + +- (void)tearDownWithCompletionHandler:(void (^)(NSError * _Nullable))completion { + dispatch_group_t group = dispatch_group_create(); + dispatch_group_enter(group); + + [self.cache removeAllObjects]; + + // Wait for disk cache to clean up its trash + dispatch_async([PINDiskCache sharedTrashQueue], ^{ + dispatch_group_leave(group); + }); + dispatch_group_wait(group, DISPATCH_TIME_FOREVER); + + self.cache = nil; + + XCTAssertNil(self.cache, @"test cache did not deallocate"); + + completion(nil); +} + +#pragma mark - Private Methods + +- (PINImage *)image +{ + static PINImage *image = nil; + + if (!image) { +#ifdef TEST_AS_SPM + NSBundle *bun = SWIFTPM_MODULE_BUNDLE; +#else + NSBundle *bun = [NSBundle bundleForClass:self.class]; + +#endif + NSURL *imageURL = [bun URLForResource:@"Default-568h@2x" withExtension:@"png"]; + NSError *error = nil; + NSData *imageData = [[NSData alloc] initWithContentsOfURL:imageURL + options:NSDataReadingUncached + error:&error]; + image = [[PINImage alloc] initWithData:imageData]; + } + + NSAssert(image, @"test image does not exist"); + + return image; +} + +- (dispatch_time_t)timeout +{ + return dispatch_time(DISPATCH_TIME_NOW, (int64_t)(PINCacheTestBlockTimeout * NSEC_PER_SEC)); +} + +#pragma mark - Tests - + +- (void)testDiskCacheStringEncoding +{ + NSString *string = [self.cache.diskCache encodedString:@"http://www.test.de-?%"]; + XCTAssertTrue([string isEqualToString:@"http%3A%2F%2Fwww%2Etest%2Ede-?%25"]); +} + +- (void)testCoreProperties +{ + PINCache *cache = [[PINCache alloc] initWithName:PINCacheTestName]; + XCTAssertTrue([cache.name isEqualToString:PINCacheTestName], @"wrong name"); + XCTAssertNotNil(cache.memoryCache, @"memory cache does not exist"); + XCTAssertNotNil(cache.diskCache, @"disk cache doe not exist"); +} + +- (void)testDiskCacheURL +{ + // Wait for URL to be created. We use enumerateObjectsWithBlock because it waits for a known disk state. + [self.cache.diskCache enumerateObjectsWithBlock:^(NSString * _Nonnull key, NSURL * _Nullable fileURL, BOOL * _Nonnull stop) {}]; + BOOL isDir = NO; + BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:[self.cache.diskCache.cacheURL path] isDirectory:&isDir]; + + XCTAssertTrue(exists, @"disk cache directory does not exist"); + XCTAssertTrue(isDir, @"disk cache url is not a directory"); +} + +- (void)testObjectSet +{ + NSString *key = @"key"; + __block PINImage *image = nil; + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + + [self.cache setObjectAsync:[self image] forKey:key completion:^(id cache, NSString *key, id object) { + image = (PINImage *)object; + dispatch_semaphore_signal(semaphore); + }]; + + dispatch_semaphore_wait(semaphore, [self timeout]); + + XCTAssertNotNil(image, @"object was not set"); +} + +- (void)testObjectSetWithCost +{ + NSString *key = @"key"; + __block PINImage *image = nil; + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + PINImage *srcImage = [self image]; + NSUInteger cost = (NSUInteger)(srcImage.size.width * srcImage.size.height); + + [self.cache setObjectAsync:srcImage forKey:key withCost:cost completion:^(id cache, NSString *key, id object) { + image = (PINImage *)object; + dispatch_semaphore_signal(semaphore); + }]; + + dispatch_semaphore_wait(semaphore, [self timeout]); + + XCTAssertNotNil(image, @"object was not set"); + XCTAssertTrue(self.cache.memoryCache.totalCost == cost, @"memory cache total cost was incorrect"); +} + +- (void)testObjectSetWithDuplicateKey +{ + NSString *key = @"key"; + NSString *value1 = @"value1"; + NSString *value2 = @"value2"; + __block NSString *cachedValue = nil; + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + + [self.cache setObject:value1 forKey:key]; + [self.cache setObject:value2 forKey:key]; + + [self.cache objectForKeyAsync:key completion:^(id cache, NSString *key, id object) { + cachedValue = (NSString *)object; + dispatch_semaphore_signal(semaphore); + }]; + + dispatch_semaphore_wait(semaphore, [self timeout]); + + XCTAssertEqual(cachedValue, value2, @"set did not overwrite previous object with same key"); +} + +- (void)testObjectContains +{ + NSString *key = @"key"; + NSString *value = @"value"; + + [self.cache setObject:value forKey:key]; + + // Synchronously + XCTAssertTrue([self.cache containsObjectForKey:key], @"object was gone"); + + // Asynchronously + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + __block BOOL cacheContainsObject = NO; + [self.cache containsObjectForKeyAsync:key completion:^(BOOL containsObject) { + cacheContainsObject = containsObject; + dispatch_semaphore_signal(semaphore); + }]; + dispatch_semaphore_wait(semaphore, [self timeout]); + + XCTAssertTrue(cacheContainsObject, @"object was gone"); +} + +- (void)testObjectContainsWithCost +{ + NSString *key = @"key"; + NSString *value = @"value"; + + [self.cache setObject:value forKey:key withCost:1]; + + // Synchronously + XCTAssertTrue([self.cache containsObjectForKey:key], @"object was gone"); + + // Asynchronously + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + __block BOOL cacheContainsObject = NO; + [self.cache containsObjectForKeyAsync:key completion:^(BOOL containsObject) { + cacheContainsObject = containsObject; + dispatch_semaphore_signal(semaphore); + }]; + dispatch_semaphore_wait(semaphore, [self timeout]); + + XCTAssertTrue(cacheContainsObject, @"object was gone"); + XCTAssertTrue(self.cache.memoryCache.totalCost == 1, @"memory cache total cost was incorrect"); +} + +- (void)testObjectGet +{ + NSString *key = @"key"; + __block PINImage *image = nil; + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + + self.cache[key] = [self image]; + + [self.cache objectForKeyAsync:key completion:^(id cache, NSString *key, id object) { + image = (PINImage *)object; + dispatch_semaphore_signal(semaphore); + }]; + + dispatch_semaphore_wait(semaphore, [self timeout]); + + XCTAssertNotNil(image, @"object was not got"); +} + +- (void)testObjectGetWithInvalidKey +{ + NSString *key = @"key"; + NSString *invalidKey = @"invalid"; + __block PINImage *image = nil; + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + + self.cache[key] = [self image]; + + [self.cache objectForKeyAsync:invalidKey completion:^(id cache, NSString *key, id object) { + image = (PINImage *)object; + dispatch_semaphore_signal(semaphore); + }]; + + dispatch_semaphore_wait(semaphore, [self timeout]); + + XCTAssertNil(image, @"object with non-existent key was not nil"); +} + +- (void)testObjectRemove +{ + NSString *key = @"key"; + + self.cache[key] = [self image]; + + __block BOOL willRemoveObjectBlockCalled = NO; + self.cache.diskCache.willRemoveObjectBlock = ^(PINDiskCache * _Nonnull cache, NSString * _Nonnull key, id _Nullable object) { + willRemoveObjectBlockCalled = YES; + }; + + __block BOOL didRemoveObjectBlockCalled = NO; + self.cache.diskCache.didRemoveObjectBlock = ^(PINDiskCache * _Nonnull cache, NSString * _Nonnull key, id _Nullable object) { + didRemoveObjectBlockCalled = YES; + }; + + // Clear out operation queue to ensure blocks are set. + [self.cache.diskCache.operationQueue waitUntilAllOperationsAreFinished]; + + [self.cache removeObjectForKey:key]; + + id object = self.cache[key]; + + XCTAssertNil(object, @"object was not removed"); + XCTAssertTrue(willRemoveObjectBlockCalled, @"willRemoveObjectBlock was not called"); + XCTAssertTrue(didRemoveObjectBlockCalled, @"didRemoveObjectBlock was not called"); +} + +- (void)testObjectRemoveAll +{ + NSString *key1 = @"key1"; + NSString *key2 = @"key2"; + + self.cache[key1] = key1; + self.cache[key2] = key2; + + __block BOOL willRemoveAllObjectsBlockCalled = NO; + self.cache.diskCache.willRemoveAllObjectsBlock = ^(id _Nonnull cache) { + willRemoveAllObjectsBlockCalled = YES; + }; + + __block BOOL didRemoveAllObjectsBlockCalled = NO; + self.cache.diskCache.didRemoveAllObjectsBlock = ^(id _Nonnull cache) { + didRemoveAllObjectsBlockCalled = YES; + }; + + [self.cache.diskCache.operationQueue waitUntilAllOperationsAreFinished]; + + [self.cache removeAllObjects]; + + id object1 = self.cache[key1]; + id object2 = self.cache[key2]; + + XCTAssertNil(object1, @"not all objects were removed"); + XCTAssertNil(object2, @"not all objects were removed"); + XCTAssertTrue(willRemoveAllObjectsBlockCalled, @"willRemoveAllObjectsBlock was not called"); + XCTAssertTrue(didRemoveAllObjectsBlockCalled, @"didRemoveAllObjectsBlock was not called"); + XCTAssertTrue(self.cache.memoryCache.totalCost == 0, @"memory cache cost was not 0 after removing all objects"); + XCTAssertTrue(self.cache.diskByteCount == 0, @"disk cache byte count was not 0 after removing all objects"); +} + +- (void)testMemoryCost +{ + NSString *key1 = @"key1"; + NSString *key2 = @"key2"; + + [self.cache.memoryCache setObject:key1 forKey:key1 withCost:1]; + [self.cache.memoryCache setObject:key2 forKey:key2 withCost:2]; + + XCTAssertTrue(self.cache.memoryCache.totalCost == 3, @"memory cache total cost was incorrect"); + + [self.cache.memoryCache trimToCost:1]; + + id object1 = self.cache.memoryCache[key1]; + id object2 = self.cache.memoryCache[key2]; + + XCTAssertNotNil(object1, @"object did not survive memory cache trim to cost"); + XCTAssertNil(object2, @"object was not trimmed despite exceeding cost"); + XCTAssertTrue(self.cache.memoryCache.totalCost == 1, @"cache had an unexpected total cost"); +} + +- (void)testMemoryCostOnReplace +{ + NSString *key1 = @"key1"; + + for(int i=0; i<10; i++) { + [self.cache.memoryCache setObject:key1 forKey:key1 withCost:1]; + } + + XCTAssertTrue(self.cache.memoryCache.totalCost == 1, @"cache had an unexpected total cost"); +} + +- (void)testMemoryCostByLRU +{ + NSString *key1 = @"key1"; + NSString *key2 = @"key2"; + + [self.cache.memoryCache setObject:key1 forKey:key1 withCost:1]; + [self.cache.memoryCache setObject:key2 forKey:key2 withCost:2]; + + [self.cache.memoryCache trimToCostByEvictionStrategy:1]; + + id object1 = self.cache.memoryCache[key1]; + id object2 = self.cache.memoryCache[key2]; + + XCTAssertNil(object1, @"object was not trimmed despite exceeding cost"); + XCTAssertNil(object2, @"object was not trimmed despite exceeding cost"); + XCTAssertTrue(self.cache.memoryCache.totalCost == 0, @"cache had an unexpected total cost"); +} + +- (void)testMemoryCostByLFU +{ + NSString *key1 = @"key1"; + NSString *key2 = @"key2"; + + self.cache.memoryCache.evictionStrategy = PINCacheEvictionStrategyLeastFrequentlyUsed; + + [self.cache.memoryCache setObject:key1 forKey:key1 withCost:1]; + [self.cache.memoryCache setObject:key2 forKey:key2 withCost:2]; + + [self.cache.memoryCache trimToCostByEvictionStrategy:1]; + + id object1 = self.cache.memoryCache[key1]; + id object2 = self.cache.memoryCache[key2]; + + XCTAssertNil(object1, @"object was not trimmed despite exceeding cost"); + XCTAssertNil(object2, @"object was not trimmed despite exceeding cost"); + XCTAssertTrue(self.cache.memoryCache.totalCost == 0, @"cache had an unexpected total cost"); +} + +- (void)testMemoryCostByLFUOnlyOneNeeded +{ + NSString *key1 = @"key1"; + NSString *key2 = @"key2"; + + self.cache.memoryCache.evictionStrategy = PINCacheEvictionStrategyLeastFrequentlyUsed; + + // Least recently used will be key1, but least frequently used will be key2 + [self.cache.memoryCache setObject:key1 forKey:key1 withCost:1]; + (void)self.cache.memoryCache[key1]; // 2nd access count + [self.cache.memoryCache setObject:key2 forKey:key2 withCost:2]; + + [self.cache.memoryCache trimToCostByEvictionStrategy:1]; + + id object1 = self.cache.memoryCache[key1]; + id object2 = self.cache.memoryCache[key2]; + + XCTAssertNotNil(object1, @"object was trimmed despite not exceeding cost"); + XCTAssertNil(object2, @"object was not trimmed despite exceeding cost"); + XCTAssertTrue(self.cache.memoryCache.totalCost == 1, @"cache had an unexpected total cost"); +} + +- (void)testMemoryCostByDateWithObjectExpiration +{ + [self.cache.memoryCache setTtlCache:YES]; + [self.cache.memoryCache removeAllObjects]; + NSString * const key1 = @"key1"; + NSString * const key2 = @"key2"; + NSString * const key3 = @"key3"; + NSString * const key4 = @"key4"; + const NSUInteger cost = 1; + const NSTimeInterval oldAgeLimit = 60.0; + const NSTimeInterval notSoOldAgeLimit = 30.0; + + // Add the objects to the cache; set the age limit of one of them (key3) so it expires before the others. + [self.cache.memoryCache setObject:[self image] forKey:key1 withCost:cost ageLimit:oldAgeLimit]; + [self.cache.memoryCache setObject:[self image] forKey:key2 withCost:cost ageLimit:oldAgeLimit]; + [self.cache.memoryCache setObject:[self image] forKey:key3 withCost:cost ageLimit:notSoOldAgeLimit]; + [self.cache.memoryCache setObject:[self image] forKey:key4 withCost:cost ageLimit:oldAgeLimit]; + + // Make the order of recently used key3, key1, key4, key2 + [self.cache.memoryCache objectForKey:key2]; + [self.cache.memoryCache objectForKey:key4]; + [self.cache.memoryCache objectForKey:key1]; + [self.cache.memoryCache objectForKey:key3]; + + // Fast forward 45 seconds. This should expire key3. + [NSDate startMockingDateWithDate:[NSDate dateWithTimeIntervalSinceNow:45]]; + + // Trim the cache enough to evict two objects. + [self.cache.memoryCache trimToCostByEvictionStrategy:self.cache.memoryCache.totalCost - cost * 2]; + + // Go back to current time, so we can check if objects exist in cache. If we don't do this, the getters will return nil + // even if the objects are in the cache. + [NSDate stopMockingDate]; + + // The only objects left should be the last two that were accessed (key3 && key1), but since key3 is expired it will be + // removed first leaving key1 and key4 to remain. + NSMutableArray *keys = [NSMutableArray array]; + [self.cache.memoryCache enumerateObjectsWithBlock:^(id cache, NSString * key, id object, BOOL *stop) { + [keys addObject:key]; + }]; + XCTAssertTrue(keys.count == 2); + XCTAssertTrue([keys.firstObject isEqualToString:key1] || [keys.firstObject isEqualToString:key4]); + XCTAssertTrue([keys.lastObject isEqualToString:key1] || [keys.lastObject isEqualToString:key4]); +} + +- (void)testDiskByteCount +{ + self.cache[@"image"] = [self image]; + + XCTAssertTrue(self.cache.diskByteCount > 0, @"disk cache byte count was not greater than zero"); +} + +- (void)testDiskByteCountWithExistingKey +{ + self.cache[@"image"] = [self image]; + NSUInteger initialDiskByteCount = self.cache.diskByteCount; + self.cache[@"image"] = [self image]; + + XCTAssertTrue(self.cache.diskByteCount == initialDiskByteCount, @"disk cache byte count should not change by adding object with existing key and size"); + + self.cache[@"image2"] = [self image]; + + XCTAssertTrue(self.cache.diskByteCount > initialDiskByteCount, @"disk cache byte count should increase with new key and object added to disk cache"); +} + +- (void)testDiskSizeByDateWithObjectExpiration +{ + [self.cache.diskCache setTtlCacheSync:YES]; + [self.cache.diskCache removeAllObjects]; + NSString * const key1 = @"key1"; + NSString * const key2 = @"key2"; + NSString * const key3 = @"key3"; + NSString * const key4 = @"key4"; + const NSUInteger cost = 1; + const NSTimeInterval oldAgeLimit = 60.0; + const NSTimeInterval notSoOldAgeLimit = 30.0; + + // Add the objects to the cache; set the age limit of one of them (key3) so it expires before the others. + [self.cache.diskCache setObject:[self image] forKey:key1 withCost:cost ageLimit:oldAgeLimit]; + [self.cache.diskCache setObject:[self image] forKey:key2 withCost:cost ageLimit:oldAgeLimit]; + [self.cache.diskCache setObject:[self image] forKey:key3 withCost:cost ageLimit:notSoOldAgeLimit]; + NSUInteger sizeOfThreeObjects = self.cache.diskCache.byteCount; + [self.cache.diskCache setObject:[self image] forKey:key4 withCost:cost ageLimit:oldAgeLimit]; + + // Make the order of recently used key3, key1, key4, key2 + [self.cache.diskCache objectForKey:key2]; + [self.cache.diskCache objectForKey:key4]; + [self.cache.diskCache objectForKey:key1]; + [self.cache.diskCache objectForKey:key3]; + + // Fast forward 45 seconds. This should expire key3. + [NSDate startMockingDateWithDate:[NSDate dateWithTimeIntervalSinceNow:45]]; + + + // Trim the cache enough to evict two objects. + [self.cache.diskCache trimToSizeByEvictionStrategy:sizeOfThreeObjects - 1]; + + // Go back to current time, so we can check if objects exist in cache. If we don't do this, the getters will return nil + // even if the objects are in the cache. + [NSDate stopMockingDate]; + + // The only objects left should be the last two that were accessed (key3 && key1), but since key3 is expired it will be + // removed first leaving key1 and key4 to remain. + NSMutableArray *keys = [NSMutableArray array]; + [self.cache.diskCache enumerateObjectsWithBlock:^(NSString * _Nonnull key, NSURL * _Nullable fileURL, BOOL * _Nonnull stop) { + [keys addObject:key]; + }]; + + XCTAssertTrue(keys.count == 2); + XCTAssertTrue([keys.firstObject isEqualToString:key1] || [keys.firstObject isEqualToString:key4]); + XCTAssertTrue([keys.lastObject isEqualToString:key1] || [keys.lastObject isEqualToString:key4]); +} + +- (void)testOneThousandAndOneWrites +{ + NSUInteger max = 1001; + __block NSInteger count = max; + + dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); + dispatch_group_t group = dispatch_group_create(); + + for (NSUInteger i = 0; i < max; i++) { + NSString *key = [[NSString alloc] initWithFormat:@"key %lu", (unsigned long)i]; + NSString *obj = [[NSString alloc] initWithFormat:@"obj %lu", (unsigned long)i]; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + dispatch_group_enter(group); + [self.cache setObjectAsync:obj forKey:key completion:^(id _Nonnull cache, NSString * _Nonnull key, id _Nullable object) { + dispatch_async(queue, ^{ + [self.cache objectForKeyAsync:key completion:^(id _Nonnull cache, NSString * _Nonnull key, id _Nullable object) { + NSString *obj = [[NSString alloc] initWithFormat:@"obj %lu", (unsigned long)i]; + XCTAssertTrue([object isEqualToString:obj] == YES, @"object returned was not object set"); + @synchronized (self) { + count -= 1; + } + dispatch_group_leave(group); + }]; + }); + }]; + } +#pragma clang diagnostic pop + + NSUInteger success = dispatch_group_wait(group, [self timeout]); + + XCTAssert(success == 0, @"Timed out waiting on operations"); + @synchronized (self) { + XCTAssertTrue(count == 0, @"one or more object blocks failed to execute, possible queue deadlock"); + } +} + +#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_VISION +- (void)testMemoryWarningBlock +{ + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + + __block BOOL blockDidExecute = NO; + + self.cache.memoryCache.didReceiveMemoryWarningBlock = ^(id cache) { + blockDidExecute = YES; + dispatch_semaphore_signal(semaphore); + }; + + [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidReceiveMemoryWarningNotification + object:[UIApplication sharedApplication]]; + + dispatch_semaphore_wait(semaphore, [self timeout]); + + XCTAssertTrue(blockDidExecute, @"memory warning block did not execute"); +} + +- (void)testBackgroundBlock +{ + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + + __block BOOL blockDidExecute = NO; + + self.cache.memoryCache.didEnterBackgroundBlock = ^(id cache) { + blockDidExecute = YES; + dispatch_semaphore_signal(semaphore); + }; + + NSNotification *notification = [NSNotification notificationWithName:UIApplicationDidEnterBackgroundNotification object:nil]; + + [self.cache.memoryCache performSelector:@selector(didReceiveEnterBackgroundNotification:) withObject:notification]; + + dispatch_semaphore_wait(semaphore, [self timeout]); + + XCTAssertTrue(blockDidExecute, @"app background block did not execute"); +} + +- (void)testMemoryWarningProperty +{ + [self.cache.memoryCache setObjectAsync:@"object" forKey:@"object" completion:nil]; + + self.cache.memoryCache.removeAllObjectsOnMemoryWarning = NO; + + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + + __block id object = nil; + + self.cache.memoryCache.didReceiveMemoryWarningBlock = ^(id cache) { + object = [cache objectForKey:@"object"]; + dispatch_semaphore_signal(semaphore); + }; + + [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidReceiveMemoryWarningNotification + object:[UIApplication sharedApplication]]; + + dispatch_semaphore_wait(semaphore, [self timeout]); + + XCTAssertNotNil(object, @"object was removed from the cache"); +} + +- (void)testMemoryCacheEnumerationWithWarning +{ + NSUInteger objectCount = 3; + + dispatch_apply(objectCount, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t index) { + NSString *key = [[NSString alloc] initWithFormat:@"key %zd", index]; + NSString *obj = [[NSString alloc] initWithFormat:@"obj %zd", index]; + self.cache.memoryCache[key] = obj; + }); + + self.cache.memoryCache.removeAllObjectsOnMemoryWarning = NO; + + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + + __block NSUInteger enumCount = 0; + + self.cache.memoryCache.didReceiveMemoryWarningBlock = ^(id cache) { + PINMemoryCache *memoryCache = (PINMemoryCache *)cache; + [memoryCache enumerateObjectsWithBlockAsync:^(id cache, NSString *key, id object, BOOL *stop) { + @synchronized (self) { + enumCount++; + } + } completionBlock:^(id cache) { + dispatch_semaphore_signal(semaphore); + }]; + }; + + [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidReceiveMemoryWarningNotification + object:[UIApplication sharedApplication]]; + + dispatch_semaphore_wait(semaphore, [self timeout]); + + @synchronized (self) { + XCTAssertTrue(objectCount == enumCount, @"some objects were not enumerated"); + } +} + +- (void)testDiskCacheEnumeration +{ + NSUInteger objectCount = 3; + + dispatch_group_t group = dispatch_group_create(); + + dispatch_apply(objectCount, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t index) { + NSString *key = [[NSString alloc] initWithFormat:@"key %zd", index]; + NSString *obj = [[NSString alloc] initWithFormat:@"obj %zd", index]; + dispatch_group_enter(group); + [self.cache.diskCache setObjectAsync:obj forKey:key completion:^(PINDiskCache *cache, NSString *key, id object) { + dispatch_group_leave(group); + }]; + }); + + dispatch_group_wait(group, DISPATCH_TIME_FOREVER); + + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + + __block NSUInteger enumCount = 0; + + [self.cache.diskCache enumerateObjectsWithBlockAsync:^(NSString *key, NSURL *fileURL, BOOL *stop) { + @synchronized (self) { + enumCount++; + } + } completionBlock:^(id cache) { + dispatch_semaphore_signal(semaphore); + }]; + + [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidReceiveMemoryWarningNotification + object:[UIApplication sharedApplication]]; + + dispatch_semaphore_wait(semaphore, [self timeout]); + + @synchronized (self) { + XCTAssertTrue(objectCount == enumCount, @"some objects were not enumerated"); + } +} +#endif + +- (void)testDeadlocks +{ + NSString *key = @"key"; + NSUInteger objectCount = 1000; + [self.cache setObject:[self image] forKey:key]; + dispatch_queue_t testQueue = dispatch_queue_create("test queue", DISPATCH_QUEUE_CONCURRENT); + + __block NSUInteger enumCount = 0; + dispatch_group_t group = dispatch_group_create(); + for (NSUInteger idx = 0; idx < objectCount; idx++) { + dispatch_group_async(group, testQueue, ^{ + [self.cache objectForKey:key]; + @synchronized (self) { + enumCount++; + } + }); + } + + dispatch_group_wait(group, [self timeout]); + @synchronized (self) { + XCTAssertTrue(objectCount == enumCount, @"was not able to fetch 1000 objects, possibly due to deadlock."); + } +} + +- (void)testAgeLimit +{ + [self.cache removeAllObjects]; + NSString *key1 = @"key1"; + NSString *key2 = @"key2"; + self.cache[key1] = [self image]; + self.cache[key2] = [self image]; + [self.cache.memoryCache setAgeLimit:60]; + [self.cache.diskCache setAgeLimit:60]; + + dispatch_group_t group = dispatch_group_create(); + + __block id memObj1 = nil; + __block id diskObj1 = nil; + __block id memObj2 = nil; + __block id diskObj2 = nil; + + dispatch_group_enter(group); + [self.cache.memoryCache objectForKeyAsync:key1 completion:^(id cache, NSString *key, id object) { + memObj1 = object; + dispatch_group_leave(group); + }]; + + dispatch_group_enter(group); + [self.cache.memoryCache objectForKeyAsync:key2 completion:^(id cache, NSString *key, id object) { + memObj2 = object; + dispatch_group_leave(group); + }]; + + dispatch_group_enter(group); + [self.cache.diskCache objectForKeyAsync:key1 completion:^(PINDiskCache * _Nonnull cache, NSString * _Nonnull key, id _Nullable object) { + diskObj1 = object; + dispatch_group_leave(group); + }]; + + dispatch_group_enter(group); + [self.cache.diskCache objectForKeyAsync:key2 completion:^(PINDiskCache * _Nonnull cache, NSString * _Nonnull key, id _Nullable object) { + diskObj2 = object; + dispatch_group_leave(group); + }]; + + dispatch_group_wait(group, DISPATCH_TIME_FOREVER); + + XCTAssert(memObj1 != nil, @"should still be in memory cache"); + XCTAssert(diskObj1 != nil, @"should still be in disk cache"); + XCTAssert(memObj2 != nil, @"should still be in memory cache"); + XCTAssert(diskObj2 != nil, @"should still be in disk cache"); + + //Set them again, but separate it out. + self.cache[key1] = [self image]; + sleep(2); + self.cache[key2] = [self image]; + + sleep(2); + + [self.cache.memoryCache setAgeLimit:3.5]; + [self.cache.diskCache setAgeLimit:3.5]; + + sleep(1); + + dispatch_group_enter(group); + [self.cache.memoryCache objectForKeyAsync:key1 completion:^(id cache, NSString *key, id object) { + memObj1 = object; + dispatch_group_leave(group); + }]; + + dispatch_group_enter(group); + [self.cache.memoryCache objectForKeyAsync:key2 completion:^(id cache, NSString *key, id object) { + memObj2 = object; + dispatch_group_leave(group); + }]; + + dispatch_group_enter(group); + [self.cache.diskCache objectForKeyAsync:key1 completion:^(PINDiskCache * _Nonnull cache, NSString * _Nonnull key, id _Nullable object) { + diskObj1 = object; + dispatch_group_leave(group); + }]; + + dispatch_group_enter(group); + [self.cache.diskCache objectForKeyAsync:key2 completion:^(PINDiskCache * _Nonnull cache, NSString * _Nonnull key, id _Nullable object) { + diskObj2 = object; + dispatch_group_leave(group); + }]; + + dispatch_group_wait(group, DISPATCH_TIME_FOREVER); + + XCTAssert(memObj1 == nil, @"should not be in memory cache"); + XCTAssert(diskObj1 == nil, @"should not be in disk cache"); + XCTAssert(memObj2 != nil, @"should be in memory cache"); + XCTAssert(diskObj2 != nil, @"should be in disk cache"); +} + +- (void)testByteLimit +{ + [self.cache removeAllObjects]; + NSString *key = @"key"; + self.cache[key] = [self image]; + + // Below is the size it's actually on disk. + [self.cache.diskCache setByteLimit:983040]; + + // ensure the object is returned + XCTAssert([self.cache.diskCache objectForKey:key] != nil, @"object should be stored"); + + [self.cache.diskCache setByteLimit:1]; + + // wait for disk cache to be trimmed + sleep(2); + + XCTAssert([self.cache.diskCache objectForKey:key] == nil, @"object should be cleared"); + + // check to see if it's actually deleted + [self.cache.diskCache synchronouslyLockFileAccessWhileExecutingBlock:^(id _Nonnull cache) { + NSError *error = nil; + NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:self.cache.diskCache.cacheURL + includingPropertiesForKeys:@[] + options:0 + error:&error]; + XCTAssertNil(error); + XCTAssert(contents.count == 0); + }]; +} + +- (void)testByteLimitWithLFU +{ + self.cache.diskCache.evictionStrategy = PINCacheEvictionStrategyLeastFrequentlyUsed; + [self.cache removeAllObjects]; + NSString *key = @"key"; + self.cache[key] = [self image]; + + // Below is the size it's actually on disk. + [self.cache.diskCache setByteLimit:983040]; + + // ensure the object is returned + XCTAssert([self.cache.diskCache objectForKey:key] != nil, @"object should be stored"); + + [self.cache.diskCache setByteLimit:1]; + + // wait for disk cache to be trimmed + sleep(2); + + XCTAssert([self.cache.diskCache objectForKey:key] == nil, @"object should be cleared"); + + // check to see if it's actually deleted + [self.cache.diskCache synchronouslyLockFileAccessWhileExecutingBlock:^(id _Nonnull cache) { + NSError *error = nil; + NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:self.cache.diskCache.cacheURL + includingPropertiesForKeys:@[] + options:0 + error:&error]; + XCTAssertNil(error); + XCTAssert(contents.count == 0); + }]; +} + +- (void)testByteLimitWithLFUEvictingOne +{ + self.cache.diskCache.evictionStrategy = PINCacheEvictionStrategyLeastFrequentlyUsed; + [self.cache removeAllObjects]; + NSString *key1 = @"key1"; + NSString *key2 = @"key2"; + self.cache[key1] = [self image]; + + NSInteger imageSizeOnDisk = self.cache.diskCache.byteCount; + self.cache[key2] = [self image]; + + // Below is the size it's actually on disk. + [self.cache.diskCache setByteLimit:2 * imageSizeOnDisk]; + + // ensure the object is returned (also access key1 twice) + XCTAssert([self.cache.diskCache objectForKey:key1] != nil, @"object should be stored"); + XCTAssert([self.cache.diskCache objectForKey:key1] != nil, @"object should be stored"); + XCTAssert([self.cache.diskCache objectForKey:key2] != nil, @"object should be stored"); + + // Force one to be evicted + [self.cache.diskCache setByteLimit:imageSizeOnDisk]; + + // wait for disk cache to be trimmed + sleep(2); + + XCTAssert([self.cache.diskCache objectForKey:key1] != nil, @"object should not be cleared"); + XCTAssert([self.cache.diskCache objectForKey:key2] == nil, @"object should be cleared"); + + // check to see if it's actually deleted + [self.cache.diskCache synchronouslyLockFileAccessWhileExecutingBlock:^(id _Nonnull cache) { + NSError *error = nil; + NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:self.cache.diskCache.cacheURL + includingPropertiesForKeys:@[] + options:0 + error:&error]; + XCTAssertNil(error); + XCTAssert(contents.count == 1); + }]; +} + +- (void)testDiskReadingAfterCacheInit +{ + NSString *cacheName = @"testDiskReadingAfterCacheInit"; + PINDiskCache *diskCache = [[PINDiskCache alloc] initWithName:cacheName]; + [diskCache removeAllObjects]; + + // Store a bunch of objects so it will take a long time to initialize. + for (NSUInteger idx = 0; idx < 5000; idx++) { + NSData *tmpData = [[@(idx) stringValue] dataUsingEncoding:NSUTF8StringEncoding]; + [diskCache setObject:tmpData forKey:[@(idx) stringValue]]; + } + + // Create a new instance, it'll have to look on disk to startup. + diskCache = nil; + diskCache = [[PINDiskCache alloc] initWithName:cacheName]; + + // Check to see if we can get an object before the disk state is known. + XCTAssertNotNil([diskCache objectForKey:[@(1) stringValue]]); + XCTAssertFalse(diskCache.diskStateKnown); + + sleep(5); + + XCTAssertTrue(diskCache.diskStateKnown); +} + +#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR +- (void)testWritingProtectionOption +{ + self.cache.diskCache.writingProtectionOption = NSDataWritingFileProtectionCompleteUnlessOpen; + + NSString *key = @"key"; + __block NSURL *diskFileURL = nil; + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + + [self.cache.diskCache setObjectAsync:[self image] forKey:key completion:^(PINDiskCache *cache, NSString *key, id object) { + [cache fileURLForKeyAsync:key completion:^(NSString * _Nonnull key, NSURL * _Nullable fileURL) { + diskFileURL = fileURL; + dispatch_semaphore_signal(semaphore); + }]; + }]; + + dispatch_semaphore_wait(semaphore, [self timeout]); + + NSError *error = nil; + NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:diskFileURL.path error:&error]; + + XCTAssertNil(error, @"error getting attributes of file"); + XCTAssertEqualObjects(attributes[NSFileProtectionKey], NSFileProtectionCompleteUnlessOpen, @"file protection key is incorrect"); +} +#endif + +//Disabled until race conditions can be addressed +- (void)_testTTLCacheObjectAccess { + [self.cache removeAllObjects]; + NSString *key = @"key"; + [self.cache.memoryCache setAgeLimit:2]; + [self.cache.diskCache setAgeLimit:2]; + + + // The cache is going to clear at 2 seconds, set an object at 1 second, so that it misses the first cache clearing + sleep(1); + [self.cache setObject:[self image] forKey:key]; + + // Wait until time 3 so that we know the object should be expired, the 1st cache clearing has happened, and the 2nd cache clearing hasn't happened yet + sleep(2); + + [self.cache.diskCache setTtlCacheSync:YES]; + [self.cache.memoryCache setTtlCache:YES]; + + dispatch_group_t group = dispatch_group_create(); + + __block id memObj = nil; + __block id diskObj = nil; + + dispatch_group_enter(group); + [self.cache.memoryCache objectForKeyAsync:key completion:^(id cache, NSString *key, id object) { + memObj = object; + dispatch_group_leave(group); + }]; + + dispatch_group_enter(group); + [self.cache.diskCache objectForKeyAsync:key completion:^(PINDiskCache * _Nonnull cache, NSString * _Nonnull key, id _Nullable object) { + diskObj = object; + dispatch_group_leave(group); + }]; + + dispatch_group_wait(group, DISPATCH_TIME_FOREVER); + + // If the cache is supposed to behave like a TTL cache, then the object shouldn't appear to be in the cache + XCTAssertNil(memObj, @"should not be in memory cache"); + XCTAssertNil(diskObj, @"should not be in disk cache"); + + [self.cache.diskCache setTtlCacheSync:NO]; + [self.cache.memoryCache setTtlCache:NO]; + + memObj = nil; + diskObj = nil; + + dispatch_group_enter(group); + [self.cache.memoryCache objectForKeyAsync:key completion:^(id cache, NSString *key, id object) { + memObj = object; + dispatch_group_leave(group); + }]; + + dispatch_group_enter(group); + [self.cache.diskCache objectForKeyAsync:key completion:^(PINDiskCache * _Nonnull cache, NSString * _Nonnull key, id _Nullable object) { + diskObj = object; + dispatch_group_leave(group); + }]; + + dispatch_group_wait(group, DISPATCH_TIME_FOREVER); + // If the cache is NOT supposed to behave like a TTL cache, then the object should appear to be in the cache because it hasn't been cleared yet + XCTAssertNotNil(memObj, @"should still be in memory cache"); + XCTAssertNotNil(diskObj, @"should still be in disk cache"); +} + +//Disabled until race conditions can be addressed +- (void)_testTTLCacheObjectEnumeration { + [self.cache removeAllObjects]; + NSString *key = @"key"; + [self.cache.memoryCache setAgeLimit:2]; + [self.cache.diskCache setAgeLimit:2]; + + + // The cache is going to clear at 2 seconds, set an object at 1 second, so that it misses the first cache clearing + sleep(1); + self.cache[key] = [self image]; + + // Wait until time 3 so that we know the object should be expired, the 1st cache clearing has happened, and the 2nd cache clearing hasn't happened yet + sleep(2); + + [self.cache.diskCache setTtlCacheSync:YES]; + [self.cache.memoryCache setTtlCache:YES]; + + // Wait for ttlCache to be set + dispatch_group_t group = dispatch_group_create(); + dispatch_group_enter(group); + [self.cache.diskCache objectForKeyAsync:key completion:^(PINDiskCache * _Nonnull cache, NSString * _Nonnull key, id _Nullable object) { + dispatch_group_leave(group); + }]; + dispatch_group_wait(group, DISPATCH_TIME_FOREVER); + + // With the TTL cache enabled, we expect enumerating over the caches to yield 0 objects + NSUInteger expectedObjCount = 0; + __block NSUInteger objCount = 0; + [self.cache.diskCache enumerateObjectsWithBlock:^(NSString * _Nonnull key, NSURL * _Nullable fileURL, BOOL *stop) { + objCount++; + }]; + + XCTAssertEqual(objCount, expectedObjCount, @"Expected %lu objects in the cache", (unsigned long)expectedObjCount); + + objCount = 0; + [self.cache.memoryCache enumerateObjectsWithBlock:^(id cache, NSString *key, id _Nullable object, BOOL *stop) { + objCount++; + }]; + + XCTAssertEqual(objCount, expectedObjCount, @"Expected %lu objects in the cache", (unsigned long)expectedObjCount); + + [self.cache.diskCache setTtlCacheSync:NO]; + [self.cache.memoryCache setTtlCache:NO]; + + // Wait for ttlCache to be set + dispatch_group_enter(group); + [self.cache.diskCache objectForKeyAsync:key completion:^(PINDiskCache * _Nonnull cache, NSString * _Nonnull key, id _Nullable object) { + dispatch_group_leave(group); + }]; + dispatch_group_wait(group, DISPATCH_TIME_FOREVER); + + // With the TTL cache disabled, we expect enumerating over the caches to yield 1 object each, since the 2nd cache clearing hasn't happened yet + expectedObjCount = 1; + objCount = 0; + [self.cache.diskCache enumerateObjectsWithBlock:^(NSString * _Nonnull key, NSURL * _Nullable fileURL, BOOL *stop) { + objCount++; + }]; + + XCTAssertEqual(objCount, expectedObjCount, @"Expected %lu objects in the cache", (unsigned long)expectedObjCount); + + objCount = 0; + [self.cache.memoryCache enumerateObjectsWithBlock:^(id _Nonnull cache, NSString * _Nonnull key, id _Nullable object, BOOL *stop) { + objCount++; + }]; + + XCTAssertEqual(objCount, expectedObjCount, @"Expected %lu objects in the cache", (unsigned long)expectedObjCount); +} + +//Disabled until race conditions can be addressed +- (void)_testTTLCacheFileURLForKey { + NSString *key = @"key"; + + dispatch_group_t group = dispatch_group_create(); + dispatch_group_enter(group); + __block NSURL *objectURL = nil; + [self.cache.diskCache setObjectAsync:[self image] forKey:key completion:^(PINDiskCache * _Nonnull cache, NSString * _Nonnull key, id _Nullable object) { + [cache fileURLForKeyAsync:key completion:^(NSString * _Nonnull key, NSURL * _Nullable fileURL) { + objectURL = fileURL; + dispatch_group_leave(group); + }]; + }]; + dispatch_group_wait(group, DISPATCH_TIME_FOREVER); + XCTAssertNotNil(objectURL, @"objectURL should have a non-nil URL"); + + // Wait a moment to ensure that the file modification time is set (done asynchronously) + sleep(1); + + NSError *error = nil; + NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[objectURL path] error:&error]; + NSDate *initialModificationDate = attributes[NSFileModificationDate]; + XCTAssertNotNil(initialModificationDate, @"The saved file should have a non-nil modification date"); + + // Wait a moment to ensure that the file modification time can be changed to something different + sleep(1); + + [self.cache.diskCache setTtlCacheSync:YES]; + + // Wait for ttlCache to be set + sleep(1); + + [self.cache.diskCache objectForKey:key]; + [self.cache.diskCache fileURLForKey:key]; + + // Wait a moment to ensure that the file modification time is set (done asynchronously) + sleep(1); + + attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[objectURL path] error:nil]; + NSDate *ttlCacheEnabledModificationDate = attributes[NSFileModificationDate]; + XCTAssertNotNil(ttlCacheEnabledModificationDate, @"The saved file should have a non-nil modification date"); + + XCTAssertEqualObjects(initialModificationDate, ttlCacheEnabledModificationDate, @"The modification date shouldn't change when accessing the file URL, when ttlCache is enabled"); + + [self.cache.diskCache setTtlCacheSync:NO]; + + // Wait for ttlCache to be set + sleep(1); + + [self.cache.diskCache objectForKey:key]; + [self.cache.diskCache fileURLForKey:key]; + + // Wait a moment to ensure that the file modification time is set (done asynchronously) + sleep(1); + + attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[objectURL path] error:nil]; + NSDate *ttlCacheDisabledModificationDate = attributes[NSFileModificationDate]; + XCTAssertNotNil(ttlCacheDisabledModificationDate, @"The saved file should have a non-nil modification date"); + + XCTAssertNotEqualObjects(initialModificationDate, ttlCacheDisabledModificationDate, @"The modification date should change when accessing the file URL, when ttlCache is not enabled"); + +} + +- (void)testObjectTTLObjectAccess +{ + [self.cache.memoryCache setTtlCache:YES]; + [self.cache.diskCache setTtlCacheSync:YES]; + [self.cache removeAllObjects]; + NSString *key1 = @"key1"; + NSString *key2 = @"key2"; + + [self.cache setObject:[self image] forKey:key1 withAgeLimit:60.0]; + [self.cache setObject:[self image] forKey:key2 withAgeLimit:120.0]; + + // Neither object should be expired at this point and should exist in both caches + + XCTestExpectation *memObjectForKey1Expectation = [self expectationWithDescription:@"memoryCache objectForKeyAsync - #1"]; + [self.cache.memoryCache objectForKeyAsync:key1 completion:^(id cache, NSString *key, id object) { + XCTAssertNotNil(object, @"should still be in memory cache"); + [memObjectForKey1Expectation fulfill]; + }]; + + XCTestExpectation *memObjectForKey2Expectation = [self expectationWithDescription:@"memoryCache objectForKeyAsync - #2"]; + [self.cache.memoryCache objectForKeyAsync:key2 completion:^(id cache, NSString *key, id object) { + XCTAssertNotNil(object, @"should still be in memory cache"); + [memObjectForKey2Expectation fulfill]; + }]; + + XCTestExpectation *diskObjectForKey1Expectation = [self expectationWithDescription:@"diskCache objectForKeyAsync - #1"]; + [self.cache.diskCache objectForKeyAsync:key1 completion:^(PINDiskCache *cache, NSString *key, id object) { + XCTAssertNotNil(object, @"should still be in disk cache"); + [diskObjectForKey1Expectation fulfill]; + }]; + + XCTestExpectation *diskObjectForKey2Expectation = [self expectationWithDescription:@"diskCache objectForKeyAsync - #2"]; + [self.cache.diskCache objectForKeyAsync:key2 completion:^(PINDiskCache *cache, NSString *key, id object) { + XCTAssertNotNil(object, @"should still be in disk cache"); + [diskObjectForKey2Expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:0.1 handler:nil]; + + // Fast forward 90 seconds. + [NSDate startMockingDateWithDate:[NSDate dateWithTimeIntervalSinceNow:90]]; + + // The first object has been expired for 30 seconds and should not exist in the cache anymore. + + memObjectForKey1Expectation = [self expectationWithDescription:@"memoryCache objectForKeyAsync - #1"]; + [self.cache.memoryCache objectForKeyAsync:key1 completion:^(id cache, NSString *key, id object) { + XCTAssertNil(object, @"should not be in memory cache"); + [memObjectForKey1Expectation fulfill]; + }]; + + memObjectForKey2Expectation = [self expectationWithDescription:@"memoryCache objectForKeyAsync - #2"]; + [self.cache.memoryCache objectForKeyAsync:key2 completion:^(id cache, NSString *key, id object) { + XCTAssertNotNil(object, @"should not be in memory cache"); + [memObjectForKey2Expectation fulfill]; + }]; + + diskObjectForKey1Expectation = [self expectationWithDescription:@"diskCache objectForKeyAsync - #1"]; + [self.cache.diskCache objectForKeyAsync:key1 completion:^(PINDiskCache *cache, NSString *key, id object) { + XCTAssertNil(object, @"should not be in disk cache"); + [diskObjectForKey1Expectation fulfill]; + }]; + + diskObjectForKey2Expectation = [self expectationWithDescription:@"diskCache objectForKeyAsync - #2"]; + [self.cache.diskCache objectForKeyAsync:key2 completion:^(PINDiskCache *cache, NSString *key, id object) { + XCTAssertNotNil(object, @"should not be in disk cache"); + [diskObjectForKey2Expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:0.1 handler:nil]; + + [NSDate stopMockingDate]; +} + +- (void)testObjectTTLObjectEnumeration +{ + [self.cache.memoryCache setTtlCache:YES]; + [self.cache.diskCache setTtlCacheSync:YES]; + [self.cache removeAllObjects]; + NSString *key1 = @"key1"; + NSString *key2 = @"key2"; + + [self.cache setObject:[self image] forKey:key1 withAgeLimit:60.0]; + [self.cache setObject:[self image] forKey:key2 withAgeLimit:120.0]; + + // Neither object should be expired at this point and should exist in both caches + + __block NSUInteger objCount = 0; + [self.cache.memoryCache enumerateObjectsWithBlock:^(id cache, NSString *key, id _Nullable object, BOOL *stop) { + objCount++; + }]; + XCTAssertEqual(objCount, 2, @"Expected 2 objects, got %tu.", objCount); + + objCount = 0; + [self.cache.diskCache enumerateObjectsWithBlock:^(NSString * _Nonnull key, NSURL * _Nullable fileURL, BOOL *stop) { + objCount++; + }]; + XCTAssertEqual(objCount, 2, @"Expected 2 objects, got %tu.", objCount); + + // Fast forward 90 seconds. + [NSDate startMockingDateWithDate:[NSDate dateWithTimeIntervalSinceNow:90]]; + + // The first object has been expired for 30 seconds and should not exist in the cache anymore. + + objCount = 0; + [self.cache.memoryCache enumerateObjectsWithBlock:^(id cache, NSString *key, id _Nullable object, BOOL *stop) { + objCount++; + }]; + XCTAssertEqual(objCount, 1, @"Expected 1 object, got %tu.", objCount); + + objCount = 0; + [self.cache.diskCache enumerateObjectsWithBlock:^(NSString * _Nonnull key, NSURL * _Nullable fileURL, BOOL *stop) { + objCount++; + }]; + XCTAssertEqual(objCount, 1, @"Expected 1 object, got %tu.", objCount); + + [NSDate stopMockingDate]; +} + +- (void)testRemoveExpiredObjects +{ + [self.cache.memoryCache setTtlCache:YES]; + [self.cache.diskCache setTtlCacheSync:YES]; + [self.cache removeAllObjects]; + NSString *key1 = @"key1"; + NSString *key2 = @"key2"; + + [self.cache setObject:[self image] forKey:key1 withAgeLimit:60.0]; + [self.cache setObject:[self image] forKey:key2 withAgeLimit:120.0]; + + // Fast forward 90 seconds. + [NSDate startMockingDateWithDate:[NSDate dateWithTimeIntervalSinceNow:90]]; + + // The first object has been expired for 30 seconds and should be cleared out. + [self.cache removeExpiredObjects]; + + // Go back to current time, so we can check if objects exist in cache. If we don't do this, the getters will return nil + // even if the objects are in the cache. + [NSDate stopMockingDate]; + + XCTestExpectation *memObjectForKey1Expectation = [self expectationWithDescription:@"memoryCache objectForKeyAsync - #1"]; + [self.cache.memoryCache objectForKeyAsync:key1 completion:^(id cache, NSString *key, id object) { + XCTAssertNil(object, @"should not be in memory cache"); + [memObjectForKey1Expectation fulfill]; + }]; + + XCTestExpectation *memObjectForKey2Expectation = [self expectationWithDescription:@"memoryCache objectForKeyAsync - #2"]; + [self.cache.memoryCache objectForKeyAsync:key2 completion:^(id cache, NSString *key, id object) { + XCTAssertNotNil(object, @"should not be in memory cache"); + [memObjectForKey2Expectation fulfill]; + }]; + + XCTestExpectation *diskObjectForKey1Expectation = [self expectationWithDescription:@"diskCache objectForKeyAsync - #1"]; + [self.cache.diskCache objectForKeyAsync:key1 completion:^(PINDiskCache *cache, NSString *key, id object) { + XCTAssertNil(object, @"should not be in disk cache"); + [diskObjectForKey1Expectation fulfill]; + }]; + + XCTestExpectation *diskObjectForKey2Expectation = [self expectationWithDescription:@"diskCache objectForKeyAsync - #2"]; + [self.cache.diskCache objectForKeyAsync:key2 completion:^(PINDiskCache *cache, NSString *key, id object) { + XCTAssertNotNil(object, @"should not be in disk cache"); + [diskObjectForKey2Expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:0.1 handler:nil]; +} + +- (void)testDiskRehydrationOfObjectAgeLimit +{ + NSString * const cacheName = @"testDiskRehydrationOfObjectAgeLimit"; + NSString * const key = @"key"; + const NSTimeInterval ageLimit = 60.0; + PINDiskCache *testCache = [[PINDiskCache alloc] initWithName:cacheName]; + [testCache setTtlCacheSync:YES]; + NSURL *testCacheURL = testCache.cacheURL; + NSError *error = nil; + + //Make sure the cache URL does not exist. + if ([[NSFileManager defaultManager] fileExistsAtPath:[testCacheURL path]]) { + [[NSFileManager defaultManager] removeItemAtURL:testCacheURL error:&error]; + XCTAssertNil(error); + } + + testCache = [[PINDiskCache alloc] initWithName:cacheName]; + [testCache setTtlCacheSync:YES]; + [testCache setObject:[self image] forKey:key withAgeLimit:ageLimit]; + + // The age limit is set asynchronously, *even* when we set the object synchronously. + sleep(1); + + // Re-initialize the cache, this should read the age limit for the object from the extended file system attributes. + testCache = [[PINDiskCache alloc] initWithName:cacheName]; + [testCache setTtlCacheSync:YES]; + + [testCache waitForKnownState]; + id object = testCache.metadata[key]; + id ageLimitFromDisk = [object valueForKey:@"ageLimit"]; + XCTAssertEqual([ageLimitFromDisk doubleValue], ageLimit); +} + +- (void)testAsyncDiskInitialization +{ + NSString * const cacheName = @"testAsyncDiskInitialization"; + PINDiskCache *testCache = [[PINDiskCache alloc] initWithName:cacheName]; + NSURL *testCacheURL = testCache.cacheURL; + NSError *error = nil; + + //Make sure the cache URL does not exist. + if ([[NSFileManager defaultManager] fileExistsAtPath:[testCacheURL path]]) { + [[NSFileManager defaultManager] removeItemAtURL:testCacheURL error:&error]; + XCTAssertNil(error); + } + + testCache = [[PINDiskCache alloc] initWithName:cacheName]; + //This should not return until *after* disk cache directory has been created + [testCache setObject:@"some bogus object" forKey:@"some bogus key"]; + XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:[testCacheURL path]]); +} + +- (void)testDiskCacheSet +{ + PINDiskCache *testCache = [[PINDiskCache alloc] initWithName:@"testDiskCacheSet"]; + const NSUInteger objectCount = 100; + [self measureBlock:^{ + for (NSUInteger idx = 0; idx < objectCount; idx++) { + [testCache setObject:[@(idx) stringValue] forKey:[@(idx) stringValue]]; + } + }]; +} + +- (void)testDiskCacheHit +{ + PINDiskCache *testCache = [[PINDiskCache alloc] initWithName:@"textDiskCacheHit"]; + const NSUInteger objectCount = 100; + for (NSUInteger idx = 0; idx < objectCount; idx++) { + [testCache setObject:[@(idx) stringValue] forKey:[@(idx) stringValue]]; + } + [self measureBlock:^{ + for (NSUInteger idx = 0; idx < objectCount; idx++) { + [testCache objectForKey:[@(idx) stringValue]]; + } + }]; +} + +- (void)testDiskCacheMiss +{ + PINDiskCache *testCache = [[PINDiskCache alloc] initWithName:@"testDiskCacheMiss"]; + const NSUInteger objectCount = 100; + [self measureBlock:^{ + for (NSUInteger idx = 0; idx < objectCount; idx++) { + [testCache objectForKey:[@(idx) stringValue]]; + } + }]; +} + +- (void)testDiskCacheEmptyTrash +{ + const NSUInteger fileCount = 100; + NSFileManager *fileManager = [NSFileManager defaultManager]; + [[PINDiskCache sharedLock] lock]; + NSString *trashPath = [[PINDiskCache sharedTrashURL] path]; + [[PINDiskCache sharedLock] unlock]; + + dispatch_group_t group = dispatch_group_create(); + + NSError *error = nil; + unsigned long long originalTempDirSize = [[fileManager attributesOfItemAtPath:trashPath error:&error] fileSize]; + XCTAssertNil(error); + + for (int i = 0; i < fileCount; i++) { + NSString *key = [NSString stringWithFormat:@"key%d", i]; + self.cache.diskCache[key] = key; + } + + dispatch_group_enter(group); + [self.cache.diskCache removeAllObjectsAsync:^(id _Nonnull cache) { + // Temporary directory should be bigger now since the trash directory is still inside it + NSError *error = nil; + unsigned long long tempDirSize = [[fileManager attributesOfItemAtPath:trashPath error:&error] fileSize]; + XCTAssertNil(error); + XCTAssertLessThan(originalTempDirSize, tempDirSize); + + // Temporary directory should be gone at the end of the trash queue. + dispatch_group_enter(group); + dispatch_async([PINDiskCache sharedTrashQueue], ^{ + XCTAssertFalse([fileManager fileExistsAtPath:trashPath isDirectory:NULL]); + dispatch_group_leave(group); + }); + + dispatch_group_leave(group); + }]; + + NSUInteger success = dispatch_group_wait(group, [self timeout]); + XCTAssert(success == 0, @"Timed out"); +} + +- (void)testCustomEncoderDecoder { + NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]; + PINDiskCacheKeyEncoderBlock encoder = ^NSString *(NSString *decodedKey) { + return decodedKey; + }; + PINDiskCacheKeyDecoderBlock decoder = ^NSString *(NSString *encodedKey) { + return encodedKey; + }; + PINDiskCache *testCache = [[PINDiskCache alloc] initWithName:@"testCustomEncoder" + prefix:PINDiskCachePrefix + rootPath:rootPath + serializer:NULL + deserializer:NULL + keyEncoder:encoder + keyDecoder:decoder + operationQueue:[PINOperationQueue sharedOperationQueue]]; + + [testCache setObject:@(1) forKey:@"test_key"]; + + XCTAssertNotNil([testCache objectForKey:@"test_key"], @"Object should not be nil"); + + NSString *encodedKey = [[testCache fileURLForKey:@"test_key"] lastPathComponent]; + XCTAssertEqualObjects(@"test_key", encodedKey, @"Encoded key should be equal to decoded one"); + +} + +- (void)testTTLCacheIsSet { + PINCache *cache = [[PINCache alloc] initWithName:@"test" rootPath:PINDiskCachePrefix serializer:nil deserializer:nil keyEncoder:nil keyDecoder:nil ttlCache:YES evictionStrategy:PINCacheEvictionStrategyLeastRecentlyUsed]; + XCTAssert(cache.diskCache.isTTLCache); + XCTAssert(cache.memoryCache.isTTLCache); +} + +- (void)testDiskRemoveAllObjectsAndRemoveObjectForKey +{ + // Regression test for https://github.com/pinterest/PINCache/issues/295, where + // -[removeAllObjects] and -[removeObjectForKey:] would race and the latter could fail. + NSString *cacheName = @"testDiskRemoveAllObjectsAndRemoveObjectForKey"; + PINDiskCache *diskCache = [[PINDiskCache alloc] initWithName:cacheName]; + + for (NSUInteger idx = 0; idx < 5000; idx++) { + [diskCache removeAllObjects]; + NSString *key = [@(idx) stringValue]; + NSData *tmpData = [key dataUsingEncoding:NSUTF8StringEncoding]; + [diskCache setObject:tmpData forKey:key]; + XCTAssertNotNil([diskCache objectForKey:key]); + [diskCache removeObjectForKey:key]; + XCTAssertNil([diskCache objectForKey:key]); + } +} + + + +@end diff --git a/Carthage/Checkouts/PINCache/Tests/PINDiskCache+PINCacheTests.h b/Carthage/Checkouts/PINCache/Tests/PINDiskCache+PINCacheTests.h new file mode 100644 index 00000000..ce487335 --- /dev/null +++ b/Carthage/Checkouts/PINCache/Tests/PINDiskCache+PINCacheTests.h @@ -0,0 +1,16 @@ +#import + +@interface PINDiskCache (PINCacheTests) + +/** + Sets `ttlCache` property synchronously. This is normally set asyncronously, but for testing purposes it is useful block until the + actual value has been set. + */ +- (void)setTtlCacheSync:(BOOL)ttlCache; + +/** + Waits until all metadata has been read off the disk + */ +- (void)waitForKnownState; + +@end diff --git a/Carthage/Checkouts/PINCache/Tests/PINDiskCache+PINCacheTests.m b/Carthage/Checkouts/PINCache/Tests/PINDiskCache+PINCacheTests.m new file mode 100644 index 00000000..fd8a164f --- /dev/null +++ b/Carthage/Checkouts/PINCache/Tests/PINDiskCache+PINCacheTests.m @@ -0,0 +1,28 @@ +#import "PINDiskCache+PINCacheTests.h" + +@interface PINDiskCache () { + BOOL _ttlCache; +} + +- (void)lock; +- (void)lockAndWaitForKnownState; +- (void)unlock; + +@end + +@implementation PINDiskCache (PINCacheTests) + +- (void)setTtlCacheSync:(BOOL)ttlCache +{ + [self lock]; + [self setValue:@(ttlCache) forKey:@"_ttlCache"]; + [self unlock]; +} + +- (void)waitForKnownState +{ + [self lockAndWaitForKnownState]; + [self unlock]; +} + +@end diff --git a/Carthage/Checkouts/PINCache/build_docs.sh b/Carthage/Checkouts/PINCache/build_docs.sh new file mode 100755 index 00000000..b50920de --- /dev/null +++ b/Carthage/Checkouts/PINCache/build_docs.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh + +appledoc \ + --company-id com.pinterest \ + --project-name PINCache \ + --project-company Pinterest \ + --project-version 2.0 \ + --docset-min-xcode-version 4.3 \ + --docset-bundle-id %COMPANYID.%PROJECTID \ + --docset-bundle-name "%PROJECT %VERSION" \ + --docset-bundle-filename %COMPANYID.%PROJECTID-%VERSIONID.docset \ + --ignore "tests" \ + --ignore "docs" \ + --ignore "*.m" \ + --no-repeat-first-par \ + --explicit-crossref \ + --clean-output \ + --keep-intermediate-files \ + --output ./docs \ + . + +mv docs/docset docs/com.pinterest.PINCache-2.0.docset +rm docs/docset-installed.txt diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Info.plist b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Info.plist new file mode 100644 index 00000000..6d0f7cf1 --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleIdentifier + com.pinterest.PINCache + CFBundleName + PINCache 2.0 + CFBundleShortVersionString + 2.0 + CFBundleVersion + 2.0 + + + + + DocSetFeedName + PINCache Documentation + + DocSetMinimumXcodeVersion + 4.3 + + DashDocSetFamily + appledoc + DocSetPublisherIdentifier + com.pinterest.documentation + DocSetPublisherName + Pinterest + NSHumanReadableCopyright + Copyright © 2016 Pinterest. All rights reserved. + + diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Blocks/PINCacheBlock.html b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Blocks/PINCacheBlock.html new file mode 100644 index 00000000..e4f1300a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Blocks/PINCacheBlock.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Blocks/PINCacheObjectBlock.html b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Blocks/PINCacheObjectBlock.html new file mode 100644 index 00000000..e4f1300a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Blocks/PINCacheObjectBlock.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Blocks/PINDiskCacheBlock.html b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Blocks/PINDiskCacheBlock.html new file mode 100644 index 00000000..e4f1300a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Blocks/PINDiskCacheBlock.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Blocks/PINDiskCacheFileURLBlock.html b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Blocks/PINDiskCacheFileURLBlock.html new file mode 100644 index 00000000..e4f1300a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Blocks/PINDiskCacheFileURLBlock.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Blocks/PINDiskCacheObjectBlock.html b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Blocks/PINDiskCacheObjectBlock.html new file mode 100644 index 00000000..e4f1300a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Blocks/PINDiskCacheObjectBlock.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Blocks/PINMemoryCacheBlock.html b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Blocks/PINMemoryCacheBlock.html new file mode 100644 index 00000000..e4f1300a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Blocks/PINMemoryCacheBlock.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Blocks/PINMemoryCacheObjectBlock.html b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Blocks/PINMemoryCacheObjectBlock.html new file mode 100644 index 00000000..e4f1300a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Blocks/PINMemoryCacheObjectBlock.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Classes/PINCache.html b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Classes/PINCache.html new file mode 100644 index 00000000..e4f1300a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Classes/PINCache.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Classes/PINDiskCache.html b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Classes/PINDiskCache.html new file mode 100644 index 00000000..e4f1300a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Classes/PINDiskCache.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Classes/PINMemoryCache.html b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Classes/PINMemoryCache.html new file mode 100644 index 00000000..e4f1300a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Classes/PINMemoryCache.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Protocols/PINCacheObjectSubscripting.html b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Protocols/PINCacheObjectSubscripting.html new file mode 100644 index 00000000..e4f1300a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/Protocols/PINCacheObjectSubscripting.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/_index.scss b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/_index.scss new file mode 100644 index 00000000..7e98029d --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/_index.scss @@ -0,0 +1,13 @@ +.index-container { + display: flex; + flex-direction: row; + flex-wrap: wrap; + + @media (max-width: $mobile-max-width) { + flex-direction: column; + } + + .index-column { + flex: 1 1 33%; + } +} diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/_layout.scss b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/_layout.scss new file mode 100644 index 00000000..40bd6d4a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/_layout.scss @@ -0,0 +1,303 @@ +* { + box-sizing: border-box; +} + +.clear { + clear: both; +} + +.clearfix { + &:before, &:after { + clear: both; + display: table; + content: ""; + } +} + +.xcode .hide-in-xcode { + display: none; +} + +body { + font: 62.5% $body-font; + background: $body-background; +} + +h1, h2, h3 { + font-weight: 300; + color: #808080; +} + +h1 { + font-size: 2em; + color: #000; +} + +h4 { + font-size: 13px; + line-height: 1.5; + margin: 21px 0 0 0; +} + +a { + color: $tint-color; + text-decoration: none; +} + +pre, code { + font-family: $code-font; + word-wrap: break-word; +} + +pre > code, .method-declaration code { + display: inline-block; + font-size: .85em; + padding: 4px 0 4px 10px; + border-left: 5px solid rgba(0, 155, 51, .2); + + &:before { + content: "Objective-C"; + display: block; + + font: 9px/1 $body-font; + color: #009b33; + text-transform: uppercase; + letter-spacing: 2px; + padding-bottom: 6px; + } +} + +pre > code { + font-size: inherit; +} + +table, th, td { + border: 1px solid #e9e9e9; +} + +table { + width: 100%; +} + +th, td { + padding: 7px; + + > :first-child { + margin-top: 0; + } + + > :last-child { + margin-bottom: 0; + } +} + +.container { + @extend .clearfix; + + max-width: 980px; + padding: 0 10px; + margin: 0 auto; + + @media (max-width: $mobile-max-width) { + padding: 0; + } +} + +header { + position: fixed; + top: 0; + left: 0; + width: 100%; + z-index: 2; + + background: #414141; + color: #fff; + font-size: 1.1em; + line-height: 25px; + letter-spacing: .05em; + + #library-title { + float: left; + } + + #developer-home { + float: right; + } + + h1 { + font-size: inherit; + font-weight: inherit; + margin: 0; + } + + p { + margin: 0; + } + + h1, a { + color: inherit; + } + + @media (max-width: $mobile-max-width) { + position: absolute; + + .container { + padding: 0 10px; + } + } +} + +aside { + position: fixed; + top: 25px; + left: 0; + width: 100%; + height: 25px; + z-index: 2; + + font-size: 1.1em; + + @media (max-width: $mobile-max-width) { + position: absolute; + } + + #header-buttons { + background: rgba(255, 255, 255, .8); + margin: 0 1px; + padding: 0; + list-style: none; + text-align: right; + line-height: 32px; + + li { + display: inline-block; + cursor: pointer; + padding: 0 10px; + } + + label, select { + cursor: inherit; + } + + #on-this-page { + position: relative; + + .chevron { + display: inline-block; + width: 14px; + height: 4px; + position: relative; + + .chevy { + background: #878787; + height: 2px; + position: absolute; + width: 10px; + + &.chevron-left { + left: 0; + transform: rotateZ(45deg) scale(0.6); + } + + &.chevron-right { + right: 0; + transform: rotateZ(-45deg) scale(0.6); + } + } + } + + #jump-to { + opacity: 0; + font-size: 16px; + + position: absolute; + top: 5px; + left: 0; + width: 100%; + height: 100%; + } + } + } +} + +article { + margin-top: 25px; + + #content { + @extend .clearfix; + + background: $content-background; + border: 1px solid $content-border; + padding: 15px 25px 30px 25px; + + font-size: 1.4em; + line-height: 1.45; + + position: relative; + + @media (max-width: $mobile-max-width) { + padding: 15px 10px 20px 10px; + } + + .navigation-top { + position: absolute; + top: 15px; + right: 25px; + } + + .title { + margin: 21px 0 0 0; + padding: 15px 0; + } + + p { + color: #414141; + margin: 0 0 15px 0; + } + + th, td { + p:last-child { + margin-bottom: 0; + } + } + + main { + ul { + list-style: none; + margin-left: 24px; + margin-bottom: 12px; + padding: 0; + + li { + position: relative; + padding-left: 1.3em; + + &:before { + content: "\02022"; + + color: #414141; + font-size: 1.08em; + line-height: 1; + + position: absolute; + left: 0; + padding-top: 2px; + } + } + } + } + + footer { + @extend .clearfix; + + .footer-copyright { + margin: 70px 25px 10px 0; + } + + p { + font-size: .71em; + color: #a0a0a0; + } + } + } +} diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/_normalize.scss b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/_normalize.scss new file mode 100644 index 00000000..9b8848a5 --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/_normalize.scss @@ -0,0 +1,581 @@ +/* ========================================================================== + Normalize.scss settings + ========================================================================== */ +/** + * Includes legacy browser support IE6/7 + * + * Set to false if you want to drop support for IE6 and IE7 + */ + +$legacy_browser_support: false !default; + +/* Base + ========================================================================== */ + +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + * 3. Corrects text resizing oddly in IE 6/7 when body `font-size` is set using + * `em` units. + */ + +html { + font-family: sans-serif; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ + @if $legacy_browser_support { + *font-size: 100%; /* 3 */ + } +} + +/** + * Remove default margin. + */ + +body { + margin: 0; +} + +/* HTML5 display definitions + ========================================================================== */ + +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} + +/** + * 1. Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ + +audio, +canvas, +progress, +video { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ + @if $legacy_browser_support { + *display: inline; + *zoom: 1; + } +} + +/** + * Prevents modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ + +[hidden], +template { + display: none; +} + +/* Links + ========================================================================== */ + +/** + * Remove the gray background color from active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ + +a { + &:active, &:hover { + outline: 0; + }; +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +@if $legacy_browser_support { + blockquote { + margin: 1em 40px; + } +} + +/** + * Address styling not present in Safari and Chrome. + */ + +dfn { + font-style: italic; +} + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +@if $legacy_browser_support { + h2 { + font-size: 1.5em; + margin: 0.83em 0; + } + + h3 { + font-size: 1.17em; + margin: 1em 0; + } + + h4 { + font-size: 1em; + margin: 1.33em 0; + } + + h5 { + font-size: 0.83em; + margin: 1.67em 0; + } + + h6 { + font-size: 0.67em; + margin: 2.33em 0; + } +} + +/** + * Addresses styling not present in IE 8/9. + */ + +mark { + background: #ff0; + color: #000; +} + +@if $legacy_browser_support { + + /** + * Addresses margins set differently in IE 6/7. + */ + + p, + pre { + *margin: 1em 0; + } + + /* + * Addresses CSS quotes not supported in IE 6/7. + */ + + q { + *quotes: none; + } + + /* + * Addresses `quotes` property not supported in Safari 4. + */ + + q:before, + q:after { + content: ''; + content: none; + } +} + +/** + * Address inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +@if $legacy_browser_support { + + /* ========================================================================== + Lists + ========================================================================== */ + + /* + * Addresses margins set differently in IE 6/7. + */ + + dl, + menu, + ol, + ul { + *margin: 1em 0; + } + + dd { + *margin: 0 0 0 40px; + } + + /* + * Addresses paddings set differently in IE 6/7. + */ + + menu, + ol, + ul { + *padding: 0 0 0 40px; + } + + /* + * Corrects list images handled incorrectly in IE 7. + */ + + nav ul, + nav ol { + *list-style: none; + *list-style-image: none; + } + +} + +/* Embedded content + ========================================================================== */ + +/** + * 1. Remove border when inside `a` element in IE 8/9/10. + * 2. Improves image quality when scaled in IE 7. + */ + +img { + border: 0; + @if $legacy_browser_support { + *-ms-interpolation-mode: bicubic; /* 2 */ + } +} + +/** + * Correct overflow not hidden in IE 9/10/11. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Grouping content + ========================================================================== */ + +/** + * Address margin not present in IE 8/9 and Safari. + */ + +figure { + margin: 1em 40px; +} + +/** + * Address differences between Firefox and other browsers. + */ + +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +/** + * Contain overflow in all browsers. + */ + +pre { + overflow: auto; +} + +/** + * Address odd `em`-unit font size rendering in all browsers. + * Correct font family set oddly in IE 6, Safari 4/5, and Chrome. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + @if $legacy_browser_support { + _font-family: 'courier new', monospace; + } + font-size: 1em; +} + +/* Forms + ========================================================================== */ + +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ + +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + * 4. Improves appearance and consistency in all browsers. + */ + +button, +input, +optgroup, +select, +textarea { + color: inherit; /* 1 */ + font: inherit; /* 2 */ + margin: 0; /* 3 */ + @if $legacy_browser_support { + vertical-align: baseline; /* 3 */ + *vertical-align: middle; /* 3 */ + } +} + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ + +button { + overflow: visible; +} + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ + +button, +select { + text-transform: none; +} + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + * 4. Removes inner spacing in IE 7 without affecting normal text inputs. + * Known issue: inner spacing remains in IE 6. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ + @if $legacy_browser_support { + *overflow: visible; /* 4 */ + } +} + +/** + * Re-set default cursor for disabled elements. + */ + +button[disabled], +html input[disabled] { + cursor: default; +} + +/** + * Remove inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +input { + line-height: normal; +} + +/** + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + * Known issue: excess padding remains in IE 6. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ + @if $legacy_browser_support { + *height: 13px; /* 3 */ + *width: 13px; /* 3 */ + } +} + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ + +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; /* 2 */ + box-sizing: content-box; +} + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + * 3. Corrects text not wrapping in Firefox 3. + * 4. Corrects alignment displayed oddly in IE 6/7. + */ + +legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ + @if $legacy_browser_support { + white-space: normal; /* 3 */ + *margin-left: -7px; /* 4 */ + } +} + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ + +textarea { + overflow: auto; +} + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ + +optgroup { + font-weight: bold; +} + +/* Tables + ========================================================================== */ + +/** + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} + +td, +th { + padding: 0; +} diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/_object.scss b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/_object.scss new file mode 100644 index 00000000..22eebd87 --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/_object.scss @@ -0,0 +1,89 @@ +.section-specification { + table { + width: auto; + + th { + text-align: left; + } + } +} + +.method-title { + margin-left: -15px; + margin-bottom: 8px; + transition: margin-left .3s ease-out; + + .section-method.hide & { + margin-left: 0; + } + + code { + font-weight: 400; + font-size: .85em; + } +} + +.method-info { + background: $object-background; + border-bottom: 1px solid $object-border; + margin: 0 -25px; + padding: 20px 25px 0 25px; + transition: height .3s ease-out; + + position: relative; + + .pointy-thing { + background: $content-background; + height: 10px; + border-bottom: 1px solid $object-border; + margin: -20px -25px 16px -25px; + + &:before { + display: inline-block; + content: ""; + + background: $object-background; + border: 1px solid $object-border; + border-bottom: 0; + border-right: 0; + + position: absolute; + left: 21px; + top: 3px; + width: 12px; + height: 12px; + transform: rotate(45deg); + } + } + + .method-subsection { + margin-bottom: 15px; + + .argument-name { + width: 1px; + text-align: right; + + code { + color: #808080; + font-style: italic; + font-weight: 400; + } + } + } +} + +.section-method { + &.hide .method-info { + height: 0 !important; + overflow: hidden; + display: none; + } + + &.hide.animating .method-info { + display: block; + } + + &.animating .method-info { + overflow: hidden; + } +} diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/_print.scss b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/_print.scss new file mode 100644 index 00000000..61bdf99f --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/_print.scss @@ -0,0 +1,42 @@ +@media print { + body { + background: #fff; + padding: 8px; + } + + header { + position: static; + background: #fff; + color: #000; + } + + aside { + display: none; + } + + .container { + max-width: none; + padding: 0; + } + + article { + margin-top: 0; + + #content { + border: 0; + background: #fff; + padding: 15px 0 0 0; + + .title { + margin-top: 0; + padding-top: 0; + } + } + } + + .method-info { + &, & .pointy-thing { + background: #fff; + } + } +} diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/_variables.scss b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/_variables.scss new file mode 100644 index 00000000..cbaff3cf --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/_variables.scss @@ -0,0 +1,11 @@ +$body-font: -apple-system-font, "Helvetica Neue", Helvetica, sans-serif; +$code-font: "Source Code Pro", Monaco, Menlo, Consolas, monospace; + +$body-background: #f2f2f2; +$content-background: #fff; +$content-border: #e9e9e9; +$tint-color: #08c; +$object-background: #f9f9f9; +$object-border: #e9e9e9; + +$mobile-max-width: 650px; diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/_xcode.scss b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/_xcode.scss new file mode 100644 index 00000000..340b1f6b --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/_xcode.scss @@ -0,0 +1,29 @@ +.xcode { + header, aside { + display: none; + } + + .container { + padding: 0; + } + + article { + margin-top: 0; + + #content { + border: 0; + margin: 0; + } + } + + .method-info { + &, .section-method.hide & { + max-height: auto; + overflow: visible; + + &.hiding { + display: block; + } + } + } +} diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/style.scss b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/style.scss new file mode 100644 index 00000000..648a6086 --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/css/scss/style.scss @@ -0,0 +1 @@ +@import "variables", "normalize", "layout", "index", "object", "print", "xcode"; diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/hierarchy.html b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/hierarchy.html new file mode 100644 index 00000000..0b83af71 --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/hierarchy.html @@ -0,0 +1,96 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/img/button_bar_background.png b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/img/button_bar_background.png new file mode 100644 index 00000000..71d1019b Binary files /dev/null and b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/img/button_bar_background.png differ diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/img/disclosure.png b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/img/disclosure.png new file mode 100644 index 00000000..4c5cbf44 Binary files /dev/null and b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/img/disclosure.png differ diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/img/disclosure_open.png b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/img/disclosure_open.png new file mode 100644 index 00000000..82396fed Binary files /dev/null and b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/img/disclosure_open.png differ diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/img/library_background.png b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/img/library_background.png new file mode 100644 index 00000000..3006248a Binary files /dev/null and b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/img/library_background.png differ diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/img/title_background.png b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/img/title_background.png new file mode 100644 index 00000000..846e4968 Binary files /dev/null and b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/img/title_background.png differ diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/index.html b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/index.html new file mode 100644 index 00000000..a6e5fa92 --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/index.html @@ -0,0 +1,96 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/js/script.js b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/js/script.js new file mode 100644 index 00000000..ca915ee4 --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Documents/js/script.js @@ -0,0 +1,58 @@ +function $() { + return document.querySelector.apply(document, arguments); +} + +if (navigator.userAgent.indexOf("Xcode") != -1) { + document.documentElement.classList.add("xcode"); +} + +var jumpTo = $("#jump-to"); + +if (jumpTo) { + jumpTo.addEventListener("change", function(e) { + location.hash = this.options[this.selectedIndex].value; + }); +} + +function hashChanged() { + if (/^#\/\/api\//.test(location.hash)) { + var element = document.querySelector("a[name='" + location.hash.substring(1) + "']"); + + if (!element) { + return; + } + + element = element.parentNode; + + element.classList.remove("hide"); + fixScrollPosition(element); + } +} + +function fixScrollPosition(element) { + var scrollTop = element.offsetTop - 150; + document.documentElement.scrollTop = scrollTop; + document.body.scrollTop = scrollTop; +} + +[].forEach.call(document.querySelectorAll(".section-method"), function(element) { + element.classList.add("hide"); + + element.querySelector(".method-title a").addEventListener("click", function(e) { + var info = element.querySelector(".method-info"), + infoContainer = element.querySelector(".method-info-container"); + + element.classList.add("animating"); + info.style.height = (infoContainer.clientHeight + 40) + "px"; + fixScrollPosition(element); + element.classList.toggle("hide"); + + setTimeout(function() { + element.classList.remove("animating"); + info.style.height = "auto"; + }, 300); + }); +}); + +window.addEventListener("hashchange", hashChanged); +hashChanged(); diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Nodes.xml b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Nodes.xml new file mode 100644 index 00000000..387151bb --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Nodes.xml @@ -0,0 +1,239 @@ + + + + + PINCache + index.html + + + + + Classes + index.html + + + + + + + + + + + + Protocols + index.html + + + + + + + + + + Blocks + index.html + + + + + + + + + + + + + + + + + + + PINCache + Classes/PINCache.html + + + + Classes/PINCache.html + Overview + overview + + + Classes/PINCache.html + Tasks + tasks + + + + Classes/PINCache.html + Properties + properties + + + + + Classes/PINCache.html + Class Methods + class_methods + + + + + Classes/PINCache.html + Instance Methods + instance_methods + + + + + + + PINDiskCache + Classes/PINDiskCache.html + + + + Classes/PINDiskCache.html + Overview + overview + + + Classes/PINDiskCache.html + Tasks + tasks + + + + Classes/PINDiskCache.html + Properties + properties + + + + + Classes/PINDiskCache.html + Class Methods + class_methods + + + + + Classes/PINDiskCache.html + Instance Methods + instance_methods + + + + + + + PINMemoryCache + Classes/PINMemoryCache.html + + + + Classes/PINMemoryCache.html + Overview + overview + + + Classes/PINMemoryCache.html + Tasks + tasks + + + + Classes/PINMemoryCache.html + Properties + properties + + + + + Classes/PINMemoryCache.html + Class Methods + class_methods + + + + + Classes/PINMemoryCache.html + Instance Methods + instance_methods + + + + + + + + + PINCacheObjectSubscripting + Protocols/PINCacheObjectSubscripting.html + + + + Protocols/PINCacheObjectSubscripting.html + Overview + overview + + + Protocols/PINCacheObjectSubscripting.html + Tasks + tasks + + + + + + Protocols/PINCacheObjectSubscripting.html + Instance Methods + instance_methods + + + + + + + + + PINCacheBlock + Blocks/PINCacheBlock.html + + + + PINCacheObjectBlock + Blocks/PINCacheObjectBlock.html + + + + PINDiskCacheBlock + Blocks/PINDiskCacheBlock.html + + + + PINDiskCacheFileURLBlock + Blocks/PINDiskCacheFileURLBlock.html + + + + PINDiskCacheObjectBlock + Blocks/PINDiskCacheObjectBlock.html + + + + PINMemoryCacheBlock + Blocks/PINMemoryCacheBlock.html + + + + PINMemoryCacheObjectBlock + Blocks/PINMemoryCacheObjectBlock.html + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens1.xml b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens1.xml new file mode 100644 index 00000000..0835e772 --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens1.xml @@ -0,0 +1,515 @@ + + + + + + //apple_ref/occ/cl/PINCache + PINCache is a thread safe key/value store designed for persisting temporary objects that are expensive to +reproduce, such as downloaded data or the results of slow processing. It is comprised of two self-similar +stores, one in memory (PINMemoryCache and one on disk (PINDiskCache. + PINCache.h + + + + + + + + //apple_ref/occ/instm/PINCache/setName: + The name of this cache, used to create the diskCache and also appearing in stack traces. + PINCache.h + + @property (readonly) NSString *name + + + //api/name/name + + + + + //apple_ref/occ/instm/PINCache/name + The name of this cache, used to create the diskCache and also appearing in stack traces. + PINCache.h + + @property (readonly) NSString *name + + + //api/name/name + + + + + //apple_ref/occ/instp/PINCache/name + The name of this cache, used to create the diskCache and also appearing in stack traces. + PINCache.h + + @property (readonly) NSString *name + + + //api/name/name + + + + + //apple_ref/occ/instm/PINCache/setConcurrentQueue: + A concurrent queue on which blocks passed to the asynchronous access methods are run. + PINCache.h + + @property (readonly) dispatch_queue_t concurrentQueue + + + //api/name/concurrentQueue + + + + + //apple_ref/occ/instm/PINCache/concurrentQueue + A concurrent queue on which blocks passed to the asynchronous access methods are run. + PINCache.h + + @property (readonly) dispatch_queue_t concurrentQueue + + + //api/name/concurrentQueue + + + + + //apple_ref/occ/instp/PINCache/concurrentQueue + A concurrent queue on which blocks passed to the asynchronous access methods are run. + PINCache.h + + @property (readonly) dispatch_queue_t concurrentQueue + + + //api/name/concurrentQueue + + + + + //apple_ref/occ/instm/PINCache/setDiskByteCount: + Synchronously retrieves the total byte count of the diskCache on the shared disk queue. + PINCache.h + + @property (readonly) NSUInteger diskByteCount + + + //api/name/diskByteCount + + + + + //apple_ref/occ/instm/PINCache/diskByteCount + Synchronously retrieves the total byte count of the diskCache on the shared disk queue. + PINCache.h + + @property (readonly) NSUInteger diskByteCount + + + //api/name/diskByteCount + + + + + //apple_ref/occ/instp/PINCache/diskByteCount + Synchronously retrieves the total byte count of the diskCache on the shared disk queue. + PINCache.h + + @property (readonly) NSUInteger diskByteCount + + + //api/name/diskByteCount + + + + + //apple_ref/occ/instm/PINCache/setDiskCache: + The underlying disk cache, see PINDiskCache for additional configuration and trimming options. + PINCache.h + + @property (readonly) PINDiskCache *diskCache + + + //api/name/diskCache + + + + + //apple_ref/occ/instm/PINCache/diskCache + The underlying disk cache, see PINDiskCache for additional configuration and trimming options. + PINCache.h + + @property (readonly) PINDiskCache *diskCache + + + //api/name/diskCache + + + + + //apple_ref/occ/instp/PINCache/diskCache + The underlying disk cache, see PINDiskCache for additional configuration and trimming options. + PINCache.h + + @property (readonly) PINDiskCache *diskCache + + + //api/name/diskCache + + + + + //apple_ref/occ/instm/PINCache/setMemoryCache: + The underlying memory cache, see PINMemoryCache for additional configuration and trimming options. + PINCache.h + + @property (readonly) PINMemoryCache *memoryCache + + + //api/name/memoryCache + + + + + //apple_ref/occ/instm/PINCache/memoryCache + The underlying memory cache, see PINMemoryCache for additional configuration and trimming options. + PINCache.h + + @property (readonly) PINMemoryCache *memoryCache + + + //api/name/memoryCache + + + + + //apple_ref/occ/instp/PINCache/memoryCache + The underlying memory cache, see PINMemoryCache for additional configuration and trimming options. + PINCache.h + + @property (readonly) PINMemoryCache *memoryCache + + + //api/name/memoryCache + + + + + //apple_ref/occ/clm/PINCache/sharedCache + A shared cache. + PINCache.h + + + (instancetype)sharedCache + + The shared singleton cache instance. + //api/name/sharedCache + + + + + //apple_ref/occ/instm/PINCache/initWithName: + Multiple instances with the same name are allowed and can safely access +the same data on disk thanks to the magic of seriality. Also used to create the diskCache. + PINCache.h + + + //apple_ref/occ/instp/PINCache/name + + + + - (instancetype)initWithName:(NSString *)name + + + name + The name of the cache. + + + A new cache with the specified name. + //api/name/initWithName: + + + + + //apple_ref/occ/instm/PINCache/initWithName:rootPath: + Multiple instances with the same name are allowed and can safely access +the same data on disk thanks to the magic of seriality. Also used to create the diskCache. + PINCache.h + + + //apple_ref/occ/instp/PINCache/name + + + + - (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath + + + name + The name of the cache. + + rootPath + The path of the cache on disk. + + + A new cache with the specified name. + //api/name/initWithName:rootPath: + + + + + //apple_ref/occ/instm/PINCache/containsObjectForKey:block: + This method determines whether an object is present for the given key in the cache. This method returns immediately +and executes the passed block after the object is available, potentially in parallel with other blocks on the +concurrentQueue. + PINCache.h + + + //apple_ref/occ/instm/PINCache/containsObjectForKey: + + + + - (void)containsObjectForKey:(NSString *)key block:(PINCacheObjectContainmentBlock)block + + + key + The key associated with the object. + + block + A block to be executed concurrently after the containment check happened + + + + //api/name/containsObjectForKey:block: + + + + + //apple_ref/occ/instm/PINCache/objectForKey:block: + Retrieves the object for the specified key. This method returns immediately and executes the passed +block after the object is available, potentially in parallel with other blocks on the concurrentQueue. + PINCache.h + + - (void)objectForKey:(NSString *)key block:(PINCacheObjectBlock)block + + + key + The key associated with the requested object. + + block + A block to be executed concurrently when the object is available. + + + + //api/name/objectForKey:block: + + + + + //apple_ref/occ/instm/PINCache/setObject:forKey:block: + Stores an object in the cache for the specified key. This method returns immediately and executes the +passed block after the object has been stored, potentially in parallel with other blocks on the concurrentQueue. + PINCache.h + + - (void)setObject:(id<NSCoding>)object forKey:(NSString *)key block:(nullable PINCacheObjectBlock)block + + + object + An object to store in the cache. + + key + A key to associate with the object. This string will be copied. + + block + A block to be executed concurrently after the object has been stored, or nil. + + + + //api/name/setObject:forKey:block: + + + + + //apple_ref/occ/instm/PINCache/removeObjectForKey:block: + Removes the object for the specified key. This method returns immediately and executes the passed +block after the object has been removed, potentially in parallel with other blocks on the concurrentQueue. + PINCache.h + + - (void)removeObjectForKey:(NSString *)key block:(nullable PINCacheObjectBlock)block + + + key + The key associated with the object to be removed. + + block + A block to be executed concurrently after the object has been removed, or nil. + + + + //api/name/removeObjectForKey:block: + + + + + //apple_ref/occ/instm/PINCache/trimToDate:block: + Removes all objects from the cache that have not been used since the specified date. This method returns immediately and +executes the passed block after the cache has been trimmed, potentially in parallel with other blocks on the concurrentQueue. + PINCache.h + + - (void)trimToDate:(NSDate *)date block:(nullable PINCacheBlock)block + + + date + Objects that haven't been accessed since this date are removed from the cache. + + block + A block to be executed concurrently after the cache has been trimmed, or nil. + + + + //api/name/trimToDate:block: + + + + + //apple_ref/occ/instm/PINCache/removeAllObjects: + Removes all objects from the cache.This method returns immediately and executes the passed block after the +cache has been cleared, potentially in parallel with other blocks on the concurrentQueue. + PINCache.h + + - (void)removeAllObjects:(nullable PINCacheBlock)block + + + block + A block to be executed concurrently after the cache has been cleared, or nil. + + + + //api/name/removeAllObjects: + + + + + //apple_ref/occ/instm/PINCache/containsObjectForKey: + This method determines whether an object is present for the given key in the cache. + PINCache.h + + + //apple_ref/occ/instm/PINCache/containsObjectForKey:block: + + + + - (BOOL)containsObjectForKey:(NSString *)key + + + key + The key associated with the object. + + + YES if an object is present for the given key in the cache, otherwise NO. + //api/name/containsObjectForKey: + + + + + //apple_ref/occ/instm/PINCache/objectForKey: + Retrieves the object for the specified key. This method blocks the calling thread until the object is available. +Uses a semaphore to achieve synchronicity on the disk cache. + PINCache.h + + + //apple_ref/occ/instm/PINCache/objectForKey:block: + + + + - (__nullable id)objectForKey:(NSString *)key + + + key + The key associated with the object. + + + The object for the specified key. + //api/name/objectForKey: + + + + + //apple_ref/occ/instm/PINCache/setObject:forKey: + Stores an object in the cache for the specified key. This method blocks the calling thread until the object has been set. +Uses a semaphore to achieve synchronicity on the disk cache. + PINCache.h + + + //apple_ref/occ/instm/PINCache/setObject:forKey:block: + + + + - (void)setObject:(id<NSCoding>)object forKey:(NSString *)key + + + object + An object to store in the cache. + + key + A key to associate with the object. This string will be copied. + + + + //api/name/setObject:forKey: + + + + + //apple_ref/occ/instm/PINCache/removeObjectForKey: + Removes the object for the specified key. This method blocks the calling thread until the object +has been removed. +Uses a semaphore to achieve synchronicity on the disk cache. + PINCache.h + + - (void)removeObjectForKey:(NSString *)key + + + key + The key associated with the object to be removed. + + + + //api/name/removeObjectForKey: + + + + + //apple_ref/occ/instm/PINCache/trimToDate: + Removes all objects from the cache that have not been used since the specified date. +This method blocks the calling thread until the cache has been trimmed. +Uses a semaphore to achieve synchronicity on the disk cache. + PINCache.h + + - (void)trimToDate:(NSDate *)date + + + date + Objects that haven't been accessed since this date are removed from the cache. + + + + //api/name/trimToDate: + + + + + //apple_ref/occ/instm/PINCache/removeAllObjects + Removes all objects from the cache. This method blocks the calling thread until the cache has been cleared. +Uses a semaphore to achieve synchronicity on the disk cache. + PINCache.h + + - (void)removeAllObjects + + + //api/name/removeAllObjects + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens10.xml b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens10.xml new file mode 100644 index 00000000..3fc40bec --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens10.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens11.xml b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens11.xml new file mode 100644 index 00000000..3fc40bec --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens11.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens2.xml b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens2.xml new file mode 100644 index 00000000..c0c44157 --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens2.xml @@ -0,0 +1,1047 @@ + + + + + + //apple_ref/occ/cl/PINDiskCache + PINDiskCache is a thread safe key/value store backed by the file system. It accepts any object conforming +to the NSCoding protocol, which includes the basic Foundation data types and collection classes and also +many UIKit classes, notably UIImage. All work is performed on a serial queue shared by all instances in +the app, and archiving is handled by NSKeyedArchiver. This is a particular advantage for UIImage because +it skips UIImagePNGRepresentation() and retains information like scale and orientation. + PINDiskCache.h + + + + + + + + //apple_ref/occ/instm/PINDiskCache/setName: + The name of this cache, used to create a directory under Library/Caches and also appearing in stack traces. + PINDiskCache.h + + @property (readonly) NSString *name + + + //api/name/name + + + + + //apple_ref/occ/instm/PINDiskCache/name + The name of this cache, used to create a directory under Library/Caches and also appearing in stack traces. + PINDiskCache.h + + @property (readonly) NSString *name + + + //api/name/name + + + + + //apple_ref/occ/instp/PINDiskCache/name + The name of this cache, used to create a directory under Library/Caches and also appearing in stack traces. + PINDiskCache.h + + @property (readonly) NSString *name + + + //api/name/name + + + + + //apple_ref/occ/instm/PINDiskCache/setCacheURL: + The URL of the directory used by this cache, usually Library/Caches/com.pinterest.PINDiskCache.(name) + PINDiskCache.h + + @property (readonly) NSURL *cacheURL + + + //api/name/cacheURL + + + + + //apple_ref/occ/instm/PINDiskCache/cacheURL + The URL of the directory used by this cache, usually Library/Caches/com.pinterest.PINDiskCache.(name) + PINDiskCache.h + + @property (readonly) NSURL *cacheURL + + + //api/name/cacheURL + + + + + //apple_ref/occ/instp/PINDiskCache/cacheURL + The URL of the directory used by this cache, usually Library/Caches/com.pinterest.PINDiskCache.(name) + PINDiskCache.h + + @property (readonly) NSURL *cacheURL + + + //api/name/cacheURL + + + + + //apple_ref/occ/instm/PINDiskCache/setByteCount: + The total number of bytes used on disk, as reported by NSURLTotalFileAllocatedSizeKey. + PINDiskCache.h + + @property (readonly) NSUInteger byteCount + + + //api/name/byteCount + + + + + //apple_ref/occ/instm/PINDiskCache/byteCount + The total number of bytes used on disk, as reported by NSURLTotalFileAllocatedSizeKey. + PINDiskCache.h + + @property (readonly) NSUInteger byteCount + + + //api/name/byteCount + + + + + //apple_ref/occ/instp/PINDiskCache/byteCount + The total number of bytes used on disk, as reported by NSURLTotalFileAllocatedSizeKey. + PINDiskCache.h + + @property (readonly) NSUInteger byteCount + + + //api/name/byteCount + + + + + //apple_ref/occ/instm/PINDiskCache/setByteLimit: + The maximum number of bytes allowed on disk. This value is checked every time an object is set, if the written +size exceeds the limit a trim call is queued. Defaults to 0.0, meaning no practical limit. + PINDiskCache.h + + @property (assign) NSUInteger byteLimit + + + //api/name/byteLimit + + + + + //apple_ref/occ/instm/PINDiskCache/byteLimit + The maximum number of bytes allowed on disk. This value is checked every time an object is set, if the written +size exceeds the limit a trim call is queued. Defaults to 0.0, meaning no practical limit. + PINDiskCache.h + + @property (assign) NSUInteger byteLimit + + + //api/name/byteLimit + + + + + //apple_ref/occ/instp/PINDiskCache/byteLimit + The maximum number of bytes allowed on disk. This value is checked every time an object is set, if the written +size exceeds the limit a trim call is queued. Defaults to 0.0, meaning no practical limit. + PINDiskCache.h + + @property (assign) NSUInteger byteLimit + + + //api/name/byteLimit + + + + + //apple_ref/occ/instm/PINDiskCache/setAgeLimit: + The maximum number of seconds an object is allowed to exist in the cache. Setting this to a value +greater than 0.0 will start a recurring GCD timer with the same period that calls trimToDate:. +Setting it back to 0.0 will stop the timer. Defaults to 0.0, meaning no limit. + PINDiskCache.h + + @property (assign) NSTimeInterval ageLimit + + + //api/name/ageLimit + + + + + //apple_ref/occ/instm/PINDiskCache/ageLimit + The maximum number of seconds an object is allowed to exist in the cache. Setting this to a value +greater than 0.0 will start a recurring GCD timer with the same period that calls trimToDate:. +Setting it back to 0.0 will stop the timer. Defaults to 0.0, meaning no limit. + PINDiskCache.h + + @property (assign) NSTimeInterval ageLimit + + + //api/name/ageLimit + + + + + //apple_ref/occ/instp/PINDiskCache/ageLimit + The maximum number of seconds an object is allowed to exist in the cache. Setting this to a value +greater than 0.0 will start a recurring GCD timer with the same period that calls trimToDate:. +Setting it back to 0.0 will stop the timer. Defaults to 0.0, meaning no limit. + PINDiskCache.h + + @property (assign) NSTimeInterval ageLimit + + + //api/name/ageLimit + + + + + //apple_ref/occ/instm/PINDiskCache/setWritingProtectionOption: + The writing protection option used when writing a file on disk. This value is used every time an object is set. +NSDataWritingAtomic and NSDataWritingWithoutOverwriting are ignored if set +Defaults to NSDataWritingFileProtectionNone. + PINDiskCache.h + + @property (assign) NSDataWritingOptions writingProtectionOption + + + //api/name/writingProtectionOption + + + + + //apple_ref/occ/instm/PINDiskCache/writingProtectionOption + The writing protection option used when writing a file on disk. This value is used every time an object is set. +NSDataWritingAtomic and NSDataWritingWithoutOverwriting are ignored if set +Defaults to NSDataWritingFileProtectionNone. + PINDiskCache.h + + @property (assign) NSDataWritingOptions writingProtectionOption + + + //api/name/writingProtectionOption + + + + + //apple_ref/occ/instp/PINDiskCache/writingProtectionOption + The writing protection option used when writing a file on disk. This value is used every time an object is set. +NSDataWritingAtomic and NSDataWritingWithoutOverwriting are ignored if set +Defaults to NSDataWritingFileProtectionNone. + PINDiskCache.h + + @property (assign) NSDataWritingOptions writingProtectionOption + + + //api/name/writingProtectionOption + + + + + //apple_ref/occ/instm/PINDiskCache/setTtlCache: + If ttlCache is YES, the cache behaves like a ttlCache. This means that once an object enters the +cache, it only lives as long as self.ageLimit. This has the following implications: + - Accessing an object in the cache does not extend that object's lifetime in the cache + - When attempting to access an object in the cache that has lived longer than self.ageLimit, + the cache will behave as if the object does not exist + PINDiskCache.h + + @property (nonatomic, assign, getter=isTTLCache) BOOL ttlCache + + + //api/name/ttlCache + + + + + //apple_ref/occ/instm/PINDiskCache/isTTLCache + If ttlCache is YES, the cache behaves like a ttlCache. This means that once an object enters the +cache, it only lives as long as self.ageLimit. This has the following implications: + - Accessing an object in the cache does not extend that object's lifetime in the cache + - When attempting to access an object in the cache that has lived longer than self.ageLimit, + the cache will behave as if the object does not exist + PINDiskCache.h + + @property (nonatomic, assign, getter=isTTLCache) BOOL ttlCache + + + //api/name/ttlCache + + + + + //apple_ref/occ/instp/PINDiskCache/ttlCache + If ttlCache is YES, the cache behaves like a ttlCache. This means that once an object enters the +cache, it only lives as long as self.ageLimit. This has the following implications: + - Accessing an object in the cache does not extend that object's lifetime in the cache + - When attempting to access an object in the cache that has lived longer than self.ageLimit, + the cache will behave as if the object does not exist + PINDiskCache.h + + @property (nonatomic, assign, getter=isTTLCache) BOOL ttlCache + + + //api/name/ttlCache + + + + + //apple_ref/occ/instm/PINDiskCache/setWillAddObjectBlock: + A block to be executed just before an object is added to the cache. The queue waits during execution. + PINDiskCache.h + + @property (copy) PINDiskCacheObjectBlock __nullable willAddObjectBlock + + + //api/name/willAddObjectBlock + + + + + //apple_ref/occ/instm/PINDiskCache/willAddObjectBlock + A block to be executed just before an object is added to the cache. The queue waits during execution. + PINDiskCache.h + + @property (copy) PINDiskCacheObjectBlock __nullable willAddObjectBlock + + + //api/name/willAddObjectBlock + + + + + //apple_ref/occ/instp/PINDiskCache/willAddObjectBlock + A block to be executed just before an object is added to the cache. The queue waits during execution. + PINDiskCache.h + + @property (copy) PINDiskCacheObjectBlock __nullable willAddObjectBlock + + + //api/name/willAddObjectBlock + + + + + //apple_ref/occ/instm/PINDiskCache/setWillRemoveObjectBlock: + A block to be executed just before an object is removed from the cache. The queue waits during execution. + PINDiskCache.h + + @property (copy) PINDiskCacheObjectBlock __nullable willRemoveObjectBlock + + + //api/name/willRemoveObjectBlock + + + + + //apple_ref/occ/instm/PINDiskCache/willRemoveObjectBlock + A block to be executed just before an object is removed from the cache. The queue waits during execution. + PINDiskCache.h + + @property (copy) PINDiskCacheObjectBlock __nullable willRemoveObjectBlock + + + //api/name/willRemoveObjectBlock + + + + + //apple_ref/occ/instp/PINDiskCache/willRemoveObjectBlock + A block to be executed just before an object is removed from the cache. The queue waits during execution. + PINDiskCache.h + + @property (copy) PINDiskCacheObjectBlock __nullable willRemoveObjectBlock + + + //api/name/willRemoveObjectBlock + + + + + //apple_ref/occ/instm/PINDiskCache/setWillRemoveAllObjectsBlock: + A block to be executed just before all objects are removed from the cache as a result of removeAllObjects:. +The queue waits during execution. + PINDiskCache.h + + @property (copy) PINDiskCacheBlock __nullable willRemoveAllObjectsBlock + + + //api/name/willRemoveAllObjectsBlock + + + + + //apple_ref/occ/instm/PINDiskCache/willRemoveAllObjectsBlock + A block to be executed just before all objects are removed from the cache as a result of removeAllObjects:. +The queue waits during execution. + PINDiskCache.h + + @property (copy) PINDiskCacheBlock __nullable willRemoveAllObjectsBlock + + + //api/name/willRemoveAllObjectsBlock + + + + + //apple_ref/occ/instp/PINDiskCache/willRemoveAllObjectsBlock + A block to be executed just before all objects are removed from the cache as a result of removeAllObjects:. +The queue waits during execution. + PINDiskCache.h + + @property (copy) PINDiskCacheBlock __nullable willRemoveAllObjectsBlock + + + //api/name/willRemoveAllObjectsBlock + + + + + //apple_ref/occ/instm/PINDiskCache/setDidAddObjectBlock: + A block to be executed just after an object is added to the cache. The queue waits during execution. + PINDiskCache.h + + @property (copy) PINDiskCacheObjectBlock __nullable didAddObjectBlock + + + //api/name/didAddObjectBlock + + + + + //apple_ref/occ/instm/PINDiskCache/didAddObjectBlock + A block to be executed just after an object is added to the cache. The queue waits during execution. + PINDiskCache.h + + @property (copy) PINDiskCacheObjectBlock __nullable didAddObjectBlock + + + //api/name/didAddObjectBlock + + + + + //apple_ref/occ/instp/PINDiskCache/didAddObjectBlock + A block to be executed just after an object is added to the cache. The queue waits during execution. + PINDiskCache.h + + @property (copy) PINDiskCacheObjectBlock __nullable didAddObjectBlock + + + //api/name/didAddObjectBlock + + + + + //apple_ref/occ/instm/PINDiskCache/setDidRemoveObjectBlock: + A block to be executed just after an object is removed from the cache. The queue waits during execution. + PINDiskCache.h + + @property (copy) PINDiskCacheObjectBlock __nullable didRemoveObjectBlock + + + //api/name/didRemoveObjectBlock + + + + + //apple_ref/occ/instm/PINDiskCache/didRemoveObjectBlock + A block to be executed just after an object is removed from the cache. The queue waits during execution. + PINDiskCache.h + + @property (copy) PINDiskCacheObjectBlock __nullable didRemoveObjectBlock + + + //api/name/didRemoveObjectBlock + + + + + //apple_ref/occ/instp/PINDiskCache/didRemoveObjectBlock + A block to be executed just after an object is removed from the cache. The queue waits during execution. + PINDiskCache.h + + @property (copy) PINDiskCacheObjectBlock __nullable didRemoveObjectBlock + + + //api/name/didRemoveObjectBlock + + + + + //apple_ref/occ/instm/PINDiskCache/setDidRemoveAllObjectsBlock: + A block to be executed just after all objects are removed from the cache as a result of removeAllObjects:. +The queue waits during execution. + PINDiskCache.h + + @property (copy) PINDiskCacheBlock __nullable didRemoveAllObjectsBlock + + + //api/name/didRemoveAllObjectsBlock + + + + + //apple_ref/occ/instm/PINDiskCache/didRemoveAllObjectsBlock + A block to be executed just after all objects are removed from the cache as a result of removeAllObjects:. +The queue waits during execution. + PINDiskCache.h + + @property (copy) PINDiskCacheBlock __nullable didRemoveAllObjectsBlock + + + //api/name/didRemoveAllObjectsBlock + + + + + //apple_ref/occ/instp/PINDiskCache/didRemoveAllObjectsBlock + A block to be executed just after all objects are removed from the cache as a result of removeAllObjects:. +The queue waits during execution. + PINDiskCache.h + + @property (copy) PINDiskCacheBlock __nullable didRemoveAllObjectsBlock + + + //api/name/didRemoveAllObjectsBlock + + + + + //apple_ref/occ/clm/PINDiskCache/sharedCache + A shared cache. + PINDiskCache.h + + + (instancetype)sharedCache + + The shared singleton cache instance. + //api/name/sharedCache + + + + + //apple_ref/occ/clm/PINDiskCache/emptyTrash + Empties the trash with DISPATCHQUEUEPRIORITY_BACKGROUND. Does not use lock. + PINDiskCache.h + + + (void)emptyTrash + + + //api/name/emptyTrash + + + + + //apple_ref/occ/instm/PINDiskCache/initWithName: + Multiple instances with the same name are allowed and can safely access +the same data on disk thanks to the magic of seriality. + PINDiskCache.h + + + //apple_ref/occ/instp/PINDiskCache/name + + + + - (instancetype)initWithName:(NSString *)name + + + name + The name of the cache. + + + A new cache with the specified name. + //api/name/initWithName: + + + + + //apple_ref/occ/instm/PINDiskCache/initWithName:rootPath: + The designated initializer. Multiple instances with the same name are allowed and can safely access +the same data on disk thanks to the magic of seriality. + PINDiskCache.h + + + //apple_ref/occ/instp/PINDiskCache/name + + + + - (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath + + + name + The name of the cache. + + rootPath + The path of the cache. + + + A new cache with the specified name. + //api/name/initWithName:rootPath: + + + + + //apple_ref/occ/instm/PINDiskCache/lockFileAccessWhileExecutingBlock: + Locks access to ivars and allows safe interaction with files on disk. This method returns immediately. + PINDiskCache.h + + - (void)lockFileAccessWhileExecutingBlock:(nullable PINDiskCacheBlock)block + + + block + A block to be executed when a lock is available. + + + + //api/name/lockFileAccessWhileExecutingBlock: + + + + + //apple_ref/occ/instm/PINDiskCache/containsObjectForKey:block: + This method determines whether an object is present for the given key in the cache. This method returns immediately +and executes the passed block after the object is available, potentially in parallel with other blocks on the +<concurrentQueue>. + PINDiskCache.h + + + //apple_ref/occ/instm/PINDiskCache/containsObjectForKey: + + + + - (void)containsObjectForKey:(NSString *)key block:(PINDiskCacheContainsBlock)block + + + key + The key associated with the object. + + block + A block to be executed concurrently after the containment check happened + + + + //api/name/containsObjectForKey:block: + + + + + //apple_ref/occ/instm/PINDiskCache/objectForKey:block: + Retrieves the object for the specified key. This method returns immediately and executes the passed +block as soon as the object is available. + PINDiskCache.h + + - (void)objectForKey:(NSString *)key block:(nullable PINDiskCacheObjectBlock)block + + + key + The key associated with the requested object. + + block + A block to be executed serially when the object is available. + + + + //api/name/objectForKey:block: + + + + + //apple_ref/occ/instm/PINDiskCache/fileURLForKey:block: + Retrieves the fileURL for the specified key without actually reading the data from disk. This method +returns immediately and executes the passed block as soon as the object is available. + PINDiskCache.h + + - (void)fileURLForKey:(nullable NSString *)key block:(nullable PINDiskCacheObjectBlock)block + + + key + The key associated with the requested object. + + block + A block to be executed serially when the file URL is available. + + + + //api/name/fileURLForKey:block: + + + + + //apple_ref/occ/instm/PINDiskCache/setObject:forKey:block: + Stores an object in the cache for the specified key. This method returns immediately and executes the +passed block as soon as the object has been stored. + PINDiskCache.h + + - (void)setObject:(id<NSCoding>)object forKey:(NSString *)key block:(nullable PINDiskCacheObjectBlock)block + + + object + An object to store in the cache. + + key + A key to associate with the object. This string will be copied. + + block + A block to be executed serially after the object has been stored, or nil. + + + + //api/name/setObject:forKey:block: + + + + + //apple_ref/occ/instm/PINDiskCache/removeObjectForKey:block: + Removes the object for the specified key. This method returns immediately and executes the passed block +as soon as the object has been removed. + PINDiskCache.h + + - (void)removeObjectForKey:(NSString *)key block:(nullable PINDiskCacheObjectBlock)block + + + key + The key associated with the object to be removed. + + block + A block to be executed serially after the object has been removed, or nil. + + + + //api/name/removeObjectForKey:block: + + + + + //apple_ref/occ/instm/PINDiskCache/trimToDate:block: + Removes all objects from the cache that have not been used since the specified date. +This method returns immediately and executes the passed block as soon as the cache has been trimmed. + PINDiskCache.h + + - (void)trimToDate:(NSDate *)date block:(nullable PINDiskCacheBlock)block + + + date + Objects that haven't been accessed since this date are removed from the cache. + + block + A block to be executed serially after the cache has been trimmed, or nil. + + + + //api/name/trimToDate:block: + + + + + //apple_ref/occ/instm/PINDiskCache/trimToSize:block: + Removes objects from the cache, largest first, until the cache is equal to or smaller than the specified byteCount. +This method returns immediately and executes the passed block as soon as the cache has been trimmed. + PINDiskCache.h + + - (void)trimToSize:(NSUInteger)byteCount block:(nullable PINDiskCacheBlock)block + + + byteCount + The cache will be trimmed equal to or smaller than this size. + + block + A block to be executed serially after the cache has been trimmed, or nil. + + + + //api/name/trimToSize:block: + + + + + //apple_ref/occ/instm/PINDiskCache/trimToSizeByDate:block: + Removes objects from the cache, ordered by date (least recently used first), until the cache is equal to or smaller +than the specified byteCount. This method returns immediately and executes the passed block as soon as the cache has +been trimmed. + PINDiskCache.h + + - (void)trimToSizeByDate:(NSUInteger)byteCount block:(nullable PINDiskCacheBlock)block + + + byteCount + The cache will be trimmed equal to or smaller than this size. + + block + A block to be executed serially after the cache has been trimmed, or nil. + + + + //api/name/trimToSizeByDate:block: + + + + + //apple_ref/occ/instm/PINDiskCache/removeAllObjects: + Removes all objects from the cache. This method returns immediately and executes the passed block as soon as the +cache has been cleared. + PINDiskCache.h + + - (void)removeAllObjects:(nullable PINDiskCacheBlock)block + + + block + A block to be executed serially after the cache has been cleared, or nil. + + + + //api/name/removeAllObjects: + + + + + //apple_ref/occ/instm/PINDiskCache/enumerateObjectsWithBlock:completionBlock: + Loops through all objects in the cache (reads and writes are suspended during the enumeration). Data is not actually +read from disk, the object parameter of the block will be nil but the fileURL will be available. +This method returns immediately. + PINDiskCache.h + + - (void)enumerateObjectsWithBlock:(PINDiskCacheObjectBlock)block completionBlock:(nullable PINDiskCacheBlock)completionBlock + + + block + A block to be executed for every object in the cache. + + completionBlock + An optional block to be executed after the enumeration is complete. + + + + //api/name/enumerateObjectsWithBlock:completionBlock: + + + + + //apple_ref/occ/instm/PINDiskCache/synchronouslyLockFileAccessWhileExecutingBlock: + Locks access to ivars and allows safe interaction with files on disk. This method only returns once the block +has been run. + PINDiskCache.h + + - (void)synchronouslyLockFileAccessWhileExecutingBlock:(nullable PINDiskCacheBlock)block + + + block + A block to be executed when a lock is available. + + + + //api/name/synchronouslyLockFileAccessWhileExecutingBlock: + + + + + //apple_ref/occ/instm/PINDiskCache/containsObjectForKey: + This method determines whether an object is present for the given key in the cache. + PINDiskCache.h + + + //apple_ref/occ/instm/PINDiskCache/containsObjectForKey:block: + + + + - (BOOL)containsObjectForKey:(NSString *)key + + + key + The key associated with the object. + + + YES if an object is present for the given key in the cache, otherwise NO. + //api/name/containsObjectForKey: + + + + + //apple_ref/occ/instm/PINDiskCache/objectForKey: + Retrieves the object for the specified key. This method blocks the calling thread until the +object is available. + PINDiskCache.h + + + //apple_ref/occ/instm/PINDiskCache/objectForKey:block: + + + + - (__nullable id<NSCoding>)objectForKey:(NSString *)key + + + key + The key associated with the object. + + + The object for the specified key. + //api/name/objectForKey: + + + + + //apple_ref/occ/instm/PINDiskCache/fileURLForKey: + Retrieves the file URL for the specified key. This method blocks the calling thread until the +url is available. Do not use this URL anywhere except with lockFileAccessWhileExecutingBlock:. This method probably +shouldn't even exist, just use the asynchronous one. + PINDiskCache.h + + + //apple_ref/occ/instm/PINDiskCache/fileURLForKey:block: + + + + - (nullable NSURL *)fileURLForKey:(nullable NSString *)key + + + key + The key associated with the object. + + + The file URL for the specified key. + //api/name/fileURLForKey: + + + + + //apple_ref/occ/instm/PINDiskCache/setObject:forKey: + Stores an object in the cache for the specified key. This method blocks the calling thread until +the object has been stored. + PINDiskCache.h + + + //apple_ref/occ/instm/PINDiskCache/setObject:forKey:block: + + + + - (void)setObject:(id<NSCoding>)object forKey:(NSString *)key + + + object + An object to store in the cache. + + key + A key to associate with the object. This string will be copied. + + + + //api/name/setObject:forKey: + + + + + //apple_ref/occ/instm/PINDiskCache/removeObjectForKey: + Removes the object for the specified key. This method blocks the calling thread until the object +has been removed. + PINDiskCache.h + + - (void)removeObjectForKey:(NSString *)key + + + key + The key associated with the object to be removed. + + + + //api/name/removeObjectForKey: + + + + + //apple_ref/occ/instm/PINDiskCache/trimToDate: + Removes all objects from the cache that have not been used since the specified date. +This method blocks the calling thread until the cache has been trimmed. + PINDiskCache.h + + - (void)trimToDate:(nullable NSDate *)date + + + date + Objects that haven't been accessed since this date are removed from the cache. + + + + //api/name/trimToDate: + + + + + //apple_ref/occ/instm/PINDiskCache/trimToSize: + Removes objects from the cache, largest first, until the cache is equal to or smaller than the +specified byteCount. This method blocks the calling thread until the cache has been trimmed. + PINDiskCache.h + + - (void)trimToSize:(NSUInteger)byteCount + + + byteCount + The cache will be trimmed equal to or smaller than this size. + + + + //api/name/trimToSize: + + + + + //apple_ref/occ/instm/PINDiskCache/trimToSizeByDate: + Removes objects from the cache, ordered by date (least recently used first), until the cache is equal to or +smaller than the specified byteCount. This method blocks the calling thread until the cache has been trimmed. + PINDiskCache.h + + - (void)trimToSizeByDate:(NSUInteger)byteCount + + + byteCount + The cache will be trimmed equal to or smaller than this size. + + + + //api/name/trimToSizeByDate: + + + + + //apple_ref/occ/instm/PINDiskCache/removeAllObjects + Removes all objects from the cache. This method blocks the calling thread until the cache has been cleared. + PINDiskCache.h + + - (void)removeAllObjects + + + //api/name/removeAllObjects + + + + + //apple_ref/occ/instm/PINDiskCache/enumerateObjectsWithBlock: + Loops through all objects in the cache (reads and writes are suspended during the enumeration). Data is not actually +read from disk, the object parameter of the block will be nil but the fileURL will be available. +This method blocks the calling thread until all objects have been enumerated. + PINDiskCache.h + + - (void)enumerateObjectsWithBlock:(nullable PINDiskCacheObjectBlock)block + + + block + A block to be executed for every object in the cache. + + + + //api/name/enumerateObjectsWithBlock: + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens3.xml b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens3.xml new file mode 100644 index 00000000..a153b1d6 --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens3.xml @@ -0,0 +1,1066 @@ + + + + + + //apple_ref/occ/cl/PINMemoryCache + PINMemoryCache is a fast, thread safe key/value store similar to NSCache. On iOS it will clear itself +automatically to reduce memory usage when the app receives a memory warning or goes into the background. + PINMemoryCache.h + + + + + + + + //apple_ref/occ/instm/PINMemoryCache/setConcurrentQueue: + A concurrent queue on which all callbacks are called. It is exposed here so that it can be set to +target some other queue, such as a global concurrent queue with a priority other than the default. + PINMemoryCache.h + + @property (readonly) dispatch_queue_t concurrentQueue + + + //api/name/concurrentQueue + + + + + //apple_ref/occ/instm/PINMemoryCache/concurrentQueue + A concurrent queue on which all callbacks are called. It is exposed here so that it can be set to +target some other queue, such as a global concurrent queue with a priority other than the default. + PINMemoryCache.h + + @property (readonly) dispatch_queue_t concurrentQueue + + + //api/name/concurrentQueue + + + + + //apple_ref/occ/instp/PINMemoryCache/concurrentQueue + A concurrent queue on which all callbacks are called. It is exposed here so that it can be set to +target some other queue, such as a global concurrent queue with a priority other than the default. + PINMemoryCache.h + + @property (readonly) dispatch_queue_t concurrentQueue + + + //api/name/concurrentQueue + + + + + //apple_ref/occ/instm/PINMemoryCache/setTotalCost: + The total accumulated cost. + PINMemoryCache.h + + @property (readonly) NSUInteger totalCost + + + //api/name/totalCost + + + + + //apple_ref/occ/instm/PINMemoryCache/totalCost + The total accumulated cost. + PINMemoryCache.h + + @property (readonly) NSUInteger totalCost + + + //api/name/totalCost + + + + + //apple_ref/occ/instp/PINMemoryCache/totalCost + The total accumulated cost. + PINMemoryCache.h + + @property (readonly) NSUInteger totalCost + + + //api/name/totalCost + + + + + //apple_ref/occ/instm/PINMemoryCache/setCostLimit: + The maximum cost allowed to accumulate before objects begin to be removed with trimToCostByDate:. + PINMemoryCache.h + + @property (assign) NSUInteger costLimit + + + //api/name/costLimit + + + + + //apple_ref/occ/instm/PINMemoryCache/costLimit + The maximum cost allowed to accumulate before objects begin to be removed with trimToCostByDate:. + PINMemoryCache.h + + @property (assign) NSUInteger costLimit + + + //api/name/costLimit + + + + + //apple_ref/occ/instp/PINMemoryCache/costLimit + The maximum cost allowed to accumulate before objects begin to be removed with trimToCostByDate:. + PINMemoryCache.h + + @property (assign) NSUInteger costLimit + + + //api/name/costLimit + + + + + //apple_ref/occ/instm/PINMemoryCache/setAgeLimit: + The maximum number of seconds an object is allowed to exist in the cache. Setting this to a value +greater than 0.0 will start a recurring GCD timer with the same period that calls trimToDate:. +Setting it back to 0.0 will stop the timer. Defaults to 0.0. + PINMemoryCache.h + + @property (assign) NSTimeInterval ageLimit + + + //api/name/ageLimit + + + + + //apple_ref/occ/instm/PINMemoryCache/ageLimit + The maximum number of seconds an object is allowed to exist in the cache. Setting this to a value +greater than 0.0 will start a recurring GCD timer with the same period that calls trimToDate:. +Setting it back to 0.0 will stop the timer. Defaults to 0.0. + PINMemoryCache.h + + @property (assign) NSTimeInterval ageLimit + + + //api/name/ageLimit + + + + + //apple_ref/occ/instp/PINMemoryCache/ageLimit + The maximum number of seconds an object is allowed to exist in the cache. Setting this to a value +greater than 0.0 will start a recurring GCD timer with the same period that calls trimToDate:. +Setting it back to 0.0 will stop the timer. Defaults to 0.0. + PINMemoryCache.h + + @property (assign) NSTimeInterval ageLimit + + + //api/name/ageLimit + + + + + //apple_ref/occ/instm/PINMemoryCache/setTtlCache: + If ttlCache is YES, the cache behaves like a ttlCache. This means that once an object enters the +cache, it only lives as long as self.ageLimit. This has the following implications: +- Accessing an object in the cache does not extend that object's lifetime in the cache +- When attempting to access an object in the cache that has lived longer than self.ageLimit, +the cache will behave as if the object does not exist + PINMemoryCache.h + + @property (nonatomic, assign, getter=isTTLCache) BOOL ttlCache + + + //api/name/ttlCache + + + + + //apple_ref/occ/instm/PINMemoryCache/isTTLCache + If ttlCache is YES, the cache behaves like a ttlCache. This means that once an object enters the +cache, it only lives as long as self.ageLimit. This has the following implications: +- Accessing an object in the cache does not extend that object's lifetime in the cache +- When attempting to access an object in the cache that has lived longer than self.ageLimit, +the cache will behave as if the object does not exist + PINMemoryCache.h + + @property (nonatomic, assign, getter=isTTLCache) BOOL ttlCache + + + //api/name/ttlCache + + + + + //apple_ref/occ/instp/PINMemoryCache/ttlCache + If ttlCache is YES, the cache behaves like a ttlCache. This means that once an object enters the +cache, it only lives as long as self.ageLimit. This has the following implications: +- Accessing an object in the cache does not extend that object's lifetime in the cache +- When attempting to access an object in the cache that has lived longer than self.ageLimit, +the cache will behave as if the object does not exist + PINMemoryCache.h + + @property (nonatomic, assign, getter=isTTLCache) BOOL ttlCache + + + //api/name/ttlCache + + + + + //apple_ref/occ/instm/PINMemoryCache/setRemoveAllObjectsOnMemoryWarning: + When YES on iOS the cache will remove all objects when the app receives a memory warning. +Defaults to YES. + PINMemoryCache.h + + @property (assign) BOOL removeAllObjectsOnMemoryWarning + + + //api/name/removeAllObjectsOnMemoryWarning + + + + + //apple_ref/occ/instm/PINMemoryCache/removeAllObjectsOnMemoryWarning + When YES on iOS the cache will remove all objects when the app receives a memory warning. +Defaults to YES. + PINMemoryCache.h + + @property (assign) BOOL removeAllObjectsOnMemoryWarning + + + //api/name/removeAllObjectsOnMemoryWarning + + + + + //apple_ref/occ/instp/PINMemoryCache/removeAllObjectsOnMemoryWarning + When YES on iOS the cache will remove all objects when the app receives a memory warning. +Defaults to YES. + PINMemoryCache.h + + @property (assign) BOOL removeAllObjectsOnMemoryWarning + + + //api/name/removeAllObjectsOnMemoryWarning + + + + + //apple_ref/occ/instm/PINMemoryCache/setRemoveAllObjectsOnEnteringBackground: + When YES on iOS the cache will remove all objects when the app enters the background. +Defaults to YES. + PINMemoryCache.h + + @property (assign) BOOL removeAllObjectsOnEnteringBackground + + + //api/name/removeAllObjectsOnEnteringBackground + + + + + //apple_ref/occ/instm/PINMemoryCache/removeAllObjectsOnEnteringBackground + When YES on iOS the cache will remove all objects when the app enters the background. +Defaults to YES. + PINMemoryCache.h + + @property (assign) BOOL removeAllObjectsOnEnteringBackground + + + //api/name/removeAllObjectsOnEnteringBackground + + + + + //apple_ref/occ/instp/PINMemoryCache/removeAllObjectsOnEnteringBackground + When YES on iOS the cache will remove all objects when the app enters the background. +Defaults to YES. + PINMemoryCache.h + + @property (assign) BOOL removeAllObjectsOnEnteringBackground + + + //api/name/removeAllObjectsOnEnteringBackground + + + + + //apple_ref/occ/instm/PINMemoryCache/setWillAddObjectBlock: + A block to be executed just before an object is added to the cache. This block will be excuted within +a lock, i.e. all reads and writes are suspended for the duration of the block. +Calling synchronous methods on the cache within this callback will likely cause a deadlock. + PINMemoryCache.h + + @property (copy) PINMemoryCacheObjectBlock __nullable willAddObjectBlock + + + //api/name/willAddObjectBlock + + + + + //apple_ref/occ/instm/PINMemoryCache/willAddObjectBlock + A block to be executed just before an object is added to the cache. This block will be excuted within +a lock, i.e. all reads and writes are suspended for the duration of the block. +Calling synchronous methods on the cache within this callback will likely cause a deadlock. + PINMemoryCache.h + + @property (copy) PINMemoryCacheObjectBlock __nullable willAddObjectBlock + + + //api/name/willAddObjectBlock + + + + + //apple_ref/occ/instp/PINMemoryCache/willAddObjectBlock + A block to be executed just before an object is added to the cache. This block will be excuted within +a lock, i.e. all reads and writes are suspended for the duration of the block. +Calling synchronous methods on the cache within this callback will likely cause a deadlock. + PINMemoryCache.h + + @property (copy) PINMemoryCacheObjectBlock __nullable willAddObjectBlock + + + //api/name/willAddObjectBlock + + + + + //apple_ref/occ/instm/PINMemoryCache/setWillRemoveObjectBlock: + A block to be executed just before an object is removed from the cache. This block will be excuted +within a lock, i.e. all reads and writes are suspended for the duration of the block. +Calling synchronous methods on the cache within this callback will likely cause a deadlock. + PINMemoryCache.h + + @property (copy) PINMemoryCacheObjectBlock __nullable willRemoveObjectBlock + + + //api/name/willRemoveObjectBlock + + + + + //apple_ref/occ/instm/PINMemoryCache/willRemoveObjectBlock + A block to be executed just before an object is removed from the cache. This block will be excuted +within a lock, i.e. all reads and writes are suspended for the duration of the block. +Calling synchronous methods on the cache within this callback will likely cause a deadlock. + PINMemoryCache.h + + @property (copy) PINMemoryCacheObjectBlock __nullable willRemoveObjectBlock + + + //api/name/willRemoveObjectBlock + + + + + //apple_ref/occ/instp/PINMemoryCache/willRemoveObjectBlock + A block to be executed just before an object is removed from the cache. This block will be excuted +within a lock, i.e. all reads and writes are suspended for the duration of the block. +Calling synchronous methods on the cache within this callback will likely cause a deadlock. + PINMemoryCache.h + + @property (copy) PINMemoryCacheObjectBlock __nullable willRemoveObjectBlock + + + //api/name/willRemoveObjectBlock + + + + + //apple_ref/occ/instm/PINMemoryCache/setWillRemoveAllObjectsBlock: + A block to be executed just before all objects are removed from the cache as a result of removeAllObjects:. +This block will be excuted within a lock, i.e. all reads and writes are suspended for the duration of the block. +Calling synchronous methods on the cache within this callback will likely cause a deadlock. + PINMemoryCache.h + + @property (copy) PINMemoryCacheBlock __nullable willRemoveAllObjectsBlock + + + //api/name/willRemoveAllObjectsBlock + + + + + //apple_ref/occ/instm/PINMemoryCache/willRemoveAllObjectsBlock + A block to be executed just before all objects are removed from the cache as a result of removeAllObjects:. +This block will be excuted within a lock, i.e. all reads and writes are suspended for the duration of the block. +Calling synchronous methods on the cache within this callback will likely cause a deadlock. + PINMemoryCache.h + + @property (copy) PINMemoryCacheBlock __nullable willRemoveAllObjectsBlock + + + //api/name/willRemoveAllObjectsBlock + + + + + //apple_ref/occ/instp/PINMemoryCache/willRemoveAllObjectsBlock + A block to be executed just before all objects are removed from the cache as a result of removeAllObjects:. +This block will be excuted within a lock, i.e. all reads and writes are suspended for the duration of the block. +Calling synchronous methods on the cache within this callback will likely cause a deadlock. + PINMemoryCache.h + + @property (copy) PINMemoryCacheBlock __nullable willRemoveAllObjectsBlock + + + //api/name/willRemoveAllObjectsBlock + + + + + //apple_ref/occ/instm/PINMemoryCache/setDidAddObjectBlock: + A block to be executed just after an object is added to the cache. This block will be excuted within +a lock, i.e. all reads and writes are suspended for the duration of the block. +Calling synchronous methods on the cache within this callback will likely cause a deadlock. + PINMemoryCache.h + + @property (copy) PINMemoryCacheObjectBlock __nullable didAddObjectBlock + + + //api/name/didAddObjectBlock + + + + + //apple_ref/occ/instm/PINMemoryCache/didAddObjectBlock + A block to be executed just after an object is added to the cache. This block will be excuted within +a lock, i.e. all reads and writes are suspended for the duration of the block. +Calling synchronous methods on the cache within this callback will likely cause a deadlock. + PINMemoryCache.h + + @property (copy) PINMemoryCacheObjectBlock __nullable didAddObjectBlock + + + //api/name/didAddObjectBlock + + + + + //apple_ref/occ/instp/PINMemoryCache/didAddObjectBlock + A block to be executed just after an object is added to the cache. This block will be excuted within +a lock, i.e. all reads and writes are suspended for the duration of the block. +Calling synchronous methods on the cache within this callback will likely cause a deadlock. + PINMemoryCache.h + + @property (copy) PINMemoryCacheObjectBlock __nullable didAddObjectBlock + + + //api/name/didAddObjectBlock + + + + + //apple_ref/occ/instm/PINMemoryCache/setDidRemoveObjectBlock: + A block to be executed just after an object is removed from the cache. This block will be excuted +within a lock, i.e. all reads and writes are suspended for the duration of the block. +Calling synchronous methods on the cache within this callback will likely cause a deadlock. + PINMemoryCache.h + + @property (copy) PINMemoryCacheObjectBlock __nullable didRemoveObjectBlock + + + //api/name/didRemoveObjectBlock + + + + + //apple_ref/occ/instm/PINMemoryCache/didRemoveObjectBlock + A block to be executed just after an object is removed from the cache. This block will be excuted +within a lock, i.e. all reads and writes are suspended for the duration of the block. +Calling synchronous methods on the cache within this callback will likely cause a deadlock. + PINMemoryCache.h + + @property (copy) PINMemoryCacheObjectBlock __nullable didRemoveObjectBlock + + + //api/name/didRemoveObjectBlock + + + + + //apple_ref/occ/instp/PINMemoryCache/didRemoveObjectBlock + A block to be executed just after an object is removed from the cache. This block will be excuted +within a lock, i.e. all reads and writes are suspended for the duration of the block. +Calling synchronous methods on the cache within this callback will likely cause a deadlock. + PINMemoryCache.h + + @property (copy) PINMemoryCacheObjectBlock __nullable didRemoveObjectBlock + + + //api/name/didRemoveObjectBlock + + + + + //apple_ref/occ/instm/PINMemoryCache/setDidRemoveAllObjectsBlock: + A block to be executed just after all objects are removed from the cache as a result of removeAllObjects:. +This block will be excuted within a lock, i.e. all reads and writes are suspended for the duration of the block. +Calling synchronous methods on the cache within this callback will likely cause a deadlock. + PINMemoryCache.h + + @property (copy) PINMemoryCacheBlock __nullable didRemoveAllObjectsBlock + + + //api/name/didRemoveAllObjectsBlock + + + + + //apple_ref/occ/instm/PINMemoryCache/didRemoveAllObjectsBlock + A block to be executed just after all objects are removed from the cache as a result of removeAllObjects:. +This block will be excuted within a lock, i.e. all reads and writes are suspended for the duration of the block. +Calling synchronous methods on the cache within this callback will likely cause a deadlock. + PINMemoryCache.h + + @property (copy) PINMemoryCacheBlock __nullable didRemoveAllObjectsBlock + + + //api/name/didRemoveAllObjectsBlock + + + + + //apple_ref/occ/instp/PINMemoryCache/didRemoveAllObjectsBlock + A block to be executed just after all objects are removed from the cache as a result of removeAllObjects:. +This block will be excuted within a lock, i.e. all reads and writes are suspended for the duration of the block. +Calling synchronous methods on the cache within this callback will likely cause a deadlock. + PINMemoryCache.h + + @property (copy) PINMemoryCacheBlock __nullable didRemoveAllObjectsBlock + + + //api/name/didRemoveAllObjectsBlock + + + + + //apple_ref/occ/instm/PINMemoryCache/setDidReceiveMemoryWarningBlock: + A block to be executed upon receiving a memory warning (iOS only) potentially in parallel with other blocks on the <queue>. +This block will be executed regardless of the value of removeAllObjectsOnMemoryWarning. Defaults to nil. + PINMemoryCache.h + + @property (copy) PINMemoryCacheBlock __nullable didReceiveMemoryWarningBlock + + + //api/name/didReceiveMemoryWarningBlock + + + + + //apple_ref/occ/instm/PINMemoryCache/didReceiveMemoryWarningBlock + A block to be executed upon receiving a memory warning (iOS only) potentially in parallel with other blocks on the <queue>. +This block will be executed regardless of the value of removeAllObjectsOnMemoryWarning. Defaults to nil. + PINMemoryCache.h + + @property (copy) PINMemoryCacheBlock __nullable didReceiveMemoryWarningBlock + + + //api/name/didReceiveMemoryWarningBlock + + + + + //apple_ref/occ/instp/PINMemoryCache/didReceiveMemoryWarningBlock + A block to be executed upon receiving a memory warning (iOS only) potentially in parallel with other blocks on the <queue>. +This block will be executed regardless of the value of removeAllObjectsOnMemoryWarning. Defaults to nil. + PINMemoryCache.h + + @property (copy) PINMemoryCacheBlock __nullable didReceiveMemoryWarningBlock + + + //api/name/didReceiveMemoryWarningBlock + + + + + //apple_ref/occ/instm/PINMemoryCache/setDidEnterBackgroundBlock: + A block to be executed when the app enters the background (iOS only) potentially in parallel with other blocks on the concurrentQueue. +This block will be executed regardless of the value of removeAllObjectsOnEnteringBackground. Defaults to nil. + PINMemoryCache.h + + @property (copy) PINMemoryCacheBlock __nullable didEnterBackgroundBlock + + + //api/name/didEnterBackgroundBlock + + + + + //apple_ref/occ/instm/PINMemoryCache/didEnterBackgroundBlock + A block to be executed when the app enters the background (iOS only) potentially in parallel with other blocks on the concurrentQueue. +This block will be executed regardless of the value of removeAllObjectsOnEnteringBackground. Defaults to nil. + PINMemoryCache.h + + @property (copy) PINMemoryCacheBlock __nullable didEnterBackgroundBlock + + + //api/name/didEnterBackgroundBlock + + + + + //apple_ref/occ/instp/PINMemoryCache/didEnterBackgroundBlock + A block to be executed when the app enters the background (iOS only) potentially in parallel with other blocks on the concurrentQueue. +This block will be executed regardless of the value of removeAllObjectsOnEnteringBackground. Defaults to nil. + PINMemoryCache.h + + @property (copy) PINMemoryCacheBlock __nullable didEnterBackgroundBlock + + + //api/name/didEnterBackgroundBlock + + + + + //apple_ref/occ/clm/PINMemoryCache/sharedCache + A shared cache. + PINMemoryCache.h + + + (instancetype)sharedCache + + The shared singleton cache instance. + //api/name/sharedCache + + + + + //apple_ref/occ/instm/PINMemoryCache/containsObjectForKey:block: + This method determines whether an object is present for the given key in the cache. This method returns immediately +and executes the passed block after the object is available, potentially in parallel with other blocks on the +concurrentQueue. + PINMemoryCache.h + + + //apple_ref/occ/instm/PINMemoryCache/containsObjectForKey: + + + + - (void)containsObjectForKey:(NSString *)key block:(PINMemoryCacheContainmentBlock)block + + + key + The key associated with the object. + + block + A block to be executed concurrently after the containment check happened + + + + //api/name/containsObjectForKey:block: + + + + + //apple_ref/occ/instm/PINMemoryCache/objectForKey:block: + Retrieves the object for the specified key. This method returns immediately and executes the passed +block after the object is available, potentially in parallel with other blocks on the concurrentQueue. + PINMemoryCache.h + + - (void)objectForKey:(NSString *)key block:(nullable PINMemoryCacheObjectBlock)block + + + key + The key associated with the requested object. + + block + A block to be executed concurrently when the object is available. + + + + //api/name/objectForKey:block: + + + + + //apple_ref/occ/instm/PINMemoryCache/setObject:forKey:block: + Stores an object in the cache for the specified key. This method returns immediately and executes the +passed block after the object has been stored, potentially in parallel with other blocks on the concurrentQueue. + PINMemoryCache.h + + - (void)setObject:(id)object forKey:(NSString *)key block:(nullable PINMemoryCacheObjectBlock)block + + + object + An object to store in the cache. + + key + A key to associate with the object. This string will be copied. + + block + A block to be executed concurrently after the object has been stored, or nil. + + + + //api/name/setObject:forKey:block: + + + + + //apple_ref/occ/instm/PINMemoryCache/setObject:forKey:withCost:block: + Stores an object in the cache for the specified key and the specified cost. If the cost causes the total +to go over the costLimit the cache is trimmed (oldest objects first). This method returns immediately +and executes the passed block after the object has been stored, potentially in parallel with other blocks +on the concurrentQueue. + PINMemoryCache.h + + - (void)setObject:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost block:(nullable PINMemoryCacheObjectBlock)block + + + object + An object to store in the cache. + + key + A key to associate with the object. This string will be copied. + + cost + An amount to add to the totalCost. + + block + A block to be executed concurrently after the object has been stored, or nil. + + + + //api/name/setObject:forKey:withCost:block: + + + + + //apple_ref/occ/instm/PINMemoryCache/removeObjectForKey:block: + Removes the object for the specified key. This method returns immediately and executes the passed +block after the object has been removed, potentially in parallel with other blocks on the concurrentQueue. + PINMemoryCache.h + + - (void)removeObjectForKey:(NSString *)key block:(nullable PINMemoryCacheObjectBlock)block + + + key + The key associated with the object to be removed. + + block + A block to be executed concurrently after the object has been removed, or nil. + + + + //api/name/removeObjectForKey:block: + + + + + //apple_ref/occ/instm/PINMemoryCache/trimToDate:block: + Removes all objects from the cache that have not been used since the specified date. +This method returns immediately and executes the passed block after the cache has been trimmed, +potentially in parallel with other blocks on the concurrentQueue. + PINMemoryCache.h + + - (void)trimToDate:(NSDate *)date block:(nullable PINMemoryCacheBlock)block + + + date + Objects that haven't been accessed since this date are removed from the cache. + + block + A block to be executed concurrently after the cache has been trimmed, or nil. + + + + //api/name/trimToDate:block: + + + + + //apple_ref/occ/instm/PINMemoryCache/trimToCost:block: + Removes objects from the cache, costliest objects first, until the totalCost is below the specified +value. This method returns immediately and executes the passed block after the cache has been trimmed, +potentially in parallel with other blocks on the concurrentQueue. + PINMemoryCache.h + + - (void)trimToCost:(NSUInteger)cost block:(nullable PINMemoryCacheBlock)block + + + cost + The total accumulation allowed to remain after the cache has been trimmed. + + block + A block to be executed concurrently after the cache has been trimmed, or nil. + + + + //api/name/trimToCost:block: + + + + + //apple_ref/occ/instm/PINMemoryCache/trimToCostByDate:block: + Removes objects from the cache, ordered by date (least recently used first), until the totalCost is below +the specified value. This method returns immediately and executes the passed block after the cache has been +trimmed, potentially in parallel with other blocks on the concurrentQueue. + PINMemoryCache.h + + - (void)trimToCostByDate:(NSUInteger)cost block:(nullable PINMemoryCacheBlock)block + + + cost + The total accumulation allowed to remain after the cache has been trimmed. + + block + A block to be executed concurrently after the cache has been trimmed, or nil. + + + + //api/name/trimToCostByDate:block: + + + + + //apple_ref/occ/instm/PINMemoryCache/removeAllObjects: + Removes all objects from the cache. This method returns immediately and executes the passed block after +the cache has been cleared, potentially in parallel with other blocks on the concurrentQueue. + PINMemoryCache.h + + - (void)removeAllObjects:(nullable PINMemoryCacheBlock)block + + + block + A block to be executed concurrently after the cache has been cleared, or nil. + + + + //api/name/removeAllObjects: + + + + + //apple_ref/occ/instm/PINMemoryCache/enumerateObjectsWithBlock:completionBlock: + Loops through all objects in the cache with reads and writes suspended. Calling serial methods which +write to the cache inside block may be unsafe and may result in a deadlock. This method returns immediately. + PINMemoryCache.h + + - (void)enumerateObjectsWithBlock:(PINMemoryCacheObjectBlock)block completionBlock:(nullable PINMemoryCacheBlock)completionBlock + + + block + A block to be executed for every object in the cache. + + completionBlock + An optional block to be executed concurrently when the enumeration is complete. + + + + //api/name/enumerateObjectsWithBlock:completionBlock: + + + + + //apple_ref/occ/instm/PINMemoryCache/containsObjectForKey: + This method determines whether an object is present for the given key in the cache. + PINMemoryCache.h + + + //apple_ref/occ/instm/PINMemoryCache/containsObjectForKey:block: + + + + - (BOOL)containsObjectForKey:(NSString *)key + + + key + The key associated with the object. + + + YES if an object is present for the given key in the cache, otherwise NO. + //api/name/containsObjectForKey: + + + + + //apple_ref/occ/instm/PINMemoryCache/objectForKey: + Retrieves the object for the specified key. This method blocks the calling thread until the +object is available. + PINMemoryCache.h + + + //apple_ref/occ/instm/PINMemoryCache/objectForKey:block: + + + + - (__nullable id)objectForKey:(nullable NSString *)key + + + key + The key associated with the object. + + + The object for the specified key. + //api/name/objectForKey: + + + + + //apple_ref/occ/instm/PINMemoryCache/setObject:forKey: + Stores an object in the cache for the specified key. This method blocks the calling thread until the object +has been set. + PINMemoryCache.h + + + //apple_ref/occ/instm/PINMemoryCache/setObject:forKey:block: + + + + - (void)setObject:(id)object forKey:(NSString *)key + + + object + An object to store in the cache. + + key + A key to associate with the object. This string will be copied. + + + + //api/name/setObject:forKey: + + + + + //apple_ref/occ/instm/PINMemoryCache/setObject:forKey:withCost: + Stores an object in the cache for the specified key and the specified cost. If the cost causes the total +to go over the costLimit the cache is trimmed (oldest objects first). This method blocks the calling thread +until the object has been stored. + PINMemoryCache.h + + - (void)setObject:(nullable id)object forKey:(nullable NSString *)key withCost:(NSUInteger)cost + + + object + An object to store in the cache. + + key + A key to associate with the object. This string will be copied. + + cost + An amount to add to the totalCost. + + + + //api/name/setObject:forKey:withCost: + + + + + //apple_ref/occ/instm/PINMemoryCache/removeObjectForKey: + Removes the object for the specified key. This method blocks the calling thread until the object +has been removed. + PINMemoryCache.h + + - (void)removeObjectForKey:(nullable NSString *)key + + + key + The key associated with the object to be removed. + + + + //api/name/removeObjectForKey: + + + + + //apple_ref/occ/instm/PINMemoryCache/trimToDate: + Removes all objects from the cache that have not been used since the specified date. +This method blocks the calling thread until the cache has been trimmed. + PINMemoryCache.h + + - (void)trimToDate:(nullable NSDate *)date + + + date + Objects that haven't been accessed since this date are removed from the cache. + + + + //api/name/trimToDate: + + + + + //apple_ref/occ/instm/PINMemoryCache/trimToCost: + Removes objects from the cache, costliest objects first, until the totalCost is below the specified +value. This method blocks the calling thread until the cache has been trimmed. + PINMemoryCache.h + + - (void)trimToCost:(NSUInteger)cost + + + cost + The total accumulation allowed to remain after the cache has been trimmed. + + + + //api/name/trimToCost: + + + + + //apple_ref/occ/instm/PINMemoryCache/trimToCostByDate: + Removes objects from the cache, ordered by date (least recently used first), until the totalCost is below +the specified value. This method blocks the calling thread until the cache has been trimmed. + PINMemoryCache.h + + - (void)trimToCostByDate:(NSUInteger)cost + + + cost + The total accumulation allowed to remain after the cache has been trimmed. + + + + //api/name/trimToCostByDate: + + + + + //apple_ref/occ/instm/PINMemoryCache/removeAllObjects + Removes all objects from the cache. This method blocks the calling thread until the cache has been cleared. + PINMemoryCache.h + + - (void)removeAllObjects + + + //api/name/removeAllObjects + + + + + //apple_ref/occ/instm/PINMemoryCache/enumerateObjectsWithBlock: + Loops through all objects in the cache within a memory lock (reads and writes are suspended during the enumeration). +This method blocks the calling thread until all objects have been enumerated. +Calling synchronous methods on the cache within this callback will likely cause a deadlock. + PINMemoryCache.h + + - (void)enumerateObjectsWithBlock:(nullable PINMemoryCacheObjectBlock)block + + + block + A block to be executed for every object in the cache. + + + + //api/name/enumerateObjectsWithBlock: + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens4.xml b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens4.xml new file mode 100644 index 00000000..683a9b5f --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens4.xml @@ -0,0 +1,55 @@ + + + + + + //apple_ref/occ/intf/PINCacheObjectSubscripting + + PINCacheObjectSubscripting.h + + + + + + + + //apple_ref/occ/intfm/PINCacheObjectSubscripting/objectForKeyedSubscript: + This method enables using literals on the receiving object, such as id object = cache[@"key"];. + PINCacheObjectSubscripting.h + + - (id)objectForKeyedSubscript:(NSString *)key + + + key + The key associated with the object. + + + The object for the specified key. + //api/name/objectForKeyedSubscript: + + + + + //apple_ref/occ/intfm/PINCacheObjectSubscripting/setObject:forKeyedSubscript: + This method enables using literals on the receiving object, such as cache[@"key"] = object;. + PINCacheObjectSubscripting.h + + - (void)setObject:(id)obj forKeyedSubscript:(NSString *)key + + + key + A key to associate with the object. This string will be copied. + + object + An object to be assigned for the key. + + + + //api/name/setObject:forKeyedSubscript: + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens5.xml b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens5.xml new file mode 100644 index 00000000..3fc40bec --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens5.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens6.xml b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens6.xml new file mode 100644 index 00000000..3fc40bec --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens6.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens7.xml b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens7.xml new file mode 100644 index 00000000..3fc40bec --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens7.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens8.xml b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens8.xml new file mode 100644 index 00000000..3fc40bec --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens8.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens9.xml b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens9.xml new file mode 100644 index 00000000..3fc40bec --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/Tokens9.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/docSet.dsidx b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/docSet.dsidx new file mode 100644 index 00000000..282aaf19 Binary files /dev/null and b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/docSet.dsidx differ diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/docSet.dsidx-shm b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/docSet.dsidx-shm new file mode 100644 index 00000000..52dc6f38 Binary files /dev/null and b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/docSet.dsidx-shm differ diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/docSet.dsidx-wal b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/docSet.dsidx-wal new file mode 100644 index 00000000..03636aea Binary files /dev/null and b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/docSet.dsidx-wal differ diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/docSet.mom b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/docSet.mom new file mode 100644 index 00000000..0503cfdd Binary files /dev/null and b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/docSet.mom differ diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/docSet.skidx b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/docSet.skidx new file mode 100644 index 00000000..c8f5c3cd Binary files /dev/null and b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/docSet.skidx differ diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/docSet.toc b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/docSet.toc new file mode 100644 index 00000000..8d7f1ec2 Binary files /dev/null and b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/docSet.toc differ diff --git a/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/docSet.tokencache b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/docSet.tokencache new file mode 100644 index 00000000..038c4656 Binary files /dev/null and b/Carthage/Checkouts/PINCache/docs/com.pinterest.PINCache-2.0.docset/Contents/Resources/docSet.tokencache differ diff --git a/Carthage/Checkouts/PINCache/docs/html/Blocks/PINCacheBlock.html b/Carthage/Checkouts/PINCache/docs/html/Blocks/PINCacheBlock.html new file mode 100644 index 00000000..e4f1300a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/html/Blocks/PINCacheBlock.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/html/Blocks/PINCacheObjectBlock.html b/Carthage/Checkouts/PINCache/docs/html/Blocks/PINCacheObjectBlock.html new file mode 100644 index 00000000..e4f1300a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/html/Blocks/PINCacheObjectBlock.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/html/Blocks/PINDiskCacheBlock.html b/Carthage/Checkouts/PINCache/docs/html/Blocks/PINDiskCacheBlock.html new file mode 100644 index 00000000..e4f1300a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/html/Blocks/PINDiskCacheBlock.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/html/Blocks/PINDiskCacheFileURLBlock.html b/Carthage/Checkouts/PINCache/docs/html/Blocks/PINDiskCacheFileURLBlock.html new file mode 100644 index 00000000..e4f1300a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/html/Blocks/PINDiskCacheFileURLBlock.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/html/Blocks/PINDiskCacheObjectBlock.html b/Carthage/Checkouts/PINCache/docs/html/Blocks/PINDiskCacheObjectBlock.html new file mode 100644 index 00000000..e4f1300a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/html/Blocks/PINDiskCacheObjectBlock.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/html/Blocks/PINMemoryCacheBlock.html b/Carthage/Checkouts/PINCache/docs/html/Blocks/PINMemoryCacheBlock.html new file mode 100644 index 00000000..e4f1300a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/html/Blocks/PINMemoryCacheBlock.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/html/Blocks/PINMemoryCacheObjectBlock.html b/Carthage/Checkouts/PINCache/docs/html/Blocks/PINMemoryCacheObjectBlock.html new file mode 100644 index 00000000..e4f1300a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/html/Blocks/PINMemoryCacheObjectBlock.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/html/Classes/PINCache.html b/Carthage/Checkouts/PINCache/docs/html/Classes/PINCache.html new file mode 100644 index 00000000..e4f1300a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/html/Classes/PINCache.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/html/Classes/PINDiskCache.html b/Carthage/Checkouts/PINCache/docs/html/Classes/PINDiskCache.html new file mode 100644 index 00000000..e4f1300a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/html/Classes/PINDiskCache.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/html/Classes/PINMemoryCache.html b/Carthage/Checkouts/PINCache/docs/html/Classes/PINMemoryCache.html new file mode 100644 index 00000000..e4f1300a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/html/Classes/PINMemoryCache.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/html/Protocols/PINCacheObjectSubscripting.html b/Carthage/Checkouts/PINCache/docs/html/Protocols/PINCacheObjectSubscripting.html new file mode 100644 index 00000000..e4f1300a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/html/Protocols/PINCacheObjectSubscripting.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/html/css/scss/_index.scss b/Carthage/Checkouts/PINCache/docs/html/css/scss/_index.scss new file mode 100644 index 00000000..7e98029d --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/html/css/scss/_index.scss @@ -0,0 +1,13 @@ +.index-container { + display: flex; + flex-direction: row; + flex-wrap: wrap; + + @media (max-width: $mobile-max-width) { + flex-direction: column; + } + + .index-column { + flex: 1 1 33%; + } +} diff --git a/Carthage/Checkouts/PINCache/docs/html/css/scss/_layout.scss b/Carthage/Checkouts/PINCache/docs/html/css/scss/_layout.scss new file mode 100644 index 00000000..40bd6d4a --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/html/css/scss/_layout.scss @@ -0,0 +1,303 @@ +* { + box-sizing: border-box; +} + +.clear { + clear: both; +} + +.clearfix { + &:before, &:after { + clear: both; + display: table; + content: ""; + } +} + +.xcode .hide-in-xcode { + display: none; +} + +body { + font: 62.5% $body-font; + background: $body-background; +} + +h1, h2, h3 { + font-weight: 300; + color: #808080; +} + +h1 { + font-size: 2em; + color: #000; +} + +h4 { + font-size: 13px; + line-height: 1.5; + margin: 21px 0 0 0; +} + +a { + color: $tint-color; + text-decoration: none; +} + +pre, code { + font-family: $code-font; + word-wrap: break-word; +} + +pre > code, .method-declaration code { + display: inline-block; + font-size: .85em; + padding: 4px 0 4px 10px; + border-left: 5px solid rgba(0, 155, 51, .2); + + &:before { + content: "Objective-C"; + display: block; + + font: 9px/1 $body-font; + color: #009b33; + text-transform: uppercase; + letter-spacing: 2px; + padding-bottom: 6px; + } +} + +pre > code { + font-size: inherit; +} + +table, th, td { + border: 1px solid #e9e9e9; +} + +table { + width: 100%; +} + +th, td { + padding: 7px; + + > :first-child { + margin-top: 0; + } + + > :last-child { + margin-bottom: 0; + } +} + +.container { + @extend .clearfix; + + max-width: 980px; + padding: 0 10px; + margin: 0 auto; + + @media (max-width: $mobile-max-width) { + padding: 0; + } +} + +header { + position: fixed; + top: 0; + left: 0; + width: 100%; + z-index: 2; + + background: #414141; + color: #fff; + font-size: 1.1em; + line-height: 25px; + letter-spacing: .05em; + + #library-title { + float: left; + } + + #developer-home { + float: right; + } + + h1 { + font-size: inherit; + font-weight: inherit; + margin: 0; + } + + p { + margin: 0; + } + + h1, a { + color: inherit; + } + + @media (max-width: $mobile-max-width) { + position: absolute; + + .container { + padding: 0 10px; + } + } +} + +aside { + position: fixed; + top: 25px; + left: 0; + width: 100%; + height: 25px; + z-index: 2; + + font-size: 1.1em; + + @media (max-width: $mobile-max-width) { + position: absolute; + } + + #header-buttons { + background: rgba(255, 255, 255, .8); + margin: 0 1px; + padding: 0; + list-style: none; + text-align: right; + line-height: 32px; + + li { + display: inline-block; + cursor: pointer; + padding: 0 10px; + } + + label, select { + cursor: inherit; + } + + #on-this-page { + position: relative; + + .chevron { + display: inline-block; + width: 14px; + height: 4px; + position: relative; + + .chevy { + background: #878787; + height: 2px; + position: absolute; + width: 10px; + + &.chevron-left { + left: 0; + transform: rotateZ(45deg) scale(0.6); + } + + &.chevron-right { + right: 0; + transform: rotateZ(-45deg) scale(0.6); + } + } + } + + #jump-to { + opacity: 0; + font-size: 16px; + + position: absolute; + top: 5px; + left: 0; + width: 100%; + height: 100%; + } + } + } +} + +article { + margin-top: 25px; + + #content { + @extend .clearfix; + + background: $content-background; + border: 1px solid $content-border; + padding: 15px 25px 30px 25px; + + font-size: 1.4em; + line-height: 1.45; + + position: relative; + + @media (max-width: $mobile-max-width) { + padding: 15px 10px 20px 10px; + } + + .navigation-top { + position: absolute; + top: 15px; + right: 25px; + } + + .title { + margin: 21px 0 0 0; + padding: 15px 0; + } + + p { + color: #414141; + margin: 0 0 15px 0; + } + + th, td { + p:last-child { + margin-bottom: 0; + } + } + + main { + ul { + list-style: none; + margin-left: 24px; + margin-bottom: 12px; + padding: 0; + + li { + position: relative; + padding-left: 1.3em; + + &:before { + content: "\02022"; + + color: #414141; + font-size: 1.08em; + line-height: 1; + + position: absolute; + left: 0; + padding-top: 2px; + } + } + } + } + + footer { + @extend .clearfix; + + .footer-copyright { + margin: 70px 25px 10px 0; + } + + p { + font-size: .71em; + color: #a0a0a0; + } + } + } +} diff --git a/Carthage/Checkouts/PINCache/docs/html/css/scss/_normalize.scss b/Carthage/Checkouts/PINCache/docs/html/css/scss/_normalize.scss new file mode 100644 index 00000000..9b8848a5 --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/html/css/scss/_normalize.scss @@ -0,0 +1,581 @@ +/* ========================================================================== + Normalize.scss settings + ========================================================================== */ +/** + * Includes legacy browser support IE6/7 + * + * Set to false if you want to drop support for IE6 and IE7 + */ + +$legacy_browser_support: false !default; + +/* Base + ========================================================================== */ + +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + * 3. Corrects text resizing oddly in IE 6/7 when body `font-size` is set using + * `em` units. + */ + +html { + font-family: sans-serif; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ + @if $legacy_browser_support { + *font-size: 100%; /* 3 */ + } +} + +/** + * Remove default margin. + */ + +body { + margin: 0; +} + +/* HTML5 display definitions + ========================================================================== */ + +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} + +/** + * 1. Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ + +audio, +canvas, +progress, +video { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ + @if $legacy_browser_support { + *display: inline; + *zoom: 1; + } +} + +/** + * Prevents modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ + +[hidden], +template { + display: none; +} + +/* Links + ========================================================================== */ + +/** + * Remove the gray background color from active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ + +a { + &:active, &:hover { + outline: 0; + }; +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +@if $legacy_browser_support { + blockquote { + margin: 1em 40px; + } +} + +/** + * Address styling not present in Safari and Chrome. + */ + +dfn { + font-style: italic; +} + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +@if $legacy_browser_support { + h2 { + font-size: 1.5em; + margin: 0.83em 0; + } + + h3 { + font-size: 1.17em; + margin: 1em 0; + } + + h4 { + font-size: 1em; + margin: 1.33em 0; + } + + h5 { + font-size: 0.83em; + margin: 1.67em 0; + } + + h6 { + font-size: 0.67em; + margin: 2.33em 0; + } +} + +/** + * Addresses styling not present in IE 8/9. + */ + +mark { + background: #ff0; + color: #000; +} + +@if $legacy_browser_support { + + /** + * Addresses margins set differently in IE 6/7. + */ + + p, + pre { + *margin: 1em 0; + } + + /* + * Addresses CSS quotes not supported in IE 6/7. + */ + + q { + *quotes: none; + } + + /* + * Addresses `quotes` property not supported in Safari 4. + */ + + q:before, + q:after { + content: ''; + content: none; + } +} + +/** + * Address inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +@if $legacy_browser_support { + + /* ========================================================================== + Lists + ========================================================================== */ + + /* + * Addresses margins set differently in IE 6/7. + */ + + dl, + menu, + ol, + ul { + *margin: 1em 0; + } + + dd { + *margin: 0 0 0 40px; + } + + /* + * Addresses paddings set differently in IE 6/7. + */ + + menu, + ol, + ul { + *padding: 0 0 0 40px; + } + + /* + * Corrects list images handled incorrectly in IE 7. + */ + + nav ul, + nav ol { + *list-style: none; + *list-style-image: none; + } + +} + +/* Embedded content + ========================================================================== */ + +/** + * 1. Remove border when inside `a` element in IE 8/9/10. + * 2. Improves image quality when scaled in IE 7. + */ + +img { + border: 0; + @if $legacy_browser_support { + *-ms-interpolation-mode: bicubic; /* 2 */ + } +} + +/** + * Correct overflow not hidden in IE 9/10/11. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Grouping content + ========================================================================== */ + +/** + * Address margin not present in IE 8/9 and Safari. + */ + +figure { + margin: 1em 40px; +} + +/** + * Address differences between Firefox and other browsers. + */ + +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +/** + * Contain overflow in all browsers. + */ + +pre { + overflow: auto; +} + +/** + * Address odd `em`-unit font size rendering in all browsers. + * Correct font family set oddly in IE 6, Safari 4/5, and Chrome. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + @if $legacy_browser_support { + _font-family: 'courier new', monospace; + } + font-size: 1em; +} + +/* Forms + ========================================================================== */ + +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ + +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + * 4. Improves appearance and consistency in all browsers. + */ + +button, +input, +optgroup, +select, +textarea { + color: inherit; /* 1 */ + font: inherit; /* 2 */ + margin: 0; /* 3 */ + @if $legacy_browser_support { + vertical-align: baseline; /* 3 */ + *vertical-align: middle; /* 3 */ + } +} + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ + +button { + overflow: visible; +} + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ + +button, +select { + text-transform: none; +} + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + * 4. Removes inner spacing in IE 7 without affecting normal text inputs. + * Known issue: inner spacing remains in IE 6. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ + @if $legacy_browser_support { + *overflow: visible; /* 4 */ + } +} + +/** + * Re-set default cursor for disabled elements. + */ + +button[disabled], +html input[disabled] { + cursor: default; +} + +/** + * Remove inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +input { + line-height: normal; +} + +/** + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + * Known issue: excess padding remains in IE 6. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ + @if $legacy_browser_support { + *height: 13px; /* 3 */ + *width: 13px; /* 3 */ + } +} + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ + +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; /* 2 */ + box-sizing: content-box; +} + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + * 3. Corrects text not wrapping in Firefox 3. + * 4. Corrects alignment displayed oddly in IE 6/7. + */ + +legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ + @if $legacy_browser_support { + white-space: normal; /* 3 */ + *margin-left: -7px; /* 4 */ + } +} + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ + +textarea { + overflow: auto; +} + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ + +optgroup { + font-weight: bold; +} + +/* Tables + ========================================================================== */ + +/** + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} + +td, +th { + padding: 0; +} diff --git a/Carthage/Checkouts/PINCache/docs/html/css/scss/_object.scss b/Carthage/Checkouts/PINCache/docs/html/css/scss/_object.scss new file mode 100644 index 00000000..22eebd87 --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/html/css/scss/_object.scss @@ -0,0 +1,89 @@ +.section-specification { + table { + width: auto; + + th { + text-align: left; + } + } +} + +.method-title { + margin-left: -15px; + margin-bottom: 8px; + transition: margin-left .3s ease-out; + + .section-method.hide & { + margin-left: 0; + } + + code { + font-weight: 400; + font-size: .85em; + } +} + +.method-info { + background: $object-background; + border-bottom: 1px solid $object-border; + margin: 0 -25px; + padding: 20px 25px 0 25px; + transition: height .3s ease-out; + + position: relative; + + .pointy-thing { + background: $content-background; + height: 10px; + border-bottom: 1px solid $object-border; + margin: -20px -25px 16px -25px; + + &:before { + display: inline-block; + content: ""; + + background: $object-background; + border: 1px solid $object-border; + border-bottom: 0; + border-right: 0; + + position: absolute; + left: 21px; + top: 3px; + width: 12px; + height: 12px; + transform: rotate(45deg); + } + } + + .method-subsection { + margin-bottom: 15px; + + .argument-name { + width: 1px; + text-align: right; + + code { + color: #808080; + font-style: italic; + font-weight: 400; + } + } + } +} + +.section-method { + &.hide .method-info { + height: 0 !important; + overflow: hidden; + display: none; + } + + &.hide.animating .method-info { + display: block; + } + + &.animating .method-info { + overflow: hidden; + } +} diff --git a/Carthage/Checkouts/PINCache/docs/html/css/scss/_print.scss b/Carthage/Checkouts/PINCache/docs/html/css/scss/_print.scss new file mode 100644 index 00000000..61bdf99f --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/html/css/scss/_print.scss @@ -0,0 +1,42 @@ +@media print { + body { + background: #fff; + padding: 8px; + } + + header { + position: static; + background: #fff; + color: #000; + } + + aside { + display: none; + } + + .container { + max-width: none; + padding: 0; + } + + article { + margin-top: 0; + + #content { + border: 0; + background: #fff; + padding: 15px 0 0 0; + + .title { + margin-top: 0; + padding-top: 0; + } + } + } + + .method-info { + &, & .pointy-thing { + background: #fff; + } + } +} diff --git a/Carthage/Checkouts/PINCache/docs/html/css/scss/_variables.scss b/Carthage/Checkouts/PINCache/docs/html/css/scss/_variables.scss new file mode 100644 index 00000000..cbaff3cf --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/html/css/scss/_variables.scss @@ -0,0 +1,11 @@ +$body-font: -apple-system-font, "Helvetica Neue", Helvetica, sans-serif; +$code-font: "Source Code Pro", Monaco, Menlo, Consolas, monospace; + +$body-background: #f2f2f2; +$content-background: #fff; +$content-border: #e9e9e9; +$tint-color: #08c; +$object-background: #f9f9f9; +$object-border: #e9e9e9; + +$mobile-max-width: 650px; diff --git a/Carthage/Checkouts/PINCache/docs/html/css/scss/_xcode.scss b/Carthage/Checkouts/PINCache/docs/html/css/scss/_xcode.scss new file mode 100644 index 00000000..340b1f6b --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/html/css/scss/_xcode.scss @@ -0,0 +1,29 @@ +.xcode { + header, aside { + display: none; + } + + .container { + padding: 0; + } + + article { + margin-top: 0; + + #content { + border: 0; + margin: 0; + } + } + + .method-info { + &, .section-method.hide & { + max-height: auto; + overflow: visible; + + &.hiding { + display: block; + } + } + } +} diff --git a/Carthage/Checkouts/PINCache/docs/html/css/scss/style.scss b/Carthage/Checkouts/PINCache/docs/html/css/scss/style.scss new file mode 100644 index 00000000..648a6086 --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/html/css/scss/style.scss @@ -0,0 +1 @@ +@import "variables", "normalize", "layout", "index", "object", "print", "xcode"; diff --git a/Carthage/Checkouts/PINCache/docs/html/hierarchy.html b/Carthage/Checkouts/PINCache/docs/html/hierarchy.html new file mode 100644 index 00000000..0b83af71 --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/html/hierarchy.html @@ -0,0 +1,96 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/html/img/button_bar_background.png b/Carthage/Checkouts/PINCache/docs/html/img/button_bar_background.png new file mode 100644 index 00000000..71d1019b Binary files /dev/null and b/Carthage/Checkouts/PINCache/docs/html/img/button_bar_background.png differ diff --git a/Carthage/Checkouts/PINCache/docs/html/img/disclosure.png b/Carthage/Checkouts/PINCache/docs/html/img/disclosure.png new file mode 100644 index 00000000..4c5cbf44 Binary files /dev/null and b/Carthage/Checkouts/PINCache/docs/html/img/disclosure.png differ diff --git a/Carthage/Checkouts/PINCache/docs/html/img/disclosure_open.png b/Carthage/Checkouts/PINCache/docs/html/img/disclosure_open.png new file mode 100644 index 00000000..82396fed Binary files /dev/null and b/Carthage/Checkouts/PINCache/docs/html/img/disclosure_open.png differ diff --git a/Carthage/Checkouts/PINCache/docs/html/img/library_background.png b/Carthage/Checkouts/PINCache/docs/html/img/library_background.png new file mode 100644 index 00000000..3006248a Binary files /dev/null and b/Carthage/Checkouts/PINCache/docs/html/img/library_background.png differ diff --git a/Carthage/Checkouts/PINCache/docs/html/img/title_background.png b/Carthage/Checkouts/PINCache/docs/html/img/title_background.png new file mode 100644 index 00000000..846e4968 Binary files /dev/null and b/Carthage/Checkouts/PINCache/docs/html/img/title_background.png differ diff --git a/Carthage/Checkouts/PINCache/docs/html/index.html b/Carthage/Checkouts/PINCache/docs/html/index.html new file mode 100644 index 00000000..a6e5fa92 --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/html/index.html @@ -0,0 +1,96 @@ + + + + + + + + + + + + +
+
+ +

+ PINCache +

+ +

+ Pinterest +

+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINCache/docs/html/js/script.js b/Carthage/Checkouts/PINCache/docs/html/js/script.js new file mode 100644 index 00000000..ca915ee4 --- /dev/null +++ b/Carthage/Checkouts/PINCache/docs/html/js/script.js @@ -0,0 +1,58 @@ +function $() { + return document.querySelector.apply(document, arguments); +} + +if (navigator.userAgent.indexOf("Xcode") != -1) { + document.documentElement.classList.add("xcode"); +} + +var jumpTo = $("#jump-to"); + +if (jumpTo) { + jumpTo.addEventListener("change", function(e) { + location.hash = this.options[this.selectedIndex].value; + }); +} + +function hashChanged() { + if (/^#\/\/api\//.test(location.hash)) { + var element = document.querySelector("a[name='" + location.hash.substring(1) + "']"); + + if (!element) { + return; + } + + element = element.parentNode; + + element.classList.remove("hide"); + fixScrollPosition(element); + } +} + +function fixScrollPosition(element) { + var scrollTop = element.offsetTop - 150; + document.documentElement.scrollTop = scrollTop; + document.body.scrollTop = scrollTop; +} + +[].forEach.call(document.querySelectorAll(".section-method"), function(element) { + element.classList.add("hide"); + + element.querySelector(".method-title a").addEventListener("click", function(e) { + var info = element.querySelector(".method-info"), + infoContainer = element.querySelector(".method-info-container"); + + element.classList.add("animating"); + info.style.height = (infoContainer.clientHeight + 40) + "px"; + fixScrollPosition(element); + element.classList.toggle("hide"); + + setTimeout(function() { + element.classList.remove("animating"); + info.style.height = "auto"; + }, 300); + }); +}); + +window.addEventListener("hashchange", hashChanged); +hashChanged(); diff --git a/Carthage/Checkouts/PINOperation/.github/workflows/ci.yml b/Carthage/Checkouts/PINOperation/.github/workflows/ci.yml new file mode 100644 index 00000000..053ed706 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/.github/workflows/ci.yml @@ -0,0 +1,54 @@ +--- +name: CI + +on: + push: + branches: + - master + - 'releases/*' + pull_request: + branches: + - master + +env: + # Use Xcode 15.2 or newer to support VisionOS + DEVELOPER_DIR: /Applications/Xcode_15.2.app + +jobs: + test: + name: Test + runs-on: macos-latest + strategy: + matrix: + platform: ['iOS Simulator,name=iPhone 15'] + steps: + - uses: actions/checkout@v2 + - name: Test + run: make test + analyze: + name: Analyze + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - name: analyze + run: make analyze + cocoapods: + name: CocoaPods + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - name: Cocoapods lint + run: make cocoapods + carthage: + name: Carthage + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - name: carthage + run: make carthage + swift-package-manager: + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - name: Verify that PINOperation can be built by SPM + run: make spm diff --git a/Carthage/Checkouts/PINOperation/.github/workflows/publish_release.yml b/Carthage/Checkouts/PINOperation/.github/workflows/publish_release.yml new file mode 100644 index 00000000..c4262e64 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/.github/workflows/publish_release.yml @@ -0,0 +1,44 @@ +name: Create Release +on: + workflow_dispatch: + inputs: + release-type: + description: 'The type of release. Must be major, minor or patch' + required: true + +env: + # Use Xcode 15.2 or newer to support VisionOS + DEVELOPER_DIR: /Applications/Xcode_15.2.app + +jobs: + create_release: + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + # Make sure we can lint before creating the release. + - name: Cocoapods lint + run: make cocoapods + - name: Create Release Commit + env: + GITHUB_CHANGELOG_API_KEY: ${{ secrets.GITHUB_TOKEN }} + OSS_PROJECT: PINOperation + run: | + gem install github_changelog_generator + Scripts/release.sh --${{ github.event.inputs.release-type }} + git push origin HEAD + - name: Tag Release + run: Scripts/tag-release-branch.sh + - name: Publish Release + uses: actions/create-release@v1 + env: + GITHUB_CHANGELOG_API_KEY: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ env.RELEASE_TAG }} + release_name: ${{ env.RELEASE_TAG }} + body_path: RELEASE_NOTES.md + draft: false + - name: Push to Cocoapods + env: + COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} + run: pod trunk push diff --git a/Carthage/Checkouts/PINOperation/.github/workflows/push_release_branch.yml b/Carthage/Checkouts/PINOperation/.github/workflows/push_release_branch.yml new file mode 100644 index 00000000..47a81bc7 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/.github/workflows/push_release_branch.yml @@ -0,0 +1,38 @@ +name: Create Release +on: + workflow_dispatch: + inputs: + release-type: + description: 'The type of release. Must be major, minor or patch' + required: true +jobs: + create_release: + runs-on: macOS-latest + steps: + - uses: actions/checkout@v2 + # Make sure we can lint before creating the release. + - name: Cocoapods lint + run: make cocoapods + - name: Create Release Branch + env: + GITHUB_CHANGELOG_API_KEY: ${{ secrets.GITHUB_TOKEN }} + run: | + gem install github_changelog_generator + Scripts/release.sh --${{ github.event.inputs.release-type }} + git push origin HEAD + - name: Tag Release + run: Scripts/tag-release-branch.sh + - name: Publish Release + uses: actions/create-release@v1 + env: + GITHUB_CHANGELOG_API_KEY: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ env.RELEASE_TAG }} + release_name: ${{ env.RELEASE_TAG }} + body_path: RELEASE_NOTES.md + draft: false + - name: Push to Cocoapods + env: + COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} + run: pod trunk push diff --git a/Carthage/Checkouts/PINOperation/.github_changelog_generator b/Carthage/Checkouts/PINOperation/.github_changelog_generator new file mode 100644 index 00000000..3bd27222 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/.github_changelog_generator @@ -0,0 +1,3 @@ +issues=false +since-tag=1.2.1 +future-release=1.2.2 diff --git a/Carthage/Checkouts/PINOperation/.gitignore b/Carthage/Checkouts/PINOperation/.gitignore new file mode 100644 index 00000000..4021767b --- /dev/null +++ b/Carthage/Checkouts/PINOperation/.gitignore @@ -0,0 +1,57 @@ +.DS_Store + +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData/ + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ + +## Other +*.moved-aside +*.xcuserstate + +## Obj-C/Swift specific +*.hmap +*.ipa +*.dSYM.zip +*.dSYM + +## Docs +docs/docsets/ + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +.build/ + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# Bundler +.bundle +vendor + +# Example project +Example/Pods diff --git a/Carthage/Checkouts/PINOperation/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/PINOperation/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Carthage/Checkouts/PINOperation/BUCK b/Carthage/Checkouts/PINOperation/BUCK new file mode 100755 index 00000000..c7ade9d1 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/BUCK @@ -0,0 +1,22 @@ +apple_library( + name = 'PINOperation', + modular = True, + exported_headers = glob(['Source/*.h']), + srcs = + glob(['Source/*.m']), + preprocessor_flags = ['-fobjc-arc'], + lang_preprocessor_flags = { + 'C': ['-std=gnu99'], + 'CXX': ['-std=gnu++11', '-stdlib=libc++'], + }, + linker_flags = [ + '-weak_framework', + 'UIKit', + '-weak_framework', + 'AppKit', + ], + frameworks = [ + '$SDKROOT/System/Library/Frameworks/Foundation.framework', + ], + visibility = ['PUBLIC'], +) diff --git a/Carthage/Checkouts/PINOperation/CHANGELOG.md b/Carthage/Checkouts/PINOperation/CHANGELOG.md new file mode 100644 index 00000000..f11e9740 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/CHANGELOG.md @@ -0,0 +1,64 @@ +# Changelog + +## [1.2.3](https://github.com/Pinterest/PINOperation/tree/1.2.3) (TBD) + +[Full Changelog](https://github.com/Pinterest/PINOperation/compare/1.2.2...1.2.3) + + +- Update project to build and run using Xcode 15 +- Update CocoaPods Podspec to include Privacy Manifest file +- Bump minimum deployment targets to iOS 12, tvOS 12, watchOS 4, and macOS 10.13 + +## [1.2.2](https://github.com/Pinterest/PINOperation/tree/1.2.2) (2022-11-28) + +[Full Changelog](https://github.com/Pinterest/PINOperation/compare/1.2.1...1.2.2) + + +- Update CI to modern xcode and fix Carthage [\#47](https://github.com/pinterest/PINOperation/pull/47) ([garrettmoon](https://github.com/garrettmoon)) +- Disable asserts in release builds when using Swift Package Manager [\#44](https://github.com/pinterest/PINOperation/pull/44) ([rcancro](https://github.com/rcancro)) +- Carthage is busted on Xcode 12 [\#41](https://github.com/pinterest/PINOperation/pull/41) ([garrettmoon](https://github.com/garrettmoon)) +- Latest release script [\#40](https://github.com/pinterest/PINOperation/pull/40) ([garrettmoon](https://github.com/garrettmoon)) +- Fixes for automated release process [\#39](https://github.com/pinterest/PINOperation/pull/39) ([garrettmoon](https://github.com/garrettmoon)) + +## [1.2.1](https://github.com/Pinterest/PINOperation/tree/1.2.1) (2020-10-22) + +[Full Changelog](https://github.com/Pinterest/PINOperation/compare/1.2...1.2.1) + + +- Add release script [\#38](https://github.com/pinterest/PINOperation/pull/38) ([garrettmoon](https://github.com/garrettmoon)) +- Only use @import for SPM [\#36](https://github.com/pinterest/PINOperation/pull/36) ([garrettmoon](https://github.com/garrettmoon)) +- Add SPM Test [\#35](https://github.com/pinterest/PINOperation/pull/35) ([garrettmoon](https://github.com/garrettmoon)) +- Remove BUCK target [\#34](https://github.com/pinterest/PINOperation/pull/34) ([adlerj](https://github.com/adlerj)) + +## [1.2](https://github.com/Pinterest/PINOperation/tree/1.2) (2020-06-30) + +[Full Changelog](https://github.com/Pinterest/PINOperation/compare/1.1.2...1.2) + +**Merged pull requests:** + +- Swift Package Manager support [\#32](https://github.com/pinterest/PINOperation/pull/32) ([martinpucik](https://github.com/martinpucik)) +- Add Carthage for watchOS, dependent by PINCache [\#31](https://github.com/pinterest/PINOperation/pull/31) ([dreampiggy](https://github.com/dreampiggy)) +- Fix analyzing [\#30](https://github.com/pinterest/PINOperation/pull/30) ([garrettmoon](https://github.com/garrettmoon)) +- Standardize our GitHub Actions CI workflow [\#29](https://github.com/pinterest/PINOperation/pull/29) ([jparise](https://github.com/jparise)) +- Github CI [\#26](https://github.com/pinterest/PINOperation/pull/26) ([rahul-malik](https://github.com/rahul-malik)) +- Fixes coalesce operation race condition [\#24](https://github.com/pinterest/PINOperation/pull/24) ([zhongwuzw](https://github.com/zhongwuzw)) + +## [1.1.2](https://github.com/Pinterest/PINOperation/tree/1.1.2) (2019-06-11) + +[Full Changelog](https://github.com/Pinterest/PINOperation/compare/1.1.1...1.1.2) + +**Merged pull requests:** + +- Modernizing project [\#21](https://github.com/pinterest/PINOperation/pull/21) ([garrettmoon](https://github.com/garrettmoon)) +- Updates BUCK build file to match source layout. [\#20](https://github.com/pinterest/PINOperation/pull/20) ([RCacheaux](https://github.com/RCacheaux)) +- 1.1.1 release [\#19](https://github.com/pinterest/PINOperation/pull/19) ([garrettmoon](https://github.com/garrettmoon)) + +## 1.1.1 -- 2018 February 3 +* Cleanup warnings [garrett](https://github.com/garrettmoon) + +## 1.1 -- 2017 October 7 +* Deprecate addOperation: in favor of scheduleOperation: [garrett](https://github.com/garrettmoon) + +## 1.0.0 -- 2017 January 10 + +- Initial release! diff --git a/Carthage/Checkouts/PINOperation/CI/build.sh b/Carthage/Checkouts/PINOperation/CI/build.sh new file mode 100755 index 00000000..bbdb8f94 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/CI/build.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -eo pipefail + +make all \ No newline at end of file diff --git a/Carthage/Checkouts/PINOperation/CI/exclude-from-build.json b/Carthage/Checkouts/PINOperation/CI/exclude-from-build.json new file mode 100644 index 00000000..03853aa7 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/CI/exclude-from-build.json @@ -0,0 +1,7 @@ +[ + "^plans/", + "^docs/", + "^CI/exclude-from-build.json$", + "^README.md$", + "^CHANGELOG.md$" +] \ No newline at end of file diff --git a/Carthage/Checkouts/PINOperation/CODE_OF_CONDUCT.md b/Carthage/Checkouts/PINOperation/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..8b4e45e2 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/CODE_OF_CONDUCT.md @@ -0,0 +1,40 @@ +# Code of Conduct + +At Pinterest, we work hard to ensure that our work environment is welcoming +and inclusive to as many people as possible. We are committed to creating this +environment for everyone involved in our open source projects as well. We +welcome all participants regardless of ability, age, ethnicity, identified +gender, religion (or lack there of), sexual orientation and socioeconomic +status. + +This code of conduct details our expectations for upholding these values. + +## Good behavior + +We expect members of our community to exhibit good behavior including (but of +course not limited to): + +- Using intentional and empathetic language. +- Focusing on resolving instead of escalating conflict. +- Providing constructive feedback. + +## Unacceptable behavior + +Some examples of unacceptable behavior (again, this is not an exhaustive +list): + +- Harassment, publicly or in private. +- Trolling. +- Sexual advances (this isn’t the place for it). +- Publishing other’s personal information. +- Any behavior which would be deemed unacceptable in a professional environment. + +## Recourse + +If you are witness to or the target of unacceptable behavior, it should be +reported to Pinterest at opensource-policy@pinterest.com. All reporters will +be kept confidential and an appropriate response for each incident will be +evaluated. + +If the maintainers do not uphold and enforce this code of conduct in +good faith, community leadership will hold them accountable. \ No newline at end of file diff --git a/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcodeproj/project.pbxproj b/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcodeproj/project.pbxproj new file mode 100644 index 00000000..01324ee2 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcodeproj/project.pbxproj @@ -0,0 +1,352 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 60; + objects = { + +/* Begin PBXBuildFile section */ + 1387274F245D5BB500C1F56D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1387274E245D5BB500C1F56D /* AppDelegate.swift */; }; + 13872758245D5BB800C1F56D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13872757245D5BB800C1F56D /* Assets.xcassets */; }; + 1387275B245D5BB800C1F56D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 13872759245D5BB800C1F56D /* LaunchScreen.storyboard */; }; + 13872765245D5D8200C1F56D /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 13872764245D5D8200C1F56D /* MainViewController.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1387274B245D5BB500C1F56D /* PINOperationExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PINOperationExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 1387274E245D5BB500C1F56D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 13872757245D5BB800C1F56D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1387275A245D5BB800C1F56D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 1387275C245D5BB800C1F56D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 13872762245D5D8200C1F56D /* PINOperationExample-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PINOperationExample-Bridging-Header.h"; sourceTree = ""; }; + 13872763245D5D8200C1F56D /* MainViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MainViewController.h; sourceTree = ""; }; + 13872764245D5D8200C1F56D /* MainViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MainViewController.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 13872748245D5BB500C1F56D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 110EBBE34DCD59092AC3306C /* Pods */ = { + isa = PBXGroup; + children = ( + ); + path = Pods; + sourceTree = ""; + }; + 13872742245D5BB500C1F56D = { + isa = PBXGroup; + children = ( + 1387274D245D5BB500C1F56D /* PINOperationExample */, + 1387274C245D5BB500C1F56D /* Products */, + 110EBBE34DCD59092AC3306C /* Pods */, + ); + sourceTree = ""; + }; + 1387274C245D5BB500C1F56D /* Products */ = { + isa = PBXGroup; + children = ( + 1387274B245D5BB500C1F56D /* PINOperationExample.app */, + ); + name = Products; + sourceTree = ""; + }; + 1387274D245D5BB500C1F56D /* PINOperationExample */ = { + isa = PBXGroup; + children = ( + 1387274E245D5BB500C1F56D /* AppDelegate.swift */, + 13872763245D5D8200C1F56D /* MainViewController.h */, + 13872764245D5D8200C1F56D /* MainViewController.m */, + 13872757245D5BB800C1F56D /* Assets.xcassets */, + 13872759245D5BB800C1F56D /* LaunchScreen.storyboard */, + 1387275C245D5BB800C1F56D /* Info.plist */, + 13872762245D5D8200C1F56D /* PINOperationExample-Bridging-Header.h */, + ); + path = PINOperationExample; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1387274A245D5BB500C1F56D /* PINOperationExample */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1387275F245D5BB800C1F56D /* Build configuration list for PBXNativeTarget "PINOperationExample" */; + buildPhases = ( + 13872747245D5BB500C1F56D /* Sources */, + 13872748245D5BB500C1F56D /* Frameworks */, + 13872749245D5BB500C1F56D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PINOperationExample; + productName = PINOperationExample; + productReference = 1387274B245D5BB500C1F56D /* PINOperationExample.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 13872743245D5BB500C1F56D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 1140; + LastUpgradeCheck = 1520; + ORGANIZATIONNAME = Pinterest; + TargetAttributes = { + 1387274A245D5BB500C1F56D = { + CreatedOnToolsVersion = 11.4.1; + LastSwiftMigration = 1140; + }; + }; + }; + buildConfigurationList = 13872746245D5BB500C1F56D /* Build configuration list for PBXProject "PINOperationExample" */; + compatibilityVersion = "Xcode 15.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 13872742245D5BB500C1F56D; + productRefGroup = 1387274C245D5BB500C1F56D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 1387274A245D5BB500C1F56D /* PINOperationExample */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 13872749245D5BB500C1F56D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1387275B245D5BB800C1F56D /* LaunchScreen.storyboard in Resources */, + 13872758245D5BB800C1F56D /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 13872747245D5BB500C1F56D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1387274F245D5BB500C1F56D /* AppDelegate.swift in Sources */, + 13872765245D5D8200C1F56D /* MainViewController.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 13872759245D5BB800C1F56D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 1387275A245D5BB800C1F56D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1387275D245D5BB800C1F56D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 1387275E245D5BB800C1F56D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 13872760245D5BB800C1F56D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = PINOperationExample/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperationExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "PINOperationExample/PINOperationExample-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 13872761245D5BB800C1F56D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = PINOperationExample/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperationExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "PINOperationExample/PINOperationExample-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 13872746245D5BB500C1F56D /* Build configuration list for PBXProject "PINOperationExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1387275D245D5BB800C1F56D /* Debug */, + 1387275E245D5BB800C1F56D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1387275F245D5BB800C1F56D /* Build configuration list for PBXNativeTarget "PINOperationExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 13872760245D5BB800C1F56D /* Debug */, + 13872761245D5BB800C1F56D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 13872743245D5BB500C1F56D /* Project object */; +} diff --git a/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..b6d9930d --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..4cdc4885 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Example/PINOperationExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Carthage/Checkouts/PINOperation/Example/PINOperationExample/AppDelegate.swift b/Carthage/Checkouts/PINOperation/Example/PINOperationExample/AppDelegate.swift new file mode 100644 index 00000000..7aa52db8 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Example/PINOperationExample/AppDelegate.swift @@ -0,0 +1,31 @@ +// +// AppDelegate.swift +// PINOperationExample +// +// Created by Martin Púčik on 02/05/2020. +// Copyright © 2020 Pinterest. All rights reserved. +// + +import UIKit + +@UIApplicationMain +final class AppDelegate: UIResponder, UIApplicationDelegate { + private let queue: PINOperationQueue = PINOperationQueue(maxConcurrentOperations: 5) + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + let operationCount = 100 + let group = DispatchGroup() + for _ in 0.. + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINOperation/Example/PINOperationExample/Info.plist b/Carthage/Checkouts/PINOperation/Example/PINOperationExample/Info.plist new file mode 100644 index 00000000..75404a26 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Example/PINOperationExample/Info.plist @@ -0,0 +1,41 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Carthage/Checkouts/PINOperation/Example/PINOperationExample/MainViewController.h b/Carthage/Checkouts/PINOperation/Example/PINOperationExample/MainViewController.h new file mode 100644 index 00000000..df2e69c3 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Example/PINOperationExample/MainViewController.h @@ -0,0 +1,17 @@ +// +// MainViewController.h +// PINOperationExample +// +// Created by Martin Púčik on 02/05/2020. +// Copyright © 2020 Pinterest. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface MainViewController : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/PINOperation/Example/PINOperationExample/MainViewController.m b/Carthage/Checkouts/PINOperation/Example/PINOperationExample/MainViewController.m new file mode 100644 index 00000000..50d0c95d --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Example/PINOperationExample/MainViewController.m @@ -0,0 +1,41 @@ +// +// MainViewController.m +// PINOperationExample +// +// Created by Martin Púčik on 02/05/2020. +// Copyright © 2020 Pinterest. All rights reserved. +// + +#import "MainViewController.h" +#import +//#import + +@interface MainViewController () +@property (nonatomic, strong) PINOperationQueue *queue; +@end + +@implementation MainViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + self.queue = [[PINOperationQueue alloc] initWithMaxConcurrentOperations:5]; + + const NSUInteger operationCount = 100; + dispatch_group_t group = dispatch_group_create(); + + for (NSUInteger count = 0; count < operationCount; count++) { + dispatch_group_enter(group); + [self.queue scheduleOperation:^{ + dispatch_group_leave(group); + } withPriority:PINOperationQueuePriorityDefault]; + } + + NSUInteger success = dispatch_group_wait(group, [self timeout]); + NSAssert(success == 0, @"Timed out before completing 100 operations"); +} + +- (dispatch_time_t)timeout { + return dispatch_time(DISPATCH_TIME_NOW, (int64_t)(20 * NSEC_PER_SEC)); +} + +@end diff --git a/Carthage/Checkouts/PINOperation/Example/PINOperationExample/PINOperationExample-Bridging-Header.h b/Carthage/Checkouts/PINOperation/Example/PINOperationExample/PINOperationExample-Bridging-Header.h new file mode 100644 index 00000000..f3b5f384 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Example/PINOperationExample/PINOperationExample-Bridging-Header.h @@ -0,0 +1 @@ +#import diff --git a/Carthage/Checkouts/PINOperation/Example/Podfile b/Carthage/Checkouts/PINOperation/Example/Podfile new file mode 100644 index 00000000..62ba7b9b --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Example/Podfile @@ -0,0 +1,6 @@ +source 'https://cdn.cocoapods.org/' +platform :ios, '12.0' + +target 'PINOperationExample' do + pod 'PINOperation', :path => '../' +end diff --git a/Carthage/Checkouts/PINOperation/Example/Podfile.lock b/Carthage/Checkouts/PINOperation/Example/Podfile.lock new file mode 100644 index 00000000..cbbd5f30 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Example/Podfile.lock @@ -0,0 +1,16 @@ +PODS: + - PINOperation (1.2.3) + +DEPENDENCIES: + - PINOperation (from `../`) + +EXTERNAL SOURCES: + PINOperation: + :path: "../" + +SPEC CHECKSUMS: + PINOperation: fb563bcc9c32c26d6c78aaff967d405aa2ee74a7 + +PODFILE CHECKSUM: 590bbecb30df161f3cdb5ab267c95244b0df928f + +COCOAPODS: 1.15.2 diff --git a/Carthage/Checkouts/PINOperation/LICENSE.txt b/Carthage/Checkouts/PINOperation/LICENSE.txt new file mode 100644 index 00000000..d0381d6d --- /dev/null +++ b/Carthage/Checkouts/PINOperation/LICENSE.txt @@ -0,0 +1,176 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/Carthage/Checkouts/PINOperation/PINOperation.podspec b/Carthage/Checkouts/PINOperation/PINOperation.podspec new file mode 100644 index 00000000..18d75d46 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/PINOperation.podspec @@ -0,0 +1,25 @@ +Pod::Spec.new do |s| + s.name = 'PINOperation' + s.version = '1.2.3' + s.homepage = 'https://github.com/pinterest/PINOperation' + s.summary = 'Fast, concurrency-limited task queue for iOS and OS X.' + s.authors = { 'Garrett Moon' => 'garrett@pinterest.com' } + s.source = { :git => 'https://github.com/pinterest/PINOperation.git', :tag => "#{s.version}" } + s.license = { :type => 'Apache 2.0', :file => 'LICENSE.txt' } + s.requires_arc = true + s.frameworks = 'Foundation' + s.cocoapods_version = '>= 1.13.0' + s.ios.deployment_target = '12.0' + s.osx.deployment_target = '10.13' + s.tvos.deployment_target = '12.0' + s.visionos.deployment_target = '1.0' + s.watchos.deployment_target = '4.0' + pch_PIN = <<-EOS +#ifndef TARGET_OS_WATCH + #define TARGET_OS_WATCH 0 +#endif +EOS + s.prefix_header_contents = pch_PIN + s.source_files = 'Source/*.{h,m}' + s.resource_bundles = { 'PINOperation' => ['Source/PrivacyInfo.xcprivacy'] } +end diff --git a/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/project.pbxproj b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/project.pbxproj new file mode 100644 index 00000000..6e8f8563 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/project.pbxproj @@ -0,0 +1,1462 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 60; + objects = { + +/* Begin PBXBuildFile section */ + 3201179424444862004FD783 /* PINOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105801E2711B700890935 /* PINOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3201179524444862004FD783 /* PINOperationGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105811E2711B700890935 /* PINOperationGroup.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3201179624444862004FD783 /* PINOperationMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105831E2711B700890935 /* PINOperationMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3201179724444862004FD783 /* PINOperationQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105841E2711B700890935 /* PINOperationQueue.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3201179824444862004FD783 /* PINOperationTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105861E2711B700890935 /* PINOperationTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3201179924444862004FD783 /* PINOperationGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0105821E2711B700890935 /* PINOperationGroup.m */; }; + 3201179A24444862004FD783 /* PINOperationQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0105851E2711B700890935 /* PINOperationQueue.m */; }; + 68133AEC2BE056A5007627EC /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 68133AEB2BE056A5007627EC /* PrivacyInfo.xcprivacy */; }; + 6817A6442BE46E48007710C1 /* PINOperationGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0105821E2711B700890935 /* PINOperationGroup.m */; }; + 6817A6452BE46E48007710C1 /* PINOperationQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0105851E2711B700890935 /* PINOperationQueue.m */; }; + 6817A6482BE46E48007710C1 /* PINOperationTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105861E2711B700890935 /* PINOperationTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6817A6492BE46E48007710C1 /* PINOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105801E2711B700890935 /* PINOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6817A64A2BE46E48007710C1 /* PINOperationGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105811E2711B700890935 /* PINOperationGroup.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6817A64B2BE46E48007710C1 /* PINOperationMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105831E2711B700890935 /* PINOperationMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6817A64C2BE46E48007710C1 /* PINOperationQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105841E2711B700890935 /* PINOperationQueue.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6817A64E2BE46E48007710C1 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 68133AEB2BE056A5007627EC /* PrivacyInfo.xcprivacy */; }; + 6850F2E62BE471CB00A38144 /* PINOperationQueueTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01059D1E27131B00890935 /* PINOperationQueueTests.m */; }; + 6850F2E72BE471CB00A38144 /* PINOperationGroupTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01059E1E27131B00890935 /* PINOperationGroupTests.m */; }; + 686ECECD2BE4731900634D9F /* PINOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6817A6522BE46E48007710C1 /* PINOperation.framework */; }; + 686ECED62BE474F300634D9F /* PINOperationQueueTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01059D1E27131B00890935 /* PINOperationQueueTests.m */; }; + 686ECED72BE474F300634D9F /* PINOperationGroupTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01059E1E27131B00890935 /* PINOperationGroupTests.m */; }; + 68B3C3072BE475FF00C335B8 /* PINOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3201178C24444859004FD783 /* PINOperation.framework */; }; + 68CEDB9F2BE0E1DF0045CBE7 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 68133AEB2BE056A5007627EC /* PrivacyInfo.xcprivacy */; }; + 68CEDBA02BE0E1E00045CBE7 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 68133AEB2BE056A5007627EC /* PrivacyInfo.xcprivacy */; }; + 68CEDBA12BE0E1E10045CBE7 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 68133AEB2BE056A5007627EC /* PrivacyInfo.xcprivacy */; }; + CC01055B1E27116600890935 /* PINOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC01052D1E27110D00890935 /* PINOperation.framework */; }; + CC01056A1E27117300890935 /* PINOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC01053D1E27113700890935 /* PINOperation.framework */; }; + CC0105791E27117F00890935 /* PINOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC01054A1E27114300890935 /* PINOperation.framework */; }; + CC0105871E2711B700890935 /* PINOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105801E2711B700890935 /* PINOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0105881E2711B700890935 /* PINOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105801E2711B700890935 /* PINOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0105891E2711B700890935 /* PINOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105801E2711B700890935 /* PINOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC01058A1E2711B700890935 /* PINOperationGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105811E2711B700890935 /* PINOperationGroup.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC01058B1E2711B700890935 /* PINOperationGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105811E2711B700890935 /* PINOperationGroup.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC01058C1E2711B700890935 /* PINOperationGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105811E2711B700890935 /* PINOperationGroup.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC01058D1E2711B700890935 /* PINOperationGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0105821E2711B700890935 /* PINOperationGroup.m */; }; + CC01058E1E2711B700890935 /* PINOperationGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0105821E2711B700890935 /* PINOperationGroup.m */; }; + CC01058F1E2711B700890935 /* PINOperationGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0105821E2711B700890935 /* PINOperationGroup.m */; }; + CC0105901E2711B700890935 /* PINOperationMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105831E2711B700890935 /* PINOperationMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0105911E2711B700890935 /* PINOperationMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105831E2711B700890935 /* PINOperationMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0105921E2711B700890935 /* PINOperationMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105831E2711B700890935 /* PINOperationMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0105931E2711B700890935 /* PINOperationQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105841E2711B700890935 /* PINOperationQueue.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0105941E2711B700890935 /* PINOperationQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105841E2711B700890935 /* PINOperationQueue.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0105951E2711B700890935 /* PINOperationQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105841E2711B700890935 /* PINOperationQueue.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0105961E2711B700890935 /* PINOperationQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0105851E2711B700890935 /* PINOperationQueue.m */; }; + CC0105971E2711B700890935 /* PINOperationQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0105851E2711B700890935 /* PINOperationQueue.m */; }; + CC0105981E2711B700890935 /* PINOperationQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0105851E2711B700890935 /* PINOperationQueue.m */; }; + CC0105991E2711B700890935 /* PINOperationTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105861E2711B700890935 /* PINOperationTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC01059A1E2711B700890935 /* PINOperationTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105861E2711B700890935 /* PINOperationTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC01059B1E2711B700890935 /* PINOperationTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0105861E2711B700890935 /* PINOperationTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0105A01E27131B00890935 /* PINOperationQueueTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01059D1E27131B00890935 /* PINOperationQueueTests.m */; }; + CC0105A11E27131B00890935 /* PINOperationQueueTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01059D1E27131B00890935 /* PINOperationQueueTests.m */; }; + CC0105A21E27131B00890935 /* PINOperationQueueTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01059D1E27131B00890935 /* PINOperationQueueTests.m */; }; + CC0105A41E27131B00890935 /* PINOperationGroupTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01059E1E27131B00890935 /* PINOperationGroupTests.m */; }; + CC0105A51E27131B00890935 /* PINOperationGroupTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01059E1E27131B00890935 /* PINOperationGroupTests.m */; }; + CC0105A61E27131B00890935 /* PINOperationGroupTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC01059E1E27131B00890935 /* PINOperationGroupTests.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 686ECECF2BE4731900634D9F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = CC0105241E27110D00890935 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6817A6422BE46E48007710C1; + remoteInfo = "PINOperation-visionOS"; + }; + 68B3C3092BE475FF00C335B8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = CC0105241E27110D00890935 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 3201178B24444859004FD783; + remoteInfo = "PINOperation-watchOS"; + }; + CC01055C1E27116600890935 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = CC0105241E27110D00890935 /* Project object */; + proxyType = 1; + remoteGlobalIDString = CC01052C1E27110D00890935; + remoteInfo = PINOperation; + }; + CC01056B1E27117300890935 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = CC0105241E27110D00890935 /* Project object */; + proxyType = 1; + remoteGlobalIDString = CC01053C1E27113700890935; + remoteInfo = "PINOperation-tvOS"; + }; + CC01057A1E27117F00890935 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = CC0105241E27110D00890935 /* Project object */; + proxyType = 1; + remoteGlobalIDString = CC0105491E27114300890935; + remoteInfo = "PINOperation-macOS"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 3201178C24444859004FD783 /* PINOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PINOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 68133AEB2BE056A5007627EC /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 6817A6522BE46E48007710C1 /* PINOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PINOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 6850F2EE2BE471CB00A38144 /* PINOperation-visionOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "PINOperation-visionOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 686ECEDE2BE474F300634D9F /* PINOperation-watchOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "PINOperation-watchOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + CC01052D1E27110D00890935 /* PINOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PINOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + CC01053D1E27113700890935 /* PINOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PINOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + CC01054A1E27114300890935 /* PINOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PINOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + CC0105561E27116600890935 /* PINOperationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PINOperationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + CC01055A1E27116600890935 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = ../Tests/Info.plist; sourceTree = ""; }; + CC0105651E27117300890935 /* PINOperation-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "PINOperation-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + CC0105741E27117F00890935 /* PINOperation-macOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "PINOperation-macOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + CC0105801E2711B700890935 /* PINOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINOperation.h; sourceTree = ""; }; + CC0105811E2711B700890935 /* PINOperationGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINOperationGroup.h; sourceTree = ""; }; + CC0105821E2711B700890935 /* PINOperationGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINOperationGroup.m; sourceTree = ""; }; + CC0105831E2711B700890935 /* PINOperationMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINOperationMacros.h; sourceTree = ""; }; + CC0105841E2711B700890935 /* PINOperationQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINOperationQueue.h; sourceTree = ""; }; + CC0105851E2711B700890935 /* PINOperationQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINOperationQueue.m; sourceTree = ""; }; + CC0105861E2711B700890935 /* PINOperationTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINOperationTypes.h; sourceTree = ""; }; + CC01059C1E27129E00890935 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + CC01059D1E27131B00890935 /* PINOperationQueueTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINOperationQueueTests.m; sourceTree = ""; }; + CC01059E1E27131B00890935 /* PINOperationGroupTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINOperationGroupTests.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 3201178924444859004FD783 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6817A6462BE46E48007710C1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6850F2E82BE471CB00A38144 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 686ECECD2BE4731900634D9F /* PINOperation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 686ECED82BE474F300634D9F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 68B3C3072BE475FF00C335B8 /* PINOperation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105291E27110D00890935 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105391E27113700890935 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105461E27114300890935 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105531E27116600890935 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CC01055B1E27116600890935 /* PINOperation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105621E27117300890935 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CC01056A1E27117300890935 /* PINOperation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105711E27117F00890935 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CC0105791E27117F00890935 /* PINOperation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 6850F2F02BE4724000A38144 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; + CC0105231E27110D00890935 = { + isa = PBXGroup; + children = ( + CC01057F1E2711B700890935 /* Source */, + CC0105571E27116600890935 /* Tests */, + CC01052E1E27110D00890935 /* Products */, + 6850F2F02BE4724000A38144 /* Frameworks */, + ); + indentWidth = 2; + sourceTree = ""; + tabWidth = 2; + usesTabs = 0; + }; + CC01052E1E27110D00890935 /* Products */ = { + isa = PBXGroup; + children = ( + CC01052D1E27110D00890935 /* PINOperation.framework */, + CC01053D1E27113700890935 /* PINOperation.framework */, + CC01054A1E27114300890935 /* PINOperation.framework */, + CC0105561E27116600890935 /* PINOperationTests.xctest */, + CC0105651E27117300890935 /* PINOperation-tvOSTests.xctest */, + CC0105741E27117F00890935 /* PINOperation-macOSTests.xctest */, + 3201178C24444859004FD783 /* PINOperation.framework */, + 6817A6522BE46E48007710C1 /* PINOperation.framework */, + 6850F2EE2BE471CB00A38144 /* PINOperation-visionOSTests.xctest */, + 686ECEDE2BE474F300634D9F /* PINOperation-watchOSTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + CC0105571E27116600890935 /* Tests */ = { + isa = PBXGroup; + children = ( + CC01059D1E27131B00890935 /* PINOperationQueueTests.m */, + CC01059E1E27131B00890935 /* PINOperationGroupTests.m */, + CC01055A1E27116600890935 /* Info.plist */, + ); + path = Tests; + sourceTree = ""; + }; + CC01057F1E2711B700890935 /* Source */ = { + isa = PBXGroup; + children = ( + CC0105801E2711B700890935 /* PINOperation.h */, + CC0105811E2711B700890935 /* PINOperationGroup.h */, + CC0105831E2711B700890935 /* PINOperationMacros.h */, + CC0105841E2711B700890935 /* PINOperationQueue.h */, + CC0105861E2711B700890935 /* PINOperationTypes.h */, + CC0105821E2711B700890935 /* PINOperationGroup.m */, + CC0105851E2711B700890935 /* PINOperationQueue.m */, + CC01059C1E27129E00890935 /* Info.plist */, + 68133AEB2BE056A5007627EC /* PrivacyInfo.xcprivacy */, + ); + path = Source; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 3201178724444859004FD783 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 3201179824444862004FD783 /* PINOperationTypes.h in Headers */, + 3201179524444862004FD783 /* PINOperationGroup.h in Headers */, + 3201179424444862004FD783 /* PINOperation.h in Headers */, + 3201179724444862004FD783 /* PINOperationQueue.h in Headers */, + 3201179624444862004FD783 /* PINOperationMacros.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6817A6472BE46E48007710C1 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 6817A6482BE46E48007710C1 /* PINOperationTypes.h in Headers */, + 6817A6492BE46E48007710C1 /* PINOperation.h in Headers */, + 6817A64A2BE46E48007710C1 /* PINOperationGroup.h in Headers */, + 6817A64B2BE46E48007710C1 /* PINOperationMacros.h in Headers */, + 6817A64C2BE46E48007710C1 /* PINOperationQueue.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC01052A1E27110D00890935 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + CC0105991E2711B700890935 /* PINOperationTypes.h in Headers */, + CC0105871E2711B700890935 /* PINOperation.h in Headers */, + CC01058A1E2711B700890935 /* PINOperationGroup.h in Headers */, + CC0105901E2711B700890935 /* PINOperationMacros.h in Headers */, + CC0105931E2711B700890935 /* PINOperationQueue.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC01053A1E27113700890935 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + CC01059A1E2711B700890935 /* PINOperationTypes.h in Headers */, + CC0105881E2711B700890935 /* PINOperation.h in Headers */, + CC01058B1E2711B700890935 /* PINOperationGroup.h in Headers */, + CC0105911E2711B700890935 /* PINOperationMacros.h in Headers */, + CC0105941E2711B700890935 /* PINOperationQueue.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105471E27114300890935 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + CC01059B1E2711B700890935 /* PINOperationTypes.h in Headers */, + CC0105891E2711B700890935 /* PINOperation.h in Headers */, + CC01058C1E2711B700890935 /* PINOperationGroup.h in Headers */, + CC0105921E2711B700890935 /* PINOperationMacros.h in Headers */, + CC0105951E2711B700890935 /* PINOperationQueue.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 3201178B24444859004FD783 /* PINOperation-watchOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3201179324444859004FD783 /* Build configuration list for PBXNativeTarget "PINOperation-watchOS" */; + buildPhases = ( + 3201178824444859004FD783 /* Sources */, + 3201178924444859004FD783 /* Frameworks */, + 3201178724444859004FD783 /* Headers */, + 3201178A24444859004FD783 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "PINOperation-watchOS"; + productName = "PINOperation-watchOS"; + productReference = 3201178C24444859004FD783 /* PINOperation.framework */; + productType = "com.apple.product-type.framework"; + }; + 6817A6422BE46E48007710C1 /* PINOperation-visionOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6817A64F2BE46E48007710C1 /* Build configuration list for PBXNativeTarget "PINOperation-visionOS" */; + buildPhases = ( + 6817A6432BE46E48007710C1 /* Sources */, + 6817A6462BE46E48007710C1 /* Frameworks */, + 6817A6472BE46E48007710C1 /* Headers */, + 6817A64D2BE46E48007710C1 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "PINOperation-visionOS"; + productName = PINOperation; + productReference = 6817A6522BE46E48007710C1 /* PINOperation.framework */; + productType = "com.apple.product-type.framework"; + }; + 6850F2E22BE471CB00A38144 /* PINOperation-visionOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6850F2EB2BE471CB00A38144 /* Build configuration list for PBXNativeTarget "PINOperation-visionOSTests" */; + buildPhases = ( + 6850F2E52BE471CB00A38144 /* Sources */, + 6850F2E82BE471CB00A38144 /* Frameworks */, + 6850F2EA2BE471CB00A38144 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 686ECED02BE4731900634D9F /* PBXTargetDependency */, + ); + name = "PINOperation-visionOSTests"; + productName = PINOperationTests; + productReference = 6850F2EE2BE471CB00A38144 /* PINOperation-visionOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 686ECED22BE474F300634D9F /* PINOperation-watchOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 686ECEDB2BE474F300634D9F /* Build configuration list for PBXNativeTarget "PINOperation-watchOSTests" */; + buildPhases = ( + 686ECED52BE474F300634D9F /* Sources */, + 686ECED82BE474F300634D9F /* Frameworks */, + 686ECEDA2BE474F300634D9F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 68B3C30A2BE475FF00C335B8 /* PBXTargetDependency */, + ); + name = "PINOperation-watchOSTests"; + productName = PINOperationTests; + productReference = 686ECEDE2BE474F300634D9F /* PINOperation-watchOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + CC01052C1E27110D00890935 /* PINOperation */ = { + isa = PBXNativeTarget; + buildConfigurationList = CC0105351E27110D00890935 /* Build configuration list for PBXNativeTarget "PINOperation" */; + buildPhases = ( + CC0105281E27110D00890935 /* Sources */, + CC0105291E27110D00890935 /* Frameworks */, + CC01052A1E27110D00890935 /* Headers */, + CC01052B1E27110D00890935 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PINOperation; + productName = PINOperation; + productReference = CC01052D1E27110D00890935 /* PINOperation.framework */; + productType = "com.apple.product-type.framework"; + }; + CC01053C1E27113700890935 /* PINOperation-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = CC0105421E27113700890935 /* Build configuration list for PBXNativeTarget "PINOperation-tvOS" */; + buildPhases = ( + CC0105381E27113700890935 /* Sources */, + CC0105391E27113700890935 /* Frameworks */, + CC01053A1E27113700890935 /* Headers */, + CC01053B1E27113700890935 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "PINOperation-tvOS"; + productName = "PINOperation-tvOS"; + productReference = CC01053D1E27113700890935 /* PINOperation.framework */; + productType = "com.apple.product-type.framework"; + }; + CC0105491E27114300890935 /* PINOperation-macOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = CC01054F1E27114300890935 /* Build configuration list for PBXNativeTarget "PINOperation-macOS" */; + buildPhases = ( + CC0105451E27114300890935 /* Sources */, + CC0105461E27114300890935 /* Frameworks */, + CC0105471E27114300890935 /* Headers */, + CC0105481E27114300890935 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "PINOperation-macOS"; + productName = "PINOperation-macOS"; + productReference = CC01054A1E27114300890935 /* PINOperation.framework */; + productType = "com.apple.product-type.framework"; + }; + CC0105551E27116600890935 /* PINOperationTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = CC01055E1E27116600890935 /* Build configuration list for PBXNativeTarget "PINOperationTests" */; + buildPhases = ( + CC0105521E27116600890935 /* Sources */, + CC0105531E27116600890935 /* Frameworks */, + CC0105541E27116600890935 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + CC01055D1E27116600890935 /* PBXTargetDependency */, + ); + name = PINOperationTests; + productName = PINOperationTests; + productReference = CC0105561E27116600890935 /* PINOperationTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + CC0105641E27117300890935 /* PINOperation-tvOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = CC01056D1E27117300890935 /* Build configuration list for PBXNativeTarget "PINOperation-tvOSTests" */; + buildPhases = ( + CC0105611E27117300890935 /* Sources */, + CC0105621E27117300890935 /* Frameworks */, + CC0105631E27117300890935 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + CC01056C1E27117300890935 /* PBXTargetDependency */, + ); + name = "PINOperation-tvOSTests"; + productName = "PINOperation-tvOSTests"; + productReference = CC0105651E27117300890935 /* PINOperation-tvOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + CC0105731E27117F00890935 /* PINOperation-macOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = CC01057C1E27117F00890935 /* Build configuration list for PBXNativeTarget "PINOperation-macOSTests" */; + buildPhases = ( + CC0105701E27117F00890935 /* Sources */, + CC0105711E27117F00890935 /* Frameworks */, + CC0105721E27117F00890935 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + CC01057B1E27117F00890935 /* PBXTargetDependency */, + ); + name = "PINOperation-macOSTests"; + productName = "PINOperation-macOSTests"; + productReference = CC0105741E27117F00890935 /* PINOperation-macOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + CC0105241E27110D00890935 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 1520; + LastUpgradeCheck = 1520; + ORGANIZATIONNAME = Pinterest; + TargetAttributes = { + 3201178B24444859004FD783 = { + CreatedOnToolsVersion = 11.4; + ProvisioningStyle = Automatic; + }; + CC01052C1E27110D00890935 = { + CreatedOnToolsVersion = 7.3.1; + }; + CC01053C1E27113700890935 = { + CreatedOnToolsVersion = 7.3.1; + }; + CC0105491E27114300890935 = { + CreatedOnToolsVersion = 7.3.1; + }; + CC0105551E27116600890935 = { + CreatedOnToolsVersion = 7.3.1; + }; + CC0105641E27117300890935 = { + CreatedOnToolsVersion = 7.3.1; + }; + CC0105731E27117F00890935 = { + CreatedOnToolsVersion = 7.3.1; + }; + }; + }; + buildConfigurationList = CC0105271E27110D00890935 /* Build configuration list for PBXProject "PINOperation" */; + compatibilityVersion = "Xcode 15.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + Base, + en, + ); + mainGroup = CC0105231E27110D00890935; + productRefGroup = CC01052E1E27110D00890935 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + CC01052C1E27110D00890935 /* PINOperation */, + CC0105551E27116600890935 /* PINOperationTests */, + CC01053C1E27113700890935 /* PINOperation-tvOS */, + CC0105641E27117300890935 /* PINOperation-tvOSTests */, + CC0105491E27114300890935 /* PINOperation-macOS */, + CC0105731E27117F00890935 /* PINOperation-macOSTests */, + 3201178B24444859004FD783 /* PINOperation-watchOS */, + 686ECED22BE474F300634D9F /* PINOperation-watchOSTests */, + 6817A6422BE46E48007710C1 /* PINOperation-visionOS */, + 6850F2E22BE471CB00A38144 /* PINOperation-visionOSTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 3201178A24444859004FD783 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 68CEDBA12BE0E1E10045CBE7 /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6817A64D2BE46E48007710C1 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6817A64E2BE46E48007710C1 /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6850F2EA2BE471CB00A38144 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 686ECEDA2BE474F300634D9F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC01052B1E27110D00890935 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 68133AEC2BE056A5007627EC /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC01053B1E27113700890935 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 68CEDB9F2BE0E1DF0045CBE7 /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105481E27114300890935 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 68CEDBA02BE0E1E00045CBE7 /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105541E27116600890935 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105631E27117300890935 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105721E27117F00890935 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 3201178824444859004FD783 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3201179924444862004FD783 /* PINOperationGroup.m in Sources */, + 3201179A24444862004FD783 /* PINOperationQueue.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6817A6432BE46E48007710C1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6817A6442BE46E48007710C1 /* PINOperationGroup.m in Sources */, + 6817A6452BE46E48007710C1 /* PINOperationQueue.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6850F2E52BE471CB00A38144 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6850F2E62BE471CB00A38144 /* PINOperationQueueTests.m in Sources */, + 6850F2E72BE471CB00A38144 /* PINOperationGroupTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 686ECED52BE474F300634D9F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 686ECED62BE474F300634D9F /* PINOperationQueueTests.m in Sources */, + 686ECED72BE474F300634D9F /* PINOperationGroupTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105281E27110D00890935 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CC01058D1E2711B700890935 /* PINOperationGroup.m in Sources */, + CC0105961E2711B700890935 /* PINOperationQueue.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105381E27113700890935 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CC01058E1E2711B700890935 /* PINOperationGroup.m in Sources */, + CC0105971E2711B700890935 /* PINOperationQueue.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105451E27114300890935 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CC01058F1E2711B700890935 /* PINOperationGroup.m in Sources */, + CC0105981E2711B700890935 /* PINOperationQueue.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105521E27116600890935 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CC0105A01E27131B00890935 /* PINOperationQueueTests.m in Sources */, + CC0105A41E27131B00890935 /* PINOperationGroupTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105611E27117300890935 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CC0105A11E27131B00890935 /* PINOperationQueueTests.m in Sources */, + CC0105A51E27131B00890935 /* PINOperationGroupTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0105701E27117F00890935 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CC0105A21E27131B00890935 /* PINOperationQueueTests.m in Sources */, + CC0105A61E27131B00890935 /* PINOperationGroupTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 686ECED02BE4731900634D9F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 6817A6422BE46E48007710C1 /* PINOperation-visionOS */; + targetProxy = 686ECECF2BE4731900634D9F /* PBXContainerItemProxy */; + }; + 68B3C30A2BE475FF00C335B8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 3201178B24444859004FD783 /* PINOperation-watchOS */; + targetProxy = 68B3C3092BE475FF00C335B8 /* PBXContainerItemProxy */; + }; + CC01055D1E27116600890935 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = CC01052C1E27110D00890935 /* PINOperation */; + targetProxy = CC01055C1E27116600890935 /* PBXContainerItemProxy */; + }; + CC01056C1E27117300890935 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = CC01053C1E27113700890935 /* PINOperation-tvOS */; + targetProxy = CC01056B1E27117300890935 /* PBXContainerItemProxy */; + }; + CC01057B1E27117F00890935 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = CC0105491E27114300890935 /* PINOperation-macOS */; + targetProxy = CC01057A1E27117F00890935 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 3201179124444859004FD783 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperation; + PRODUCT_NAME = PINOperation; + SDKROOT = watchos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 4; + }; + name = Debug; + }; + 3201179224444859004FD783 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperation; + PRODUCT_NAME = PINOperation; + SDKROOT = watchos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 4; + }; + name = Release; + }; + 6817A6502BE46E48007710C1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperation; + PRODUCT_NAME = PINOperation; + RESOURCES_TARGETED_DEVICE_FAMILY = ""; + SDKROOT = xros; + SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + TARGETED_DEVICE_FAMILY = 7; + }; + name = Debug; + }; + 6817A6512BE46E48007710C1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperation; + PRODUCT_NAME = PINOperation; + RESOURCES_TARGETED_DEVICE_FAMILY = ""; + SDKROOT = xros; + SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + TARGETED_DEVICE_FAMILY = 7; + }; + name = Release; + }; + 6850F2EC2BE471CB00A38144 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperationTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = xros; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + TARGETED_DEVICE_FAMILY = 7; + }; + name = Debug; + }; + 6850F2ED2BE471CB00A38144 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperationTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = xros; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + TARGETED_DEVICE_FAMILY = 7; + }; + name = Release; + }; + 686ECEDC2BE474F300634D9F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperationTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + TARGETED_DEVICE_FAMILY = 4; + }; + name = Debug; + }; + 686ECEDD2BE474F300634D9F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperationTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + TARGETED_DEVICE_FAMILY = 4; + }; + name = Release; + }; + CC0105331E27110D00890935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 12.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 4.0; + XROS_DEPLOYMENT_TARGET = 1.0; + }; + name = Debug; + }; + CC0105341E27110D00890935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 4.0; + XROS_DEPLOYMENT_TARGET = 1.0; + }; + name = Release; + }; + CC0105361E27110D00890935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperation; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = YES; + }; + name = Debug; + }; + CC0105371E27110D00890935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperation; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = YES; + }; + name = Release; + }; + CC0105431E27113700890935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperation; + PRODUCT_NAME = PINOperation; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + CC0105441E27113700890935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperation; + PRODUCT_NAME = PINOperation; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + CC0105501E27114300890935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperation; + PRODUCT_NAME = PINOperation; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + CC0105511E27114300890935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperation; + PRODUCT_NAME = PINOperation; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Release; + }; + CC01055F1E27116600890935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperationTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + CC0105601E27116600890935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINOperationTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + CC01056E1E27117300890935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.pinterest.PINOperation-tvOSTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + CC01056F1E27117300890935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.pinterest.PINOperation-tvOSTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + CC01057D1E27117F00890935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.pinterest.PINOperation-macOSTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + CC01057E1E27117F00890935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; + INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.pinterest.PINOperation-macOSTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 3201179324444859004FD783 /* Build configuration list for PBXNativeTarget "PINOperation-watchOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3201179124444859004FD783 /* Debug */, + 3201179224444859004FD783 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6817A64F2BE46E48007710C1 /* Build configuration list for PBXNativeTarget "PINOperation-visionOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6817A6502BE46E48007710C1 /* Debug */, + 6817A6512BE46E48007710C1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6850F2EB2BE471CB00A38144 /* Build configuration list for PBXNativeTarget "PINOperation-visionOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6850F2EC2BE471CB00A38144 /* Debug */, + 6850F2ED2BE471CB00A38144 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 686ECEDB2BE474F300634D9F /* Build configuration list for PBXNativeTarget "PINOperation-watchOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 686ECEDC2BE474F300634D9F /* Debug */, + 686ECEDD2BE474F300634D9F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CC0105271E27110D00890935 /* Build configuration list for PBXProject "PINOperation" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CC0105331E27110D00890935 /* Debug */, + CC0105341E27110D00890935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CC0105351E27110D00890935 /* Build configuration list for PBXNativeTarget "PINOperation" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CC0105361E27110D00890935 /* Debug */, + CC0105371E27110D00890935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CC0105421E27113700890935 /* Build configuration list for PBXNativeTarget "PINOperation-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CC0105431E27113700890935 /* Debug */, + CC0105441E27113700890935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CC01054F1E27114300890935 /* Build configuration list for PBXNativeTarget "PINOperation-macOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CC0105501E27114300890935 /* Debug */, + CC0105511E27114300890935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CC01055E1E27116600890935 /* Build configuration list for PBXNativeTarget "PINOperationTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CC01055F1E27116600890935 /* Debug */, + CC0105601E27116600890935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CC01056D1E27117300890935 /* Build configuration list for PBXNativeTarget "PINOperation-tvOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CC01056E1E27117300890935 /* Debug */, + CC01056F1E27117300890935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CC01057C1E27117F00890935 /* Build configuration list for PBXNativeTarget "PINOperation-macOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CC01057D1E27117F00890935 /* Debug */, + CC01057E1E27117F00890935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = CC0105241E27110D00890935 /* Project object */; +} diff --git a/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..645415a1 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-macOS.xcscheme b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-macOS.xcscheme new file mode 100644 index 00000000..020b8ba3 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-macOS.xcscheme @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-macOSTests.xcscheme b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-macOSTests.xcscheme new file mode 100644 index 00000000..12133d33 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-macOSTests.xcscheme @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-tvOS.xcscheme b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-tvOS.xcscheme new file mode 100644 index 00000000..d4c1804c --- /dev/null +++ b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-tvOS.xcscheme @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-tvOSTests.xcscheme b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-tvOSTests.xcscheme new file mode 100644 index 00000000..95d71307 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-tvOSTests.xcscheme @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-visionOS.xcscheme b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-visionOS.xcscheme new file mode 100644 index 00000000..1fb9fbe6 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-visionOS.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-visionOSTests.xcscheme b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-visionOSTests.xcscheme new file mode 100644 index 00000000..152666b7 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-visionOSTests.xcscheme @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-watchOS.xcscheme b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-watchOS.xcscheme new file mode 100644 index 00000000..1d2f7431 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-watchOS.xcscheme @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-watchOSTests.xcscheme b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-watchOSTests.xcscheme new file mode 100644 index 00000000..d24b717e --- /dev/null +++ b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation-watchOSTests.xcscheme @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation.xcscheme b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation.xcscheme new file mode 100644 index 00000000..9767c050 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperation.xcscheme @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperationTests.xcscheme b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperationTests.xcscheme new file mode 100644 index 00000000..49d28ec8 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/PINOperation.xcodeproj/xcshareddata/xcschemes/PINOperationTests.xcscheme @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/PINOperation/Package.swift b/Carthage/Checkouts/PINOperation/Package.swift new file mode 100644 index 00000000..2be5b4e0 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Package.swift @@ -0,0 +1,34 @@ +// swift-tools-version:5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "PINOperation", + products: [ + // Products define the executables and libraries produced by a package, and make them visible to other packages. + .library( + name: "PINOperation", + targets: ["PINOperation"]), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages which this package depends on. + .target( + name: "PINOperation", + path: "Source", + exclude: ["Info.plist"], + resources: [.process("PrivacyInfo.xcprivacy")], + // Path to public header symlinks (allows for angle bracket imports) + publicHeadersPath: "include", + cSettings: [ + .headerSearchPath("."), + .define("NS_BLOCK_ASSERTIONS", to: "1", .when(configuration: .release)), + ]), + .testTarget( + name: "PINOperationTests", + dependencies: ["PINOperation"], + path: "Tests", + exclude: ["Info.plist"]), + ] +) diff --git a/Carthage/Checkouts/PINOperation/README.md b/Carthage/Checkouts/PINOperation/README.md new file mode 100644 index 00000000..2e29c80f --- /dev/null +++ b/Carthage/Checkouts/PINOperation/README.md @@ -0,0 +1,47 @@ +# PINOperation + +[![CocoaPods](https://img.shields.io/cocoapods/v/PINOperation.svg)](http://cocoadocs.org/docsets/PINOperation/) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![Build status](https://github.com/pinterest/PINOperation/workflows/CI/badge.svg)](https://github.com/pinterest/PINOperation/actions?query=workflow%3ACI+branch%3Amaster) + +## Fast, concurrency-limited task queue for iOS and macOS. + +## Installation + +### Manually + +[Download the latest tag](https://github.com/pinterest/PINOperation/tags) and drag the `PINOperation` folder into your Xcode project. + +Install the docs by double clicking the `.docset` file under `docs/`, or view them online at [cocoadocs.org](http://cocoadocs.org/docsets/PINOperation/) + +### Git Submodule + + git submodule add https://github.com/pinterest/PINOperation.git + git submodule update --init + +### CocoaPods + +Add [PINOperation](http://cocoapods.org/?q=name%3APINOperation) to your `Podfile` and run `pod install`. + +### Carthage + +Add the following line to your `Cartfile` and run `carthage update --platform ios`. Then follow [this instruction of Carthage](https://github.com/carthage/carthage#adding-frameworks-to-unit-tests-or-a-framework) to embed the framework. + +```github "pinterest/PINOperation"``` + +## Requirements + +__PINOperation__ requires iOS 12.0, tvOS 12.0, macOS 10.13 or watchOS 4.0 and greater. + +## Contact + +[Garrett Moon](mailto:garrett@pinterest.com) + +## License + +Copyright 2013 Tumblr, Inc. +Copyright 2015 Pinterest, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. [See the License](LICENSE.txt) for the specific language governing permissions and limitations under the License. diff --git a/Carthage/Checkouts/PINOperation/RELEASE.md b/Carthage/Checkouts/PINOperation/RELEASE.md new file mode 100644 index 00000000..807cee6a --- /dev/null +++ b/Carthage/Checkouts/PINOperation/RELEASE.md @@ -0,0 +1,7 @@ +# Release Process +This document describes the process for a public PINOperation release. + +### Process +- Ensure the latest master build is green. +- Run the github action 'Create Release'. +- Check that the release was successfully published to [Github](https://github.com/pinterest/PINOperation/releases) and [Cocoapods](https://cocoapods.org/pods/PINOperation). diff --git a/Carthage/Checkouts/PINOperation/Scripts/release.sh b/Carthage/Checkouts/PINOperation/Scripts/release.sh new file mode 100755 index 00000000..bd685725 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Scripts/release.sh @@ -0,0 +1,98 @@ +#!/bin/bash +set -e + +if [ -z "$OSS_PROJECT" ]; then + echo "Must set \$OSS_PROJECT envirnonment variable before running." +fi + +PROJECT="$OSS_PROJECT" + +if ! git diff-index --quiet HEAD --; then + echo "Please commit or stash any changes before running." + exit 1 +fi + +if [ -z "$GITHUB_CHANGELOG_API_KEY" ]; then + echo "Must set \$GITHUB_CHANGELOG_API_KEY environment variable" + exit 1 +fi + +case $1 in + "--major") + UPDATE_TYPE="major" + ;; + + "--minor") + UPDATE_TYPE="minor" + ;; + + "--patch") + UPDATE_TYPE="patch" + ;; + + *) + echo "Usage release.sh --patch / --minor / --major" + exit 1 + ;; +esac + +PODSPEC="$PROJECT.podspec" +CURRENT_VERSION=$(grep "version" -m 1 $PODSPEC | sed -E "s/^.*version[ \t]*=[ \t]*['\"]([0-9\.]+)['\"]/\1/") +DOT_COUNT=$(echo "$CURRENT_VERSION" | grep -o '\.' | wc -l) + +if [ "$DOT_COUNT" -eq "0" ]; then + major=$CURRENT_VERSION + minor="0" + patch="0" +elif [ "$DOT_COUNT" -eq "1" ]; then + major=$(echo "$CURRENT_VERSION" | sed -E "s/([0-9])+\.([0-9]+)/\1/") + minor=$(echo "$CURRENT_VERSION" | sed -E "s/([0-9])+\.([0-9]+)/\2/") + patch="0" +elif [ "$DOT_COUNT" -eq "2" ]; then + major=$(echo "$CURRENT_VERSION" | sed -E "s/([0-9])+\.([0-9]+)\.([0-9]+)/\1/") + minor=$(echo "$CURRENT_VERSION" | sed -E "s/([0-9])+\.([0-9]+)\.([0-9]+)/\2/") + patch=$(echo "$CURRENT_VERSION" | sed -E "s/([0-9])+\.([0-9]+)\.([0-9]+)/\3/") +fi + +echo "Current version: $major.$minor.$patch" + +if [ "$UPDATE_TYPE" == "major" ]; then + major=$((major + 1)) + minor=0 + patch=0 +elif [ "$UPDATE_TYPE" == "minor" ]; then + minor=$((minor + 1)) + patch=0 +elif [ "$UPDATE_TYPE" == "patch" ]; then + patch=$((patch + 1)) +fi + +NEW_VERSION="$major.$minor.$patch" +echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV +echo "New version: $NEW_VERSION" + +echo "Updating $PODSPEC" +sed -E "s/^(.*version[ \t]*=[ \t]*)['|\"]$CURRENT_VERSION['|\"]/\1'$NEW_VERSION'/" $PODSPEC > new.podspec +mv new.podspec $PODSPEC + +echo "Updating .github_changelog_generator" +cat << EOF > .github_changelog_generator +issues=false +since-tag=$CURRENT_VERSION +future-release=$NEW_VERSION +EOF + +github_changelog_generator --token $GITHUB_CHANGELOG_API_KEY --user Pinterest --project $PROJECT --output NEW_CHANGES.md + +# Delete # Changelog at the top of the old CHANGELOG +grep -v "# Changelog" CHANGELOG.md > CHANGELOG.tmp && mv CHANGELOG.tmp CHANGELOG.md + +# Delete the last line and first line then use a magic sed command the internet told me +# about to delete trailing newlines (except the last one) +# Then prepend to existing changelog +grep -v "\*" NEW_CHANGES.md | sed -e :a -e '/^\n*$/{$d;N;};/\n$/ba' | cat - CHANGELOG.md > CHANGELOG.tmp +mv CHANGELOG.tmp CHANGELOG.md +rm NEW_CHANGES.md + +git add .github_changelog_generator CHANGELOG.md $PODSPEC +git commit --message "[AUTO] Update CHANGELOG.md and bump for $UPDATE_TYPE update." diff --git a/Carthage/Checkouts/PINOperation/Scripts/tag-release-branch.sh b/Carthage/Checkouts/PINOperation/Scripts/tag-release-branch.sh new file mode 100755 index 00000000..a66af230 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Scripts/tag-release-branch.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -ex + +echo "Tagging release branch" +TAG=$NEW_VERSION + +echo "RELEASE_TAG=$TAG" >> $GITHUB_ENV +git tag $TAG +git push origin --tags + +echo "Setting Release Notes" +cat CHANGELOG.md | awk '/^#/{f=1} f; /^#/ && ++c==3{exit}' | sed '$ d' > RELEASE_NOTES.md diff --git a/Carthage/Checkouts/PINOperation/Source/Info.plist b/Carthage/Checkouts/PINOperation/Source/Info.plist new file mode 100644 index 00000000..faedaa13 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Source/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2017 Pinterest. All rights reserved. + NSPrincipalClass + + + diff --git a/Carthage/Checkouts/PINOperation/Source/PINOperation.h b/Carthage/Checkouts/PINOperation/Source/PINOperation.h new file mode 100644 index 00000000..1f67472b --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Source/PINOperation.h @@ -0,0 +1,12 @@ +// +// PINOperation.h +// PINOperation +// +// Created by Adlai Holler on 1/10/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import +#import +#import +#import diff --git a/Carthage/Checkouts/PINOperation/Source/PINOperationGroup.h b/Carthage/Checkouts/PINOperation/Source/PINOperationGroup.h new file mode 100644 index 00000000..989061c3 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Source/PINOperationGroup.h @@ -0,0 +1,38 @@ +// +// PINOperationGroup.h +// PINOperation +// +// Created by Garrett Moon on 10/8/16. +// Copyright © 2016 Pinterest. All rights reserved. +// + +#import +#import +#import + +@class PINOperationQueue; + +NS_ASSUME_NONNULL_BEGIN + +@protocol PINGroupOperationReference; + +PINOP_SUBCLASSING_RESTRICTED +@interface PINOperationGroup : NSObject + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)asyncOperationGroupWithQueue:(PINOperationQueue *)operationQueue; + +- (nullable id )addOperation:(dispatch_block_t)operation; +- (nullable id )addOperation:(dispatch_block_t)operation withPriority:(PINOperationQueuePriority)priority; +- (void)start; +- (void)cancel; +- (void)setCompletion:(dispatch_block_t)completion; +- (void)waitUntilComplete; + +@end + +@protocol PINGroupOperationReference + +@end + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/PINOperation/Source/PINOperationGroup.m b/Carthage/Checkouts/PINOperation/Source/PINOperationGroup.m new file mode 100644 index 00000000..94d09178 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Source/PINOperationGroup.m @@ -0,0 +1,187 @@ +// +// PINOperationGroup.m +// PINOperation +// +// Created by Garrett Moon on 10/8/16. +// Copyright © 2016 Pinterest. All rights reserved. +// + +#import "PINOperationGroup.h" +#import +#import + +@interface NSNumber (PINGroupOperationQueue) +@end + +@interface PINOperationGroup () +{ + pthread_mutex_t _lock; + + PINOperationQueue *_operationQueue; + NSMutableArray *_operations; + NSMutableArray *_operationPriorities; + NSMutableArray > *_operationReferences; + NSMapTable , id > *_groupToOperationReferences; + NSUInteger _operationReferenceCount; + + dispatch_group_t _group; + + dispatch_block_t _completion; + + BOOL _started; + BOOL _canceled; +} + +- (instancetype)initWithOperationQueue:(PINOperationQueue *)operationQueue NS_DESIGNATED_INITIALIZER; + +@end + +@implementation PINOperationGroup + +- (instancetype)initWithOperationQueue:(PINOperationQueue *)operationQueue +{ + if (self = [super init]) { + pthread_mutex_init(&_lock, NULL); + + _operationQueue = operationQueue; + + _operations = [[NSMutableArray alloc] init]; + _operationReferences = [[NSMutableArray alloc] init]; + _operationPriorities = [[NSMutableArray alloc] init]; + + _groupToOperationReferences = [NSMapTable weakToStrongObjectsMapTable]; + _group = dispatch_group_create(); + } + return self; +} + +- (void)dealloc +{ + pthread_mutex_destroy(&_lock); +} + ++ (instancetype)asyncOperationGroupWithQueue:(PINOperationQueue *)operationQueue +{ + return [[self alloc] initWithOperationQueue:operationQueue]; +} + +- (id )locked_nextOperationReference +{ + id reference = [NSNumber numberWithUnsignedInteger:++_operationReferenceCount]; + return reference; +} + +- (void)start +{ + [self lock]; + NSAssert(_canceled == NO, @"Operation group canceled."); + if (_started == NO && _canceled == NO) { + for (NSUInteger idx = 0; idx < _operations.count; idx++) { + dispatch_group_enter(_group); + dispatch_block_t originalOperation = _operations[idx]; + dispatch_block_t groupBlock = ^{ + originalOperation(); + dispatch_group_leave(self->_group); + }; + + id operationReference = [_operationQueue scheduleOperation:groupBlock withPriority:[_operationPriorities[idx] unsignedIntegerValue]]; + [_groupToOperationReferences setObject:operationReference forKey:_operationReferences[idx]]; + } + + if (_completion) { + dispatch_queue_t completionQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + dispatch_group_notify(_group, completionQueue, ^{ + [self runCompletionIfNeeded]; + }); + } + + _operations = nil; + _operationPriorities = nil; + _operationReferences = nil; + } + [self unlock]; +} + +- (void)cancel +{ + [self lock]; + _canceled = YES; + + for (id operationReference in [_groupToOperationReferences objectEnumerator]) { + if ([_operationQueue cancelOperation:operationReference]) { + dispatch_group_leave(_group); + } + } + + //TODO just nil out instead? Does it make sense to support adding operations after cancelation? + [_groupToOperationReferences removeAllObjects]; + [_operations removeAllObjects]; + [_operationPriorities removeAllObjects]; + [_operationReferences removeAllObjects]; + + _completion = nil; + [self unlock]; +} + +- (id )addOperation:(dispatch_block_t)operation +{ + return [self addOperation:operation withPriority:PINOperationQueuePriorityDefault]; +} + +- (id )addOperation:(dispatch_block_t)operation withPriority:(PINOperationQueuePriority)priority +{ + [self lock]; + id reference = nil; + NSAssert(_started == NO && _canceled == NO, @"Operation group already started or canceled."); + if (_started == NO && _canceled == NO) { + reference = [self locked_nextOperationReference]; + [_operations addObject:operation]; + [_operationPriorities addObject:@(priority)]; + [_operationReferences addObject:reference]; + } + [self unlock]; + + return reference; +} + +- (void)setCompletion:(dispatch_block_t)completion +{ + [self lock]; + NSAssert(_started == NO && _canceled == NO, @"Operation group already started or canceled."); + if (_started == NO && _canceled == NO) { + _completion = completion; + } + [self unlock]; +} + +- (void)waitUntilComplete +{ + [self start]; + dispatch_group_wait(_group, DISPATCH_TIME_FOREVER); + [self runCompletionIfNeeded]; +} + +- (void)runCompletionIfNeeded +{ + dispatch_block_t completion; + [self lock]; + completion = _completion; + _completion = nil; + [self unlock]; + + if (completion) { + completion(); + } +} + +- (void)lock +{ + pthread_mutex_lock(&_lock); +} + +- (void)unlock +{ + pthread_mutex_unlock(&_lock); +} + +@end diff --git a/Carthage/Checkouts/PINOperation/Source/PINOperationMacros.h b/Carthage/Checkouts/PINOperation/Source/PINOperationMacros.h new file mode 100644 index 00000000..5be3a216 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Source/PINOperationMacros.h @@ -0,0 +1,15 @@ +// +// PINOperationMacros.h +// PINOperation +// +// Created by Adlai Holler on 1/10/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#ifndef PINOP_SUBCLASSING_RESTRICTED +#if defined(__has_attribute) && __has_attribute(objc_subclassing_restricted) +#define PINOP_SUBCLASSING_RESTRICTED __attribute__((objc_subclassing_restricted)) +#else +#define PINOP_SUBCLASSING_RESTRICTED +#endif // #if defined(__has_attribute) && __has_attribute(objc_subclassing_restricted) +#endif // #ifndef PINOP_SUBCLASSING_RESTRICTED diff --git a/Carthage/Checkouts/PINOperation/Source/PINOperationQueue.h b/Carthage/Checkouts/PINOperation/Source/PINOperationQueue.h new file mode 100644 index 00000000..48c30928 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Source/PINOperationQueue.h @@ -0,0 +1,141 @@ +// +// PINOperationQueue.h +// PINOperation +// +// Created by Garrett Moon on 8/23/16. +// +// + +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef void(^PINOperationBlock)(id _Nullable data); +typedef _Nullable id(^PINOperationDataCoalescingBlock)(id _Nullable existingData, id _Nullable newData); + +@protocol PINOperationReference; + +PINOP_SUBCLASSING_RESTRICTED +@interface PINOperationQueue : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +/** + * Initializes and returns a newly allocated operation queue with the specified number of maximum concurrent operations. + * + * @param maxConcurrentOperations The maximum number of queued operations that can execute at the same time. + * + */ +- (instancetype)initWithMaxConcurrentOperations:(NSUInteger)maxConcurrentOperations; + +/** + * Initializes and returns a newly allocated operation queue with the specified number of maximum concurrent operations and the concurrent queue they will be scheduled on. + * + * @param maxConcurrentOperations The maximum number of queued operations that can execute at the same time. + * @param concurrentQueue The operation queue to schedule concurrent operations + * + */ +- (instancetype)initWithMaxConcurrentOperations:(NSUInteger)maxConcurrentOperations concurrentQueue:(dispatch_queue_t)concurrentQueue NS_DESIGNATED_INITIALIZER; + +/** + * Returns the shared instance of the PINOperationQueue class. + */ ++ (instancetype)sharedOperationQueue; + +/** + * Adds the specified operation object to the receiver. + * + * @param operation The operation object to be added to the queue. + * + */ +- (id )scheduleOperation:(dispatch_block_t)operation; + +/** + * Adds the specified operation object to the receiver. + * + * @param operation The operation object to be added to the queue. + * @param priority The execution priority of the operation in an operation queue. + */ +- (id )scheduleOperation:(dispatch_block_t)operation withPriority:(PINOperationQueuePriority)priority; + +/** + * Adds the specified operation object to the receiver. + * + * @param operation The operation object to be added to the queue. + * @param priority The execution priority of the operation in an operation queue. + * @param identifier A string that identifies the operations that can be coalesced. + * @param coalescingData The optional data consumed by this operation that needs to be updated/coalesced with data of a new operation when coalescing the two operations happens. + * @param dataCoalescingBlock The optional block called to update/coalesce the data of this operation with data of a new operation when coalescing the two operations happens. + * @param completion The block to execute after the operation finished. + */ +- (id )scheduleOperation:(PINOperationBlock)operation + withPriority:(PINOperationQueuePriority)priority + identifier:(nullable NSString *)identifier + coalescingData:(nullable id)coalescingData + dataCoalescingBlock:(nullable PINOperationDataCoalescingBlock)dataCoalescingBlock + completion:(nullable dispatch_block_t)completion; + +/** + * The maximum number of queued operations that can execute at the same time. + * + * @discussion The value in this property affects only the operations that the current queue has executing at the same time. Other operation queues can also execute their maximum number of operations in parallel. + * Reducing the number of concurrent operations does not affect any operations that are currently executing. + * + * Setting this value to 1 the operations will not be processed by priority as the operations will processed in a FIFO order to prevent deadlocks if operations depend on certain other operations to run in order. + * + */ +@property (assign) NSUInteger maxConcurrentOperations; + +/** + * Marks the operation as cancelled + */ +- (BOOL)cancelOperation:(id )operationReference; + +/** + * Cancels all queued operations + */ +- (void)cancelAllOperations; + +/** + * Blocks the current thread until all of the receiver’s queued and executing operations finish executing. + * + * @discussion When called, this method blocks the current thread and waits for the receiver’s current and queued + * operations to finish executing. While the current thread is blocked, the receiver continues to launch already + * queued operations and monitor those that are executing. + * + * @warning This should never be called from within an operation submitted to the PINOperationQueue as this will result + * in a deadlock. + */ +- (void)waitUntilAllOperationsAreFinished; + +/** + * Sets the priority for a operation via it's reference + * + * @param priority The new priority for the operation + * @param reference The reference for the operation + * + */ +- (void)setOperationPriority:(PINOperationQueuePriority)priority withReference:(id )reference; + +#pragma mark - Deprecated + +- (id )addOperation:(dispatch_block_t)operation __deprecated_msg("Use scheduleOperation: instead."); + +- (id )addOperation:(dispatch_block_t)operation withPriority:(PINOperationQueuePriority)priority __deprecated_msg("Use scheduleOperation:withPriority: instead."); + +- (id )addOperation:(PINOperationBlock)operation + withPriority:(PINOperationQueuePriority)priority + identifier:(nullable NSString *)identifier + coalescingData:(nullable id)coalescingData + dataCoalescingBlock:(nullable PINOperationDataCoalescingBlock)dataCoalescingBlock + completion:(nullable dispatch_block_t)completion __deprecated_msg("Use scheduleOperation:withPriority:identifier:coalescingData:dataCoalescingBlock:completion: instead."); + +@end + +@protocol PINOperationReference + +@end + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/PINOperation/Source/PINOperationQueue.m b/Carthage/Checkouts/PINOperation/Source/PINOperationQueue.m new file mode 100644 index 00000000..e05451b5 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Source/PINOperationQueue.m @@ -0,0 +1,471 @@ +// +// PINOperationQueue.m +// PINOperation +// +// Created by Garrett Moon on 8/23/16. +// +// + +#import "PINOperationQueue.h" +#import + +@class PINOperation; + +@interface NSNumber (PINOperationQueue) + +@end + +@interface PINOperationQueue () { + pthread_mutex_t _lock; + //increments with every operation to allow cancelation + NSUInteger _operationReferenceCount; + NSUInteger _maxConcurrentOperations; + + dispatch_group_t _group; + + dispatch_queue_t _serialQueue; + BOOL _serialQueueBusy; + + dispatch_semaphore_t _concurrentSemaphore; + dispatch_queue_t _concurrentQueue; + dispatch_queue_t _semaphoreQueue; + + NSMutableOrderedSet *_queuedOperations; + NSMutableOrderedSet *_lowPriorityOperations; + NSMutableOrderedSet *_defaultPriorityOperations; + NSMutableOrderedSet *_highPriorityOperations; + + NSMapTable, PINOperation *> *_referenceToOperations; + NSMapTable *_identifierToOperations; +} + +@end + +@interface PINOperation : NSObject + +@property (nonatomic, strong) PINOperationBlock block; +@property (nonatomic, strong) id reference; +@property (nonatomic, assign) PINOperationQueuePriority priority; +@property (nonatomic, strong) NSMutableArray *completions; +@property (nonatomic, strong) NSString *identifier; +@property (nonatomic, strong) id data; + ++ (instancetype)operationWithBlock:(PINOperationBlock)block reference:(id )reference priority:(PINOperationQueuePriority)priority identifier:(nullable NSString *)identifier data:(nullable id)data completion:(nullable dispatch_block_t)completion; + +- (void)addCompletion:(nullable dispatch_block_t)completion; + +@end + +@implementation PINOperation + ++ (instancetype)operationWithBlock:(PINOperationBlock)block reference:(id)reference priority:(PINOperationQueuePriority)priority identifier:(NSString *)identifier data:(id)data completion:(dispatch_block_t)completion +{ + PINOperation *operation = [[self alloc] init]; + operation.block = block; + operation.reference = reference; + operation.priority = priority; + operation.identifier = identifier; + operation.data = data; + [operation addCompletion:completion]; + + return operation; +} + +- (void)addCompletion:(dispatch_block_t)completion +{ + if (completion == nil) { + return; + } + if (_completions == nil) { + _completions = [NSMutableArray array]; + } + [_completions addObject:completion]; +} + +@end + +@implementation PINOperationQueue + +- (instancetype)initWithMaxConcurrentOperations:(NSUInteger)maxConcurrentOperations +{ + return [self initWithMaxConcurrentOperations:maxConcurrentOperations concurrentQueue:dispatch_queue_create("PINOperationQueue Concurrent Queue", DISPATCH_QUEUE_CONCURRENT)]; +} + +- (instancetype)initWithMaxConcurrentOperations:(NSUInteger)maxConcurrentOperations concurrentQueue:(dispatch_queue_t)concurrentQueue +{ + if (self = [super init]) { + NSAssert(maxConcurrentOperations > 0, @"Max concurrent operations must be greater than 0."); + _maxConcurrentOperations = maxConcurrentOperations; + _operationReferenceCount = 0; + + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + //mutex must be recursive to allow scheduling of operations from within operations + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&_lock, &attr); + + _group = dispatch_group_create(); + + _serialQueue = dispatch_queue_create("PINOperationQueue Serial Queue", DISPATCH_QUEUE_SERIAL); + + _concurrentQueue = concurrentQueue; + + //Create a queue with max - 1 because this plus the serial queue add up to max. + _concurrentSemaphore = dispatch_semaphore_create(_maxConcurrentOperations - 1); + _semaphoreQueue = dispatch_queue_create("PINOperationQueue Serial Semaphore Queue", DISPATCH_QUEUE_SERIAL); + + _queuedOperations = [[NSMutableOrderedSet alloc] init]; + _lowPriorityOperations = [[NSMutableOrderedSet alloc] init]; + _defaultPriorityOperations = [[NSMutableOrderedSet alloc] init]; + _highPriorityOperations = [[NSMutableOrderedSet alloc] init]; + + _referenceToOperations = [NSMapTable weakToWeakObjectsMapTable]; + _identifierToOperations = [NSMapTable weakToWeakObjectsMapTable]; + } + return self; +} + +- (void)dealloc +{ + pthread_mutex_destroy(&_lock); +} + ++ (instancetype)sharedOperationQueue +{ + static PINOperationQueue *sharedOperationQueue = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedOperationQueue = [[PINOperationQueue alloc] initWithMaxConcurrentOperations:MAX([[NSProcessInfo processInfo] activeProcessorCount], 2)]; + }); + return sharedOperationQueue; +} + +- (id )nextOperationReference +{ + [self lock]; + id reference = [NSNumber numberWithUnsignedInteger:++_operationReferenceCount]; + [self unlock]; + return reference; +} + +// Deprecated +- (id )addOperation:(dispatch_block_t)block +{ + return [self scheduleOperation:block]; +} + +- (id )scheduleOperation:(dispatch_block_t)block +{ + return [self scheduleOperation:block withPriority:PINOperationQueuePriorityDefault]; +} + +// Deprecated +- (id )addOperation:(dispatch_block_t)block withPriority:(PINOperationQueuePriority)priority +{ + return [self scheduleOperation:block withPriority:priority]; +} + +- (id )scheduleOperation:(dispatch_block_t)block withPriority:(PINOperationQueuePriority)priority +{ + PINOperation *operation = [PINOperation operationWithBlock:^(id data) { block(); } + reference:[self nextOperationReference] + priority:priority + identifier:nil + data:nil + completion:nil]; + [self lock]; + [self locked_addOperation:operation]; + [self unlock]; + + [self scheduleNextOperations:NO]; + + return operation.reference; +} + +// Deprecated +- (id)addOperation:(PINOperationBlock)block + withPriority:(PINOperationQueuePriority)priority + identifier:(NSString *)identifier + coalescingData:(id)coalescingData + dataCoalescingBlock:(PINOperationDataCoalescingBlock)dataCoalescingBlock + completion:(dispatch_block_t)completion +{ + return [self scheduleOperation:block + withPriority:priority + identifier:identifier + coalescingData:coalescingData + dataCoalescingBlock:dataCoalescingBlock + completion:completion]; +} + +- (id)scheduleOperation:(PINOperationBlock)block + withPriority:(PINOperationQueuePriority)priority + identifier:(NSString *)identifier + coalescingData:(id)coalescingData + dataCoalescingBlock:(PINOperationDataCoalescingBlock)dataCoalescingBlock + completion:(dispatch_block_t)completion +{ + id reference = nil; + BOOL isNewOperation = NO; + + [self lock]; + PINOperation *operation = nil; + if (identifier != nil && (operation = [_identifierToOperations objectForKey:identifier]) != nil) { + // There is an exisiting operation with the provided identifier, let's coalesce these operations + if (dataCoalescingBlock != nil) { + operation.data = dataCoalescingBlock(operation.data, coalescingData); + } + + [operation addCompletion:completion]; + } else { + isNewOperation = YES; + operation = [PINOperation operationWithBlock:block + reference:[self nextOperationReference] + priority:priority + identifier:identifier + data:coalescingData + completion:completion]; + [self locked_addOperation:operation]; + } + reference = operation.reference; + [self unlock]; + + if (isNewOperation) { + [self scheduleNextOperations:NO]; + } + + return reference; +} + +- (void)locked_addOperation:(PINOperation *)operation +{ + NSMutableOrderedSet *queue = [self operationQueueWithPriority:operation.priority]; + + dispatch_group_enter(_group); + [queue addObject:operation]; + [_queuedOperations addObject:operation]; + [_referenceToOperations setObject:operation forKey:operation.reference]; + if (operation.identifier != nil) { + [_identifierToOperations setObject:operation forKey:operation.identifier]; + } +} + +- (void)cancelAllOperations +{ + [self lock]; + for (PINOperation *operation in [[_referenceToOperations copy] objectEnumerator]) { + [self locked_cancelOperation:operation.reference]; + } + [self unlock]; +} + + +- (BOOL)cancelOperation:(id )operationReference +{ + [self lock]; + BOOL success = [self locked_cancelOperation:operationReference]; + [self unlock]; + return success; +} + +- (NSUInteger)maxConcurrentOperations +{ + [self lock]; + NSUInteger maxConcurrentOperations = _maxConcurrentOperations; + [self unlock]; + return maxConcurrentOperations; +} + +- (void)setMaxConcurrentOperations:(NSUInteger)maxConcurrentOperations +{ + NSAssert(maxConcurrentOperations > 0, @"Max concurrent operations must be greater than 0."); + [self lock]; + __block NSInteger difference = maxConcurrentOperations - _maxConcurrentOperations; + _maxConcurrentOperations = maxConcurrentOperations; + [self unlock]; + + if (difference == 0) { + return; + } + + dispatch_async(_semaphoreQueue, ^{ + while (difference != 0) { + if (difference > 0) { + dispatch_semaphore_signal(self->_concurrentSemaphore); + difference--; + } else { + dispatch_semaphore_wait(self->_concurrentSemaphore, DISPATCH_TIME_FOREVER); + difference++; + } + } + }); +} + +#pragma mark - private methods + +- (BOOL)locked_cancelOperation:(id )operationReference +{ + PINOperation *operation = [_referenceToOperations objectForKey:operationReference]; + BOOL success = [self locked_removeOperation:operation]; + if (success) { + dispatch_group_leave(_group); + } + return success; +} + +- (void)setOperationPriority:(PINOperationQueuePriority)priority withReference:(id )operationReference +{ + [self lock]; + PINOperation *operation = [_referenceToOperations objectForKey:operationReference]; + if (operation && operation.priority != priority) { + NSMutableOrderedSet *oldQueue = [self operationQueueWithPriority:operation.priority]; + [oldQueue removeObject:operation]; + + operation.priority = priority; + + NSMutableOrderedSet *queue = [self operationQueueWithPriority:priority]; + [queue addObject:operation]; + } + [self unlock]; +} + +/** + Schedule next operations schedules the next operation by queue order onto the serial queue if + it's available and one operation by priority order onto the concurrent queue. + */ +- (void)scheduleNextOperations:(BOOL)onlyCheckSerial +{ + [self lock]; + + //get next available operation in order, ignoring priority and run it on the serial queue + if (_serialQueueBusy == NO) { + PINOperation *operation = [self locked_nextOperationByQueue]; + if (operation) { + _serialQueueBusy = YES; + dispatch_async(_serialQueue, ^{ + operation.block(operation.data); + for (dispatch_block_t completion in operation.completions) { + completion(); + } + dispatch_group_leave(self->_group); + + [self lock]; + self->_serialQueueBusy = NO; + [self unlock]; + + //see if there are any other operations + [self scheduleNextOperations:YES]; + }); + } + } + + NSInteger maxConcurrentOperations = _maxConcurrentOperations; + + [self unlock]; + + if (onlyCheckSerial) { + return; + } + + //if only one concurrent operation is set, let's just use the serial queue for executing it + if (maxConcurrentOperations < 2) { + return; + } + + dispatch_async(_semaphoreQueue, ^{ + dispatch_semaphore_wait(self->_concurrentSemaphore, DISPATCH_TIME_FOREVER); + [self lock]; + PINOperation *operation = [self locked_nextOperationByPriority]; + [self unlock]; + + if (operation) { + dispatch_async(self->_concurrentQueue, ^{ + operation.block(operation.data); + for (dispatch_block_t completion in operation.completions) { + completion(); + } + dispatch_group_leave(self->_group); + dispatch_semaphore_signal(self->_concurrentSemaphore); + }); + } else { + dispatch_semaphore_signal(self->_concurrentSemaphore); + } + }); +} + +- (NSMutableOrderedSet *)operationQueueWithPriority:(PINOperationQueuePriority)priority +{ + switch (priority) { + case PINOperationQueuePriorityLow: + return _lowPriorityOperations; + + case PINOperationQueuePriorityDefault: + return _defaultPriorityOperations; + + case PINOperationQueuePriorityHigh: + return _highPriorityOperations; + + default: + NSAssert(NO, @"Invalid priority set"); + return _defaultPriorityOperations; + } +} + +//Call with lock held +- (PINOperation *)locked_nextOperationByPriority +{ + PINOperation *operation = [_highPriorityOperations firstObject]; + if (operation == nil) { + operation = [_defaultPriorityOperations firstObject]; + } + if (operation == nil) { + operation = [_lowPriorityOperations firstObject]; + } + if (operation) { + [self locked_removeOperation:operation]; + } + return operation; +} + +//Call with lock held +- (PINOperation *)locked_nextOperationByQueue +{ + PINOperation *operation = [_queuedOperations firstObject]; + [self locked_removeOperation:operation]; + return operation; +} + +- (void)waitUntilAllOperationsAreFinished +{ + [self scheduleNextOperations:NO]; + dispatch_group_wait(_group, DISPATCH_TIME_FOREVER); +} + +//Call with lock held +- (BOOL)locked_removeOperation:(PINOperation *)operation +{ + if (operation) { + NSMutableOrderedSet *priorityQueue = [self operationQueueWithPriority:operation.priority]; + if ([priorityQueue containsObject:operation]) { + [priorityQueue removeObject:operation]; + [_queuedOperations removeObject:operation]; + if (operation.identifier) { + [_identifierToOperations removeObjectForKey:operation.identifier]; + } + return YES; + } + } + return NO; +} + +- (void)lock +{ + pthread_mutex_lock(&_lock); +} + +- (void)unlock +{ + pthread_mutex_unlock(&_lock); +} + +@end diff --git a/Carthage/Checkouts/PINOperation/Source/PINOperationTypes.h b/Carthage/Checkouts/PINOperation/Source/PINOperationTypes.h new file mode 100644 index 00000000..be7293db --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Source/PINOperationTypes.h @@ -0,0 +1,15 @@ +// +// PINOperationTypes.h +// PINOperation +// +// Created by Adlai Holler on 1/10/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import + +typedef NS_ENUM(NSUInteger, PINOperationQueuePriority) { + PINOperationQueuePriorityLow, + PINOperationQueuePriorityDefault, + PINOperationQueuePriorityHigh, +}; diff --git a/Carthage/Checkouts/PINOperation/Source/PrivacyInfo.xcprivacy b/Carthage/Checkouts/PINOperation/Source/PrivacyInfo.xcprivacy new file mode 100644 index 00000000..e08a130b --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Source/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + NSPrivacyCollectedDataTypes + + NSPrivacyAccessedAPITypes + + + diff --git a/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperation.h b/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperation.h new file mode 120000 index 00000000..0f8eb5e6 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperation.h @@ -0,0 +1 @@ +../../PINOperation.h \ No newline at end of file diff --git a/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationGroup.h b/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationGroup.h new file mode 120000 index 00000000..2fd30a28 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationGroup.h @@ -0,0 +1 @@ +../../PINOperationGroup.h \ No newline at end of file diff --git a/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationMacros.h b/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationMacros.h new file mode 120000 index 00000000..b7be0637 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationMacros.h @@ -0,0 +1 @@ +../../PINOperationMacros.h \ No newline at end of file diff --git a/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationQueue.h b/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationQueue.h new file mode 120000 index 00000000..db4dc22a --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationQueue.h @@ -0,0 +1 @@ +../../PINOperationQueue.h \ No newline at end of file diff --git a/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationTypes.h b/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationTypes.h new file mode 120000 index 00000000..bf9c4040 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Source/include/PINOperation/PINOperationTypes.h @@ -0,0 +1 @@ +../../PINOperationTypes.h \ No newline at end of file diff --git a/Carthage/Checkouts/PINOperation/Tests/Info.plist b/Carthage/Checkouts/PINOperation/Tests/Info.plist new file mode 100644 index 00000000..ba72822e --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Tests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Carthage/Checkouts/PINOperation/Tests/PINOperationGroupTests.m b/Carthage/Checkouts/PINOperation/Tests/PINOperationGroupTests.m new file mode 100644 index 00000000..d42d2e85 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Tests/PINOperationGroupTests.m @@ -0,0 +1,133 @@ +// +// PINOperationGroupTests.m +// PINOperation +// +// Created by Garrett Moon on 10/12/16. +// Copyright © 2016 Pinterest. All rights reserved. +// + +#if SWIFT_PACKAGE +@import PINOperation; +#else +#import +#endif + +#import +#import + +static NSTimeInterval PINOperationGroupTestBlockTimeout = 20; + +@interface PINOperationGroupTests : XCTestCase + +@property PINOperationQueue *queue; + +@end + +@implementation PINOperationGroupTests + +- (dispatch_time_t)timeout +{ + return dispatch_time(DISPATCH_TIME_NOW, (int64_t)(PINOperationGroupTestBlockTimeout * NSEC_PER_SEC)); +} + +- (void)setUp { + [super setUp]; + self.queue = [[PINOperationQueue alloc] initWithMaxConcurrentOperations:5]; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testAllOperationsRunBeforeCompletion +{ + __block NSUInteger operationsRun = 0; + PINOperationGroup *group = [PINOperationGroup asyncOperationGroupWithQueue:self.queue]; + + for (NSUInteger idx = 0; idx < 100; idx++) { + __weak typeof(self) weakSelf = self; + [group addOperation:^{ + typeof(self) strongSelf = weakSelf; + @synchronized (strongSelf) { + operationsRun++; + } + }]; + } + + XCTestExpectation *completionRun = [self expectationWithDescription:@"Completion Run"]; + + __weak typeof(self) weakSelf = self; + [group setCompletion:^{ + typeof(self) strongSelf = weakSelf; + @synchronized (strongSelf) { + XCTAssert(operationsRun == 100, @"Not all operations were run before completion"); + } + [completionRun fulfill]; + }]; + + [group start]; + + [self waitForExpectationsWithTimeout:PINOperationGroupTestBlockTimeout handler:nil]; +} + +- (void)testWaitUntilOperationsComplete +{ + __block NSUInteger operationsRun = 0; + PINOperationGroup *group = [PINOperationGroup asyncOperationGroupWithQueue:self.queue]; + + for (NSUInteger idx = 0; idx < 100; idx++) { + __weak typeof(self) weakSelf = self; + [group addOperation:^{ + typeof(self) strongSelf = weakSelf; + @synchronized (strongSelf) { + operationsRun++; + } + }]; + } + __block BOOL completionBlockCalled = NO; + [group setCompletion:^{ + completionBlockCalled = YES; + }]; + + [group waitUntilComplete]; + XCTAssert(completionBlockCalled, @"Completion block should have been called after waiting."); + + @synchronized (self) { + XCTAssert(operationsRun == 100, @"All operations should be run"); + } +} + +- (void)testCancelation +{ + __block NSUInteger operationsRun = 0; + PINOperationGroup *group = [PINOperationGroup asyncOperationGroupWithQueue:self.queue]; + + const NSUInteger operationsToRun = 100; + + for (NSUInteger idx = 0; idx < operationsToRun; idx++) { + __weak typeof(self) weakSelf = self; + [group addOperation:^{ + usleep(10000); + typeof(self) strongSelf = weakSelf; + @synchronized (strongSelf) { + operationsRun++; + } + }]; + } + + [group setCompletion:^{ + XCTAssert(NO, @"completion should not be run"); + }]; + + [group start]; + [group cancel]; + + usleep(10000 * operationsToRun); + + @synchronized (self) { + XCTAssert(operationsRun < operationsToRun, @"All operations should not be run."); + } +} + +@end diff --git a/Carthage/Checkouts/PINOperation/Tests/PINOperationQueueTests.m b/Carthage/Checkouts/PINOperation/Tests/PINOperationQueueTests.m new file mode 100644 index 00000000..77f8627d --- /dev/null +++ b/Carthage/Checkouts/PINOperation/Tests/PINOperationQueueTests.m @@ -0,0 +1,528 @@ +// +// PINOperationQueueTests.m +// PINOperation +// +// Created by Garrett Moon on 8/28/16. +// Copyright © 2016 Pinterest. All rights reserved. +// + +#if SWIFT_PACKAGE +@import PINOperation; +#else +#import +#endif + +#import +#import + +static NSTimeInterval PINOperationQueueTestBlockTimeout = 20; + +@interface PINOperationQueueTests : XCTestCase + +@property (nonatomic, strong) PINOperationQueue *queue; + +@end + +static const NSUInteger PINOperationQueueTestsLowestMaxOperations = 1; +static const NSUInteger PINOperationQueueTestsMaxOperations = 5; + +@implementation PINOperationQueueTests + +- (void)setUp +{ + [super setUp]; + self.queue = [[PINOperationQueue alloc] initWithMaxConcurrentOperations:PINOperationQueueTestsMaxOperations]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown +{ + // Put teardown code here. This method is called after the invocation of each test method in the class. + self.queue = nil; + [super tearDown]; +} + +- (dispatch_time_t)timeout +{ + return dispatch_time(DISPATCH_TIME_NOW, (int64_t)(PINOperationQueueTestBlockTimeout * NSEC_PER_SEC)); +} + +- (void)testAllOperationsRun +{ + const NSUInteger operationCount = 100; + dispatch_group_t group = dispatch_group_create(); + + for (NSUInteger count = 0; count < operationCount; count++) { + dispatch_group_enter(group); + [self.queue scheduleOperation:^{ + dispatch_group_leave(group); + } withPriority:PINOperationQueuePriorityDefault]; + } + + NSUInteger success = dispatch_group_wait(group, [self timeout]); + XCTAssert(success == 0, @"Timed out before completing 100 operations"); +} + +- (void)testAllOperationsReleased +{ + const NSUInteger operationCount = 100; + NSPointerArray *weakOperationPointers = [NSPointerArray weakObjectsPointerArray]; + + for (int i = 0; i < operationCount; i++) { + @autoreleasepool { + dispatch_block_t operation = ^{ + usleep(i); + }; + + [weakOperationPointers addPointer:(__bridge void * _Nullable)(operation)]; + [self.queue scheduleOperation:operation withPriority:PINOperationQueuePriorityDefault]; + } + } + + [self.queue waitUntilAllOperationsAreFinished]; + + // Autorelease pool is drained at the end of each run loop + // Dispatch to the next loop before asserting that all blocks are gone + XCTestExpectation *expectation = [self expectationWithDescription:@"next run loop expectation"]; + dispatch_async(dispatch_get_main_queue(), ^{ + [expectation fulfill]; + }); + + [self waitForExpectationsWithTimeout:10 handler:nil]; + XCTAssertEqual(0, weakOperationPointers.allObjects.count); +} + +- (void)testWaitUntilAllOperationsFinished +{ + const NSUInteger operationCount = 100; + __block NSInteger operationsRun = 0; + + __weak PINOperationQueueTests *weakSelf = self; + for (NSUInteger count = 0; count < operationCount; count++) { + [self.queue scheduleOperation:^{ + __strong PINOperationQueueTests *strongSelf = weakSelf; + @synchronized (strongSelf) { + operationsRun += 1; + } + } withPriority:PINOperationQueuePriorityDefault]; + } + + [self.queue waitUntilAllOperationsAreFinished]; + + XCTAssert(operationCount == operationsRun, @"Timed out before completing 100 operations"); +} + +- (void)testWaitUntilAllOperationsFinishedWithNestedOperations +{ + const NSUInteger operationCount = 100; + + __block NSInteger operationsRun = 0; + for (NSUInteger count = 0; count < operationCount; count++) { + __weak PINOperationQueueTests *weakSelf = self; + [self.queue scheduleOperation:^{ + __strong PINOperationQueueTests *strongSelf = weakSelf; + @synchronized (strongSelf) { + operationsRun += 1; + } + [strongSelf.queue scheduleOperation:^{ + __strong PINOperationQueueTests *strongSelf = weakSelf; + @synchronized (strongSelf) { + operationsRun += 1; + } + } withPriority:PINOperationQueuePriorityHigh]; + } withPriority:PINOperationQueuePriorityDefault]; + } + + [self.queue waitUntilAllOperationsAreFinished]; + + XCTAssert(operationsRun == (operationCount*2), @"Timed out before completing 100 operations"); +} + +- (void)helperConfirmMaxOperations:(NSUInteger)maxOperations queue:(PINOperationQueue *)queue +{ + const NSUInteger operationCount = 100; + dispatch_group_t group = dispatch_group_create(); + + __block NSUInteger runningOperationCount = 0; + __block BOOL operationCountMaxedOut = NO; + + XCTAssert(queue.maxConcurrentOperations == maxOperations, @"Max concurrent operations not correctly set."); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + for (NSUInteger count = 0; count < operationCount; count++) { + dispatch_group_enter(group); + [queue scheduleOperation:^{ + @synchronized (self) { + runningOperationCount++; + if (runningOperationCount == maxOperations) { + operationCountMaxedOut = YES; + } + XCTAssert(runningOperationCount <= maxOperations, @"Running too many operations at once: %lu", (unsigned long)runningOperationCount); + } + + usleep(10000); + + @synchronized (self) { + runningOperationCount--; + XCTAssert(runningOperationCount <= maxOperations, @"Running too many operations at once: %lu", (unsigned long)runningOperationCount); + } + + dispatch_group_leave(group); + } withPriority:PINOperationQueuePriorityDefault]; + } +#pragma clang diagnostic pop + + NSUInteger success = dispatch_group_wait(group, [self timeout]); + XCTAssert(success == 0, @"Timed out before completing 100 operations"); + XCTAssert(operationCountMaxedOut == YES, @"Never reached maximum number of concurrent operations: %lu", (unsigned long)maxOperations); +} + +- (void)testMaximumNumberOfConcurrentOperations +{ + [self helperConfirmMaxOperations:PINOperationQueueTestsMaxOperations queue:self.queue]; +} + +- (void)testMaximumNumberOfConcurrentOperationsIsOne +{ + self.queue = [[PINOperationQueue alloc] initWithMaxConcurrentOperations:PINOperationQueueTestsLowestMaxOperations]; + [self helperConfirmMaxOperations:PINOperationQueueTestsLowestMaxOperations queue:self.queue]; +} + +//We expect operations to run in priority order when added in that order as well +- (void)testPriority +{ + const NSUInteger highOperationCount = 100; + const NSUInteger defaultOperationCount = 100; + const NSUInteger lowOperationCount = 100; + + __block NSUInteger highOperationComplete = 0; + __block NSUInteger defaultOperationComplete = 0; + __block NSUInteger lowOperationComplete = 0; + + dispatch_group_t group = dispatch_group_create(); + + //This is actually a pretty annoying unit test to write. Because multiple operations are allowed to be concurrent, lower priority operations can potentially repeatidly + //obtain the lock while higher priority operations wait… So I'm attempting to make the operations less about lock contention and more about the length of time they take + //to execute and adding a sleep before they obtain the lock to hopefully improve reliability. + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + for (NSUInteger count = 0; count < highOperationCount; count++) { + dispatch_group_enter(group); + [self.queue scheduleOperation:^{ + usleep(10000); + @synchronized (self) { + ++highOperationComplete; + XCTAssert(defaultOperationComplete <= PINOperationQueueTestsMaxOperations, @"Running default operations before high. Default operations complete: %lu", (unsigned long)defaultOperationComplete); + XCTAssert(lowOperationComplete <= PINOperationQueueTestsMaxOperations, @"Running low operations before high. Low operations complete: %lu", (unsigned long)lowOperationComplete); + } + dispatch_group_leave(group); + } withPriority:PINOperationQueuePriorityHigh]; + } + + for (NSUInteger count = 0; count < defaultOperationCount; count++) { + dispatch_group_enter(group); + [self.queue scheduleOperation:^{ + usleep(10000); + @synchronized (self) { + ++defaultOperationComplete; + XCTAssert(lowOperationComplete <= PINOperationQueueTestsMaxOperations, @"Running low operations before default. Low operations complete: %lu", (unsigned long)lowOperationComplete); + XCTAssert(highOperationComplete > highOperationCount - PINOperationQueueTestsMaxOperations, @"Running high operations after default. High operations complete: %lu", (unsigned long)highOperationComplete); + } + dispatch_group_leave(group); + } withPriority:PINOperationQueuePriorityDefault]; + } + + for (NSUInteger count = 0; count < lowOperationCount; count++) { + dispatch_group_enter(group); + [self.queue scheduleOperation:^{ + usleep(10000); + @synchronized (self) { + ++lowOperationComplete; + XCTAssert(defaultOperationComplete > defaultOperationCount - PINOperationQueueTestsMaxOperations, @"Running default operations after low. Default operations complete: %lu", (unsigned long)defaultOperationComplete); + XCTAssert(highOperationComplete > highOperationCount - PINOperationQueueTestsMaxOperations, @"Running high operations after low. High operations complete: %lu", (unsigned long)highOperationComplete); + } + dispatch_group_leave(group); + } withPriority:PINOperationQueuePriorityLow]; + } +#pragma clang diagnostic pop + + NSUInteger success = dispatch_group_wait(group, [self timeout]); + XCTAssert(success == 0, @"Timed out"); +} + +//We expect low priority operations to eventually run even if the queue is continually kept full with higher priority operations +- (void)testOutOfOrderOperations +{ + const NSUInteger operationCount = 100; + dispatch_group_t group = dispatch_group_create(); + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + for (NSUInteger count = 0; count < PINOperationQueueTestsMaxOperations + 1; count++) { + [self.queue scheduleOperation:^{ + [self recursivelyAddOperation]; + } withPriority:PINOperationQueuePriorityHigh]; + } +#pragma clang diagnostic pop + + for (NSUInteger count = 0; count < operationCount; count++) { + dispatch_group_enter(group); + [self.queue scheduleOperation:^{ + dispatch_group_leave(group); + } withPriority:PINOperationQueuePriorityLow]; + } + + NSUInteger success = dispatch_group_wait(group, [self timeout]); + XCTAssert(success == 0, @"Timed out"); +} + +- (void)recursivelyAddOperation +{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + [self.queue scheduleOperation:^{ + [self recursivelyAddOperation]; + } withPriority:PINOperationQueuePriorityHigh]; +#pragma clang diagnostic pop +} + +- (void)testCancelation +{ + const NSUInteger sleepTime = 100000; + for (NSUInteger count = 0; count < PINOperationQueueTestsMaxOperations + 1; count++) { + [self.queue scheduleOperation:^{ + usleep(sleepTime); + } withPriority:PINOperationQueuePriorityDefault]; + } + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + id operation = [self.queue scheduleOperation:^{ + XCTAssertTrue(NO, @"operation should have been canceled"); + } withPriority:PINOperationQueuePriorityDefault]; +#pragma clang diagnostics pop + + [self.queue cancelOperation:operation]; + + usleep(sleepTime * (PINOperationQueueTestsMaxOperations + 1)); +} + +- (void)testChangingPriority +{ + const NSUInteger defaultOperationCount = 100; + + __block NSUInteger defaultOperationComplete = 0; + + dispatch_group_t group = dispatch_group_create(); + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + for (NSUInteger count = 0; count < defaultOperationCount; count++) { + dispatch_group_enter(group); + [self.queue scheduleOperation:^{ + usleep(100); + @synchronized (self) { + ++defaultOperationComplete; + } + dispatch_group_leave(group); + } withPriority:PINOperationQueuePriorityDefault]; + } + + dispatch_group_enter(group); + id operation = [self.queue scheduleOperation:^{ + @synchronized (self) { + //Make sure we're less than defaultOperationCount - PINOperationQueueTestsMaxOperations because this operation could start even while the others are running even + //if started last. + XCTAssert(defaultOperationComplete < defaultOperationCount - PINOperationQueueTestsMaxOperations, @"operation was not completed before default operations even though reprioritized."); + } + dispatch_group_leave(group); + } withPriority:PINOperationQueuePriorityLow]; +#pragma clang diagnostic pop + [self.queue setOperationPriority:PINOperationQueuePriorityHigh withReference:operation]; + + NSUInteger success = dispatch_group_wait(group, [self timeout]); + XCTAssert(success == 0, @"Timed out"); +} + +- (void)testCoalescingOperations +{ + self.queue = [[PINOperationQueue alloc] initWithMaxConcurrentOperations:PINOperationQueueTestsMaxOperations]; + + const NSUInteger totalOperationCount = 100; + dispatch_group_t group = dispatch_group_create(); + + NSString *normalDesc = @"Normal"; + NSString *coallescedDesc = @"Coallesced"; + NSArray *descs = @[normalDesc, coallescedDesc]; + + __block NSMutableDictionary *operationCount = [NSMutableDictionary dictionaryWithObjectsAndKeys:@(0), normalDesc, @(0), coallescedDesc, nil]; + __block NSMutableDictionary *operationRun = [NSMutableDictionary dictionaryWithObjectsAndKeys:@(0), normalDesc, @(0), coallescedDesc, nil]; + __block NSMutableDictionary *operationComplete = [NSMutableDictionary dictionaryWithObjectsAndKeys:@(0), normalDesc, @(0), coallescedDesc, nil]; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + // Fill up the queue with dummy operations so we have time to add real ones without them being unexpectedly executed + for (NSUInteger i = 0; i < PINOperationQueueTestsMaxOperations * 2; i++) { + dispatch_group_enter(group); + [self.queue scheduleOperation:^{ + usleep(1000); + dispatch_group_leave(group); + }]; + } + + for (NSUInteger i = 0; i < totalOperationCount; i++) { + dispatch_group_enter(group); + + NSString *desc = descs[i % descs.count]; + BOOL isNormalOperation = [desc isEqualToString:normalDesc]; + + NSString *identifier = desc; + if (isNormalOperation) { + identifier = [NSString stringWithFormat:@"%@ %tu", desc, i]; + } + + operationCount[desc] = @([operationCount[desc] intValue] + 1); + + PINOperationBlock operation = ^(id _Nullable data) { + @synchronized (self) { + operationRun[desc] = @([operationRun[desc] intValue] + 1); + } + }; + + dispatch_block_t completion = ^{ + @synchronized (self) { + operationComplete[desc] = @([operationComplete[desc] intValue] + 1); + } + dispatch_group_leave(group); + }; + + [self.queue scheduleOperation:operation + withPriority:PINOperationQueuePriorityLow + identifier:identifier + coalescingData:nil + dataCoalescingBlock:nil + completion:completion]; + } +#pragma clang diagnostic pop + + NSUInteger success = dispatch_group_wait(group, [self timeout]); + XCTAssert(success == 0, @"Timed out"); + XCTAssert([operationRun[normalDesc] intValue] == [operationCount[normalDesc] intValue]); + XCTAssert([operationComplete[normalDesc] intValue] == [operationCount[normalDesc] intValue]); + XCTAssert([operationRun[coallescedDesc] intValue] == 1); + XCTAssert([operationComplete[coallescedDesc] intValue] == [operationCount[coallescedDesc] intValue]); +} + +- (void)testCoalescingOperationCompletions +{ + dispatch_group_t group = dispatch_group_create(); + + NSArray *completionFlags = @[@(NO), @(NO), @(YES), @(NO), @(YES)]; + NSIndexSet *expectedCompletedIndexSet = [completionFlags indexesOfObjectsPassingTest:^BOOL(NSNumber * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { return [obj boolValue]; }]; + NSMutableIndexSet *completedIndexSet = [NSMutableIndexSet indexSet]; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + // Fill up the queue with dummy operations so we have time to add real ones without them being unexpectedly executed + for (NSUInteger i = 0; i < PINOperationQueueTestsMaxOperations * 2; i++) { + dispatch_group_enter(group); + [self.queue scheduleOperation:^{ + usleep(1000); + dispatch_group_leave(group); + }]; + } + + for (NSUInteger i = 0; i < completionFlags.count; i++) { + dispatch_group_enter(group); + + PINOperationBlock operation = ^(id _Nullable data) { + for (NSNumber *hasCompletion in completionFlags) { + if ([hasCompletion boolValue] == NO) { + dispatch_group_leave(group); + } + } + }; + + dispatch_block_t completion = [completionFlags[i] boolValue] == NO ? nil : ^{ + XCTAssert([expectedCompletedIndexSet containsIndex:i]); + @synchronized (self) { + [completedIndexSet addIndex:i]; + } + dispatch_group_leave(group); + }; + + [self.queue scheduleOperation:operation + withPriority:PINOperationQueuePriorityLow + identifier:@"Identifier" + coalescingData:nil + dataCoalescingBlock:nil + completion:completion]; + } +#pragma clang diagnostic pop + + NSUInteger success = dispatch_group_wait(group, [self timeout]); + XCTAssert(success == 0, @"Timed out"); + XCTAssert([completedIndexSet isEqual:expectedCompletedIndexSet]); +} + +- (void)testCoalescingOperationData +{ + dispatch_group_t group = dispatch_group_create(); + + NSArray *dataset = @[@(100), @(50), @(50), @(100), @(10)]; + NSNumber *expectedData = [dataset sortedArrayUsingSelector:@selector(compare:)][0]; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + // Fill up the queue with dummy operations so we have time to add real ones without them being unexpectedly executed + for (NSUInteger i = 0; i < PINOperationQueueTestsMaxOperations * 2; i++) { + dispatch_group_enter(group); + [self.queue scheduleOperation:^{ + usleep(1000); + dispatch_group_leave(group); + }]; + } + + for (NSNumber *data in dataset) { + dispatch_group_enter(group); + + PINOperationBlock operation = ^(id _Nullable obj) { + XCTAssert([expectedData compare:obj] == NSOrderedSame); + }; + + PINOperationDataCoalescingBlock dataCoalescingBlock = ^id(id existingData, id newData) { + NSComparisonResult result = [existingData compare:newData]; + return (result == NSOrderedDescending) ? newData : existingData; + }; + + dispatch_block_t completion = ^{ + dispatch_group_leave(group); + }; + + [self.queue scheduleOperation:operation + withPriority:PINOperationQueuePriorityLow + identifier:@"Identifier" + coalescingData:data + dataCoalescingBlock:dataCoalescingBlock + completion:completion]; + } +#pragma clang diagnostic pop + + NSUInteger success = dispatch_group_wait(group, [self timeout]); + XCTAssert(success == 0, @"Timed out"); +} + +- (void)testChangingMaximumNumberOfOperations +{ + PINOperationQueue *queue = [[PINOperationQueue alloc] initWithMaxConcurrentOperations:2]; + [self helperConfirmMaxOperations:2 queue:queue]; + queue.maxConcurrentOperations = 4; + usleep(10000); + [self helperConfirmMaxOperations:4 queue:queue]; + queue.maxConcurrentOperations = 2; + usleep(10000); + [self helperConfirmMaxOperations:2 queue:queue]; +} + +@end diff --git a/Carthage/Checkouts/PINOperation/build_docs.sh b/Carthage/Checkouts/PINOperation/build_docs.sh new file mode 100755 index 00000000..8566ae2e --- /dev/null +++ b/Carthage/Checkouts/PINOperation/build_docs.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh + +appledoc \ + --company-id com.pinterest \ + --project-name PINOperation \ + --project-company Pinterest \ + --project-version 1.0 \ + --docset-min-xcode-version 4.3 \ + --docset-bundle-id %COMPANYID.%PROJECTID \ + --docset-bundle-name "%PROJECT %VERSION" \ + --docset-bundle-filename %COMPANYID.%PROJECTID-%VERSIONID.docset \ + --ignore "tests" \ + --ignore "docs" \ + --ignore "*.m" \ + --no-repeat-first-par \ + --explicit-crossref \ + --clean-output \ + --keep-intermediate-files \ + --output ./docs \ + . + +mv docs/docset docs/com.pinterest.PINOperation-1.0.docset +rm docs/docset-installed.txt diff --git a/Carthage/Checkouts/PINOperation/build_tests.sh b/Carthage/Checkouts/PINOperation/build_tests.sh new file mode 100755 index 00000000..79b6386a --- /dev/null +++ b/Carthage/Checkouts/PINOperation/build_tests.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env sh + +# Have to specify destination because http://www.openradar.me/23857648 +xcodebuild ONLY_ACTIVE_ARCH=NO -project tests/PINOperation.xcodeproj -scheme PINOperationTests -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 15,OS=latest' clean build test diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Info.plist b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Info.plist new file mode 100644 index 00000000..3f0c2925 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleIdentifier + com.pinterest.PINOperationQueue + CFBundleName + PINOperationQueue 1.0 + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1.0 + + + + + DocSetFeedName + PINOperationQueue Documentation + + DocSetMinimumXcodeVersion + 4.3 + + DashDocSetFamily + appledoc + DocSetPublisherIdentifier + com.pinterest.documentation + DocSetPublisherName + Pinterest + NSHumanReadableCopyright + Copyright © 2017 Pinterest. All rights reserved. + + diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/Blocks/PINOperationBlock.html b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/Blocks/PINOperationBlock.html new file mode 100644 index 00000000..b7481d79 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/Blocks/PINOperationBlock.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINOperationQueue +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/Constants/PINOperationQueuePriority.html b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/Constants/PINOperationQueuePriority.html new file mode 100644 index 00000000..810f085f --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/Constants/PINOperationQueuePriority.html @@ -0,0 +1,145 @@ + + + + + + + + + + + + +
+
+ +

+ PINOperationQueue +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +

PINOperationQueuePriority

+ +
+ + +

Definition

+ typedef NS_ENUM(NSUInteger, PINOperationQueuePriority ) {
+ +    PINOperationQueuePriorityLow,
+ +    PINOperationQueuePriorityDefault,
+ +    PINOperationQueuePriorityHigh,
+ + };
+ +
+ +
+

Constants

+
+ +
PINOperationQueuePriorityLow
+
+ + +

+ PINOperationQueue.h. +

+ +
+ +
PINOperationQueuePriorityDefault
+
+ + +

+ PINOperationQueue.h. +

+ +
+ +
PINOperationQueuePriorityHigh
+
+ + +

+ PINOperationQueue.h. +

+ +
+ +
+
+ + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/Protocols/PINOperationReference.html b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/Protocols/PINOperationReference.html new file mode 100644 index 00000000..b7481d79 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/Protocols/PINOperationReference.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINOperationQueue +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_index.scss b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_index.scss new file mode 100644 index 00000000..7e98029d --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_index.scss @@ -0,0 +1,13 @@ +.index-container { + display: flex; + flex-direction: row; + flex-wrap: wrap; + + @media (max-width: $mobile-max-width) { + flex-direction: column; + } + + .index-column { + flex: 1 1 33%; + } +} diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_layout.scss b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_layout.scss new file mode 100644 index 00000000..40bd6d4a --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_layout.scss @@ -0,0 +1,303 @@ +* { + box-sizing: border-box; +} + +.clear { + clear: both; +} + +.clearfix { + &:before, &:after { + clear: both; + display: table; + content: ""; + } +} + +.xcode .hide-in-xcode { + display: none; +} + +body { + font: 62.5% $body-font; + background: $body-background; +} + +h1, h2, h3 { + font-weight: 300; + color: #808080; +} + +h1 { + font-size: 2em; + color: #000; +} + +h4 { + font-size: 13px; + line-height: 1.5; + margin: 21px 0 0 0; +} + +a { + color: $tint-color; + text-decoration: none; +} + +pre, code { + font-family: $code-font; + word-wrap: break-word; +} + +pre > code, .method-declaration code { + display: inline-block; + font-size: .85em; + padding: 4px 0 4px 10px; + border-left: 5px solid rgba(0, 155, 51, .2); + + &:before { + content: "Objective-C"; + display: block; + + font: 9px/1 $body-font; + color: #009b33; + text-transform: uppercase; + letter-spacing: 2px; + padding-bottom: 6px; + } +} + +pre > code { + font-size: inherit; +} + +table, th, td { + border: 1px solid #e9e9e9; +} + +table { + width: 100%; +} + +th, td { + padding: 7px; + + > :first-child { + margin-top: 0; + } + + > :last-child { + margin-bottom: 0; + } +} + +.container { + @extend .clearfix; + + max-width: 980px; + padding: 0 10px; + margin: 0 auto; + + @media (max-width: $mobile-max-width) { + padding: 0; + } +} + +header { + position: fixed; + top: 0; + left: 0; + width: 100%; + z-index: 2; + + background: #414141; + color: #fff; + font-size: 1.1em; + line-height: 25px; + letter-spacing: .05em; + + #library-title { + float: left; + } + + #developer-home { + float: right; + } + + h1 { + font-size: inherit; + font-weight: inherit; + margin: 0; + } + + p { + margin: 0; + } + + h1, a { + color: inherit; + } + + @media (max-width: $mobile-max-width) { + position: absolute; + + .container { + padding: 0 10px; + } + } +} + +aside { + position: fixed; + top: 25px; + left: 0; + width: 100%; + height: 25px; + z-index: 2; + + font-size: 1.1em; + + @media (max-width: $mobile-max-width) { + position: absolute; + } + + #header-buttons { + background: rgba(255, 255, 255, .8); + margin: 0 1px; + padding: 0; + list-style: none; + text-align: right; + line-height: 32px; + + li { + display: inline-block; + cursor: pointer; + padding: 0 10px; + } + + label, select { + cursor: inherit; + } + + #on-this-page { + position: relative; + + .chevron { + display: inline-block; + width: 14px; + height: 4px; + position: relative; + + .chevy { + background: #878787; + height: 2px; + position: absolute; + width: 10px; + + &.chevron-left { + left: 0; + transform: rotateZ(45deg) scale(0.6); + } + + &.chevron-right { + right: 0; + transform: rotateZ(-45deg) scale(0.6); + } + } + } + + #jump-to { + opacity: 0; + font-size: 16px; + + position: absolute; + top: 5px; + left: 0; + width: 100%; + height: 100%; + } + } + } +} + +article { + margin-top: 25px; + + #content { + @extend .clearfix; + + background: $content-background; + border: 1px solid $content-border; + padding: 15px 25px 30px 25px; + + font-size: 1.4em; + line-height: 1.45; + + position: relative; + + @media (max-width: $mobile-max-width) { + padding: 15px 10px 20px 10px; + } + + .navigation-top { + position: absolute; + top: 15px; + right: 25px; + } + + .title { + margin: 21px 0 0 0; + padding: 15px 0; + } + + p { + color: #414141; + margin: 0 0 15px 0; + } + + th, td { + p:last-child { + margin-bottom: 0; + } + } + + main { + ul { + list-style: none; + margin-left: 24px; + margin-bottom: 12px; + padding: 0; + + li { + position: relative; + padding-left: 1.3em; + + &:before { + content: "\02022"; + + color: #414141; + font-size: 1.08em; + line-height: 1; + + position: absolute; + left: 0; + padding-top: 2px; + } + } + } + } + + footer { + @extend .clearfix; + + .footer-copyright { + margin: 70px 25px 10px 0; + } + + p { + font-size: .71em; + color: #a0a0a0; + } + } + } +} diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_normalize.scss b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_normalize.scss new file mode 100644 index 00000000..9b8848a5 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_normalize.scss @@ -0,0 +1,581 @@ +/* ========================================================================== + Normalize.scss settings + ========================================================================== */ +/** + * Includes legacy browser support IE6/7 + * + * Set to false if you want to drop support for IE6 and IE7 + */ + +$legacy_browser_support: false !default; + +/* Base + ========================================================================== */ + +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + * 3. Corrects text resizing oddly in IE 6/7 when body `font-size` is set using + * `em` units. + */ + +html { + font-family: sans-serif; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ + @if $legacy_browser_support { + *font-size: 100%; /* 3 */ + } +} + +/** + * Remove default margin. + */ + +body { + margin: 0; +} + +/* HTML5 display definitions + ========================================================================== */ + +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} + +/** + * 1. Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ + +audio, +canvas, +progress, +video { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ + @if $legacy_browser_support { + *display: inline; + *zoom: 1; + } +} + +/** + * Prevents modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ + +[hidden], +template { + display: none; +} + +/* Links + ========================================================================== */ + +/** + * Remove the gray background color from active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ + +a { + &:active, &:hover { + outline: 0; + }; +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +@if $legacy_browser_support { + blockquote { + margin: 1em 40px; + } +} + +/** + * Address styling not present in Safari and Chrome. + */ + +dfn { + font-style: italic; +} + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +@if $legacy_browser_support { + h2 { + font-size: 1.5em; + margin: 0.83em 0; + } + + h3 { + font-size: 1.17em; + margin: 1em 0; + } + + h4 { + font-size: 1em; + margin: 1.33em 0; + } + + h5 { + font-size: 0.83em; + margin: 1.67em 0; + } + + h6 { + font-size: 0.67em; + margin: 2.33em 0; + } +} + +/** + * Addresses styling not present in IE 8/9. + */ + +mark { + background: #ff0; + color: #000; +} + +@if $legacy_browser_support { + + /** + * Addresses margins set differently in IE 6/7. + */ + + p, + pre { + *margin: 1em 0; + } + + /* + * Addresses CSS quotes not supported in IE 6/7. + */ + + q { + *quotes: none; + } + + /* + * Addresses `quotes` property not supported in Safari 4. + */ + + q:before, + q:after { + content: ''; + content: none; + } +} + +/** + * Address inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +@if $legacy_browser_support { + + /* ========================================================================== + Lists + ========================================================================== */ + + /* + * Addresses margins set differently in IE 6/7. + */ + + dl, + menu, + ol, + ul { + *margin: 1em 0; + } + + dd { + *margin: 0 0 0 40px; + } + + /* + * Addresses paddings set differently in IE 6/7. + */ + + menu, + ol, + ul { + *padding: 0 0 0 40px; + } + + /* + * Corrects list images handled incorrectly in IE 7. + */ + + nav ul, + nav ol { + *list-style: none; + *list-style-image: none; + } + +} + +/* Embedded content + ========================================================================== */ + +/** + * 1. Remove border when inside `a` element in IE 8/9/10. + * 2. Improves image quality when scaled in IE 7. + */ + +img { + border: 0; + @if $legacy_browser_support { + *-ms-interpolation-mode: bicubic; /* 2 */ + } +} + +/** + * Correct overflow not hidden in IE 9/10/11. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Grouping content + ========================================================================== */ + +/** + * Address margin not present in IE 8/9 and Safari. + */ + +figure { + margin: 1em 40px; +} + +/** + * Address differences between Firefox and other browsers. + */ + +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +/** + * Contain overflow in all browsers. + */ + +pre { + overflow: auto; +} + +/** + * Address odd `em`-unit font size rendering in all browsers. + * Correct font family set oddly in IE 6, Safari 4/5, and Chrome. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + @if $legacy_browser_support { + _font-family: 'courier new', monospace; + } + font-size: 1em; +} + +/* Forms + ========================================================================== */ + +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ + +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + * 4. Improves appearance and consistency in all browsers. + */ + +button, +input, +optgroup, +select, +textarea { + color: inherit; /* 1 */ + font: inherit; /* 2 */ + margin: 0; /* 3 */ + @if $legacy_browser_support { + vertical-align: baseline; /* 3 */ + *vertical-align: middle; /* 3 */ + } +} + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ + +button { + overflow: visible; +} + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ + +button, +select { + text-transform: none; +} + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + * 4. Removes inner spacing in IE 7 without affecting normal text inputs. + * Known issue: inner spacing remains in IE 6. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ + @if $legacy_browser_support { + *overflow: visible; /* 4 */ + } +} + +/** + * Re-set default cursor for disabled elements. + */ + +button[disabled], +html input[disabled] { + cursor: default; +} + +/** + * Remove inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +input { + line-height: normal; +} + +/** + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + * Known issue: excess padding remains in IE 6. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ + @if $legacy_browser_support { + *height: 13px; /* 3 */ + *width: 13px; /* 3 */ + } +} + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ + +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; /* 2 */ + box-sizing: content-box; +} + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + * 3. Corrects text not wrapping in Firefox 3. + * 4. Corrects alignment displayed oddly in IE 6/7. + */ + +legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ + @if $legacy_browser_support { + white-space: normal; /* 3 */ + *margin-left: -7px; /* 4 */ + } +} + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ + +textarea { + overflow: auto; +} + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ + +optgroup { + font-weight: bold; +} + +/* Tables + ========================================================================== */ + +/** + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} + +td, +th { + padding: 0; +} diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_object.scss b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_object.scss new file mode 100644 index 00000000..22eebd87 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_object.scss @@ -0,0 +1,89 @@ +.section-specification { + table { + width: auto; + + th { + text-align: left; + } + } +} + +.method-title { + margin-left: -15px; + margin-bottom: 8px; + transition: margin-left .3s ease-out; + + .section-method.hide & { + margin-left: 0; + } + + code { + font-weight: 400; + font-size: .85em; + } +} + +.method-info { + background: $object-background; + border-bottom: 1px solid $object-border; + margin: 0 -25px; + padding: 20px 25px 0 25px; + transition: height .3s ease-out; + + position: relative; + + .pointy-thing { + background: $content-background; + height: 10px; + border-bottom: 1px solid $object-border; + margin: -20px -25px 16px -25px; + + &:before { + display: inline-block; + content: ""; + + background: $object-background; + border: 1px solid $object-border; + border-bottom: 0; + border-right: 0; + + position: absolute; + left: 21px; + top: 3px; + width: 12px; + height: 12px; + transform: rotate(45deg); + } + } + + .method-subsection { + margin-bottom: 15px; + + .argument-name { + width: 1px; + text-align: right; + + code { + color: #808080; + font-style: italic; + font-weight: 400; + } + } + } +} + +.section-method { + &.hide .method-info { + height: 0 !important; + overflow: hidden; + display: none; + } + + &.hide.animating .method-info { + display: block; + } + + &.animating .method-info { + overflow: hidden; + } +} diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_print.scss b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_print.scss new file mode 100644 index 00000000..61bdf99f --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_print.scss @@ -0,0 +1,42 @@ +@media print { + body { + background: #fff; + padding: 8px; + } + + header { + position: static; + background: #fff; + color: #000; + } + + aside { + display: none; + } + + .container { + max-width: none; + padding: 0; + } + + article { + margin-top: 0; + + #content { + border: 0; + background: #fff; + padding: 15px 0 0 0; + + .title { + margin-top: 0; + padding-top: 0; + } + } + } + + .method-info { + &, & .pointy-thing { + background: #fff; + } + } +} diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_variables.scss b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_variables.scss new file mode 100644 index 00000000..cbaff3cf --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_variables.scss @@ -0,0 +1,11 @@ +$body-font: -apple-system-font, "Helvetica Neue", Helvetica, sans-serif; +$code-font: "Source Code Pro", Monaco, Menlo, Consolas, monospace; + +$body-background: #f2f2f2; +$content-background: #fff; +$content-border: #e9e9e9; +$tint-color: #08c; +$object-background: #f9f9f9; +$object-border: #e9e9e9; + +$mobile-max-width: 650px; diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_xcode.scss b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_xcode.scss new file mode 100644 index 00000000..340b1f6b --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/_xcode.scss @@ -0,0 +1,29 @@ +.xcode { + header, aside { + display: none; + } + + .container { + padding: 0; + } + + article { + margin-top: 0; + + #content { + border: 0; + margin: 0; + } + } + + .method-info { + &, .section-method.hide & { + max-height: auto; + overflow: visible; + + &.hiding { + display: block; + } + } + } +} diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/style.scss b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/style.scss new file mode 100644 index 00000000..648a6086 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/css/scss/style.scss @@ -0,0 +1 @@ +@import "variables", "normalize", "layout", "index", "object", "print", "xcode"; diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/hierarchy.html b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/hierarchy.html new file mode 100644 index 00000000..9bd0aa1f --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/hierarchy.html @@ -0,0 +1,82 @@ + + + + + + + + + + + + +
+
+ +

+ PINOperationQueue +

+ +

+ Pinterest +

+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/button_bar_background.png b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/button_bar_background.png new file mode 100644 index 00000000..71d1019b Binary files /dev/null and b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/button_bar_background.png differ diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/disclosure.png b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/disclosure.png new file mode 100644 index 00000000..4c5cbf44 Binary files /dev/null and b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/disclosure.png differ diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/disclosure_open.png b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/disclosure_open.png new file mode 100644 index 00000000..82396fed Binary files /dev/null and b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/disclosure_open.png differ diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/library_background.png b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/library_background.png new file mode 100644 index 00000000..3006248a Binary files /dev/null and b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/library_background.png differ diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/title_background.png b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/title_background.png new file mode 100644 index 00000000..846e4968 Binary files /dev/null and b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/img/title_background.png differ diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/index.html b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/index.html new file mode 100644 index 00000000..fbc5d19d --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/index.html @@ -0,0 +1,90 @@ + + + + + + + + + + + + +
+
+ +

+ PINOperationQueue +

+ +

+ Pinterest +

+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/js/script.js b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/js/script.js new file mode 100644 index 00000000..ca915ee4 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Documents/js/script.js @@ -0,0 +1,58 @@ +function $() { + return document.querySelector.apply(document, arguments); +} + +if (navigator.userAgent.indexOf("Xcode") != -1) { + document.documentElement.classList.add("xcode"); +} + +var jumpTo = $("#jump-to"); + +if (jumpTo) { + jumpTo.addEventListener("change", function(e) { + location.hash = this.options[this.selectedIndex].value; + }); +} + +function hashChanged() { + if (/^#\/\/api\//.test(location.hash)) { + var element = document.querySelector("a[name='" + location.hash.substring(1) + "']"); + + if (!element) { + return; + } + + element = element.parentNode; + + element.classList.remove("hide"); + fixScrollPosition(element); + } +} + +function fixScrollPosition(element) { + var scrollTop = element.offsetTop - 150; + document.documentElement.scrollTop = scrollTop; + document.body.scrollTop = scrollTop; +} + +[].forEach.call(document.querySelectorAll(".section-method"), function(element) { + element.classList.add("hide"); + + element.querySelector(".method-title a").addEventListener("click", function(e) { + var info = element.querySelector(".method-info"), + infoContainer = element.querySelector(".method-info-container"); + + element.classList.add("animating"); + info.style.height = (infoContainer.clientHeight + 40) + "px"; + fixScrollPosition(element); + element.classList.toggle("hide"); + + setTimeout(function() { + element.classList.remove("animating"); + info.style.height = "auto"; + }, 300); + }); +}); + +window.addEventListener("hashchange", hashChanged); +hashChanged(); diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Nodes.xml b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Nodes.xml new file mode 100644 index 00000000..a824d9a5 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Nodes.xml @@ -0,0 +1,67 @@ + + + + + PINOperationQueue + index.html + + + + + + + Protocols + index.html + + + + + + + + + Constants + index.html + + + + + + + + + Blocks + index.html + + + + + + + + + + + + + + + PINOperationReference + Protocols/PINOperationReference.html + + + + + PINOperationQueuePriority + Constants/PINOperationQueuePriority.html + + + + + PINOperationBlock + Blocks/PINOperationBlock.html + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Tokens1.xml b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Tokens1.xml new file mode 100644 index 00000000..03332c47 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Tokens1.xml @@ -0,0 +1,18 @@ + + + + + + //apple_ref/occ/intf/PINOperationReference + Cancels all queued operations + PINOperationQueue.h + + + + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Tokens2.xml b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Tokens2.xml new file mode 100644 index 00000000..b6618281 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Tokens2.xml @@ -0,0 +1,48 @@ + + + + + + //apple_ref/c/tdef/PINOperationQueuePriority + + PINOperationQueue.h + + + + + + + + + //apple_ref/c/econst/PINOperationQueuePriorityLow + + PINOperationQueuePriorityLow + + PINOperationQueue.h + + + + + + //apple_ref/c/econst/PINOperationQueuePriorityDefault + + PINOperationQueuePriorityDefault + + PINOperationQueue.h + + + + + + //apple_ref/c/econst/PINOperationQueuePriorityHigh + + PINOperationQueuePriorityHigh + + PINOperationQueue.h + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Tokens3.xml b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Tokens3.xml new file mode 100644 index 00000000..3fc40bec --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/Tokens3.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.dsidx b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.dsidx new file mode 100644 index 00000000..cf3289f0 Binary files /dev/null and b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.dsidx differ diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.dsidx-shm b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.dsidx-shm new file mode 100644 index 00000000..c6022c76 Binary files /dev/null and b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.dsidx-shm differ diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.dsidx-wal b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.dsidx-wal new file mode 100644 index 00000000..4f824904 Binary files /dev/null and b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.dsidx-wal differ diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.mom b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.mom new file mode 100644 index 00000000..0503cfdd Binary files /dev/null and b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.mom differ diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.skidx b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.skidx new file mode 100644 index 00000000..99e1cd2b Binary files /dev/null and b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.skidx differ diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.toc b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.toc new file mode 100644 index 00000000..2088a3ff Binary files /dev/null and b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.toc differ diff --git a/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.tokencache b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.tokencache new file mode 100644 index 00000000..5118133e Binary files /dev/null and b/Carthage/Checkouts/PINOperation/docs/com.pinterest.PINOperationQueue-1.0.docset/Contents/Resources/docSet.tokencache differ diff --git a/Carthage/Checkouts/PINOperation/docs/html/Blocks/PINOperationBlock.html b/Carthage/Checkouts/PINOperation/docs/html/Blocks/PINOperationBlock.html new file mode 100644 index 00000000..b7481d79 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/html/Blocks/PINOperationBlock.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINOperationQueue +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINOperation/docs/html/Constants/PINOperationQueuePriority.html b/Carthage/Checkouts/PINOperation/docs/html/Constants/PINOperationQueuePriority.html new file mode 100644 index 00000000..810f085f --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/html/Constants/PINOperationQueuePriority.html @@ -0,0 +1,145 @@ + + + + + + + + + + + + +
+
+ +

+ PINOperationQueue +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +

PINOperationQueuePriority

+ +
+ + +

Definition

+ typedef NS_ENUM(NSUInteger, PINOperationQueuePriority ) {
+ +    PINOperationQueuePriorityLow,
+ +    PINOperationQueuePriorityDefault,
+ +    PINOperationQueuePriorityHigh,
+ + };
+ +
+ +
+

Constants

+
+ +
PINOperationQueuePriorityLow
+
+ + +

+ PINOperationQueue.h. +

+ +
+ +
PINOperationQueuePriorityDefault
+
+ + +

+ PINOperationQueue.h. +

+ +
+ +
PINOperationQueuePriorityHigh
+
+ + +

+ PINOperationQueue.h. +

+ +
+ +
+
+ + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINOperation/docs/html/Protocols/PINOperationReference.html b/Carthage/Checkouts/PINOperation/docs/html/Protocols/PINOperationReference.html new file mode 100644 index 00000000..b7481d79 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/html/Protocols/PINOperationReference.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + +
+
+ +

+ PINOperationQueue +

+ +

+ Pinterest +

+ +
+
+ + + +
+
+
+
+

+ + + + + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINOperation/docs/html/css/scss/_index.scss b/Carthage/Checkouts/PINOperation/docs/html/css/scss/_index.scss new file mode 100644 index 00000000..7e98029d --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/html/css/scss/_index.scss @@ -0,0 +1,13 @@ +.index-container { + display: flex; + flex-direction: row; + flex-wrap: wrap; + + @media (max-width: $mobile-max-width) { + flex-direction: column; + } + + .index-column { + flex: 1 1 33%; + } +} diff --git a/Carthage/Checkouts/PINOperation/docs/html/css/scss/_layout.scss b/Carthage/Checkouts/PINOperation/docs/html/css/scss/_layout.scss new file mode 100644 index 00000000..40bd6d4a --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/html/css/scss/_layout.scss @@ -0,0 +1,303 @@ +* { + box-sizing: border-box; +} + +.clear { + clear: both; +} + +.clearfix { + &:before, &:after { + clear: both; + display: table; + content: ""; + } +} + +.xcode .hide-in-xcode { + display: none; +} + +body { + font: 62.5% $body-font; + background: $body-background; +} + +h1, h2, h3 { + font-weight: 300; + color: #808080; +} + +h1 { + font-size: 2em; + color: #000; +} + +h4 { + font-size: 13px; + line-height: 1.5; + margin: 21px 0 0 0; +} + +a { + color: $tint-color; + text-decoration: none; +} + +pre, code { + font-family: $code-font; + word-wrap: break-word; +} + +pre > code, .method-declaration code { + display: inline-block; + font-size: .85em; + padding: 4px 0 4px 10px; + border-left: 5px solid rgba(0, 155, 51, .2); + + &:before { + content: "Objective-C"; + display: block; + + font: 9px/1 $body-font; + color: #009b33; + text-transform: uppercase; + letter-spacing: 2px; + padding-bottom: 6px; + } +} + +pre > code { + font-size: inherit; +} + +table, th, td { + border: 1px solid #e9e9e9; +} + +table { + width: 100%; +} + +th, td { + padding: 7px; + + > :first-child { + margin-top: 0; + } + + > :last-child { + margin-bottom: 0; + } +} + +.container { + @extend .clearfix; + + max-width: 980px; + padding: 0 10px; + margin: 0 auto; + + @media (max-width: $mobile-max-width) { + padding: 0; + } +} + +header { + position: fixed; + top: 0; + left: 0; + width: 100%; + z-index: 2; + + background: #414141; + color: #fff; + font-size: 1.1em; + line-height: 25px; + letter-spacing: .05em; + + #library-title { + float: left; + } + + #developer-home { + float: right; + } + + h1 { + font-size: inherit; + font-weight: inherit; + margin: 0; + } + + p { + margin: 0; + } + + h1, a { + color: inherit; + } + + @media (max-width: $mobile-max-width) { + position: absolute; + + .container { + padding: 0 10px; + } + } +} + +aside { + position: fixed; + top: 25px; + left: 0; + width: 100%; + height: 25px; + z-index: 2; + + font-size: 1.1em; + + @media (max-width: $mobile-max-width) { + position: absolute; + } + + #header-buttons { + background: rgba(255, 255, 255, .8); + margin: 0 1px; + padding: 0; + list-style: none; + text-align: right; + line-height: 32px; + + li { + display: inline-block; + cursor: pointer; + padding: 0 10px; + } + + label, select { + cursor: inherit; + } + + #on-this-page { + position: relative; + + .chevron { + display: inline-block; + width: 14px; + height: 4px; + position: relative; + + .chevy { + background: #878787; + height: 2px; + position: absolute; + width: 10px; + + &.chevron-left { + left: 0; + transform: rotateZ(45deg) scale(0.6); + } + + &.chevron-right { + right: 0; + transform: rotateZ(-45deg) scale(0.6); + } + } + } + + #jump-to { + opacity: 0; + font-size: 16px; + + position: absolute; + top: 5px; + left: 0; + width: 100%; + height: 100%; + } + } + } +} + +article { + margin-top: 25px; + + #content { + @extend .clearfix; + + background: $content-background; + border: 1px solid $content-border; + padding: 15px 25px 30px 25px; + + font-size: 1.4em; + line-height: 1.45; + + position: relative; + + @media (max-width: $mobile-max-width) { + padding: 15px 10px 20px 10px; + } + + .navigation-top { + position: absolute; + top: 15px; + right: 25px; + } + + .title { + margin: 21px 0 0 0; + padding: 15px 0; + } + + p { + color: #414141; + margin: 0 0 15px 0; + } + + th, td { + p:last-child { + margin-bottom: 0; + } + } + + main { + ul { + list-style: none; + margin-left: 24px; + margin-bottom: 12px; + padding: 0; + + li { + position: relative; + padding-left: 1.3em; + + &:before { + content: "\02022"; + + color: #414141; + font-size: 1.08em; + line-height: 1; + + position: absolute; + left: 0; + padding-top: 2px; + } + } + } + } + + footer { + @extend .clearfix; + + .footer-copyright { + margin: 70px 25px 10px 0; + } + + p { + font-size: .71em; + color: #a0a0a0; + } + } + } +} diff --git a/Carthage/Checkouts/PINOperation/docs/html/css/scss/_normalize.scss b/Carthage/Checkouts/PINOperation/docs/html/css/scss/_normalize.scss new file mode 100644 index 00000000..9b8848a5 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/html/css/scss/_normalize.scss @@ -0,0 +1,581 @@ +/* ========================================================================== + Normalize.scss settings + ========================================================================== */ +/** + * Includes legacy browser support IE6/7 + * + * Set to false if you want to drop support for IE6 and IE7 + */ + +$legacy_browser_support: false !default; + +/* Base + ========================================================================== */ + +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + * 3. Corrects text resizing oddly in IE 6/7 when body `font-size` is set using + * `em` units. + */ + +html { + font-family: sans-serif; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ + @if $legacy_browser_support { + *font-size: 100%; /* 3 */ + } +} + +/** + * Remove default margin. + */ + +body { + margin: 0; +} + +/* HTML5 display definitions + ========================================================================== */ + +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} + +/** + * 1. Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ + +audio, +canvas, +progress, +video { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ + @if $legacy_browser_support { + *display: inline; + *zoom: 1; + } +} + +/** + * Prevents modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ + +[hidden], +template { + display: none; +} + +/* Links + ========================================================================== */ + +/** + * Remove the gray background color from active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ + +a { + &:active, &:hover { + outline: 0; + }; +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +@if $legacy_browser_support { + blockquote { + margin: 1em 40px; + } +} + +/** + * Address styling not present in Safari and Chrome. + */ + +dfn { + font-style: italic; +} + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +@if $legacy_browser_support { + h2 { + font-size: 1.5em; + margin: 0.83em 0; + } + + h3 { + font-size: 1.17em; + margin: 1em 0; + } + + h4 { + font-size: 1em; + margin: 1.33em 0; + } + + h5 { + font-size: 0.83em; + margin: 1.67em 0; + } + + h6 { + font-size: 0.67em; + margin: 2.33em 0; + } +} + +/** + * Addresses styling not present in IE 8/9. + */ + +mark { + background: #ff0; + color: #000; +} + +@if $legacy_browser_support { + + /** + * Addresses margins set differently in IE 6/7. + */ + + p, + pre { + *margin: 1em 0; + } + + /* + * Addresses CSS quotes not supported in IE 6/7. + */ + + q { + *quotes: none; + } + + /* + * Addresses `quotes` property not supported in Safari 4. + */ + + q:before, + q:after { + content: ''; + content: none; + } +} + +/** + * Address inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +@if $legacy_browser_support { + + /* ========================================================================== + Lists + ========================================================================== */ + + /* + * Addresses margins set differently in IE 6/7. + */ + + dl, + menu, + ol, + ul { + *margin: 1em 0; + } + + dd { + *margin: 0 0 0 40px; + } + + /* + * Addresses paddings set differently in IE 6/7. + */ + + menu, + ol, + ul { + *padding: 0 0 0 40px; + } + + /* + * Corrects list images handled incorrectly in IE 7. + */ + + nav ul, + nav ol { + *list-style: none; + *list-style-image: none; + } + +} + +/* Embedded content + ========================================================================== */ + +/** + * 1. Remove border when inside `a` element in IE 8/9/10. + * 2. Improves image quality when scaled in IE 7. + */ + +img { + border: 0; + @if $legacy_browser_support { + *-ms-interpolation-mode: bicubic; /* 2 */ + } +} + +/** + * Correct overflow not hidden in IE 9/10/11. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Grouping content + ========================================================================== */ + +/** + * Address margin not present in IE 8/9 and Safari. + */ + +figure { + margin: 1em 40px; +} + +/** + * Address differences between Firefox and other browsers. + */ + +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +/** + * Contain overflow in all browsers. + */ + +pre { + overflow: auto; +} + +/** + * Address odd `em`-unit font size rendering in all browsers. + * Correct font family set oddly in IE 6, Safari 4/5, and Chrome. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + @if $legacy_browser_support { + _font-family: 'courier new', monospace; + } + font-size: 1em; +} + +/* Forms + ========================================================================== */ + +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ + +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + * 4. Improves appearance and consistency in all browsers. + */ + +button, +input, +optgroup, +select, +textarea { + color: inherit; /* 1 */ + font: inherit; /* 2 */ + margin: 0; /* 3 */ + @if $legacy_browser_support { + vertical-align: baseline; /* 3 */ + *vertical-align: middle; /* 3 */ + } +} + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ + +button { + overflow: visible; +} + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ + +button, +select { + text-transform: none; +} + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + * 4. Removes inner spacing in IE 7 without affecting normal text inputs. + * Known issue: inner spacing remains in IE 6. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ + @if $legacy_browser_support { + *overflow: visible; /* 4 */ + } +} + +/** + * Re-set default cursor for disabled elements. + */ + +button[disabled], +html input[disabled] { + cursor: default; +} + +/** + * Remove inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +input { + line-height: normal; +} + +/** + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + * Known issue: excess padding remains in IE 6. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ + @if $legacy_browser_support { + *height: 13px; /* 3 */ + *width: 13px; /* 3 */ + } +} + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ + +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; /* 2 */ + box-sizing: content-box; +} + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + * 3. Corrects text not wrapping in Firefox 3. + * 4. Corrects alignment displayed oddly in IE 6/7. + */ + +legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ + @if $legacy_browser_support { + white-space: normal; /* 3 */ + *margin-left: -7px; /* 4 */ + } +} + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ + +textarea { + overflow: auto; +} + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ + +optgroup { + font-weight: bold; +} + +/* Tables + ========================================================================== */ + +/** + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} + +td, +th { + padding: 0; +} diff --git a/Carthage/Checkouts/PINOperation/docs/html/css/scss/_object.scss b/Carthage/Checkouts/PINOperation/docs/html/css/scss/_object.scss new file mode 100644 index 00000000..22eebd87 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/html/css/scss/_object.scss @@ -0,0 +1,89 @@ +.section-specification { + table { + width: auto; + + th { + text-align: left; + } + } +} + +.method-title { + margin-left: -15px; + margin-bottom: 8px; + transition: margin-left .3s ease-out; + + .section-method.hide & { + margin-left: 0; + } + + code { + font-weight: 400; + font-size: .85em; + } +} + +.method-info { + background: $object-background; + border-bottom: 1px solid $object-border; + margin: 0 -25px; + padding: 20px 25px 0 25px; + transition: height .3s ease-out; + + position: relative; + + .pointy-thing { + background: $content-background; + height: 10px; + border-bottom: 1px solid $object-border; + margin: -20px -25px 16px -25px; + + &:before { + display: inline-block; + content: ""; + + background: $object-background; + border: 1px solid $object-border; + border-bottom: 0; + border-right: 0; + + position: absolute; + left: 21px; + top: 3px; + width: 12px; + height: 12px; + transform: rotate(45deg); + } + } + + .method-subsection { + margin-bottom: 15px; + + .argument-name { + width: 1px; + text-align: right; + + code { + color: #808080; + font-style: italic; + font-weight: 400; + } + } + } +} + +.section-method { + &.hide .method-info { + height: 0 !important; + overflow: hidden; + display: none; + } + + &.hide.animating .method-info { + display: block; + } + + &.animating .method-info { + overflow: hidden; + } +} diff --git a/Carthage/Checkouts/PINOperation/docs/html/css/scss/_print.scss b/Carthage/Checkouts/PINOperation/docs/html/css/scss/_print.scss new file mode 100644 index 00000000..61bdf99f --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/html/css/scss/_print.scss @@ -0,0 +1,42 @@ +@media print { + body { + background: #fff; + padding: 8px; + } + + header { + position: static; + background: #fff; + color: #000; + } + + aside { + display: none; + } + + .container { + max-width: none; + padding: 0; + } + + article { + margin-top: 0; + + #content { + border: 0; + background: #fff; + padding: 15px 0 0 0; + + .title { + margin-top: 0; + padding-top: 0; + } + } + } + + .method-info { + &, & .pointy-thing { + background: #fff; + } + } +} diff --git a/Carthage/Checkouts/PINOperation/docs/html/css/scss/_variables.scss b/Carthage/Checkouts/PINOperation/docs/html/css/scss/_variables.scss new file mode 100644 index 00000000..cbaff3cf --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/html/css/scss/_variables.scss @@ -0,0 +1,11 @@ +$body-font: -apple-system-font, "Helvetica Neue", Helvetica, sans-serif; +$code-font: "Source Code Pro", Monaco, Menlo, Consolas, monospace; + +$body-background: #f2f2f2; +$content-background: #fff; +$content-border: #e9e9e9; +$tint-color: #08c; +$object-background: #f9f9f9; +$object-border: #e9e9e9; + +$mobile-max-width: 650px; diff --git a/Carthage/Checkouts/PINOperation/docs/html/css/scss/_xcode.scss b/Carthage/Checkouts/PINOperation/docs/html/css/scss/_xcode.scss new file mode 100644 index 00000000..340b1f6b --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/html/css/scss/_xcode.scss @@ -0,0 +1,29 @@ +.xcode { + header, aside { + display: none; + } + + .container { + padding: 0; + } + + article { + margin-top: 0; + + #content { + border: 0; + margin: 0; + } + } + + .method-info { + &, .section-method.hide & { + max-height: auto; + overflow: visible; + + &.hiding { + display: block; + } + } + } +} diff --git a/Carthage/Checkouts/PINOperation/docs/html/css/scss/style.scss b/Carthage/Checkouts/PINOperation/docs/html/css/scss/style.scss new file mode 100644 index 00000000..648a6086 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/html/css/scss/style.scss @@ -0,0 +1 @@ +@import "variables", "normalize", "layout", "index", "object", "print", "xcode"; diff --git a/Carthage/Checkouts/PINOperation/docs/html/hierarchy.html b/Carthage/Checkouts/PINOperation/docs/html/hierarchy.html new file mode 100644 index 00000000..9bd0aa1f --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/html/hierarchy.html @@ -0,0 +1,82 @@ + + + + + + + + + + + + +
+
+ +

+ PINOperationQueue +

+ +

+ Pinterest +

+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINOperation/docs/html/img/button_bar_background.png b/Carthage/Checkouts/PINOperation/docs/html/img/button_bar_background.png new file mode 100644 index 00000000..71d1019b Binary files /dev/null and b/Carthage/Checkouts/PINOperation/docs/html/img/button_bar_background.png differ diff --git a/Carthage/Checkouts/PINOperation/docs/html/img/disclosure.png b/Carthage/Checkouts/PINOperation/docs/html/img/disclosure.png new file mode 100644 index 00000000..4c5cbf44 Binary files /dev/null and b/Carthage/Checkouts/PINOperation/docs/html/img/disclosure.png differ diff --git a/Carthage/Checkouts/PINOperation/docs/html/img/disclosure_open.png b/Carthage/Checkouts/PINOperation/docs/html/img/disclosure_open.png new file mode 100644 index 00000000..82396fed Binary files /dev/null and b/Carthage/Checkouts/PINOperation/docs/html/img/disclosure_open.png differ diff --git a/Carthage/Checkouts/PINOperation/docs/html/img/library_background.png b/Carthage/Checkouts/PINOperation/docs/html/img/library_background.png new file mode 100644 index 00000000..3006248a Binary files /dev/null and b/Carthage/Checkouts/PINOperation/docs/html/img/library_background.png differ diff --git a/Carthage/Checkouts/PINOperation/docs/html/img/title_background.png b/Carthage/Checkouts/PINOperation/docs/html/img/title_background.png new file mode 100644 index 00000000..846e4968 Binary files /dev/null and b/Carthage/Checkouts/PINOperation/docs/html/img/title_background.png differ diff --git a/Carthage/Checkouts/PINOperation/docs/html/index.html b/Carthage/Checkouts/PINOperation/docs/html/index.html new file mode 100644 index 00000000..fbc5d19d --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/html/index.html @@ -0,0 +1,90 @@ + + + + + + + + + + + + +
+
+ +

+ PINOperationQueue +

+ +

+ Pinterest +

+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/PINOperation/docs/html/js/script.js b/Carthage/Checkouts/PINOperation/docs/html/js/script.js new file mode 100644 index 00000000..ca915ee4 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/docs/html/js/script.js @@ -0,0 +1,58 @@ +function $() { + return document.querySelector.apply(document, arguments); +} + +if (navigator.userAgent.indexOf("Xcode") != -1) { + document.documentElement.classList.add("xcode"); +} + +var jumpTo = $("#jump-to"); + +if (jumpTo) { + jumpTo.addEventListener("change", function(e) { + location.hash = this.options[this.selectedIndex].value; + }); +} + +function hashChanged() { + if (/^#\/\/api\//.test(location.hash)) { + var element = document.querySelector("a[name='" + location.hash.substring(1) + "']"); + + if (!element) { + return; + } + + element = element.parentNode; + + element.classList.remove("hide"); + fixScrollPosition(element); + } +} + +function fixScrollPosition(element) { + var scrollTop = element.offsetTop - 150; + document.documentElement.scrollTop = scrollTop; + document.body.scrollTop = scrollTop; +} + +[].forEach.call(document.querySelectorAll(".section-method"), function(element) { + element.classList.add("hide"); + + element.querySelector(".method-title a").addEventListener("click", function(e) { + var info = element.querySelector(".method-info"), + infoContainer = element.querySelector(".method-info-container"); + + element.classList.add("animating"); + info.style.height = (infoContainer.clientHeight + 40) + "px"; + fixScrollPosition(element); + element.classList.toggle("hide"); + + setTimeout(function() { + element.classList.remove("animating"); + info.style.height = "auto"; + }, 300); + }); +}); + +window.addEventListener("hashchange", hashChanged); +hashChanged(); diff --git a/Carthage/Checkouts/PINOperation/makefile b/Carthage/Checkouts/PINOperation/makefile new file mode 100644 index 00000000..4e24e342 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/makefile @@ -0,0 +1,43 @@ +PLATFORM="platform=iOS Simulator,name=iPhone 15" +SDK="iphonesimulator" +SHELL=/bin/bash -o pipefail +XCODE_MAJOR_VERSION=$(shell xcodebuild -version | HEAD -n 1 | sed -E 's/Xcode ([0-9]+).*/\1/') + +.PHONY: all cocoapods test analyze carthage spm install_xcbeautify + +carthage: + carthage build --no-skip-current --use-xcframeworks + +cocoapods: + pod lib lint + +install_xcbeautify: + if ! command -v xcbeautify &> /dev/null; then brew install xcbeautify; fi + +analyze: install_xcbeautify + xcodebuild clean analyze -destination ${PLATFORM} -sdk ${SDK} -project PINOperation.xcodeproj -scheme PINOperation \ + ONLY_ACTIVE_ARCH=NO \ + CODE_SIGNING_REQUIRED=NO \ + CLANG_ANALYZER_OUTPUT=plist-html \ + CLANG_ANALYZER_OUTPUT_DIR="$(shell pwd)/clang" | xcbeautify + if [[ -n `find $(shell pwd)/clang -name "*.html"` ]] ; then rm -rf `pwd`/clang; exit 1; fi + rm -rf $(shell pwd)/clang + +test: install_xcbeautify + # TODO: Fix data races and enable thread sanitizer with '-enableThreadSanitizer YES' + xcodebuild clean test -destination ${PLATFORM} -sdk ${SDK} -project PINOperation.xcodeproj -scheme PINOperation \ + ONLY_ACTIVE_ARCH=NO \ + CODE_SIGNING_REQUIRED=NO | xcbeautify + +spm: + # TODO: Fix data races and enable thread sanitizer with '--sanitize thread' + swift test + +release-major: + +release-minor: + +release-patch: + + +all: carthage cocoapods test analyze spm diff --git a/Carthage/Checkouts/PINOperation/run_tests_update_status.sh b/Carthage/Checkouts/PINOperation/run_tests_update_status.sh new file mode 100755 index 00000000..5d7e4bd6 --- /dev/null +++ b/Carthage/Checkouts/PINOperation/run_tests_update_status.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +set -eo pipefail + +UPDATE_STATUS_PATH=$1 +BUILDKITE_PULL_REQUEST=$2 +BUILDKITE_BUILD_URL=$3 + +function updateStatus() { + if [ "${BUILDKITE_PULL_REQUEST}" != "false" ] ; then + ${UPDATE_STATUS_PATH} "pinterest" "PINOperation" ${BUILDKITE_PULL_REQUEST} "$1" ${BUILDKITE_BUILD_URL} "$2" "CI/Pinterest" + fi +} + +if [[ -z "${UPDATE_STATUS_PATH}" || -z "${BUILDKITE_PULL_REQUEST}" || -z "${BUILDKITE_BUILD_URL}" ]] ; then + echo "Update status path (${UPDATE_STATUS_PATH}), pull request (${BUILDKITE_BUILD_URL}) or build url (${BUILDKITE_PULL_REQUEST}) unset." + trap - EXIT + exit 255 +fi + +trapped="false" +function trap_handler() { + if [[ "$trapped" = "false" ]]; then + updateStatus failure "Tests failed…" + echo "Tests failed, updated status to failure" + fi + trapped="true" +} +trap trap_handler INT TERM EXIT + +updateStatus pending "Starting build…" + +make all + +updateStatus success "Tests passed" + +echo "All tests succeeded, updated status to success" +trap - EXIT +exit 0 \ No newline at end of file diff --git a/Example-Mac/PINRemoteImage.xcodeproj/project.pbxproj b/Example-Mac/PINRemoteImage.xcodeproj/project.pbxproj deleted file mode 100644 index 6cdaaa4c..00000000 --- a/Example-Mac/PINRemoteImage.xcodeproj/project.pbxproj +++ /dev/null @@ -1,561 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 42796FDA2C0B59B150630DA3 /* libPods-PINRemoteImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0141C54D0963FCEA0DB0381A /* libPods-PINRemoteImage.a */; }; - 9D9328C51C3C60E700E1F1D3 /* PINViewWithBackgroundColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9328C41C3C60E700E1F1D3 /* PINViewWithBackgroundColor.m */; }; - 9D9328C91C3D09BB00E1F1D3 /* WebPViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9328C71C3D09BB00E1F1D3 /* WebPViewController.m */; }; - 9D9328CA1C3D09BB00E1F1D3 /* WebPViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9D9328C81C3D09BB00E1F1D3 /* WebPViewController.xib */; }; - 9D9328CF1C3D0C0D00E1F1D3 /* ScrollViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9328CD1C3D0C0D00E1F1D3 /* ScrollViewController.m */; }; - 9D9328D01C3D0C0D00E1F1D3 /* ScrollViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9D9328CE1C3D0C0D00E1F1D3 /* ScrollViewController.xib */; }; - 9D9328D41C3D131900E1F1D3 /* ProcessingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9328D21C3D131900E1F1D3 /* ProcessingViewController.m */; }; - 9D9328D51C3D131900E1F1D3 /* ProcessingViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9D9328D31C3D131900E1F1D3 /* ProcessingViewController.xib */; }; - 9D9328D91C3D243A00E1F1D3 /* ProgressiveViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9328D71C3D243A00E1F1D3 /* ProgressiveViewController.m */; }; - 9D9328DA1C3D243A00E1F1D3 /* ProgressiveViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9D9328D81C3D243A00E1F1D3 /* ProgressiveViewController.xib */; }; - 9D9328DE1C3D275D00E1F1D3 /* DegradedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9328DC1C3D275D00E1F1D3 /* DegradedViewController.m */; }; - 9D9328DF1C3D275D00E1F1D3 /* DegradedViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9D9328DD1C3D275D00E1F1D3 /* DegradedViewController.xib */; }; - 9D9328E21C3D489400E1F1D3 /* Kitten.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9328E11C3D489400E1F1D3 /* Kitten.m */; }; - 9D97D09D1C3C4D960006C115 /* PINImageCollectionViewItemView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9D97D09B1C3C4D960006C115 /* PINImageCollectionViewItemView.xib */; }; - 9DC09DB81C39AB0D00C6451E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DC09DB71C39AB0D00C6451E /* AppDelegate.m */; }; - 9DC09DBB1C39AB0D00C6451E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DC09DBA1C39AB0D00C6451E /* main.m */; }; - 9DC09DBD1C39AB0D00C6451E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9DC09DBC1C39AB0D00C6451E /* Assets.xcassets */; }; - 9DC09DC01C39AB0D00C6451E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9DC09DBE1C39AB0D00C6451E /* MainMenu.xib */; }; - 9DC09DCB1C39AB0D00C6451E /* PINRemoteImageTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DC09DCA1C39AB0D00C6451E /* PINRemoteImageTests.m */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 9DC09DC71C39AB0D00C6451E /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 9DC09DAB1C39AB0D00C6451E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 9DC09DB21C39AB0D00C6451E; - remoteInfo = PINRemoteImage; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 0141C54D0963FCEA0DB0381A /* libPods-PINRemoteImage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PINRemoteImage.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 0C7B3B480ECE116693899B73 /* Pods-PINRemoteImage.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PINRemoteImage.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage.debug.xcconfig"; sourceTree = ""; }; - 9D9328C31C3C60E700E1F1D3 /* PINViewWithBackgroundColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINViewWithBackgroundColor.h; sourceTree = ""; }; - 9D9328C41C3C60E700E1F1D3 /* PINViewWithBackgroundColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINViewWithBackgroundColor.m; sourceTree = ""; }; - 9D9328C61C3D09BB00E1F1D3 /* WebPViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPViewController.h; sourceTree = ""; }; - 9D9328C71C3D09BB00E1F1D3 /* WebPViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebPViewController.m; sourceTree = ""; }; - 9D9328C81C3D09BB00E1F1D3 /* WebPViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = WebPViewController.xib; sourceTree = ""; }; - 9D9328CC1C3D0C0D00E1F1D3 /* ScrollViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollViewController.h; sourceTree = ""; }; - 9D9328CD1C3D0C0D00E1F1D3 /* ScrollViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScrollViewController.m; sourceTree = ""; }; - 9D9328CE1C3D0C0D00E1F1D3 /* ScrollViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ScrollViewController.xib; sourceTree = ""; }; - 9D9328D11C3D131900E1F1D3 /* ProcessingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessingViewController.h; sourceTree = ""; }; - 9D9328D21C3D131900E1F1D3 /* ProcessingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProcessingViewController.m; sourceTree = ""; }; - 9D9328D31C3D131900E1F1D3 /* ProcessingViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ProcessingViewController.xib; sourceTree = ""; }; - 9D9328D61C3D243A00E1F1D3 /* ProgressiveViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProgressiveViewController.h; sourceTree = ""; }; - 9D9328D71C3D243A00E1F1D3 /* ProgressiveViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProgressiveViewController.m; sourceTree = ""; }; - 9D9328D81C3D243A00E1F1D3 /* ProgressiveViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ProgressiveViewController.xib; sourceTree = ""; }; - 9D9328DB1C3D275D00E1F1D3 /* DegradedViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DegradedViewController.h; sourceTree = ""; }; - 9D9328DC1C3D275D00E1F1D3 /* DegradedViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DegradedViewController.m; sourceTree = ""; }; - 9D9328DD1C3D275D00E1F1D3 /* DegradedViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = DegradedViewController.xib; sourceTree = ""; }; - 9D9328E01C3D489400E1F1D3 /* Kitten.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Kitten.h; path = "../../Example-Shared/Kitten.h"; sourceTree = ""; }; - 9D9328E11C3D489400E1F1D3 /* Kitten.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Kitten.m; path = "../../Example-Shared/Kitten.m"; sourceTree = ""; }; - 9D97D09C1C3C4D960006C115 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/PINImageCollectionViewItemView.xib; sourceTree = ""; }; - 9DC09DB31C39AB0D00C6451E /* PINRemoteImage.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PINRemoteImage.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 9DC09DB61C39AB0D00C6451E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 9DC09DB71C39AB0D00C6451E /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 9DC09DBA1C39AB0D00C6451E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 9DC09DBC1C39AB0D00C6451E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 9DC09DBF1C39AB0D00C6451E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 9DC09DC11C39AB0D00C6451E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 9DC09DC61C39AB0D00C6451E /* PINRemoteImageTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PINRemoteImageTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 9DC09DCA1C39AB0D00C6451E /* PINRemoteImageTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageTests.m; sourceTree = ""; }; - 9DC09DCC1C39AB0D00C6451E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - A560E2F6800411CCF5086206 /* Pods-PINRemoteImage.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PINRemoteImage.release.xcconfig"; path = "Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage.release.xcconfig"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 9DC09DB01C39AB0D00C6451E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 42796FDA2C0B59B150630DA3 /* libPods-PINRemoteImage.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 9DC09DC31C39AB0D00C6451E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 19057E8A9A6779B7C486AF2B /* Frameworks */ = { - isa = PBXGroup; - children = ( - 0141C54D0963FCEA0DB0381A /* libPods-PINRemoteImage.a */, - ); - name = Frameworks; - sourceTree = ""; - }; - 9D9328CB1C3D09BE00E1F1D3 /* Views */ = { - isa = PBXGroup; - children = ( - 9D97D09B1C3C4D960006C115 /* PINImageCollectionViewItemView.xib */, - 9D9328C31C3C60E700E1F1D3 /* PINViewWithBackgroundColor.h */, - 9D9328C41C3C60E700E1F1D3 /* PINViewWithBackgroundColor.m */, - ); - name = Views; - sourceTree = ""; - }; - 9DC09DAA1C39AB0D00C6451E = { - isa = PBXGroup; - children = ( - 9DC09DB51C39AB0D00C6451E /* PINRemoteImage */, - 9DC09DC91C39AB0D00C6451E /* PINRemoteImageTests */, - 9DC09DB41C39AB0D00C6451E /* Products */, - D8AD56B80C0F0D90F37F7BC5 /* Pods */, - 19057E8A9A6779B7C486AF2B /* Frameworks */, - ); - sourceTree = ""; - }; - 9DC09DB41C39AB0D00C6451E /* Products */ = { - isa = PBXGroup; - children = ( - 9DC09DB31C39AB0D00C6451E /* PINRemoteImage.app */, - 9DC09DC61C39AB0D00C6451E /* PINRemoteImageTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 9DC09DB51C39AB0D00C6451E /* PINRemoteImage */ = { - isa = PBXGroup; - children = ( - 9DC09DB91C39AB0D00C6451E /* Supporting Files */, - 9D9328CB1C3D09BE00E1F1D3 /* Views */, - 9D9328E01C3D489400E1F1D3 /* Kitten.h */, - 9D9328E11C3D489400E1F1D3 /* Kitten.m */, - 9DC09DB61C39AB0D00C6451E /* AppDelegate.h */, - 9DC09DB71C39AB0D00C6451E /* AppDelegate.m */, - 9DC09DBE1C39AB0D00C6451E /* MainMenu.xib */, - 9DC09DC11C39AB0D00C6451E /* Info.plist */, - 9D9328CC1C3D0C0D00E1F1D3 /* ScrollViewController.h */, - 9D9328CD1C3D0C0D00E1F1D3 /* ScrollViewController.m */, - 9D9328CE1C3D0C0D00E1F1D3 /* ScrollViewController.xib */, - 9D9328C61C3D09BB00E1F1D3 /* WebPViewController.h */, - 9D9328C71C3D09BB00E1F1D3 /* WebPViewController.m */, - 9D9328C81C3D09BB00E1F1D3 /* WebPViewController.xib */, - 9D9328D61C3D243A00E1F1D3 /* ProgressiveViewController.h */, - 9D9328D71C3D243A00E1F1D3 /* ProgressiveViewController.m */, - 9D9328D81C3D243A00E1F1D3 /* ProgressiveViewController.xib */, - 9D9328DB1C3D275D00E1F1D3 /* DegradedViewController.h */, - 9D9328DC1C3D275D00E1F1D3 /* DegradedViewController.m */, - 9D9328DD1C3D275D00E1F1D3 /* DegradedViewController.xib */, - 9D9328D11C3D131900E1F1D3 /* ProcessingViewController.h */, - 9D9328D21C3D131900E1F1D3 /* ProcessingViewController.m */, - 9D9328D31C3D131900E1F1D3 /* ProcessingViewController.xib */, - ); - path = PINRemoteImage; - sourceTree = ""; - }; - 9DC09DB91C39AB0D00C6451E /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 9DC09DBC1C39AB0D00C6451E /* Assets.xcassets */, - 9DC09DBA1C39AB0D00C6451E /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 9DC09DC91C39AB0D00C6451E /* PINRemoteImageTests */ = { - isa = PBXGroup; - children = ( - 9DC09DCA1C39AB0D00C6451E /* PINRemoteImageTests.m */, - 9DC09DCC1C39AB0D00C6451E /* Info.plist */, - ); - path = PINRemoteImageTests; - sourceTree = ""; - }; - D8AD56B80C0F0D90F37F7BC5 /* Pods */ = { - isa = PBXGroup; - children = ( - 0C7B3B480ECE116693899B73 /* Pods-PINRemoteImage.debug.xcconfig */, - A560E2F6800411CCF5086206 /* Pods-PINRemoteImage.release.xcconfig */, - ); - name = Pods; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 9DC09DB21C39AB0D00C6451E /* PINRemoteImage */ = { - isa = PBXNativeTarget; - buildConfigurationList = 9DC09DCF1C39AB0D00C6451E /* Build configuration list for PBXNativeTarget "PINRemoteImage" */; - buildPhases = ( - 8CFB37DD63603884BA1E041F /* Check Pods Manifest.lock */, - 9DC09DAF1C39AB0D00C6451E /* Sources */, - 9DC09DB01C39AB0D00C6451E /* Frameworks */, - 9DC09DB11C39AB0D00C6451E /* Resources */, - 16F443D310E08F018ED7D05A /* Copy Pods Resources */, - 86B463CD99BA36A3184D5560 /* Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = PINRemoteImage; - productName = PINRemoteImage; - productReference = 9DC09DB31C39AB0D00C6451E /* PINRemoteImage.app */; - productType = "com.apple.product-type.application"; - }; - 9DC09DC51C39AB0D00C6451E /* PINRemoteImageTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 9DC09DD21C39AB0D00C6451E /* Build configuration list for PBXNativeTarget "PINRemoteImageTests" */; - buildPhases = ( - 9DC09DC21C39AB0D00C6451E /* Sources */, - 9DC09DC31C39AB0D00C6451E /* Frameworks */, - 9DC09DC41C39AB0D00C6451E /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 9DC09DC81C39AB0D00C6451E /* PBXTargetDependency */, - ); - name = PINRemoteImageTests; - productName = PINRemoteImageTests; - productReference = 9DC09DC61C39AB0D00C6451E /* PINRemoteImageTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 9DC09DAB1C39AB0D00C6451E /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0720; - ORGANIZATIONNAME = mischneider; - TargetAttributes = { - 9DC09DB21C39AB0D00C6451E = { - CreatedOnToolsVersion = 7.2; - }; - 9DC09DC51C39AB0D00C6451E = { - CreatedOnToolsVersion = 7.2; - TestTargetID = 9DC09DB21C39AB0D00C6451E; - }; - }; - }; - buildConfigurationList = 9DC09DAE1C39AB0D00C6451E /* Build configuration list for PBXProject "PINRemoteImage" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 9DC09DAA1C39AB0D00C6451E; - productRefGroup = 9DC09DB41C39AB0D00C6451E /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 9DC09DB21C39AB0D00C6451E /* PINRemoteImage */, - 9DC09DC51C39AB0D00C6451E /* PINRemoteImageTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 9DC09DB11C39AB0D00C6451E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 9DC09DBD1C39AB0D00C6451E /* Assets.xcassets in Resources */, - 9D9328DA1C3D243A00E1F1D3 /* ProgressiveViewController.xib in Resources */, - 9D9328DF1C3D275D00E1F1D3 /* DegradedViewController.xib in Resources */, - 9D9328CA1C3D09BB00E1F1D3 /* WebPViewController.xib in Resources */, - 9D9328D01C3D0C0D00E1F1D3 /* ScrollViewController.xib in Resources */, - 9D97D09D1C3C4D960006C115 /* PINImageCollectionViewItemView.xib in Resources */, - 9DC09DC01C39AB0D00C6451E /* MainMenu.xib in Resources */, - 9D9328D51C3D131900E1F1D3 /* ProcessingViewController.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 9DC09DC41C39AB0D00C6451E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 16F443D310E08F018ED7D05A /* Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - 86B463CD99BA36A3184D5560 /* Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Embed Pods Frameworks"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - 8CFB37DD63603884BA1E041F /* Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Check Pods Manifest.lock"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 9DC09DAF1C39AB0D00C6451E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 9D9328CF1C3D0C0D00E1F1D3 /* ScrollViewController.m in Sources */, - 9D9328C91C3D09BB00E1F1D3 /* WebPViewController.m in Sources */, - 9D9328E21C3D489400E1F1D3 /* Kitten.m in Sources */, - 9D9328DE1C3D275D00E1F1D3 /* DegradedViewController.m in Sources */, - 9DC09DBB1C39AB0D00C6451E /* main.m in Sources */, - 9D9328D41C3D131900E1F1D3 /* ProcessingViewController.m in Sources */, - 9D9328D91C3D243A00E1F1D3 /* ProgressiveViewController.m in Sources */, - 9DC09DB81C39AB0D00C6451E /* AppDelegate.m in Sources */, - 9D9328C51C3C60E700E1F1D3 /* PINViewWithBackgroundColor.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 9DC09DC21C39AB0D00C6451E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 9DC09DCB1C39AB0D00C6451E /* PINRemoteImageTests.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 9DC09DC81C39AB0D00C6451E /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 9DC09DB21C39AB0D00C6451E /* PINRemoteImage */; - targetProxy = 9DC09DC71C39AB0D00C6451E /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 9D97D09B1C3C4D960006C115 /* PINImageCollectionViewItemView.xib */ = { - isa = PBXVariantGroup; - children = ( - 9D97D09C1C3C4D960006C115 /* Base */, - ); - name = PINImageCollectionViewItemView.xib; - sourceTree = ""; - }; - 9DC09DBE1C39AB0D00C6451E /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 9DC09DBF1C39AB0D00C6451E /* Base */, - ); - name = MainMenu.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 9DC09DCD1C39AB0D00C6451E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - }; - name = Debug; - }; - 9DC09DCE1C39AB0D00C6451E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - }; - name = Release; - }; - 9DC09DD01C39AB0D00C6451E /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 0C7B3B480ECE116693899B73 /* Pods-PINRemoteImage.debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = PINRemoteImage/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = net.mischneider.PINRemoteImage; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 9DC09DD11C39AB0D00C6451E /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = A560E2F6800411CCF5086206 /* Pods-PINRemoteImage.release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = PINRemoteImage/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = net.mischneider.PINRemoteImage; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 9DC09DD31C39AB0D00C6451E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = PINRemoteImageTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = net.mischneider.PINRemoteImageTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PINRemoteImage.app/Contents/MacOS/PINRemoteImage"; - }; - name = Debug; - }; - 9DC09DD41C39AB0D00C6451E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = PINRemoteImageTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = net.mischneider.PINRemoteImageTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PINRemoteImage.app/Contents/MacOS/PINRemoteImage"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 9DC09DAE1C39AB0D00C6451E /* Build configuration list for PBXProject "PINRemoteImage" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 9DC09DCD1C39AB0D00C6451E /* Debug */, - 9DC09DCE1C39AB0D00C6451E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 9DC09DCF1C39AB0D00C6451E /* Build configuration list for PBXNativeTarget "PINRemoteImage" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 9DC09DD01C39AB0D00C6451E /* Debug */, - 9DC09DD11C39AB0D00C6451E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 9DC09DD21C39AB0D00C6451E /* Build configuration list for PBXNativeTarget "PINRemoteImageTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 9DC09DD31C39AB0D00C6451E /* Debug */, - 9DC09DD41C39AB0D00C6451E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 9DC09DAB1C39AB0D00C6451E /* Project object */; -} diff --git a/Example-Mac/PINRemoteImage.xcworkspace/contents.xcworkspacedata b/Example-Mac/PINRemoteImage.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 4d95871b..00000000 --- a/Example-Mac/PINRemoteImage.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/Example-Mac/PINRemoteImage/ProcessingViewController.m b/Example-Mac/PINRemoteImage/ProcessingViewController.m deleted file mode 100644 index 7526aa16..00000000 --- a/Example-Mac/PINRemoteImage/ProcessingViewController.m +++ /dev/null @@ -1,80 +0,0 @@ -// -// ProcessingViewController.m -// PINRemoteImage -// -// Created by Michael Schneider on 1/6/16. -// Copyright © 2016 mischneider. All rights reserved. -// - -#import "ProcessingViewController.h" - -#import -#import - -@interface ProcessingViewController () -@property (weak) IBOutlet NSImageView *imageView; - -@end - -@implementation ProcessingViewController - -#pragma mark - Lifecycle - -- (instancetype)init -{ - self = [super initWithNibName:NSStringFromClass(self.class) bundle:nil]; - if (self == nil) { return self; } - return self; -} - - -#pragma mark - NSViewController - -- (void)viewWillAppear -{ - [super viewWillAppear]; - - [self.imageView pin_setImageFromURL:[NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/5b/c6/c5/5bc6c5387ff6f104fd642f2b375efba3.jpg"] processorKey:@"rounded" processor:^NSImage *(PINRemoteImageManagerResult *result, NSUInteger *cost) - { - NSImage *image = result.image; - CGFloat radius = 7.0f; - CGSize targetSize = CGSizeMake(200, 300); - CGRect imageRect = CGRectMake(0, 0, targetSize.width, targetSize.height); - - NSImage *processedImage = [[NSImage alloc] initWithSize:targetSize]; - [processedImage lockFocus]; - - NSBezierPath *bezierPath = [NSBezierPath bezierPathWithRoundedRect:imageRect xRadius:radius yRadius:radius]; - [bezierPath addClip]; - - CGFloat widthMultiplier = targetSize.width / image.size.width; - CGFloat heightMultiplier = targetSize.height / image.size.height; - CGFloat sizeMultiplier = MAX(widthMultiplier, heightMultiplier); - - CGRect drawRect = CGRectMake(0, 0, image.size.width * sizeMultiplier, image.size.height * sizeMultiplier); - if (CGRectGetMaxX(drawRect) > CGRectGetMaxX(imageRect)) { - drawRect.origin.x -= (CGRectGetMaxX(drawRect) - CGRectGetMaxX(imageRect)) / 2.0; - } - if (CGRectGetMaxY(drawRect) > CGRectGetMaxY(imageRect)) { - drawRect.origin.y -= (CGRectGetMaxY(drawRect) - CGRectGetMaxY(imageRect)) / 2.0; - } - - [image drawInRect:drawRect]; - - [[NSColor redColor] setStroke]; - [bezierPath setLineWidth:5.0]; - [bezierPath stroke]; - - NSImage *logo = [NSImage imageNamed:@"white-pinterest-logo"]; - CGContextRef ctx = [[NSGraphicsContext currentContext] graphicsPort]; - CGContextSetBlendMode(ctx, kCGBlendModeOverlay); - CGContextSetAlpha(ctx, 0.5); - CGContextDrawImage(ctx, CGRectMake(90, 10, logo.size.width, logo.size.height), [logo CGImage]); - - [processedImage unlockFocus]; - - return processedImage; - }]; -} - -@end diff --git a/Example-Mac/PINRemoteImage/ProgressiveViewController.m b/Example-Mac/PINRemoteImage/ProgressiveViewController.m deleted file mode 100644 index 41e29188..00000000 --- a/Example-Mac/PINRemoteImage/ProgressiveViewController.m +++ /dev/null @@ -1,60 +0,0 @@ -// -// ProgressiveViewController.m -// PINRemoteImage -// -// Created by Michael Schneider on 1/6/16. -// Copyright © 2016 mischneider. All rights reserved. -// - -#import "ProgressiveViewController.h" - -#import -#import - -@interface ProgressiveViewController () -@property (weak) IBOutlet NSImageView *imageView; - -@end - -@implementation ProgressiveViewController - -#pragma mark - Lifecycle - -- (instancetype)init -{ - self = [super initWithNibName:NSStringFromClass(self.class) bundle:nil]; - if (self == nil) { return self; } - return self; -} - - -#pragma mark - NSViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - // MUST BE SET ON IMAGE VIEW TO GET PROGRESS UPDATES! - self.imageView.pin_updateWithProgress = YES; -} - -- (void)viewDidAppear -{ - [super viewDidAppear]; - - NSURL *progressiveURL = [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/1200x/2e/0c/c5/2e0cc5d86e7b7cd42af225c29f21c37f.jpg"]; - [[PINRemoteImageManager sharedImageManager] setProgressThresholds:@[@(0.1), @(0.2), @(0.3), @(0.4), @(0.5), @(0.6), @(0.7), @(0.8), @(0.9)] completion:nil]; - [[[PINRemoteImageManager sharedImageManager] cache] removeObjectForKey:[[PINRemoteImageManager sharedImageManager] cacheKeyForURL:progressiveURL processorKey:nil]]; - [self.imageView pin_setImageFromURL:progressiveURL]; - - NSMutableArray *progress = [[NSMutableArray alloc] init]; - [[PINRemoteImageManager sharedImageManager] - downloadImageWithURL:progressiveURL - options:PINRemoteImageManagerDownloadOptionsNone progressImage:^(PINRemoteImageManagerResult *result) { - [progress addObject:result.image]; - } completion:^(PINRemoteImageManagerResult *result) { - [progress addObject:result.image]; - }]; -} - -@end diff --git a/Example-Mac/PINRemoteImage/WebPViewController.m b/Example-Mac/PINRemoteImage/WebPViewController.m deleted file mode 100644 index ff44b4ce..00000000 --- a/Example-Mac/PINRemoteImage/WebPViewController.m +++ /dev/null @@ -1,38 +0,0 @@ -// -// WebPViewController.m -// PINRemoteImage -// -// Created by Michael Schneider on 1/6/16. -// Copyright © 2016 mischneider. All rights reserved. -// - -#import "WebPViewController.h" - -#import - -@interface WebPViewController () -@property (weak) IBOutlet NSImageView *imageView; -@end - -@implementation WebPViewController - -#pragma mark - Lifecycle - -- (instancetype)init -{ - self = [super initWithNibName:NSStringFromClass(self.class) bundle:nil]; - if (self == nil) { return self; } - return self; -} - - -#pragma mark - NSViewController - -- (void)viewDidAppear -{ - [super viewDidAppear]; - - [self.imageView pin_setImageFromURL:[NSURL URLWithString:@"https://github.com/samdutton/simpl/blob/master/picturetype/kittens.webp?raw=true"]]; -} - -@end diff --git a/Example-Mac/PINRemoteImageTests/PINRemoteImageTests.m b/Example-Mac/PINRemoteImageTests/PINRemoteImageTests.m deleted file mode 100644 index 5b39776f..00000000 --- a/Example-Mac/PINRemoteImageTests/PINRemoteImageTests.m +++ /dev/null @@ -1,39 +0,0 @@ -// -// PINRemoteImageTests.m -// PINRemoteImageTests -// -// Created by Michael Schneider on 1/3/16. -// Copyright © 2016 mischneider. All rights reserved. -// - -#import - -@interface PINRemoteImageTests : XCTestCase - -@end - -@implementation PINRemoteImageTests - -- (void)setUp { - [super setUp]; - // Put setup code here. This method is called before the invocation of each test method in the class. -} - -- (void)tearDown { - // Put teardown code here. This method is called after the invocation of each test method in the class. - [super tearDown]; -} - -- (void)testExample { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct results. -} - -- (void)testPerformanceExample { - // This is an example of a performance test case. - [self measureBlock:^{ - // Put the code you want to measure the time of here. - }]; -} - -@end diff --git a/Example-Mac/Podfile b/Example-Mac/Podfile deleted file mode 100644 index 6b83aa3f..00000000 --- a/Example-Mac/Podfile +++ /dev/null @@ -1,6 +0,0 @@ -target 'PINRemoteImage', :exclusive => true do - pod "PINRemoteImage/OSX", :path => "../" - pod "PINRemoteImage/WebP", :path => "../" - pod "PINCache" - pod "libwebp" -end diff --git a/Example-Mac/Podfile.lock b/Example-Mac/Podfile.lock deleted file mode 100644 index d4d3ec7a..00000000 --- a/Example-Mac/Podfile.lock +++ /dev/null @@ -1,50 +0,0 @@ -PODS: - - libwebp (0.5.0): - - libwebp/core (= 0.5.0) - - libwebp/dec (= 0.5.0) - - libwebp/demux (= 0.5.0) - - libwebp/dsp (= 0.5.0) - - libwebp/enc (= 0.5.0) - - libwebp/mux (= 0.5.0) - - libwebp/utils (= 0.5.0) - - libwebp/webp (= 0.5.0) - - libwebp/core (0.5.0): - - libwebp/webp - - libwebp/dec (0.5.0): - - libwebp/core - - libwebp/demux (0.5.0): - - libwebp/core - - libwebp/dsp (0.5.0): - - libwebp/core - - libwebp/enc (0.5.0): - - libwebp/core - - libwebp/mux (0.5.0): - - libwebp/core - - libwebp/utils (0.5.0): - - libwebp/core - - libwebp/webp (0.5.0) - - PINCache (2.2.2) - - PINRemoteImage/Core (2.1.2): - - PINCache (>= 2.1) - - PINRemoteImage/OSX (2.1.2): - - PINRemoteImage/Core - - PINRemoteImage/WebP (2.1.2): - - libwebp - - PINRemoteImage/Core - -DEPENDENCIES: - - libwebp - - PINCache - - PINRemoteImage/OSX (from `../`) - - PINRemoteImage/WebP (from `../`) - -EXTERNAL SOURCES: - PINRemoteImage: - :path: ../ - -SPEC CHECKSUMS: - libwebp: 68ba2001ba6806ee52837ebd77a551a0b6567e4e - PINCache: 078426d356ab95ef875e9e62e5c35a2ea3333c28 - PINRemoteImage: cee13f6a46c58d6ebfa1975da97f7674c7e6f305 - -COCOAPODS: 0.39.0 diff --git a/Example-Mac/Pods/Headers/Private/PINCache/Nullability.h b/Example-Mac/Pods/Headers/Private/PINCache/Nullability.h deleted file mode 120000 index b90c434a..00000000 --- a/Example-Mac/Pods/Headers/Private/PINCache/Nullability.h +++ /dev/null @@ -1 +0,0 @@ -../../../PINCache/PINCache/Nullability.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINCache/PINCache.h b/Example-Mac/Pods/Headers/Private/PINCache/PINCache.h deleted file mode 120000 index 149e0bb6..00000000 --- a/Example-Mac/Pods/Headers/Private/PINCache/PINCache.h +++ /dev/null @@ -1 +0,0 @@ -../../../PINCache/PINCache/PINCache.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINCache/PINDiskCache.h b/Example-Mac/Pods/Headers/Private/PINCache/PINDiskCache.h deleted file mode 120000 index c5206f89..00000000 --- a/Example-Mac/Pods/Headers/Private/PINCache/PINDiskCache.h +++ /dev/null @@ -1 +0,0 @@ -../../../PINCache/PINCache/PINDiskCache.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINCache/PINMemoryCache.h b/Example-Mac/Pods/Headers/Private/PINCache/PINMemoryCache.h deleted file mode 120000 index c1b9753b..00000000 --- a/Example-Mac/Pods/Headers/Private/PINCache/PINMemoryCache.h +++ /dev/null @@ -1 +0,0 @@ -../../../PINCache/PINCache/PINMemoryCache.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINRemoteImage/NSData+ImageDetectors.h b/Example-Mac/Pods/Headers/Private/PINRemoteImage/NSData+ImageDetectors.h deleted file mode 120000 index 8d98e1a4..00000000 --- a/Example-Mac/Pods/Headers/Private/PINRemoteImage/NSData+ImageDetectors.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Categories/NSData+ImageDetectors.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINAlternateRepresentationProvider.h b/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINAlternateRepresentationProvider.h deleted file mode 120000 index ce662f35..00000000 --- a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINAlternateRepresentationProvider.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINAlternateRepresentationProvider.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINAnimatedImage.h b/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINAnimatedImage.h deleted file mode 120000 index 4ad10fe3..00000000 --- a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINAnimatedImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINAnimatedImage.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINAnimatedImageManager.h b/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINAnimatedImageManager.h deleted file mode 120000 index c9139ffe..00000000 --- a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINAnimatedImageManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINAnimatedImageManager.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINButton+PINRemoteImage.h b/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINButton+PINRemoteImage.h deleted file mode 120000 index 0ed989a1..00000000 --- a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINButton+PINRemoteImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Image Categories/PINButton+PINRemoteImage.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINDataTaskOperation.h b/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINDataTaskOperation.h deleted file mode 120000 index 6ebb4a80..00000000 --- a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINDataTaskOperation.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINDataTaskOperation.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINImage+DecodedImage.h b/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINImage+DecodedImage.h deleted file mode 120000 index 96d0ec62..00000000 --- a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINImage+DecodedImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Categories/PINImage+DecodedImage.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINImage+WebP.h b/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINImage+WebP.h deleted file mode 120000 index 6d484bc7..00000000 --- a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINImage+WebP.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Categories/PINImage+WebP.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINImageView+PINRemoteImage.h b/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINImageView+PINRemoteImage.h deleted file mode 120000 index a94e8f7c..00000000 --- a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINImageView+PINRemoteImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Image Categories/PINImageView+PINRemoteImage.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINProgressiveImage.h b/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINProgressiveImage.h deleted file mode 120000 index 03e8769f..00000000 --- a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINProgressiveImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINProgressiveImage.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImage.h b/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImage.h deleted file mode 120000 index 64ec7893..00000000 --- a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImage.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageCallbacks.h b/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageCallbacks.h deleted file mode 120000 index 790720bb..00000000 --- a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageCallbacks.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageCallbacks.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageCategoryManager.h b/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageCategoryManager.h deleted file mode 120000 index cba384e6..00000000 --- a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageCategoryManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageCategoryManager.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageDownloadTask.h b/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageDownloadTask.h deleted file mode 120000 index e492464a..00000000 --- a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageDownloadTask.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageDownloadTask.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageMacros.h b/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageMacros.h deleted file mode 120000 index 5c9588e9..00000000 --- a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageMacros.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageMacros.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageManager.h b/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageManager.h deleted file mode 120000 index d0e9703d..00000000 --- a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageManager.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageManagerResult.h b/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageManagerResult.h deleted file mode 120000 index b719636b..00000000 --- a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageManagerResult.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageManagerResult.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageMemoryContainer.h b/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageMemoryContainer.h deleted file mode 120000 index 8e2c8de9..00000000 --- a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageMemoryContainer.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageMemoryContainer.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageProcessorTask.h b/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageProcessorTask.h deleted file mode 120000 index 89c8a48b..00000000 --- a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageProcessorTask.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageProcessorTask.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageTask.h b/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageTask.h deleted file mode 120000 index 8379dfef..00000000 --- a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteImageTask.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageTask.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteLock.h b/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteLock.h deleted file mode 120000 index 1712bbd3..00000000 --- a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINRemoteLock.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteLock.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINURLSessionManager.h b/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINURLSessionManager.h deleted file mode 120000 index ad2ce3c8..00000000 --- a/Example-Mac/Pods/Headers/Private/PINRemoteImage/PINURLSessionManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINURLSessionManager.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/alphai.h b/Example-Mac/Pods/Headers/Private/libwebp/alphai.h deleted file mode 120000 index 3a6f3b9b..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/alphai.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/alphai.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/backward_references.h b/Example-Mac/Pods/Headers/Private/libwebp/backward_references.h deleted file mode 120000 index 0881ff9b..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/backward_references.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/enc/backward_references.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/bit_reader.h b/Example-Mac/Pods/Headers/Private/libwebp/bit_reader.h deleted file mode 120000 index 93789582..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/bit_reader.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/bit_reader.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/bit_reader_inl.h b/Example-Mac/Pods/Headers/Private/libwebp/bit_reader_inl.h deleted file mode 120000 index be415894..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/bit_reader_inl.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/bit_reader_inl.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/bit_writer.h b/Example-Mac/Pods/Headers/Private/libwebp/bit_writer.h deleted file mode 120000 index abe7119f..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/bit_writer.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/bit_writer.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/color_cache.h b/Example-Mac/Pods/Headers/Private/libwebp/color_cache.h deleted file mode 120000 index 5bba961d..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/color_cache.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/color_cache.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/common.h b/Example-Mac/Pods/Headers/Private/libwebp/common.h deleted file mode 120000 index 8f4827f8..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/common.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/common.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/cost.h b/Example-Mac/Pods/Headers/Private/libwebp/cost.h deleted file mode 120000 index a9c6f4ae..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/cost.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/enc/cost.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/decode_vp8.h b/Example-Mac/Pods/Headers/Private/libwebp/decode_vp8.h deleted file mode 120000 index b5ac83e7..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/decode_vp8.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/decode_vp8.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/delta_palettization.h b/Example-Mac/Pods/Headers/Private/libwebp/delta_palettization.h deleted file mode 120000 index c8e6fb64..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/delta_palettization.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/enc/delta_palettization.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/dsp.h b/Example-Mac/Pods/Headers/Private/libwebp/dsp.h deleted file mode 120000 index 1bace906..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/dsp.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dsp/dsp.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/endian_inl.h b/Example-Mac/Pods/Headers/Private/libwebp/endian_inl.h deleted file mode 120000 index 2be74a78..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/endian_inl.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/endian_inl.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/filters.h b/Example-Mac/Pods/Headers/Private/libwebp/filters.h deleted file mode 120000 index ab7b5327..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/filters.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/filters.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/histogram.h b/Example-Mac/Pods/Headers/Private/libwebp/histogram.h deleted file mode 120000 index c6950516..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/histogram.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/enc/histogram.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/huffman.h b/Example-Mac/Pods/Headers/Private/libwebp/huffman.h deleted file mode 120000 index 6245e139..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/huffman.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/huffman.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/huffman_encode.h b/Example-Mac/Pods/Headers/Private/libwebp/huffman_encode.h deleted file mode 120000 index 19a28b2a..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/huffman_encode.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/huffman_encode.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/lossless.h b/Example-Mac/Pods/Headers/Private/libwebp/lossless.h deleted file mode 120000 index a3b07cfe..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/lossless.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dsp/lossless.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/mips_macro.h b/Example-Mac/Pods/Headers/Private/libwebp/mips_macro.h deleted file mode 120000 index da76de07..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/mips_macro.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dsp/mips_macro.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/muxi.h b/Example-Mac/Pods/Headers/Private/libwebp/muxi.h deleted file mode 120000 index d96d5988..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/muxi.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/mux/muxi.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/neon.h b/Example-Mac/Pods/Headers/Private/libwebp/neon.h deleted file mode 120000 index 8213e481..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/neon.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dsp/neon.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/quant_levels.h b/Example-Mac/Pods/Headers/Private/libwebp/quant_levels.h deleted file mode 120000 index d620fa9c..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/quant_levels.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/quant_levels.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/quant_levels_dec.h b/Example-Mac/Pods/Headers/Private/libwebp/quant_levels_dec.h deleted file mode 120000 index 6930b5dd..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/quant_levels_dec.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/quant_levels_dec.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/random.h b/Example-Mac/Pods/Headers/Private/libwebp/random.h deleted file mode 120000 index 7ccc260c..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/random.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/random.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/rescaler.h b/Example-Mac/Pods/Headers/Private/libwebp/rescaler.h deleted file mode 120000 index 3c1c538c..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/rescaler.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/rescaler.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/thread.h b/Example-Mac/Pods/Headers/Private/libwebp/thread.h deleted file mode 120000 index 3033ec5a..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/thread.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/thread.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/utils.h b/Example-Mac/Pods/Headers/Private/libwebp/utils.h deleted file mode 120000 index ba046686..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/utils.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/utils.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/vp8enci.h b/Example-Mac/Pods/Headers/Private/libwebp/vp8enci.h deleted file mode 120000 index 4b202757..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/vp8enci.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/enc/vp8enci.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/vp8i.h b/Example-Mac/Pods/Headers/Private/libwebp/vp8i.h deleted file mode 120000 index 1c5d8a56..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/vp8i.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/vp8i.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/vp8li.h b/Example-Mac/Pods/Headers/Private/libwebp/vp8li.h deleted file mode 120000 index ee31158b..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/vp8li.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/vp8li.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/webp/decode.h b/Example-Mac/Pods/Headers/Private/libwebp/webp/decode.h deleted file mode 120000 index cb9e6a20..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/webp/decode.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/decode.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/webp/demux.h b/Example-Mac/Pods/Headers/Private/libwebp/webp/demux.h deleted file mode 120000 index 4b1b1081..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/webp/demux.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/demux.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/webp/encode.h b/Example-Mac/Pods/Headers/Private/libwebp/webp/encode.h deleted file mode 120000 index 336598ae..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/webp/encode.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/encode.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/webp/extras.h b/Example-Mac/Pods/Headers/Private/libwebp/webp/extras.h deleted file mode 120000 index 1aef3627..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/webp/extras.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/extras.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/webp/format_constants.h b/Example-Mac/Pods/Headers/Private/libwebp/webp/format_constants.h deleted file mode 120000 index 2b3e467c..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/webp/format_constants.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/format_constants.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/webp/mux.h b/Example-Mac/Pods/Headers/Private/libwebp/webp/mux.h deleted file mode 120000 index 03e49641..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/webp/mux.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/mux.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/webp/mux_types.h b/Example-Mac/Pods/Headers/Private/libwebp/webp/mux_types.h deleted file mode 120000 index 20761020..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/webp/mux_types.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/mux_types.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/webp/types.h b/Example-Mac/Pods/Headers/Private/libwebp/webp/types.h deleted file mode 120000 index e00cbb0a..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/webp/types.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/types.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/webpi.h b/Example-Mac/Pods/Headers/Private/libwebp/webpi.h deleted file mode 120000 index 6cf10ad5..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/webpi.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/webpi.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Private/libwebp/yuv.h b/Example-Mac/Pods/Headers/Private/libwebp/yuv.h deleted file mode 120000 index eaa7fa95..00000000 --- a/Example-Mac/Pods/Headers/Private/libwebp/yuv.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dsp/yuv.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINCache/Nullability.h b/Example-Mac/Pods/Headers/Public/PINCache/Nullability.h deleted file mode 120000 index b90c434a..00000000 --- a/Example-Mac/Pods/Headers/Public/PINCache/Nullability.h +++ /dev/null @@ -1 +0,0 @@ -../../../PINCache/PINCache/Nullability.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINCache/PINCache.h b/Example-Mac/Pods/Headers/Public/PINCache/PINCache.h deleted file mode 120000 index 149e0bb6..00000000 --- a/Example-Mac/Pods/Headers/Public/PINCache/PINCache.h +++ /dev/null @@ -1 +0,0 @@ -../../../PINCache/PINCache/PINCache.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINCache/PINDiskCache.h b/Example-Mac/Pods/Headers/Public/PINCache/PINDiskCache.h deleted file mode 120000 index c5206f89..00000000 --- a/Example-Mac/Pods/Headers/Public/PINCache/PINDiskCache.h +++ /dev/null @@ -1 +0,0 @@ -../../../PINCache/PINCache/PINDiskCache.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINCache/PINMemoryCache.h b/Example-Mac/Pods/Headers/Public/PINCache/PINMemoryCache.h deleted file mode 120000 index c1b9753b..00000000 --- a/Example-Mac/Pods/Headers/Public/PINCache/PINMemoryCache.h +++ /dev/null @@ -1 +0,0 @@ -../../../PINCache/PINCache/PINMemoryCache.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINRemoteImage/NSData+ImageDetectors.h b/Example-Mac/Pods/Headers/Public/PINRemoteImage/NSData+ImageDetectors.h deleted file mode 120000 index 8d98e1a4..00000000 --- a/Example-Mac/Pods/Headers/Public/PINRemoteImage/NSData+ImageDetectors.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Categories/NSData+ImageDetectors.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINAlternateRepresentationProvider.h b/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINAlternateRepresentationProvider.h deleted file mode 120000 index ce662f35..00000000 --- a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINAlternateRepresentationProvider.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINAlternateRepresentationProvider.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINAnimatedImage.h b/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINAnimatedImage.h deleted file mode 120000 index 4ad10fe3..00000000 --- a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINAnimatedImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINAnimatedImage.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINAnimatedImageManager.h b/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINAnimatedImageManager.h deleted file mode 120000 index c9139ffe..00000000 --- a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINAnimatedImageManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINAnimatedImageManager.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINButton+PINRemoteImage.h b/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINButton+PINRemoteImage.h deleted file mode 120000 index 0ed989a1..00000000 --- a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINButton+PINRemoteImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Image Categories/PINButton+PINRemoteImage.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINDataTaskOperation.h b/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINDataTaskOperation.h deleted file mode 120000 index 6ebb4a80..00000000 --- a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINDataTaskOperation.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINDataTaskOperation.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINImage+DecodedImage.h b/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINImage+DecodedImage.h deleted file mode 120000 index 96d0ec62..00000000 --- a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINImage+DecodedImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Categories/PINImage+DecodedImage.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINImage+WebP.h b/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINImage+WebP.h deleted file mode 120000 index 6d484bc7..00000000 --- a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINImage+WebP.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Categories/PINImage+WebP.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINImageView+PINRemoteImage.h b/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINImageView+PINRemoteImage.h deleted file mode 120000 index a94e8f7c..00000000 --- a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINImageView+PINRemoteImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Image Categories/PINImageView+PINRemoteImage.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINProgressiveImage.h b/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINProgressiveImage.h deleted file mode 120000 index 03e8769f..00000000 --- a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINProgressiveImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINProgressiveImage.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImage.h b/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImage.h deleted file mode 120000 index 64ec7893..00000000 --- a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImage.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageCallbacks.h b/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageCallbacks.h deleted file mode 120000 index 790720bb..00000000 --- a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageCallbacks.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageCallbacks.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageCategoryManager.h b/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageCategoryManager.h deleted file mode 120000 index cba384e6..00000000 --- a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageCategoryManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageCategoryManager.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageDownloadTask.h b/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageDownloadTask.h deleted file mode 120000 index e492464a..00000000 --- a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageDownloadTask.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageDownloadTask.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageMacros.h b/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageMacros.h deleted file mode 120000 index 5c9588e9..00000000 --- a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageMacros.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageMacros.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageManager.h b/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageManager.h deleted file mode 120000 index d0e9703d..00000000 --- a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageManager.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageManagerResult.h b/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageManagerResult.h deleted file mode 120000 index b719636b..00000000 --- a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageManagerResult.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageManagerResult.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageMemoryContainer.h b/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageMemoryContainer.h deleted file mode 120000 index 8e2c8de9..00000000 --- a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageMemoryContainer.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageMemoryContainer.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageProcessorTask.h b/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageProcessorTask.h deleted file mode 120000 index 89c8a48b..00000000 --- a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageProcessorTask.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageProcessorTask.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageTask.h b/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageTask.h deleted file mode 120000 index 8379dfef..00000000 --- a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteImageTask.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageTask.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteLock.h b/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteLock.h deleted file mode 120000 index 1712bbd3..00000000 --- a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINRemoteLock.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteLock.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINURLSessionManager.h b/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINURLSessionManager.h deleted file mode 120000 index ad2ce3c8..00000000 --- a/Example-Mac/Pods/Headers/Public/PINRemoteImage/PINURLSessionManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINURLSessionManager.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/alphai.h b/Example-Mac/Pods/Headers/Public/libwebp/alphai.h deleted file mode 120000 index 3a6f3b9b..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/alphai.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/alphai.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/backward_references.h b/Example-Mac/Pods/Headers/Public/libwebp/backward_references.h deleted file mode 120000 index 0881ff9b..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/backward_references.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/enc/backward_references.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/bit_reader.h b/Example-Mac/Pods/Headers/Public/libwebp/bit_reader.h deleted file mode 120000 index 93789582..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/bit_reader.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/bit_reader.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/bit_reader_inl.h b/Example-Mac/Pods/Headers/Public/libwebp/bit_reader_inl.h deleted file mode 120000 index be415894..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/bit_reader_inl.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/bit_reader_inl.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/bit_writer.h b/Example-Mac/Pods/Headers/Public/libwebp/bit_writer.h deleted file mode 120000 index abe7119f..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/bit_writer.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/bit_writer.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/color_cache.h b/Example-Mac/Pods/Headers/Public/libwebp/color_cache.h deleted file mode 120000 index 5bba961d..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/color_cache.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/color_cache.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/common.h b/Example-Mac/Pods/Headers/Public/libwebp/common.h deleted file mode 120000 index 8f4827f8..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/common.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/common.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/cost.h b/Example-Mac/Pods/Headers/Public/libwebp/cost.h deleted file mode 120000 index a9c6f4ae..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/cost.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/enc/cost.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/decode_vp8.h b/Example-Mac/Pods/Headers/Public/libwebp/decode_vp8.h deleted file mode 120000 index b5ac83e7..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/decode_vp8.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/decode_vp8.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/delta_palettization.h b/Example-Mac/Pods/Headers/Public/libwebp/delta_palettization.h deleted file mode 120000 index c8e6fb64..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/delta_palettization.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/enc/delta_palettization.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/dsp.h b/Example-Mac/Pods/Headers/Public/libwebp/dsp.h deleted file mode 120000 index 1bace906..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/dsp.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dsp/dsp.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/endian_inl.h b/Example-Mac/Pods/Headers/Public/libwebp/endian_inl.h deleted file mode 120000 index 2be74a78..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/endian_inl.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/endian_inl.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/filters.h b/Example-Mac/Pods/Headers/Public/libwebp/filters.h deleted file mode 120000 index ab7b5327..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/filters.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/filters.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/histogram.h b/Example-Mac/Pods/Headers/Public/libwebp/histogram.h deleted file mode 120000 index c6950516..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/histogram.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/enc/histogram.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/huffman.h b/Example-Mac/Pods/Headers/Public/libwebp/huffman.h deleted file mode 120000 index 6245e139..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/huffman.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/huffman.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/huffman_encode.h b/Example-Mac/Pods/Headers/Public/libwebp/huffman_encode.h deleted file mode 120000 index 19a28b2a..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/huffman_encode.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/huffman_encode.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/lossless.h b/Example-Mac/Pods/Headers/Public/libwebp/lossless.h deleted file mode 120000 index a3b07cfe..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/lossless.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dsp/lossless.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/mips_macro.h b/Example-Mac/Pods/Headers/Public/libwebp/mips_macro.h deleted file mode 120000 index da76de07..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/mips_macro.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dsp/mips_macro.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/muxi.h b/Example-Mac/Pods/Headers/Public/libwebp/muxi.h deleted file mode 120000 index d96d5988..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/muxi.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/mux/muxi.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/neon.h b/Example-Mac/Pods/Headers/Public/libwebp/neon.h deleted file mode 120000 index 8213e481..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/neon.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dsp/neon.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/quant_levels.h b/Example-Mac/Pods/Headers/Public/libwebp/quant_levels.h deleted file mode 120000 index d620fa9c..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/quant_levels.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/quant_levels.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/quant_levels_dec.h b/Example-Mac/Pods/Headers/Public/libwebp/quant_levels_dec.h deleted file mode 120000 index 6930b5dd..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/quant_levels_dec.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/quant_levels_dec.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/random.h b/Example-Mac/Pods/Headers/Public/libwebp/random.h deleted file mode 120000 index 7ccc260c..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/random.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/random.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/rescaler.h b/Example-Mac/Pods/Headers/Public/libwebp/rescaler.h deleted file mode 120000 index 3c1c538c..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/rescaler.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/rescaler.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/thread.h b/Example-Mac/Pods/Headers/Public/libwebp/thread.h deleted file mode 120000 index 3033ec5a..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/thread.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/thread.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/utils.h b/Example-Mac/Pods/Headers/Public/libwebp/utils.h deleted file mode 120000 index ba046686..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/utils.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/utils.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/vp8enci.h b/Example-Mac/Pods/Headers/Public/libwebp/vp8enci.h deleted file mode 120000 index 4b202757..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/vp8enci.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/enc/vp8enci.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/vp8i.h b/Example-Mac/Pods/Headers/Public/libwebp/vp8i.h deleted file mode 120000 index 1c5d8a56..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/vp8i.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/vp8i.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/vp8li.h b/Example-Mac/Pods/Headers/Public/libwebp/vp8li.h deleted file mode 120000 index ee31158b..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/vp8li.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/vp8li.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/webp/decode.h b/Example-Mac/Pods/Headers/Public/libwebp/webp/decode.h deleted file mode 120000 index cb9e6a20..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/webp/decode.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/decode.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/webp/demux.h b/Example-Mac/Pods/Headers/Public/libwebp/webp/demux.h deleted file mode 120000 index 4b1b1081..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/webp/demux.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/demux.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/webp/encode.h b/Example-Mac/Pods/Headers/Public/libwebp/webp/encode.h deleted file mode 120000 index 336598ae..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/webp/encode.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/encode.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/webp/extras.h b/Example-Mac/Pods/Headers/Public/libwebp/webp/extras.h deleted file mode 120000 index 1aef3627..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/webp/extras.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/extras.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/webp/format_constants.h b/Example-Mac/Pods/Headers/Public/libwebp/webp/format_constants.h deleted file mode 120000 index 2b3e467c..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/webp/format_constants.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/format_constants.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/webp/mux.h b/Example-Mac/Pods/Headers/Public/libwebp/webp/mux.h deleted file mode 120000 index 03e49641..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/webp/mux.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/mux.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/webp/mux_types.h b/Example-Mac/Pods/Headers/Public/libwebp/webp/mux_types.h deleted file mode 120000 index 20761020..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/webp/mux_types.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/mux_types.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/webp/types.h b/Example-Mac/Pods/Headers/Public/libwebp/webp/types.h deleted file mode 120000 index e00cbb0a..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/webp/types.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/types.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/webpi.h b/Example-Mac/Pods/Headers/Public/libwebp/webpi.h deleted file mode 120000 index 6cf10ad5..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/webpi.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/webpi.h \ No newline at end of file diff --git a/Example-Mac/Pods/Headers/Public/libwebp/yuv.h b/Example-Mac/Pods/Headers/Public/libwebp/yuv.h deleted file mode 120000 index eaa7fa95..00000000 --- a/Example-Mac/Pods/Headers/Public/libwebp/yuv.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dsp/yuv.h \ No newline at end of file diff --git a/Example-Mac/Pods/Local Podspecs/PINRemoteImage.podspec.json b/Example-Mac/Pods/Local Podspecs/PINRemoteImage.podspec.json deleted file mode 100644 index 82fade1f..00000000 --- a/Example-Mac/Pods/Local Podspecs/PINRemoteImage.podspec.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "name": "PINRemoteImage", - "version": "2.1.2", - "summary": "A thread safe, performant, feature rich image fetcher", - "homepage": "https://github.com/pinterest/PINRemoteImage", - "license": "Apache 2.0", - "authors": { - "Garrett Moon": "garrett@pinterest.com" - }, - "source": { - "git": "https://github.com/pinterest/PINRemoteImage.git", - "tag": "2.1.2" - }, - "social_media_url": "https://twitter.com/garrettmoon", - "platforms": { - "ios": "6.0", - "osx": "10.8", - "tvos": "9.0" - }, - "requires_arc": true, - "default_subspecs": "FLAnimatedImage", - "subspecs": [ - { - "name": "Core", - "source_files": "Pod/Classes/**/*.{h,m}", - "exclude_files": [ - "Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.h", - "Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.m" - ], - "public_header_files": "Pod/Classes/**/*.h", - "frameworks": [ - "ImageIO", - "Accelerate" - ], - "dependencies": { - "PINCache": [ - ">=2.1" - ] - } - }, - { - "name": "iOS", - "platforms": "ios", - "dependencies": { - "PINRemoteImage/Core": [ - - ] - }, - "frameworks": [ - "UIKit", - "MobileCoreServices" - ] - }, - { - "name": "OSX", - "platforms": "osx", - "dependencies": { - "PINRemoteImage/Core": [ - - ] - }, - "frameworks": [ - "Cocoa", - "CoreServices" - ] - }, - { - "name": "tvOS", - "platforms": "tvos", - "dependencies": { - "PINRemoteImage/Core": [ - - ] - }, - "frameworks": "UIKit" - }, - { - "name": "FLAnimatedImage", - "platforms": "ios", - "dependencies": { - "PINRemoteImage/Core": [ - - ], - "FLAnimatedImage": [ - ">= 1.0" - ] - }, - "source_files": [ - "Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.h", - "Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.m" - ] - }, - { - "name": "WebP", - "xcconfig": { - "GCC_PREPROCESSOR_DEFINITIONS": "$(inherited) PIN_WEBP=1" - }, - "dependencies": { - "PINRemoteImage/Core": [ - - ], - "libwebp": [ - - ] - } - } - ] -} diff --git a/Example-Mac/Pods/Manifest.lock b/Example-Mac/Pods/Manifest.lock deleted file mode 100644 index d4d3ec7a..00000000 --- a/Example-Mac/Pods/Manifest.lock +++ /dev/null @@ -1,50 +0,0 @@ -PODS: - - libwebp (0.5.0): - - libwebp/core (= 0.5.0) - - libwebp/dec (= 0.5.0) - - libwebp/demux (= 0.5.0) - - libwebp/dsp (= 0.5.0) - - libwebp/enc (= 0.5.0) - - libwebp/mux (= 0.5.0) - - libwebp/utils (= 0.5.0) - - libwebp/webp (= 0.5.0) - - libwebp/core (0.5.0): - - libwebp/webp - - libwebp/dec (0.5.0): - - libwebp/core - - libwebp/demux (0.5.0): - - libwebp/core - - libwebp/dsp (0.5.0): - - libwebp/core - - libwebp/enc (0.5.0): - - libwebp/core - - libwebp/mux (0.5.0): - - libwebp/core - - libwebp/utils (0.5.0): - - libwebp/core - - libwebp/webp (0.5.0) - - PINCache (2.2.2) - - PINRemoteImage/Core (2.1.2): - - PINCache (>= 2.1) - - PINRemoteImage/OSX (2.1.2): - - PINRemoteImage/Core - - PINRemoteImage/WebP (2.1.2): - - libwebp - - PINRemoteImage/Core - -DEPENDENCIES: - - libwebp - - PINCache - - PINRemoteImage/OSX (from `../`) - - PINRemoteImage/WebP (from `../`) - -EXTERNAL SOURCES: - PINRemoteImage: - :path: ../ - -SPEC CHECKSUMS: - libwebp: 68ba2001ba6806ee52837ebd77a551a0b6567e4e - PINCache: 078426d356ab95ef875e9e62e5c35a2ea3333c28 - PINRemoteImage: cee13f6a46c58d6ebfa1975da97f7674c7e6f305 - -COCOAPODS: 0.39.0 diff --git a/Example-Mac/Pods/PINCache/PINCache/Nullability.h b/Example-Mac/Pods/PINCache/PINCache/Nullability.h deleted file mode 100644 index 437a16f3..00000000 --- a/Example-Mac/Pods/PINCache/PINCache/Nullability.h +++ /dev/null @@ -1,20 +0,0 @@ -// PINCache is a modified version of TMCache -// Modifications by Garrett Moon -// Copyright (c) 2015 Pinterest. All rights reserved. - -#ifndef PINCache_nullability_h -#define PINCache_nullability_h - -#if !__has_feature(nullability) -#define NS_ASSUME_NONNULL_BEGIN -#define NS_ASSUME_NONNULL_END -#define nullable -#define nonnull -#define null_unspecified -#define null_resettable -#define __nullable -#define __nonnull -#define __null_unspecified -#endif - -#endif diff --git a/Example-Mac/Pods/PINCache/PINCache/PINCache.h b/Example-Mac/Pods/PINCache/PINCache/PINCache.h deleted file mode 100644 index 9af2d18d..00000000 --- a/Example-Mac/Pods/PINCache/PINCache/PINCache.h +++ /dev/null @@ -1,203 +0,0 @@ -// PINCache is a modified version of TMCache -// Modifications by Garrett Moon -// Copyright (c) 2015 Pinterest. All rights reserved. - -#import - -#import "PINDiskCache.h" -#import "PINMemoryCache.h" - -NS_ASSUME_NONNULL_BEGIN - -@class PINCache; - -/** - A callback block which provides only the cache as an argument - */ - -typedef void (^PINCacheBlock)(PINCache *cache); - -/** - A callback block which provides the cache, key and object as arguments - */ - -typedef void (^PINCacheObjectBlock)(PINCache *cache, NSString *key, id __nullable object); - -/** - `PINCache` is a thread safe key/value store designed for persisting temporary objects that are expensive to - reproduce, such as downloaded data or the results of slow processing. It is comprised of two self-similar - stores, one in memory () and one on disk (). - - `PINCache` itself actually does very little; its main function is providing a front end for a common use case: - a small, fast memory cache that asynchronously persists itself to a large, slow disk cache. When objects are - removed from the memory cache in response to an "apocalyptic" event they remain in the disk cache and are - repopulated in memory the next time they are accessed. `PINCache` also does the tedious work of creating a - dispatch group to wait for both caches to finish their operations without blocking each other. - - The parallel caches are accessible as public properties ( and ) and can be manipulated - separately if necessary. See the docs for and for more details. - - @warning when using in extension or watch extension, define PIN_APP_EXTENSIONS=1 - */ - -@interface PINCache : NSObject - -#pragma mark - -/// @name Core - -/** - The name of this cache, used to create the and also appearing in stack traces. - */ -@property (readonly) NSString *name; - -/** - A concurrent queue on which blocks passed to the asynchronous access methods are run. - */ -@property (readonly) dispatch_queue_t concurrentQueue; - -/** - Synchronously retrieves the total byte count of the on the shared disk queue. - */ -@property (readonly) NSUInteger diskByteCount; - -/** - The underlying disk cache, see for additional configuration and trimming options. - */ -@property (readonly) PINDiskCache *diskCache; - -/** - The underlying memory cache, see for additional configuration and trimming options. - */ -@property (readonly) PINMemoryCache *memoryCache; - -#pragma mark - -/// @name Initialization - -/** - A shared cache. - - @result The shared singleton cache instance. - */ -+ (instancetype)sharedCache; - -- (instancetype)init NS_UNAVAILABLE; - -/** - Multiple instances with the same name are allowed and can safely access - the same data on disk thanks to the magic of seriality. Also used to create the . - - @see name - @param name The name of the cache. - @result A new cache with the specified name. - */ -- (instancetype)initWithName:(NSString *)name; - -/** - Multiple instances with the same name are allowed and can safely access - the same data on disk thanks to the magic of seriality. Also used to create the . - - @see name - @param name The name of the cache. - @param rootPath The path of the cache on disk. - @result A new cache with the specified name. - */ -- (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath NS_DESIGNATED_INITIALIZER; - -#pragma mark - -/// @name Asynchronous Methods - -/** - Retrieves the object for the specified key. This method returns immediately and executes the passed - block after the object is available, potentially in parallel with other blocks on the . - - @param key The key associated with the requested object. - @param block A block to be executed concurrently when the object is available. - */ -- (void)objectForKey:(NSString *)key block:(PINCacheObjectBlock)block; - -/** - Stores an object in the cache for the specified key. This method returns immediately and executes the - passed block after the object has been stored, potentially in parallel with other blocks on the . - - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - @param block A block to be executed concurrently after the object has been stored, or nil. - */ -- (void)setObject:(id )object forKey:(NSString *)key block:(nullable PINCacheObjectBlock)block; - -/** - Removes the object for the specified key. This method returns immediately and executes the passed - block after the object has been removed, potentially in parallel with other blocks on the . - - @param key The key associated with the object to be removed. - @param block A block to be executed concurrently after the object has been removed, or nil. - */ -- (void)removeObjectForKey:(NSString *)key block:(nullable PINCacheObjectBlock)block; - -/** - Removes all objects from the cache that have not been used since the specified date. This method returns immediately and - executes the passed block after the cache has been trimmed, potentially in parallel with other blocks on the . - - @param date Objects that haven't been accessed since this date are removed from the cache. - @param block A block to be executed concurrently after the cache has been trimmed, or nil. - */ -- (void)trimToDate:(NSDate *)date block:(nullable PINCacheBlock)block; - -/** - Removes all objects from the cache.This method returns immediately and executes the passed block after the - cache has been cleared, potentially in parallel with other blocks on the . - - @param block A block to be executed concurrently after the cache has been cleared, or nil. - */ -- (void)removeAllObjects:(nullable PINCacheBlock)block; - -#pragma mark - -/// @name Synchronous Methods - -/** - Retrieves the object for the specified key. This method blocks the calling thread until the object is available. - Uses a semaphore to achieve synchronicity on the disk cache. - - @see objectForKey:block: - @param key The key associated with the object. - @result The object for the specified key. - */ -- (__nullable id)objectForKey:(NSString *)key; - -/** - Stores an object in the cache for the specified key. This method blocks the calling thread until the object has been set. - Uses a semaphore to achieve synchronicity on the disk cache. - - @see setObject:forKey:block: - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - */ -- (void)setObject:(id )object forKey:(NSString *)key; - -/** - Removes the object for the specified key. This method blocks the calling thread until the object - has been removed. - Uses a semaphore to achieve synchronicity on the disk cache. - - @param key The key associated with the object to be removed. - */ -- (void)removeObjectForKey:(NSString *)key; - -/** - Removes all objects from the cache that have not been used since the specified date. - This method blocks the calling thread until the cache has been trimmed. - Uses a semaphore to achieve synchronicity on the disk cache. - - @param date Objects that haven't been accessed since this date are removed from the cache. - */ -- (void)trimToDate:(NSDate *)date; - -/** - Removes all objects from the cache. This method blocks the calling thread until the cache has been cleared. - Uses a semaphore to achieve synchronicity on the disk cache. - */ -- (void)removeAllObjects; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example-Mac/Pods/PINCache/PINCache/PINCache.m b/Example-Mac/Pods/PINCache/PINCache/PINCache.m deleted file mode 100644 index 53cdcd6c..00000000 --- a/Example-Mac/Pods/PINCache/PINCache/PINCache.m +++ /dev/null @@ -1,359 +0,0 @@ -// PINCache is a modified version of PINCache -// Modifications by Garrett Moon -// Copyright (c) 2015 Pinterest. All rights reserved. - -#import "PINCache.h" - -static NSString * const PINCachePrefix = @"com.pinterest.PINCache"; -static NSString * const PINCacheSharedName = @"PINCacheShared"; - -@interface PINCache () -#if OS_OBJECT_USE_OBJC -@property (strong, nonatomic) dispatch_queue_t concurrentQueue; -#else -@property (assign, nonatomic) dispatch_queue_t concurrentQueue; -#endif -@end - -@implementation PINCache - -#pragma mark - Initialization - - -#if !OS_OBJECT_USE_OBJC -- (void)dealloc -{ - dispatch_release(_concurrentQueue); - _concurrentQueue = nil; -} -#endif - -- (instancetype)init -{ - @throw [NSException exceptionWithName:@"Must initialize with a name" reason:@"PINCache must be initialized with a name. Call initWithName: instead." userInfo:nil]; - return [self initWithName:@""]; -} - -- (instancetype)initWithName:(NSString *)name -{ - return [self initWithName:name rootPath:[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]]; -} - -- (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath -{ - if (!name) - return nil; - - if (self = [super init]) { - _name = [name copy]; - - NSString *queueName = [[NSString alloc] initWithFormat:@"%@.%p", PINCachePrefix, self]; - _concurrentQueue = dispatch_queue_create([[NSString stringWithFormat:@"%@ Asynchronous Queue", queueName] UTF8String], DISPATCH_QUEUE_CONCURRENT); - - _diskCache = [[PINDiskCache alloc] initWithName:_name rootPath:rootPath]; - _memoryCache = [[PINMemoryCache alloc] init]; - } - return self; -} - -- (NSString *)description -{ - return [[NSString alloc] initWithFormat:@"%@.%@.%p", PINCachePrefix, _name, self]; -} - -+ (instancetype)sharedCache -{ - static id cache; - static dispatch_once_t predicate; - - dispatch_once(&predicate, ^{ - cache = [[self alloc] initWithName:PINCacheSharedName]; - }); - - return cache; -} - -#pragma mark - Public Asynchronous Methods - - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wshadow" - -- (void)objectForKey:(NSString *)key block:(PINCacheObjectBlock)block -{ - if (!key || !block) - return; - - __weak PINCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - __weak PINCache *weakSelf = strongSelf; - - [strongSelf->_memoryCache objectForKey:key block:^(PINMemoryCache *memoryCache, NSString *memoryCacheKey, id memoryCacheObject) { - PINCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - if (memoryCacheObject) { - [strongSelf->_diskCache fileURLForKey:memoryCacheKey block:^(PINDiskCache *diskCache, NSString *diskCacheKey, id diskCacheObject, NSURL *fileURL) { - // update the access time on disk - }]; - - __weak PINCache *weakSelf = strongSelf; - - dispatch_async(strongSelf->_concurrentQueue, ^{ - PINCache *strongSelf = weakSelf; - if (strongSelf) - block(strongSelf, memoryCacheKey, memoryCacheObject); - }); - } else { - __weak PINCache *weakSelf = strongSelf; - - [strongSelf->_diskCache objectForKey:memoryCacheKey block:^(PINDiskCache *diskCache, NSString *diskCacheKey, id diskCacheObject, NSURL *fileURL) { - PINCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf->_memoryCache setObject:diskCacheObject forKey:diskCacheKey block:nil]; - - __weak PINCache *weakSelf = strongSelf; - - dispatch_async(strongSelf->_concurrentQueue, ^{ - PINCache *strongSelf = weakSelf; - if (strongSelf) - block(strongSelf, diskCacheKey, diskCacheObject); - }); - }]; - } - }]; - }); -} - -#pragma clang diagnostic pop - -- (void)setObject:(id )object forKey:(NSString *)key block:(PINCacheObjectBlock)block -{ - if (!key || !object) - return; - - dispatch_group_t group = nil; - PINMemoryCacheObjectBlock memBlock = nil; - PINDiskCacheObjectBlock diskBlock = nil; - - if (block) { - group = dispatch_group_create(); - dispatch_group_enter(group); - dispatch_group_enter(group); - - memBlock = ^(PINMemoryCache *memoryCache, NSString *memoryCacheKey, id memoryCacheObject) { - dispatch_group_leave(group); - }; - - diskBlock = ^(PINDiskCache *diskCache, NSString *diskCacheKey, id memoryCacheObject, NSURL *memoryCacheFileURL) { - dispatch_group_leave(group); - }; - } - - [_memoryCache setObject:object forKey:key block:memBlock]; - [_diskCache setObject:object forKey:key block:diskBlock]; - - if (group) { - __weak PINCache *weakSelf = self; - dispatch_group_notify(group, _concurrentQueue, ^{ - PINCache *strongSelf = weakSelf; - if (strongSelf) - block(strongSelf, key, object); - }); - -#if !OS_OBJECT_USE_OBJC - dispatch_release(group); -#endif - } -} - -- (void)removeObjectForKey:(NSString *)key block:(PINCacheObjectBlock)block -{ - if (!key) - return; - - dispatch_group_t group = nil; - PINMemoryCacheObjectBlock memBlock = nil; - PINDiskCacheObjectBlock diskBlock = nil; - - if (block) { - group = dispatch_group_create(); - dispatch_group_enter(group); - dispatch_group_enter(group); - - memBlock = ^(PINMemoryCache *memoryCache, NSString *memoryCacheKey, id memoryCacheObject) { - dispatch_group_leave(group); - }; - - diskBlock = ^(PINDiskCache *diskCache, NSString *diskCacheKey, id memoryCacheObject, NSURL *memoryCacheFileURL) { - dispatch_group_leave(group); - }; - } - - [_memoryCache removeObjectForKey:key block:memBlock]; - [_diskCache removeObjectForKey:key block:diskBlock]; - - if (group) { - __weak PINCache *weakSelf = self; - dispatch_group_notify(group, _concurrentQueue, ^{ - PINCache *strongSelf = weakSelf; - if (strongSelf) - block(strongSelf, key, nil); - }); - -#if !OS_OBJECT_USE_OBJC - dispatch_release(group); -#endif - } -} - -- (void)removeAllObjects:(PINCacheBlock)block -{ - dispatch_group_t group = nil; - PINMemoryCacheBlock memBlock = nil; - PINDiskCacheBlock diskBlock = nil; - - if (block) { - group = dispatch_group_create(); - dispatch_group_enter(group); - dispatch_group_enter(group); - - memBlock = ^(PINMemoryCache *cache) { - dispatch_group_leave(group); - }; - - diskBlock = ^(PINDiskCache *cache) { - dispatch_group_leave(group); - }; - } - - [_memoryCache removeAllObjects:memBlock]; - [_diskCache removeAllObjects:diskBlock]; - - if (group) { - __weak PINCache *weakSelf = self; - dispatch_group_notify(group, _concurrentQueue, ^{ - PINCache *strongSelf = weakSelf; - if (strongSelf) - block(strongSelf); - }); - -#if !OS_OBJECT_USE_OBJC - dispatch_release(group); -#endif - } -} - -- (void)trimToDate:(NSDate *)date block:(PINCacheBlock)block -{ - if (!date) - return; - - dispatch_group_t group = nil; - PINMemoryCacheBlock memBlock = nil; - PINDiskCacheBlock diskBlock = nil; - - if (block) { - group = dispatch_group_create(); - dispatch_group_enter(group); - dispatch_group_enter(group); - - memBlock = ^(PINMemoryCache *cache) { - dispatch_group_leave(group); - }; - - diskBlock = ^(PINDiskCache *cache) { - dispatch_group_leave(group); - }; - } - - [_memoryCache trimToDate:date block:memBlock]; - [_diskCache trimToDate:date block:diskBlock]; - - if (group) { - __weak PINCache *weakSelf = self; - dispatch_group_notify(group, _concurrentQueue, ^{ - PINCache *strongSelf = weakSelf; - if (strongSelf) - block(strongSelf); - }); - -#if !OS_OBJECT_USE_OBJC - dispatch_release(group); -#endif - } -} - -#pragma mark - Public Synchronous Accessors - - -- (NSUInteger)diskByteCount -{ - __block NSUInteger byteCount = 0; - - [_diskCache synchronouslyLockFileAccessWhileExecutingBlock:^(PINDiskCache *diskCache) { - byteCount = diskCache.byteCount; - }]; - - return byteCount; -} - -- (__nullable id)objectForKey:(NSString *)key -{ - if (!key) - return nil; - - __block id object = nil; - - object = [_memoryCache objectForKey:key]; - - if (object) { - // update the access time on disk - [_diskCache fileURLForKey:key block:NULL]; - } else { - object = [_diskCache objectForKey:key]; - [_memoryCache setObject:object forKey:key]; - } - - return object; -} - -- (void)setObject:(id )object forKey:(NSString *)key -{ - if (!key || !object) - return; - - [_memoryCache setObject:object forKey:key]; - [_diskCache setObject:object forKey:key]; -} - -- (void)removeObjectForKey:(NSString *)key -{ - if (!key) - return; - - [_memoryCache removeObjectForKey:key]; - [_diskCache removeObjectForKey:key]; -} - -- (void)trimToDate:(NSDate *)date -{ - if (!date) - return; - - [_memoryCache trimToDate:date]; - [_diskCache trimToDate:date]; -} - -- (void)removeAllObjects -{ - [_memoryCache removeAllObjects]; - [_diskCache removeAllObjects]; -} - -@end diff --git a/Example-Mac/Pods/PINCache/PINCache/PINDiskCache.h b/Example-Mac/Pods/PINCache/PINCache/PINDiskCache.h deleted file mode 100644 index 8f2da086..00000000 --- a/Example-Mac/Pods/PINCache/PINCache/PINDiskCache.h +++ /dev/null @@ -1,373 +0,0 @@ -// PINCache is a modified version of TMCache -// Modifications by Garrett Moon -// Copyright (c) 2015 Pinterest. All rights reserved. - -#import -#import "Nullability.h" - -NS_ASSUME_NONNULL_BEGIN - -@class PINDiskCache; - -/** - A callback block which provides only the cache as an argument - */ - -typedef void (^PINDiskCacheBlock)(PINDiskCache *cache); - -/** - A callback block which provides the cache, key and object as arguments - */ - -typedef void (^PINDiskCacheObjectBlock)(PINDiskCache *cache, NSString *key, id __nullable object, NSURL * __nullable fileURL); - -/** - `PINDiskCache` is a thread safe key/value store backed by the file system. It accepts any object conforming - to the `NSCoding` protocol, which includes the basic Foundation data types and collection classes and also - many UIKit classes, notably `UIImage`. All work is performed on a serial queue shared by all instances in - the app, and archiving is handled by `NSKeyedArchiver`. This is a particular advantage for `UIImage` because - it skips `UIImagePNGRepresentation()` and retains information like scale and orientation. - - The designated initializer for `PINDiskCache` is . The string is used to create a directory - under Library/Caches that scopes disk access for this instance. Multiple instances with the same name are *not* - allowed as they would conflict with each other. - - Unless otherwise noted, all properties and methods are safe to access from any thread at any time. All blocks - will cause the queue to wait, making it safe to access and manipulate the actual cache files on disk for the - duration of the block. - - Because this cache is bound by disk I/O it can be much slower than , although values stored in - `PINDiskCache` persist after application relaunch. Using is recommended over using `PINDiskCache` - by itself, as it adds a fast layer of additional memory caching while still writing to disk. - - All access to the cache is dated so the that the least-used objects can be trimmed first. Setting an optional - will trigger a GCD timer to periodically to trim the cache with . - */ - -@interface PINDiskCache : NSObject - - - -#pragma mark - -/// @name Core - -/** - The name of this cache, used to create a directory under Library/Caches and also appearing in stack traces. - */ -@property (readonly) NSString *name; - -/** - The URL of the directory used by this cache, usually `Library/Caches/com.pinterest.PINDiskCache.(name)` - - @warning Do not interact with files under this URL except in or - . - */ -@property (readonly) NSURL *cacheURL; - -/** - The total number of bytes used on disk, as reported by `NSURLTotalFileAllocatedSizeKey`. - - @warning This property should only be read from a call to or - its asynchronous equivolent - - For example: - - // some background thread - - __block NSUInteger byteCount = 0; - - [_diskCache synchronouslyLockFileAccessWhileExecutingBlock:^(PINDiskCache *diskCache) { - byteCount = diskCache.byteCount; - }]; - */ -@property (readonly) NSUInteger byteCount; - -/** - The maximum number of bytes allowed on disk. This value is checked every time an object is set, if the written - size exceeds the limit a trim call is queued. Defaults to `0.0`, meaning no practical limit. - - */ -@property (assign) NSUInteger byteLimit; - -/** - The maximum number of seconds an object is allowed to exist in the cache. Setting this to a value - greater than `0.0` will start a recurring GCD timer with the same period that calls . - Setting it back to `0.0` will stop the timer. Defaults to `0.0`, meaning no limit. - - */ -@property (assign) NSTimeInterval ageLimit; - -/** - If ttlCache is YES, the cache behaves like a ttlCache. This means that once an object enters the - cache, it only lives as long as self.ageLimit. This has the following implications: - - Accessing an object in the cache does not extend that object's lifetime in the cache - - When attempting to access an object in the cache that has lived longer than self.ageLimit, - the cache will behave as if the object does not exist - - */ -@property (nonatomic, assign, getter=isTTLCache) BOOL ttlCache; - -#pragma mark - -/// @name Event Blocks - -/** - A block to be executed just before an object is added to the cache. The queue waits during execution. - */ -@property (copy) PINDiskCacheObjectBlock __nullable willAddObjectBlock; - -/** - A block to be executed just before an object is removed from the cache. The queue waits during execution. - */ -@property (copy) PINDiskCacheObjectBlock __nullable willRemoveObjectBlock; - -/** - A block to be executed just before all objects are removed from the cache as a result of . - The queue waits during execution. - */ -@property (copy) PINDiskCacheBlock __nullable willRemoveAllObjectsBlock; - -/** - A block to be executed just after an object is added to the cache. The queue waits during execution. - */ -@property (copy) PINDiskCacheObjectBlock __nullable didAddObjectBlock; - -/** - A block to be executed just after an object is removed from the cache. The queue waits during execution. - */ -@property (copy) PINDiskCacheObjectBlock __nullable didRemoveObjectBlock; - -/** - A block to be executed just after all objects are removed from the cache as a result of . - The queue waits during execution. - */ -@property (copy) PINDiskCacheBlock __nullable didRemoveAllObjectsBlock; - -#pragma mark - -/// @name Initialization - -/** - A shared cache. - - @result The shared singleton cache instance. - */ -+ (instancetype)sharedCache; - -/** - Empties the trash with `DISPATCH_QUEUE_PRIORITY_BACKGROUND`. Does not use lock. - */ -+ (void)emptyTrash; - -- (instancetype)init NS_UNAVAILABLE; - -/** - Multiple instances with the same name are allowed and can safely access - the same data on disk thanks to the magic of seriality. - - @see name - @param name The name of the cache. - @result A new cache with the specified name. - */ -- (instancetype)initWithName:(NSString *)name; - -/** - The designated initializer. Multiple instances with the same name are allowed and can safely access - the same data on disk thanks to the magic of seriality. - - @see name - @param name The name of the cache. - @param rootPath The path of the cache. - @result A new cache with the specified name. - */ -- (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath NS_DESIGNATED_INITIALIZER; - -#pragma mark - -/// @name Asynchronous Methods -/** - Locks access to ivars and allows safe interaction with files on disk. This method returns immediately. - - @warning Calling synchronous methods on the diskCache inside this block will likely cause a deadlock. - - @param block A block to be executed when a lock is available. - */ -- (void)lockFileAccessWhileExecutingBlock:(nullable PINDiskCacheBlock)block; - -/** - Retrieves the object for the specified key. This method returns immediately and executes the passed - block as soon as the object is available. - - @warning The fileURL is only valid for the duration of this block, do not use it after the block ends. - - @param key The key associated with the requested object. - @param block A block to be executed serially when the object is available. - */ -- (void)objectForKey:(NSString *)key block:(nullable PINDiskCacheObjectBlock)block; - -/** - Retrieves the fileURL for the specified key without actually reading the data from disk. This method - returns immediately and executes the passed block as soon as the object is available. - - @warning Access is protected for the duration of the block, but to maintain safe disk access do not - access this fileURL after the block has ended. - - @param key The key associated with the requested object. - @param block A block to be executed serially when the file URL is available. - */ -- (void)fileURLForKey:(nullable NSString *)key block:(nullable PINDiskCacheObjectBlock)block; - -/** - Stores an object in the cache for the specified key. This method returns immediately and executes the - passed block as soon as the object has been stored. - - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - @param block A block to be executed serially after the object has been stored, or nil. - */ -- (void)setObject:(id )object forKey:(NSString *)key block:(nullable PINDiskCacheObjectBlock)block; - -/** - Removes the object for the specified key. This method returns immediately and executes the passed block - as soon as the object has been removed. - - @param key The key associated with the object to be removed. - @param block A block to be executed serially after the object has been removed, or nil. - */ -- (void)removeObjectForKey:(NSString *)key block:(nullable PINDiskCacheObjectBlock)block; - -/** - Removes all objects from the cache that have not been used since the specified date. - This method returns immediately and executes the passed block as soon as the cache has been trimmed. - - @param date Objects that haven't been accessed since this date are removed from the cache. - @param block A block to be executed serially after the cache has been trimmed, or nil. - */ -- (void)trimToDate:(NSDate *)date block:(nullable PINDiskCacheBlock)block; - -/** - Removes objects from the cache, largest first, until the cache is equal to or smaller than the specified byteCount. - This method returns immediately and executes the passed block as soon as the cache has been trimmed. - - @param byteCount The cache will be trimmed equal to or smaller than this size. - @param block A block to be executed serially after the cache has been trimmed, or nil. - */ -- (void)trimToSize:(NSUInteger)byteCount block:(nullable PINDiskCacheBlock)block; - -/** - Removes objects from the cache, ordered by date (least recently used first), until the cache is equal to or smaller - than the specified byteCount. This method returns immediately and executes the passed block as soon as the cache has - been trimmed. - - @param byteCount The cache will be trimmed equal to or smaller than this size. - @param block A block to be executed serially after the cache has been trimmed, or nil. - */ -- (void)trimToSizeByDate:(NSUInteger)byteCount block:(nullable PINDiskCacheBlock)block; - -/** - Removes all objects from the cache. This method returns immediately and executes the passed block as soon as the - cache has been cleared. - - @param block A block to be executed serially after the cache has been cleared, or nil. - */ -- (void)removeAllObjects:(nullable PINDiskCacheBlock)block; - -/** - Loops through all objects in the cache (reads and writes are suspended during the enumeration). Data is not actually - read from disk, the `object` parameter of the block will be `nil` but the `fileURL` will be available. - This method returns immediately. - - @param block A block to be executed for every object in the cache. - @param completionBlock An optional block to be executed after the enumeration is complete. - */ -- (void)enumerateObjectsWithBlock:(PINDiskCacheObjectBlock)block completionBlock:(nullable PINDiskCacheBlock)completionBlock; - -#pragma mark - -/// @name Synchronous Methods - -/** - Locks access to ivars and allows safe interaction with files on disk. This method only returns once the block - has been run. - - @warning Calling synchronous methods on the diskCache inside this block will likely cause a deadlock. - - @param block A block to be executed when a lock is available. - */ -- (void)synchronouslyLockFileAccessWhileExecutingBlock:(nullable PINDiskCacheBlock)block; - -/** - Retrieves the object for the specified key. This method blocks the calling thread until the - object is available. - - @see objectForKey:block: - @param key The key associated with the object. - @result The object for the specified key. - */ -- (__nullable id )objectForKey:(NSString *)key; - -/** - Retrieves the file URL for the specified key. This method blocks the calling thread until the - url is available. Do not use this URL anywhere except with . This method probably - shouldn't even exist, just use the asynchronous one. - - @see fileURLForKey:block: - @param key The key associated with the object. - @result The file URL for the specified key. - */ -- (NSURL *)fileURLForKey:(nullable NSString *)key; - -/** - Stores an object in the cache for the specified key. This method blocks the calling thread until - the object has been stored. - - @see setObject:forKey:block: - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - */ -- (void)setObject:(id )object forKey:(NSString *)key; - -/** - Removes the object for the specified key. This method blocks the calling thread until the object - has been removed. - - @param key The key associated with the object to be removed. - */ -- (void)removeObjectForKey:(NSString *)key; - -/** - Removes all objects from the cache that have not been used since the specified date. - This method blocks the calling thread until the cache has been trimmed. - @param date Objects that haven't been accessed since this date are removed from the cache. - */ -- (void)trimToDate:(nullable NSDate *)date; - -/** - Removes objects from the cache, largest first, until the cache is equal to or smaller than the - specified byteCount. This method blocks the calling thread until the cache has been trimmed. - - @param byteCount The cache will be trimmed equal to or smaller than this size. - */ -- (void)trimToSize:(NSUInteger)byteCount; - -/** - Removes objects from the cache, ordered by date (least recently used first), until the cache is equal to or - smaller than the specified byteCount. This method blocks the calling thread until the cache has been trimmed. - @param byteCount The cache will be trimmed equal to or smaller than this size. - */ -- (void)trimToSizeByDate:(NSUInteger)byteCount; - -/** - Removes all objects from the cache. This method blocks the calling thread until the cache has been cleared. - */ -- (void)removeAllObjects; - -/** - Loops through all objects in the cache (reads and writes are suspended during the enumeration). Data is not actually - read from disk, the `object` parameter of the block will be `nil` but the `fileURL` will be available. - This method blocks the calling thread until all objects have been enumerated. - @param block A block to be executed for every object in the cache. - @warning Do not call this method within the event blocks (, etc.) - Instead use the asynchronous version, . - */ -- (void)enumerateObjectsWithBlock:(nullable PINDiskCacheObjectBlock)block; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example-Mac/Pods/PINCache/PINCache/PINDiskCache.m b/Example-Mac/Pods/PINCache/PINCache/PINDiskCache.m deleted file mode 100644 index 3755abbb..00000000 --- a/Example-Mac/Pods/PINCache/PINCache/PINDiskCache.m +++ /dev/null @@ -1,1171 +0,0 @@ -// PINCache is a modified version of TMCache -// Modifications by Garrett Moon -// Copyright (c) 2015 Pinterest. All rights reserved. - -#import "PINDiskCache.h" - -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 -#import -#endif - -#define PINDiskCacheError(error) if (error) { NSLog(@"%@ (%d) ERROR: %@", \ -[[NSString stringWithUTF8String:__FILE__] lastPathComponent], \ -__LINE__, [error localizedDescription]); } - -static NSString * const PINDiskCachePrefix = @"com.pinterest.PINDiskCache"; -static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared"; - -@interface PINBackgroundTask : NSObject -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 && !TARGET_OS_WATCH -@property (atomic, assign) UIBackgroundTaskIdentifier taskID; -#endif -+ (instancetype)start; -- (void)end; -@end - -@interface PINDiskCache () - -@property (assign) NSUInteger byteCount; -@property (strong, nonatomic) NSURL *cacheURL; -#if OS_OBJECT_USE_OBJC -@property (strong, nonatomic) dispatch_queue_t asyncQueue; -@property (strong, nonatomic) dispatch_semaphore_t lockSemaphore; -#else -@property (assign, nonatomic) dispatch_queue_t asyncQueue; -@property (assign, nonatomic) dispatch_semaphore_t lockSemaphore; -#endif -@property (strong, nonatomic) NSMutableDictionary *dates; -@property (strong, nonatomic) NSMutableDictionary *sizes; -@end - -@implementation PINDiskCache - -@synthesize willAddObjectBlock = _willAddObjectBlock; -@synthesize willRemoveObjectBlock = _willRemoveObjectBlock; -@synthesize willRemoveAllObjectsBlock = _willRemoveAllObjectsBlock; -@synthesize didAddObjectBlock = _didAddObjectBlock; -@synthesize didRemoveObjectBlock = _didRemoveObjectBlock; -@synthesize didRemoveAllObjectsBlock = _didRemoveAllObjectsBlock; -@synthesize byteLimit = _byteLimit; -@synthesize ageLimit = _ageLimit; -@synthesize ttlCache = _ttlCache; - -#pragma mark - Initialization - - -- (void)dealloc -{ -#if !OS_OBJECT_USE_OBJC - dispatch_release(_lockSemaphore); - dispatch_release(_asyncQueue); - _asyncQueue = nil; -#endif -} - -- (instancetype)init -{ - @throw [NSException exceptionWithName:@"Must initialize with a name" reason:@"PINDiskCache must be initialized with a name. Call initWithName: instead." userInfo:nil]; - return [self initWithName:@""]; -} - -- (instancetype)initWithName:(NSString *)name -{ - return [self initWithName:name rootPath:[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0]]; -} - -- (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath -{ - if (!name) - return nil; - - if (self = [super init]) { - _name = [name copy]; - _asyncQueue = dispatch_queue_create([[NSString stringWithFormat:@"%@ Asynchronous Queue", PINDiskCachePrefix] UTF8String], DISPATCH_QUEUE_CONCURRENT); - _lockSemaphore = dispatch_semaphore_create(1); - _willAddObjectBlock = nil; - _willRemoveObjectBlock = nil; - _willRemoveAllObjectsBlock = nil; - _didAddObjectBlock = nil; - _didRemoveObjectBlock = nil; - _didRemoveAllObjectsBlock = nil; - - _byteCount = 0; - _byteLimit = 0; - _ageLimit = 0.0; - - _dates = [[NSMutableDictionary alloc] init]; - _sizes = [[NSMutableDictionary alloc] init]; - - NSString *pathComponent = [[NSString alloc] initWithFormat:@"%@.%@", PINDiskCachePrefix, _name]; - _cacheURL = [NSURL fileURLWithPathComponents:@[ rootPath, pathComponent ]]; - - //we don't want to do anything without setting up the disk cache, but we also don't want to block init, it can take a while to initialize - //this is only safe because we use a dispatch_semaphore as a lock. If we switch to an NSLock or posix locks, this will *no longer be safe*. - [self lock]; - dispatch_async(_asyncQueue, ^{ - [self createCacheDirectory]; - [self initializeDiskProperties]; - - [self unlock]; - }); - } - return self; -} - -- (NSString *)description -{ - return [[NSString alloc] initWithFormat:@"%@.%@.%p", PINDiskCachePrefix, _name, self]; -} - -+ (instancetype)sharedCache -{ - static id cache; - static dispatch_once_t predicate; - - dispatch_once(&predicate, ^{ - cache = [[self alloc] initWithName:PINDiskCacheSharedName]; - }); - - return cache; -} - -#pragma mark - Private Methods - - -- (NSURL *)encodedFileURLForKey:(NSString *)key -{ - if (![key length]) - return nil; - - return [_cacheURL URLByAppendingPathComponent:[self encodedString:key]]; -} - -- (NSString *)keyForEncodedFileURL:(NSURL *)url -{ - NSString *fileName = [url lastPathComponent]; - if (!fileName) - return nil; - - return [self decodedString:fileName]; -} - -- (NSString *)encodedString:(NSString *)string -{ - if (![string length]) { - return @""; - } - - if ([string respondsToSelector:@selector(stringByAddingPercentEncodingWithAllowedCharacters:)]) { - return [string stringByAddingPercentEncodingWithAllowedCharacters:[[NSCharacterSet characterSetWithCharactersInString:@".:/%"] invertedSet]]; - } - else { - CFStringRef static const charsToEscape = CFSTR(".:/%"); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - CFStringRef escapedString = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, - (__bridge CFStringRef)string, - NULL, - charsToEscape, - kCFStringEncodingUTF8); -#pragma clang diagnostic pop - return (__bridge_transfer NSString *)escapedString; - } -} - -- (NSString *)decodedString:(NSString *)string -{ - if (![string length]) { - return @""; - } - - if ([string respondsToSelector:@selector(stringByRemovingPercentEncoding)]) { - return [string stringByRemovingPercentEncoding]; - } - else { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - CFStringRef unescapedString = CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault, - (__bridge CFStringRef)string, - CFSTR(""), - kCFStringEncodingUTF8); -#pragma clang diagnostic pop - return (__bridge_transfer NSString *)unescapedString; - } -} - -#pragma mark - Private Trash Methods - - -+ (dispatch_queue_t)sharedTrashQueue -{ - static dispatch_queue_t trashQueue; - static dispatch_once_t predicate; - - dispatch_once(&predicate, ^{ - NSString *queueName = [[NSString alloc] initWithFormat:@"%@.trash", PINDiskCachePrefix]; - trashQueue = dispatch_queue_create([queueName UTF8String], DISPATCH_QUEUE_SERIAL); - dispatch_set_target_queue(trashQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)); - }); - - return trashQueue; -} - -+ (NSURL *)sharedTrashURL -{ - static NSURL *sharedTrashURL; - static dispatch_once_t predicate; - - dispatch_once(&predicate, ^{ - sharedTrashURL = [[[NSURL alloc] initFileURLWithPath:NSTemporaryDirectory()] URLByAppendingPathComponent:PINDiskCachePrefix isDirectory:YES]; - - if (![[NSFileManager defaultManager] fileExistsAtPath:[sharedTrashURL path]]) { - NSError *error = nil; - [[NSFileManager defaultManager] createDirectoryAtURL:sharedTrashURL - withIntermediateDirectories:YES - attributes:nil - error:&error]; - PINDiskCacheError(error); - } - }); - - return sharedTrashURL; -} - -+(BOOL)moveItemAtURLToTrash:(NSURL *)itemURL -{ - if (![[NSFileManager defaultManager] fileExistsAtPath:[itemURL path]]) - return NO; - - NSError *error = nil; - NSString *uniqueString = [[NSProcessInfo processInfo] globallyUniqueString]; - NSURL *uniqueTrashURL = [[PINDiskCache sharedTrashURL] URLByAppendingPathComponent:uniqueString]; - BOOL moved = [[NSFileManager defaultManager] moveItemAtURL:itemURL toURL:uniqueTrashURL error:&error]; - PINDiskCacheError(error); - return moved; -} - -+ (void)emptyTrash -{ - PINBackgroundTask *task = [PINBackgroundTask start]; - - dispatch_async([self sharedTrashQueue], ^{ - NSError *searchTrashedItemsError = nil; - NSArray *trashedItems = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:[self sharedTrashURL] - includingPropertiesForKeys:nil - options:0 - error:&searchTrashedItemsError]; - PINDiskCacheError(searchTrashedItemsError); - - for (NSURL *trashedItemURL in trashedItems) { - NSError *removeTrashedItemError = nil; - [[NSFileManager defaultManager] removeItemAtURL:trashedItemURL error:&removeTrashedItemError]; - PINDiskCacheError(removeTrashedItemError); - } - - [task end]; - }); -} - -#pragma mark - Private Queue Methods - - -- (BOOL)createCacheDirectory -{ - if ([[NSFileManager defaultManager] fileExistsAtPath:[_cacheURL path]]) - return NO; - - NSError *error = nil; - BOOL success = [[NSFileManager defaultManager] createDirectoryAtURL:_cacheURL - withIntermediateDirectories:YES - attributes:nil - error:&error]; - PINDiskCacheError(error); - - return success; -} - -- (void)initializeDiskProperties -{ - NSUInteger byteCount = 0; - NSArray *keys = @[ NSURLContentModificationDateKey, NSURLTotalFileAllocatedSizeKey ]; - - NSError *error = nil; - NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:_cacheURL - includingPropertiesForKeys:keys - options:NSDirectoryEnumerationSkipsHiddenFiles - error:&error]; - PINDiskCacheError(error); - - for (NSURL *fileURL in files) { - NSString *key = [self keyForEncodedFileURL:fileURL]; - - error = nil; - NSDictionary *dictionary = [fileURL resourceValuesForKeys:keys error:&error]; - PINDiskCacheError(error); - - NSDate *date = [dictionary objectForKey:NSURLContentModificationDateKey]; - if (date && key) - [_dates setObject:date forKey:key]; - - NSNumber *fileSize = [dictionary objectForKey:NSURLTotalFileAllocatedSizeKey]; - if (fileSize) { - [_sizes setObject:fileSize forKey:key]; - byteCount += [fileSize unsignedIntegerValue]; - } - } - - if (byteCount > 0) - self.byteCount = byteCount; // atomic -} - -- (BOOL)setFileModificationDate:(NSDate *)date forURL:(NSURL *)fileURL -{ - if (!date || !fileURL) { - return NO; - } - - NSError *error = nil; - BOOL success = [[NSFileManager defaultManager] setAttributes:@{ NSFileModificationDate: date } - ofItemAtPath:[fileURL path] - error:&error]; - PINDiskCacheError(error); - - if (success) { - NSString *key = [self keyForEncodedFileURL:fileURL]; - if (key) { - [_dates setObject:date forKey:key]; - } - } - - return success; -} - -- (BOOL)removeFileAndExecuteBlocksForKey:(NSString *)key -{ - NSURL *fileURL = [self encodedFileURLForKey:key]; - if (!fileURL || ![[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]]) - return NO; - - if (_willRemoveObjectBlock) - _willRemoveObjectBlock(self, key, nil, fileURL); - - BOOL trashed = [PINDiskCache moveItemAtURLToTrash:fileURL]; - if (!trashed) - return NO; - - [PINDiskCache emptyTrash]; - - NSNumber *byteSize = [_sizes objectForKey:key]; - if (byteSize) - self.byteCount = _byteCount - [byteSize unsignedIntegerValue]; // atomic - - [_sizes removeObjectForKey:key]; - [_dates removeObjectForKey:key]; - - if (_didRemoveObjectBlock) - _didRemoveObjectBlock(self, key, nil, fileURL); - - return YES; -} - -- (void)trimDiskToSize:(NSUInteger)trimByteCount -{ - if (_byteCount <= trimByteCount) - return; - - NSArray *keysSortedBySize = [_sizes keysSortedByValueUsingSelector:@selector(compare:)]; - - for (NSString *key in [keysSortedBySize reverseObjectEnumerator]) { // largest objects first - [self removeFileAndExecuteBlocksForKey:key]; - - if (_byteCount <= trimByteCount) - break; - } -} - -- (void)trimDiskToSizeByDate:(NSUInteger)trimByteCount -{ - if (_byteCount <= trimByteCount) - return; - - NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)]; - - for (NSString *key in keysSortedByDate) { // oldest objects first - [self removeFileAndExecuteBlocksForKey:key]; - - if (_byteCount <= trimByteCount) - break; - } -} - -- (void)trimDiskToDate:(NSDate *)trimDate -{ - NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)]; - - for (NSString *key in keysSortedByDate) { // oldest files first - NSDate *accessDate = [_dates objectForKey:key]; - if (!accessDate) - continue; - - if ([accessDate compare:trimDate] == NSOrderedAscending) { // older than trim date - [self removeFileAndExecuteBlocksForKey:key]; - } else { - break; - } - } -} - -- (void)trimToAgeLimitRecursively -{ - [self lock]; - NSTimeInterval ageLimit = _ageLimit; - [self unlock]; - if (ageLimit == 0.0) - return; - - [self lock]; - NSDate *date = [[NSDate alloc] initWithTimeIntervalSinceNow:-ageLimit]; - [self trimDiskToDate:date]; - [self unlock]; - - __weak PINDiskCache *weakSelf = self; - - dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_ageLimit * NSEC_PER_SEC)); - dispatch_after(time, _asyncQueue, ^(void) { - PINDiskCache *strongSelf = weakSelf; - [strongSelf trimToAgeLimitRecursively]; - }); -} - -#pragma mark - Public Asynchronous Methods - - -- (void)lockFileAccessWhileExecutingBlock:(void(^)(PINDiskCache *diskCache))block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (block) { - [strongSelf lock]; - block(strongSelf); - [strongSelf unlock]; - } - }); -} - -- (void)objectForKey:(NSString *)key block:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - NSURL *fileURL = nil; - id object = [strongSelf objectForKey:key fileURL:&fileURL]; - - if (block) { - [strongSelf lock]; - block(strongSelf, key, object, fileURL); - [strongSelf unlock]; - } - }); -} - -- (void)fileURLForKey:(NSString *)key block:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - NSURL *fileURL = [strongSelf fileURLForKey:key]; - - if (block) { - [strongSelf lock]; - block(strongSelf, key, nil, fileURL); - [strongSelf unlock]; - } - }); -} - -- (void)setObject:(id )object forKey:(NSString *)key block:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - NSURL *fileURL = nil; - [strongSelf setObject:object forKey:key fileURL:&fileURL]; - - if (block) { - [strongSelf lock]; - block(strongSelf, key, object, fileURL); - [strongSelf unlock]; - } - }); -} - -- (void)removeObjectForKey:(NSString *)key block:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - NSURL *fileURL = nil; - [strongSelf removeObjectForKey:key fileURL:&fileURL]; - - if (block) { - [strongSelf lock]; - block(strongSelf, key, nil, fileURL); - [strongSelf unlock]; - } - }); -} - -- (void)trimToSize:(NSUInteger)trimByteCount block:(PINDiskCacheBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - [strongSelf trimToSize:trimByteCount]; - - if (block) { - [strongSelf lock]; - block(strongSelf); - [strongSelf unlock]; - } - }); -} - -- (void)trimToDate:(NSDate *)trimDate block:(PINDiskCacheBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - [strongSelf trimToDate:trimDate]; - - if (block) { - [strongSelf lock]; - block(strongSelf); - [strongSelf unlock]; - } - }); -} - -- (void)trimToSizeByDate:(NSUInteger)trimByteCount block:(PINDiskCacheBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - [strongSelf trimToSizeByDate:trimByteCount]; - - if (block) { - [strongSelf lock]; - block(strongSelf); - [strongSelf unlock]; - } - }); -} - -- (void)removeAllObjects:(PINDiskCacheBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - [strongSelf removeAllObjects]; - - if (block) { - [strongSelf lock]; - block(strongSelf); - [strongSelf unlock]; - } - }); -} - -- (void)enumerateObjectsWithBlock:(PINDiskCacheObjectBlock)block completionBlock:(PINDiskCacheBlock)completionBlock -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - [strongSelf enumerateObjectsWithBlock:block]; - - if (completionBlock) { - [self lock]; - completionBlock(strongSelf); - [self unlock]; - } - }); -} - -#pragma mark - Public Synchronous Methods - - -- (void)synchronouslyLockFileAccessWhileExecutingBlock:(void(^)(PINDiskCache *diskCache))block -{ - if (block) { - [self lock]; - block(self); - [self unlock]; - } -} - -- (__nullable id)objectForKey:(NSString *)key -{ - return [self objectForKey:key fileURL:nil]; -} - -- (__nullable id )objectForKey:(NSString *)key fileURL:(NSURL **)outFileURL -{ - NSDate *now = [[NSDate alloc] init]; - - if (!key) - return nil; - - id object = nil; - NSURL *fileURL = nil; - - [self lock]; - fileURL = [self encodedFileURLForKey:key]; - object = nil; - - if ([[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]] && - // If the cache should behave like a TTL cache, then only fetch the object if there's a valid ageLimit and the object is still alive - (!self->_ttlCache || self->_ageLimit <= 0 || fabs([[_dates objectForKey:key] timeIntervalSinceDate:now]) < self->_ageLimit)) { - @try { - object = [NSKeyedUnarchiver unarchiveObjectWithFile:[fileURL path]]; - } - @catch (NSException *exception) { - NSError *error = nil; - [[NSFileManager defaultManager] removeItemAtPath:[fileURL path] error:&error]; - PINDiskCacheError(error); - } - if (!self->_ttlCache) { - [self setFileModificationDate:now forURL:fileURL]; - } - } - [self unlock]; - - if (outFileURL) { - *outFileURL = fileURL; - } - - return object; -} - -- (NSURL *)fileURLForKey:(NSString *)key -{ - NSDate *now = [[NSDate alloc] init]; - - if (!key) - return nil; - - NSURL *fileURL = nil; - - [self lock]; - fileURL = [self encodedFileURLForKey:key]; - - if ([[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]]) { - // Don't update the file modification time, if self is a ttlCache - if (!self->_ttlCache) { - [self setFileModificationDate:now forURL:fileURL]; - } - } else { - fileURL = nil; - } - [self unlock]; - return fileURL; -} - -- (void)setObject:(id )object forKey:(NSString *)key -{ - [self setObject:object forKey:key fileURL:nil]; -} - -- (void)setObject:(id )object forKey:(NSString *)key fileURL:(NSURL **)outFileURL -{ - NSDate *now = [[NSDate alloc] init]; - - if (!key || !object) - return; - - PINBackgroundTask *task = [PINBackgroundTask start]; - - NSURL *fileURL = nil; - - [self lock]; - fileURL = [self encodedFileURLForKey:key]; - - if (self->_willAddObjectBlock) - self->_willAddObjectBlock(self, key, object, fileURL); - - BOOL written = [NSKeyedArchiver archiveRootObject:object toFile:[fileURL path]]; - - if (written) { - [self setFileModificationDate:now forURL:fileURL]; - - NSError *error = nil; - NSDictionary *values = [fileURL resourceValuesForKeys:@[ NSURLTotalFileAllocatedSizeKey ] error:&error]; - PINDiskCacheError(error); - - NSNumber *diskFileSize = [values objectForKey:NSURLTotalFileAllocatedSizeKey]; - if (diskFileSize) { - NSNumber *prevDiskFileSize = [self->_sizes objectForKey:key]; - if (prevDiskFileSize) { - self.byteCount = self->_byteCount - [prevDiskFileSize unsignedIntegerValue]; - } - [self->_sizes setObject:diskFileSize forKey:key]; - self.byteCount = self->_byteCount + [diskFileSize unsignedIntegerValue]; // atomic - } - - if (self->_byteLimit > 0 && self->_byteCount > self->_byteLimit) - [self trimToSizeByDate:self->_byteLimit block:nil]; - } else { - fileURL = nil; - } - - if (self->_didAddObjectBlock) - self->_didAddObjectBlock(self, key, object, written ? fileURL : nil); - [self unlock]; - - if (outFileURL) { - *outFileURL = fileURL; - } - - [task end]; -} - -- (void)removeObjectForKey:(NSString *)key -{ - [self removeObjectForKey:key fileURL:nil]; -} - -- (void)removeObjectForKey:(NSString *)key fileURL:(NSURL **)outFileURL -{ - if (!key) - return; - - PINBackgroundTask *task = [PINBackgroundTask start]; - - NSURL *fileURL = nil; - - [self lock]; - fileURL = [self encodedFileURLForKey:key]; - [self removeFileAndExecuteBlocksForKey:key]; - [self unlock]; - - [task end]; - - if (outFileURL) { - *outFileURL = fileURL; - } -} - -- (void)trimToSize:(NSUInteger)trimByteCount -{ - if (trimByteCount == 0) { - [self removeAllObjects]; - return; - } - - PINBackgroundTask *task = [PINBackgroundTask start]; - - [self lock]; - [self trimDiskToSize:trimByteCount]; - [self unlock]; - - [task end]; -} - -- (void)trimToDate:(NSDate *)trimDate -{ - if (!trimDate) - return; - - if ([trimDate isEqualToDate:[NSDate distantPast]]) { - [self removeAllObjects]; - return; - } - - PINBackgroundTask *task = [PINBackgroundTask start]; - - [self lock]; - [self trimDiskToDate:trimDate]; - [self unlock]; - - [task end]; -} - -- (void)trimToSizeByDate:(NSUInteger)trimByteCount -{ - if (trimByteCount == 0) { - [self removeAllObjects]; - return; - } - - PINBackgroundTask *task = [PINBackgroundTask start]; - - [self lock]; - [self trimDiskToSizeByDate:trimByteCount]; - [self unlock]; - - [task end]; -} - -- (void)removeAllObjects -{ - PINBackgroundTask *task = [PINBackgroundTask start]; - - [self lock]; - if (self->_willRemoveAllObjectsBlock) - self->_willRemoveAllObjectsBlock(self); - - [PINDiskCache moveItemAtURLToTrash:self->_cacheURL]; - [PINDiskCache emptyTrash]; - - [self createCacheDirectory]; - - [self->_dates removeAllObjects]; - [self->_sizes removeAllObjects]; - self.byteCount = 0; // atomic - - if (self->_didRemoveAllObjectsBlock) - self->_didRemoveAllObjectsBlock(self); - [self unlock]; - - [task end]; -} - -- (void)enumerateObjectsWithBlock:(PINDiskCacheObjectBlock)block -{ - if (!block) - return; - - PINBackgroundTask *task = [PINBackgroundTask start]; - - [self lock]; - NSDate *now = [NSDate date]; - NSArray *keysSortedByDate = [self->_dates keysSortedByValueUsingSelector:@selector(compare:)]; - - for (NSString *key in keysSortedByDate) { - NSURL *fileURL = [self encodedFileURLForKey:key]; - // If the cache should behave like a TTL cache, then only fetch the object if there's a valid ageLimit and the object is still alive - if (!self->_ttlCache || self->_ageLimit <= 0 || fabs([[_dates objectForKey:key] timeIntervalSinceDate:now]) < self->_ageLimit) { - block(self, key, nil, fileURL); - } - } - [self unlock]; - - [task end]; -} - -#pragma mark - Public Thread Safe Accessors - - -- (PINDiskCacheObjectBlock)willAddObjectBlock -{ - PINDiskCacheObjectBlock block = nil; - - [self lock]; - block = _willAddObjectBlock; - [self unlock]; - - return block; -} - -- (void)setWillAddObjectBlock:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - [strongSelf lock]; - strongSelf->_willAddObjectBlock = [block copy]; - [strongSelf unlock]; - }); -} - -- (PINDiskCacheObjectBlock)willRemoveObjectBlock -{ - PINDiskCacheObjectBlock block = nil; - - [self lock]; - block = _willRemoveObjectBlock; - [self unlock]; - - return block; -} - -- (void)setWillRemoveObjectBlock:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_willRemoveObjectBlock = [block copy]; - [strongSelf unlock]; - }); -} - -- (PINDiskCacheBlock)willRemoveAllObjectsBlock -{ - PINDiskCacheBlock block = nil; - - [self lock]; - block = _willRemoveAllObjectsBlock; - [self unlock]; - - return block; -} - -- (void)setWillRemoveAllObjectsBlock:(PINDiskCacheBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_willRemoveAllObjectsBlock = [block copy]; - [strongSelf unlock]; - }); -} - -- (PINDiskCacheObjectBlock)didAddObjectBlock -{ - PINDiskCacheObjectBlock block = nil; - - [self lock]; - block = _didAddObjectBlock; - [self unlock]; - - return block; -} - -- (void)setDidAddObjectBlock:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_didAddObjectBlock = [block copy]; - [strongSelf unlock]; - }); -} - -- (PINDiskCacheObjectBlock)didRemoveObjectBlock -{ - PINDiskCacheObjectBlock block = nil; - - [self lock]; - block = _didRemoveObjectBlock; - [self unlock]; - - return block; -} - -- (void)setDidRemoveObjectBlock:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_didRemoveObjectBlock = [block copy]; - [strongSelf unlock]; - }); -} - -- (PINDiskCacheBlock)didRemoveAllObjectsBlock -{ - PINDiskCacheBlock block = nil; - - [self lock]; - block = _didRemoveAllObjectsBlock; - [self unlock]; - - return block; -} - -- (void)setDidRemoveAllObjectsBlock:(PINDiskCacheBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_didRemoveAllObjectsBlock = [block copy]; - [strongSelf unlock]; - }); -} - -- (NSUInteger)byteLimit -{ - NSUInteger byteLimit; - - [self lock]; - byteLimit = _byteLimit; - [self unlock]; - - return byteLimit; -} - -- (void)setByteLimit:(NSUInteger)byteLimit -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_byteLimit = byteLimit; - - if (byteLimit > 0) - [strongSelf trimDiskToSizeByDate:byteLimit]; - [strongSelf unlock]; - }); -} - -- (NSTimeInterval)ageLimit -{ - NSTimeInterval ageLimit; - - [self lock]; - ageLimit = _ageLimit; - [self unlock]; - - return ageLimit; -} - -- (void)setAgeLimit:(NSTimeInterval)ageLimit -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_ageLimit = ageLimit; - [strongSelf unlock]; - - [strongSelf trimToAgeLimitRecursively]; - }); -} - -- (BOOL)isTTLCache { - BOOL isTTLCache; - - [self lock]; - isTTLCache = _ttlCache; - [self unlock]; - - return isTTLCache; -} - -- (void)setTtlCache:(BOOL)ttlCache { - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_ttlCache = ttlCache; - [strongSelf unlock]; - }); -} - -- (void)lock -{ - dispatch_semaphore_wait(_lockSemaphore, DISPATCH_TIME_FOREVER); -} - -- (void)unlock -{ - dispatch_semaphore_signal(_lockSemaphore); -} - -@end - -@implementation PINBackgroundTask - -+ (BOOL)isAppExtension { - - static BOOL isExtension; - static dispatch_once_t onceToken; - - dispatch_once(&onceToken, ^{ - NSDictionary *extensionDictionary = [[NSBundle mainBundle] infoDictionary][@"NSExtension"]; - isExtension = [extensionDictionary isKindOfClass:[NSDictionary class]]; - }); - - return isExtension; -} - -- (instancetype)init -{ - if (self = [super init]) { -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 && !TARGET_OS_WATCH - _taskID = UIBackgroundTaskInvalid; -#endif - } - return self; -} - -+ (instancetype)start -{ - PINBackgroundTask *task = nil; - -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 && !TARGET_OS_WATCH - if ([self.class isAppExtension]) { - return task; - } - - task = [[self alloc] init]; - - UIApplication *sharedApplication = [UIApplication performSelector:@selector(sharedApplication)]; - task.taskID = [sharedApplication beginBackgroundTaskWithExpirationHandler:^{ - UIBackgroundTaskIdentifier taskID = task.taskID; - task.taskID = UIBackgroundTaskInvalid; - [sharedApplication endBackgroundTask:taskID]; - }]; -#endif - - return task; -} - -- (void)end -{ -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 && !TARGET_OS_WATCH - if ([self.class isAppExtension]) { - return; - } - - UIBackgroundTaskIdentifier taskID = self.taskID; - self.taskID = UIBackgroundTaskInvalid; - - UIApplication *sharedApplication = [UIApplication performSelector:@selector(sharedApplication)]; - [sharedApplication endBackgroundTask:taskID]; -#endif -} - -@end diff --git a/Example-Mac/Pods/PINCache/PINCache/PINMemoryCache.h b/Example-Mac/Pods/PINCache/PINCache/PINMemoryCache.h deleted file mode 100644 index f0b244c0..00000000 --- a/Example-Mac/Pods/PINCache/PINCache/PINMemoryCache.h +++ /dev/null @@ -1,334 +0,0 @@ -// PINCache is a modified version of TMCache -// Modifications by Garrett Moon -// Copyright (c) 2015 Pinterest. All rights reserved. - -#import -#import "Nullability.h" - -NS_ASSUME_NONNULL_BEGIN - -@class PINMemoryCache; - -/** - A callback block which provides only the cache as an argument - */ - -typedef void (^PINMemoryCacheBlock)(PINMemoryCache *cache); - -/** - A callback block which provides the cache, key and object as arguments - */ -typedef void (^PINMemoryCacheObjectBlock)(PINMemoryCache *cache, NSString *key, id __nullable object); - -/** - `PINMemoryCache` is a fast, thread safe key/value store similar to `NSCache`. On iOS it will clear itself - automatically to reduce memory usage when the app receives a memory warning or goes into the background. - - Access is natively synchronous. Asynchronous variations are provided. Every asynchronous method accepts a - callback block that runs on a concurrent , with cache reads and writes protected by an semaphore. - - All access to the cache is dated so the that the least-used objects can be trimmed first. Setting an - optional will trigger a GCD timer to periodically to trim the cache to that age. - - Objects can optionally be set with a "cost", which could be a byte count or any other meaningful integer. - Setting a will automatically keep the cache below that value with . - - Values will not persist after application relaunch or returning from the background. See for - a memory cache backed by a disk cache. - */ - -@interface PINMemoryCache : NSObject - -#pragma mark - -/// @name Core - -/** - A concurrent queue on which all callbacks are called. It is exposed here so that it can be set to - target some other queue, such as a global concurrent queue with a priority other than the default. - */ -@property (readonly) dispatch_queue_t concurrentQueue; - -/** - The total accumulated cost. - */ -@property (readonly) NSUInteger totalCost; - -/** - The maximum cost allowed to accumulate before objects begin to be removed with . - */ -@property (assign) NSUInteger costLimit; - -/** - The maximum number of seconds an object is allowed to exist in the cache. Setting this to a value - greater than `0.0` will start a recurring GCD timer with the same period that calls . - Setting it back to `0.0` will stop the timer. Defaults to `0.0`. - */ -@property (assign) NSTimeInterval ageLimit; - -/** - If ttlCache is YES, the cache behaves like a ttlCache. This means that once an object enters the - cache, it only lives as long as self.ageLimit. This has the following implications: - - Accessing an object in the cache does not extend that object's lifetime in the cache - - When attempting to access an object in the cache that has lived longer than self.ageLimit, - the cache will behave as if the object does not exist - - */ -@property (nonatomic, assign, getter=isTTLCache) BOOL ttlCache; - -/** - When `YES` on iOS the cache will remove all objects when the app receives a memory warning. - Defaults to `YES`. - */ -@property (assign) BOOL removeAllObjectsOnMemoryWarning; - -/** - When `YES` on iOS the cache will remove all objects when the app enters the background. - Defaults to `YES`. - */ -@property (assign) BOOL removeAllObjectsOnEnteringBackground; - -#pragma mark - -/// @name Event Blocks - -/** - A block to be executed just before an object is added to the cache. This block will be excuted within - a lock, i.e. all reads and writes are suspended for the duration of the block. - Calling synchronous methods on the cache within this callback will likely cause a deadlock. - */ -@property (copy) PINMemoryCacheObjectBlock __nullable willAddObjectBlock; - -/** - A block to be executed just before an object is removed from the cache. This block will be excuted - within a lock, i.e. all reads and writes are suspended for the duration of the block. - Calling synchronous methods on the cache within this callback will likely cause a deadlock. - */ -@property (copy) PINMemoryCacheObjectBlock __nullable willRemoveObjectBlock; - -/** - A block to be executed just before all objects are removed from the cache as a result of . - This block will be excuted within a lock, i.e. all reads and writes are suspended for the duration of the block. - Calling synchronous methods on the cache within this callback will likely cause a deadlock. - */ -@property (copy) PINMemoryCacheBlock __nullable willRemoveAllObjectsBlock; - -/** - A block to be executed just after an object is added to the cache. This block will be excuted within - a lock, i.e. all reads and writes are suspended for the duration of the block. - Calling synchronous methods on the cache within this callback will likely cause a deadlock. - */ -@property (copy) PINMemoryCacheObjectBlock __nullable didAddObjectBlock; - -/** - A block to be executed just after an object is removed from the cache. This block will be excuted - within a lock, i.e. all reads and writes are suspended for the duration of the block. - Calling synchronous methods on the cache within this callback will likely cause a deadlock. - */ -@property (copy) PINMemoryCacheObjectBlock __nullable didRemoveObjectBlock; - -/** - A block to be executed just after all objects are removed from the cache as a result of . - This block will be excuted within a lock, i.e. all reads and writes are suspended for the duration of the block. - Calling synchronous methods on the cache within this callback will likely cause a deadlock. - */ -@property (copy) PINMemoryCacheBlock __nullable didRemoveAllObjectsBlock; - -/** - A block to be executed upon receiving a memory warning (iOS only) potentially in parallel with other blocks on the . - This block will be executed regardless of the value of . Defaults to `nil`. - */ -@property (copy) PINMemoryCacheBlock __nullable didReceiveMemoryWarningBlock; - -/** - A block to be executed when the app enters the background (iOS only) potentially in parallel with other blocks on the . - This block will be executed regardless of the value of . Defaults to `nil`. - */ -@property (copy) PINMemoryCacheBlock __nullable didEnterBackgroundBlock; - -#pragma mark - -/// @name Shared Cache - -/** - A shared cache. - - @result The shared singleton cache instance. - */ -+ (instancetype)sharedCache; - -#pragma mark - -/// @name Asynchronous Methods - -/** - Retrieves the object for the specified key. This method returns immediately and executes the passed - block after the object is available, potentially in parallel with other blocks on the . - - @param key The key associated with the requested object. - @param block A block to be executed concurrently when the object is available. - */ -- (void)objectForKey:(NSString *)key block:(nullable PINMemoryCacheObjectBlock)block; - -/** - Stores an object in the cache for the specified key. This method returns immediately and executes the - passed block after the object has been stored, potentially in parallel with other blocks on the . - - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - @param block A block to be executed concurrently after the object has been stored, or nil. - */ -- (void)setObject:(id)object forKey:(NSString *)key block:(nullable PINMemoryCacheObjectBlock)block; - -/** - Stores an object in the cache for the specified key and the specified cost. If the cost causes the total - to go over the the cache is trimmed (oldest objects first). This method returns immediately - and executes the passed block after the object has been stored, potentially in parallel with other blocks - on the . - - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - @param cost An amount to add to the . - @param block A block to be executed concurrently after the object has been stored, or nil. - */ -- (void)setObject:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost block:(nullable PINMemoryCacheObjectBlock)block; - -/** - Removes the object for the specified key. This method returns immediately and executes the passed - block after the object has been removed, potentially in parallel with other blocks on the . - - @param key The key associated with the object to be removed. - @param block A block to be executed concurrently after the object has been removed, or nil. - */ -- (void)removeObjectForKey:(NSString *)key block:(nullable PINMemoryCacheObjectBlock)block; - -/** - Removes all objects from the cache that have not been used since the specified date. - This method returns immediately and executes the passed block after the cache has been trimmed, - potentially in parallel with other blocks on the . - - @param date Objects that haven't been accessed since this date are removed from the cache. - @param block A block to be executed concurrently after the cache has been trimmed, or nil. - */ -- (void)trimToDate:(NSDate *)date block:(nullable PINMemoryCacheBlock)block; - -/** - Removes objects from the cache, costliest objects first, until the is below the specified - value. This method returns immediately and executes the passed block after the cache has been trimmed, - potentially in parallel with other blocks on the . - - @param cost The total accumulation allowed to remain after the cache has been trimmed. - @param block A block to be executed concurrently after the cache has been trimmed, or nil. - */ -- (void)trimToCost:(NSUInteger)cost block:(nullable PINMemoryCacheBlock)block; - -/** - Removes objects from the cache, ordered by date (least recently used first), until the is below - the specified value. This method returns immediately and executes the passed block after the cache has been - trimmed, potentially in parallel with other blocks on the . - - @param cost The total accumulation allowed to remain after the cache has been trimmed. - @param block A block to be executed concurrently after the cache has been trimmed, or nil. - */ -- (void)trimToCostByDate:(NSUInteger)cost block:(nullable PINMemoryCacheBlock)block; - -/** - Removes all objects from the cache. This method returns immediately and executes the passed block after - the cache has been cleared, potentially in parallel with other blocks on the . - - @param block A block to be executed concurrently after the cache has been cleared, or nil. - */ -- (void)removeAllObjects:(nullable PINMemoryCacheBlock)block; - -/** - Loops through all objects in the cache with reads and writes suspended. Calling serial methods which - write to the cache inside block may be unsafe and may result in a deadlock. This method returns immediately. - - @param block A block to be executed for every object in the cache. - @param completionBlock An optional block to be executed concurrently when the enumeration is complete. - */ -- (void)enumerateObjectsWithBlock:(PINMemoryCacheObjectBlock)block completionBlock:(nullable PINMemoryCacheBlock)completionBlock; - -#pragma mark - -/// @name Synchronous Methods - -/** - Retrieves the object for the specified key. This method blocks the calling thread until the - object is available. - - @see objectForKey:block: - @param key The key associated with the object. - @result The object for the specified key. - */ -- (__nullable id)objectForKey:(nullable NSString *)key; - -/** - Stores an object in the cache for the specified key. This method blocks the calling thread until the object - has been set. - - @see setObject:forKey:block: - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - */ -- (void)setObject:(id)object forKey:(NSString *)key; - -/** - Stores an object in the cache for the specified key and the specified cost. If the cost causes the total - to go over the the cache is trimmed (oldest objects first). This method blocks the calling thread - until the object has been stored. - - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - @param cost An amount to add to the . - */ -- (void)setObject:(nullable id)object forKey:(nullable NSString *)key withCost:(NSUInteger)cost; - -/** - Removes the object for the specified key. This method blocks the calling thread until the object - has been removed. - - @param key The key associated with the object to be removed. - */ -- (void)removeObjectForKey:(nullable NSString *)key; - -/** - Removes all objects from the cache that have not been used since the specified date. - This method blocks the calling thread until the cache has been trimmed. - - @param date Objects that haven't been accessed since this date are removed from the cache. - */ -- (void)trimToDate:(nullable NSDate *)date; - -/** - Removes objects from the cache, costliest objects first, until the is below the specified - value. This method blocks the calling thread until the cache has been trimmed. - - @param cost The total accumulation allowed to remain after the cache has been trimmed. - */ -- (void)trimToCost:(NSUInteger)cost; - -/** - Removes objects from the cache, ordered by date (least recently used first), until the is below - the specified value. This method blocks the calling thread until the cache has been trimmed. - - @param cost The total accumulation allowed to remain after the cache has been trimmed. - */ -- (void)trimToCostByDate:(NSUInteger)cost; - -/** - Removes all objects from the cache. This method blocks the calling thread until the cache has been cleared. - */ -- (void)removeAllObjects; - -/** - Loops through all objects in the cache within a memory lock (reads and writes are suspended during the enumeration). - This method blocks the calling thread until all objects have been enumerated. - Calling synchronous methods on the cache within this callback will likely cause a deadlock. - - @param block A block to be executed for every object in the cache. - - @warning Do not call this method within the event blocks (, etc.) - Instead use the asynchronous version, . - - */ -- (void)enumerateObjectsWithBlock:(nullable PINMemoryCacheObjectBlock)block; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example-Mac/Pods/PINCache/PINCache/PINMemoryCache.m b/Example-Mac/Pods/PINCache/PINCache/PINMemoryCache.m deleted file mode 100644 index 63ea2acf..00000000 --- a/Example-Mac/Pods/PINCache/PINCache/PINMemoryCache.m +++ /dev/null @@ -1,716 +0,0 @@ -// PINCache is a modified version of TMCache -// Modifications by Garrett Moon -// Copyright (c) 2015 Pinterest. All rights reserved. - -#import "PINMemoryCache.h" - -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 -#import -#endif - -static NSString * const PINMemoryCachePrefix = @"com.pinterest.PINMemoryCache"; - -@interface PINMemoryCache () -#if OS_OBJECT_USE_OBJC -@property (strong, nonatomic) dispatch_queue_t concurrentQueue; -@property (strong, nonatomic) dispatch_semaphore_t lockSemaphore; -#else -@property (assign, nonatomic) dispatch_queue_t concurrentQueue; -@property (assign, nonatomic) dispatch_semaphore_t lockSemaphore; -#endif -@property (strong, nonatomic) NSMutableDictionary *dictionary; -@property (strong, nonatomic) NSMutableDictionary *dates; -@property (strong, nonatomic) NSMutableDictionary *costs; -@end - -@implementation PINMemoryCache - -@synthesize ageLimit = _ageLimit; -@synthesize costLimit = _costLimit; -@synthesize totalCost = _totalCost; -@synthesize ttlCache = _ttlCache; -@synthesize willAddObjectBlock = _willAddObjectBlock; -@synthesize willRemoveObjectBlock = _willRemoveObjectBlock; -@synthesize willRemoveAllObjectsBlock = _willRemoveAllObjectsBlock; -@synthesize didAddObjectBlock = _didAddObjectBlock; -@synthesize didRemoveObjectBlock = _didRemoveObjectBlock; -@synthesize didRemoveAllObjectsBlock = _didRemoveAllObjectsBlock; -@synthesize didReceiveMemoryWarningBlock = _didReceiveMemoryWarningBlock; -@synthesize didEnterBackgroundBlock = _didEnterBackgroundBlock; - -#pragma mark - Initialization - - -- (void)dealloc -{ - [[NSNotificationCenter defaultCenter] removeObserver:self]; - - #if !OS_OBJECT_USE_OBJC - dispatch_release(_concurrentQueue); - dispatch_release(_lockSemaphore); - _concurrentQueue = nil; - #endif -} - -- (instancetype)init -{ - if (self = [super init]) { - _lockSemaphore = dispatch_semaphore_create(1); - NSString *queueName = [[NSString alloc] initWithFormat:@"%@.%p", PINMemoryCachePrefix, self]; - _concurrentQueue = dispatch_queue_create([queueName UTF8String], DISPATCH_QUEUE_CONCURRENT); - - _dictionary = [[NSMutableDictionary alloc] init]; - _dates = [[NSMutableDictionary alloc] init]; - _costs = [[NSMutableDictionary alloc] init]; - - _willAddObjectBlock = nil; - _willRemoveObjectBlock = nil; - _willRemoveAllObjectsBlock = nil; - - _didAddObjectBlock = nil; - _didRemoveObjectBlock = nil; - _didRemoveAllObjectsBlock = nil; - - _didReceiveMemoryWarningBlock = nil; - _didEnterBackgroundBlock = nil; - - _ageLimit = 0.0; - _costLimit = 0; - _totalCost = 0; - - _removeAllObjectsOnMemoryWarning = YES; - _removeAllObjectsOnEnteringBackground = YES; - -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 && !TARGET_OS_WATCH - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(didReceiveEnterBackgroundNotification:) - name:UIApplicationDidEnterBackgroundNotification - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(didReceiveMemoryWarningNotification:) - name:UIApplicationDidReceiveMemoryWarningNotification - object:nil]; - -#endif - } - return self; -} - -+ (instancetype)sharedCache -{ - static id cache; - static dispatch_once_t predicate; - - dispatch_once(&predicate, ^{ - cache = [[self alloc] init]; - }); - - return cache; -} - -#pragma mark - Private Methods - - -- (void)didReceiveMemoryWarningNotification:(NSNotification *)notification { - if (self.removeAllObjectsOnMemoryWarning) - [self removeAllObjects:nil]; - - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - if (!strongSelf) { - return; - } - - [strongSelf lock]; - PINMemoryCacheBlock didReceiveMemoryWarningBlock = strongSelf->_didReceiveMemoryWarningBlock; - [strongSelf unlock]; - - if (didReceiveMemoryWarningBlock) - didReceiveMemoryWarningBlock(strongSelf); - }); -} - -- (void)didReceiveEnterBackgroundNotification:(NSNotification *)notification -{ - if (self.removeAllObjectsOnEnteringBackground) - [self removeAllObjects:nil]; - - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - if (!strongSelf) { - return; - } - - [strongSelf lock]; - PINMemoryCacheBlock didEnterBackgroundBlock = strongSelf->_didEnterBackgroundBlock; - [strongSelf unlock]; - - if (didEnterBackgroundBlock) - didEnterBackgroundBlock(strongSelf); - }); -} - -- (void)removeObjectAndExecuteBlocksForKey:(NSString *)key -{ - [self lock]; - id object = _dictionary[key]; - NSNumber *cost = _costs[key]; - PINMemoryCacheObjectBlock willRemoveObjectBlock = _willRemoveObjectBlock; - PINMemoryCacheObjectBlock didRemoveObjectBlock = _didRemoveObjectBlock; - [self unlock]; - - if (willRemoveObjectBlock) - willRemoveObjectBlock(self, key, object); - - [self lock]; - if (cost) - _totalCost -= [cost unsignedIntegerValue]; - - [_dictionary removeObjectForKey:key]; - [_dates removeObjectForKey:key]; - [_costs removeObjectForKey:key]; - [self unlock]; - - if (didRemoveObjectBlock) - didRemoveObjectBlock(self, key, nil); -} - -- (void)trimMemoryToDate:(NSDate *)trimDate -{ - [self lock]; - NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)]; - NSDictionary *dates = [_dates copy]; - [self unlock]; - - for (NSString *key in keysSortedByDate) { // oldest objects first - NSDate *accessDate = dates[key]; - if (!accessDate) - continue; - - if ([accessDate compare:trimDate] == NSOrderedAscending) { // older than trim date - [self removeObjectAndExecuteBlocksForKey:key]; - } else { - break; - } - } -} - -- (void)trimToCostLimit:(NSUInteger)limit -{ - NSUInteger totalCost = 0; - - [self lock]; - totalCost = _totalCost; - NSArray *keysSortedByCost = [_costs keysSortedByValueUsingSelector:@selector(compare:)]; - [self unlock]; - - if (totalCost <= limit) { - return; - } - - for (NSString *key in [keysSortedByCost reverseObjectEnumerator]) { // costliest objects first - [self removeObjectAndExecuteBlocksForKey:key]; - - [self lock]; - totalCost = _totalCost; - [self unlock]; - - if (totalCost <= limit) - break; - } -} - -- (void)trimToCostLimitByDate:(NSUInteger)limit -{ - NSUInteger totalCost = 0; - - [self lock]; - totalCost = _totalCost; - NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)]; - [self unlock]; - - if (totalCost <= limit) - return; - - for (NSString *key in keysSortedByDate) { // oldest objects first - [self removeObjectAndExecuteBlocksForKey:key]; - - [self lock]; - totalCost = _totalCost; - [self unlock]; - if (totalCost <= limit) - break; - } -} - -- (void)trimToAgeLimitRecursively -{ - [self lock]; - NSTimeInterval ageLimit = _ageLimit; - [self unlock]; - - if (ageLimit == 0.0) - return; - - NSDate *date = [[NSDate alloc] initWithTimeIntervalSinceNow:-ageLimit]; - - [self trimMemoryToDate:date]; - - __weak PINMemoryCache *weakSelf = self; - - dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(ageLimit * NSEC_PER_SEC)); - dispatch_after(time, _concurrentQueue, ^(void){ - PINMemoryCache *strongSelf = weakSelf; - - [strongSelf trimToAgeLimitRecursively]; - }); -} - -#pragma mark - Public Asynchronous Methods - - -- (void)objectForKey:(NSString *)key block:(PINMemoryCacheObjectBlock)block -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - id object = [strongSelf objectForKey:key]; - - if (block) - block(strongSelf, key, object); - }); -} - -- (void)setObject:(id)object forKey:(NSString *)key block:(PINMemoryCacheObjectBlock)block -{ - [self setObject:object forKey:key withCost:0 block:block]; -} - -- (void)setObject:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost block:(PINMemoryCacheObjectBlock)block -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - [strongSelf setObject:object forKey:key withCost:cost]; - - if (block) - block(strongSelf, key, object); - }); -} - -- (void)removeObjectForKey:(NSString *)key block:(PINMemoryCacheObjectBlock)block -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - [strongSelf removeObjectForKey:key]; - - if (block) - block(strongSelf, key, nil); - }); -} - -- (void)trimToDate:(NSDate *)trimDate block:(PINMemoryCacheBlock)block -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - [strongSelf trimToDate:trimDate]; - - if (block) - block(strongSelf); - }); -} - -- (void)trimToCost:(NSUInteger)cost block:(PINMemoryCacheBlock)block -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - [strongSelf trimToCost:cost]; - - if (block) - block(strongSelf); - }); -} - -- (void)trimToCostByDate:(NSUInteger)cost block:(PINMemoryCacheBlock)block -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - [strongSelf trimToCostByDate:cost]; - - if (block) - block(strongSelf); - }); -} - -- (void)removeAllObjects:(PINMemoryCacheBlock)block -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - [strongSelf removeAllObjects]; - - if (block) - block(strongSelf); - }); -} - -- (void)enumerateObjectsWithBlock:(PINMemoryCacheObjectBlock)block completionBlock:(PINMemoryCacheBlock)completionBlock -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - [strongSelf enumerateObjectsWithBlock:block]; - - if (completionBlock) - completionBlock(strongSelf); - }); -} - -#pragma mark - Public Synchronous Methods - - -- (__nullable id)objectForKey:(NSString *)key -{ - if (!key) - return nil; - - NSDate *now = [[NSDate alloc] init]; - [self lock]; - id object = nil; - // If the cache should behave like a TTL cache, then only fetch the object if there's a valid ageLimit and the object is still alive - if (!self->_ttlCache || self->_ageLimit <= 0 || fabs([[_dates objectForKey:key] timeIntervalSinceDate:now]) < self->_ageLimit) { - object = _dictionary[key]; - } - [self unlock]; - - if (object) { - [self lock]; - _dates[key] = now; - [self unlock]; - } - - return object; -} - -- (void)setObject:(id)object forKey:(NSString *)key -{ - [self setObject:object forKey:key withCost:0]; -} - -- (void)setObject:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost -{ - if (!key || !object) - return; - - [self lock]; - PINMemoryCacheObjectBlock willAddObjectBlock = _willAddObjectBlock; - PINMemoryCacheObjectBlock didAddObjectBlock = _didAddObjectBlock; - NSUInteger costLimit = _costLimit; - [self unlock]; - - if (willAddObjectBlock) - willAddObjectBlock(self, key, object); - - [self lock]; - _dictionary[key] = object; - _dates[key] = [[NSDate alloc] init]; - _costs[key] = @(cost); - - _totalCost += cost; - [self unlock]; - - if (didAddObjectBlock) - didAddObjectBlock(self, key, object); - - if (costLimit > 0) - [self trimToCostByDate:costLimit]; -} - -- (void)removeObjectForKey:(NSString *)key -{ - if (!key) - return; - - [self removeObjectAndExecuteBlocksForKey:key]; -} - -- (void)trimToDate:(NSDate *)trimDate -{ - if (!trimDate) - return; - - if ([trimDate isEqualToDate:[NSDate distantPast]]) { - [self removeAllObjects]; - return; - } - - [self trimMemoryToDate:trimDate]; -} - -- (void)trimToCost:(NSUInteger)cost -{ - [self trimToCostLimit:cost]; -} - -- (void)trimToCostByDate:(NSUInteger)cost -{ - [self trimToCostLimitByDate:cost]; -} - -- (void)removeAllObjects -{ - [self lock]; - PINMemoryCacheBlock willRemoveAllObjectsBlock = _willRemoveAllObjectsBlock; - PINMemoryCacheBlock didRemoveAllObjectsBlock = _didRemoveAllObjectsBlock; - [self unlock]; - - if (willRemoveAllObjectsBlock) - willRemoveAllObjectsBlock(self); - - [self lock]; - [_dictionary removeAllObjects]; - [_dates removeAllObjects]; - [_costs removeAllObjects]; - - _totalCost = 0; - [self unlock]; - - if (didRemoveAllObjectsBlock) - didRemoveAllObjectsBlock(self); - -} - -- (void)enumerateObjectsWithBlock:(PINMemoryCacheObjectBlock)block -{ - if (!block) - return; - - [self lock]; - NSDate *now = [[NSDate alloc] init]; - NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)]; - - for (NSString *key in keysSortedByDate) { - // If the cache should behave like a TTL cache, then only fetch the object if there's a valid ageLimit and the object is still alive - if (!self->_ttlCache || self->_ageLimit <= 0 || fabs([[_dates objectForKey:key] timeIntervalSinceDate:now]) < self->_ageLimit) { - block(self, key, _dictionary[key]); - } - } - [self unlock]; -} - -#pragma mark - Public Thread Safe Accessors - - -- (PINMemoryCacheObjectBlock)willAddObjectBlock -{ - [self lock]; - PINMemoryCacheObjectBlock block = _willAddObjectBlock; - [self unlock]; - - return block; -} - -- (void)setWillAddObjectBlock:(PINMemoryCacheObjectBlock)block -{ - [self lock]; - _willAddObjectBlock = [block copy]; - [self unlock]; -} - -- (PINMemoryCacheObjectBlock)willRemoveObjectBlock -{ - [self lock]; - PINMemoryCacheObjectBlock block = _willRemoveObjectBlock; - [self unlock]; - - return block; -} - -- (void)setWillRemoveObjectBlock:(PINMemoryCacheObjectBlock)block -{ - [self lock]; - _willRemoveObjectBlock = [block copy]; - [self unlock]; -} - -- (PINMemoryCacheBlock)willRemoveAllObjectsBlock -{ - [self lock]; - PINMemoryCacheBlock block = _willRemoveAllObjectsBlock; - [self unlock]; - - return block; -} - -- (void)setWillRemoveAllObjectsBlock:(PINMemoryCacheBlock)block -{ - [self lock]; - _willRemoveAllObjectsBlock = [block copy]; - [self unlock]; -} - -- (PINMemoryCacheObjectBlock)didAddObjectBlock -{ - [self lock]; - PINMemoryCacheObjectBlock block = _didAddObjectBlock; - [self unlock]; - - return block; -} - -- (void)setDidAddObjectBlock:(PINMemoryCacheObjectBlock)block -{ - [self lock]; - _didAddObjectBlock = [block copy]; - [self unlock]; -} - -- (PINMemoryCacheObjectBlock)didRemoveObjectBlock -{ - [self lock]; - PINMemoryCacheObjectBlock block = _didRemoveObjectBlock; - [self unlock]; - - return block; -} - -- (void)setDidRemoveObjectBlock:(PINMemoryCacheObjectBlock)block -{ - [self lock]; - _didRemoveObjectBlock = [block copy]; - [self unlock]; -} - -- (PINMemoryCacheBlock)didRemoveAllObjectsBlock -{ - [self lock]; - PINMemoryCacheBlock block = _didRemoveAllObjectsBlock; - [self unlock]; - - return block; -} - -- (void)setDidRemoveAllObjectsBlock:(PINMemoryCacheBlock)block -{ - [self lock]; - _didRemoveAllObjectsBlock = [block copy]; - [self unlock]; -} - -- (PINMemoryCacheBlock)didReceiveMemoryWarningBlock -{ - [self lock]; - PINMemoryCacheBlock block = _didReceiveMemoryWarningBlock; - [self unlock]; - - return block; -} - -- (void)setDidReceiveMemoryWarningBlock:(PINMemoryCacheBlock)block -{ - [self lock]; - _didReceiveMemoryWarningBlock = [block copy]; - [self unlock]; -} - -- (PINMemoryCacheBlock)didEnterBackgroundBlock -{ - [self lock]; - PINMemoryCacheBlock block = _didEnterBackgroundBlock; - [self unlock]; - - return block; -} - -- (void)setDidEnterBackgroundBlock:(PINMemoryCacheBlock)block -{ - [self lock]; - _didEnterBackgroundBlock = [block copy]; - [self unlock]; -} - -- (NSTimeInterval)ageLimit -{ - [self lock]; - NSTimeInterval ageLimit = _ageLimit; - [self unlock]; - - return ageLimit; -} - -- (void)setAgeLimit:(NSTimeInterval)ageLimit -{ - [self lock]; - _ageLimit = ageLimit; - [self unlock]; - - [self trimToAgeLimitRecursively]; -} - -- (NSUInteger)costLimit -{ - [self lock]; - NSUInteger costLimit = _costLimit; - [self unlock]; - - return costLimit; -} - -- (void)setCostLimit:(NSUInteger)costLimit -{ - [self lock]; - _costLimit = costLimit; - [self unlock]; - - if (costLimit > 0) - [self trimToCostLimitByDate:costLimit]; -} - -- (NSUInteger)totalCost -{ - [self lock]; - NSUInteger cost = _totalCost; - [self unlock]; - - return cost; -} - -- (BOOL)isTTLCache { - BOOL isTTLCache; - - [self lock]; - isTTLCache = _ttlCache; - [self unlock]; - - return isTTLCache; -} - -- (void)setTtlCache:(BOOL)ttlCache { - [self lock]; - _ttlCache = ttlCache; - [self unlock]; -} - - -- (void)lock -{ - dispatch_semaphore_wait(_lockSemaphore, DISPATCH_TIME_FOREVER); -} - -- (void)unlock -{ - dispatch_semaphore_signal(_lockSemaphore); -} - -@end diff --git a/Example-Mac/Pods/PINCache/README.md b/Example-Mac/Pods/PINCache/README.md deleted file mode 100644 index 071f1ea5..00000000 --- a/Example-Mac/Pods/PINCache/README.md +++ /dev/null @@ -1,75 +0,0 @@ -# PINCache - -[![CocoaPods](https://img.shields.io/cocoapods/v/PINCache.svg)](http://cocoadocs.org/docsets/PINCache/) -[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) - -## Fast, non-deadlocking parallel object cache for iOS and OS X. - -[PINCache](PINCache/PINCache.h) is a fork of [TMCache](https://github.com/tumblr/TMCache) re-architected to fix issues with deadlocking caused by heavy use. It is a key/value store designed for persisting temporary objects that are expensive to reproduce, such as downloaded data or the results of slow processing. It is comprised of two self-similar stores, one in memory ([PINMemoryCache](PINCache/PINMemoryCache.h)) and one on disk ([PINDiskCache](PINCache/PINDiskCache.h)), all backed by GCD and safe to access from multiple threads simultaneously. On iOS, `PINMemoryCache` will clear itself when the app receives a memory warning or goes into the background. Objects stored in `PINDiskCache` remain until you trim the cache yourself, either manually or by setting a byte or age limit. - -`PINCache` and `PINDiskCache` accept any object conforming to [NSCoding](https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Protocols/NSCoding_Protocol/Reference/Reference.html). Put things in like this: - -```objective-c -UIImage *img = [[UIImage alloc] initWithData:data scale:[[UIScreen mainScreen] scale]]; -[[PINCache sharedCache] setObject:img forKey:@"image" block:nil]; // returns immediately -``` - -Get them back out like this: - -```objective-c -[[PINCache sharedCache] objectForKey:@"image" - block:^(PINCache *cache, NSString *key, id object) { - UIImage *image = (UIImage *)object; - NSLog(@"image scale: %f", image.scale); - }]; -``` - -Both `PINMemoryCache` and PINDiskCache use locks to protect reads and writes. `PINCache` coordinates them so that objects added to memory are available immediately to other threads while being written to disk safely in the background. Both caches are public properties of `PINCache`, so it's easy to manipulate one or the other separately if necessary. - -Collections work too. Thanks to the magic of `NSKeyedArchiver`, objects repeated in a collection only occupy the space of one on disk: - -```objective-c -NSArray *images = @[ image, image, image ]; -[[PINCache sharedCache] setObject:images forKey:@"images"]; -NSLog(@"3 for the price of 1: %d", [[[PINCache sharedCache] diskCache] byteCount]); -``` - -## Installation - -### Manually - -[Download the latest tag](https://github.com/pinterest/PINCache/tags) and drag the `PINCache` folder into your Xcode project. - -Install the docs by double clicking the `.docset` file under `docs/`, or view them online at [cocoadocs.org](http://cocoadocs.org/docsets/PINCache/) - -### Git Submodule - - git submodule add https://github.com/pinterest/PINCache.git - git submodule update --init - -### CocoaPods - -Add [PINCache](http://cocoapods.org/?q=name%3APINCache) to your `Podfile` and run `pod install`. - -### Carthage - -Add the following line to your `Cartfile` and run `carthage update --platform ios`. Then follow [this instruction of Carthage](https://github.com/carthage/carthage#adding-frameworks-to-unit-tests-or-a-framework) to embed the framework. - -```github "pinterest/PINCache"``` - -## Requirements - -__PINCache__ requires iOS 5.0 or OS X 10.7 and greater. - -## Contact - -[Garrett Moon](mailto:garrett@pinterest.com) - -## License - -Copyright 2013 Tumblr, Inc. -Copyright 2015 Pinterest, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. [See the License](LICENSE.txt) for the specific language governing permissions and limitations under the License. diff --git a/Example-Mac/Pods/Pods.xcodeproj/project.pbxproj b/Example-Mac/Pods/Pods.xcodeproj/project.pbxproj deleted file mode 100644 index ae04ce9e..00000000 --- a/Example-Mac/Pods/Pods.xcodeproj/project.pbxproj +++ /dev/null @@ -1,6980 +0,0 @@ - - - - - archiveVersion - 1 - classes - - objectVersion - 46 - objects - - 0004A378FDCA54B7480AEB7987CB2FB3 - - includeInIndex - 1 - isa - PBXFileReference - name - argb.c - path - src/dsp/argb.c - sourceTree - <group> - - 01D8C9CB03CD8E823A419412F9415111 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINImageView+PINRemoteImage.h - sourceTree - <group> - - 022891CD3C29415D1572CB15581E9FC9 - - fileRef - 65347844787A41A2F0E848FA51EA725B - isa - PBXBuildFile - - 0245A25FD1BCE61C6AAC2D5D5369778A - - fileRef - 83397620B5FCDC996DB5C56ADE4FF1F9 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 0314C236143A4F5C7DB88A7C63894C43 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - neon.h - path - src/dsp/neon.h - sourceTree - <group> - - 03D76B1839E8B92203D849620D80659D - - children - - C7F4A899A302F13CEA24F45F292CAC1D - E56EFC94FD15573B0B427C984A9AD0A7 - B46C6B5F5186E6B2930248A79E4E25B3 - E61017926E4C5B70D20FAB84E278EF7F - B96F0796CF410388EC2CD6E630F4653B - C716806CED5D85E3B92E3D16B2292A83 - 0723546CB29E7CBB6EFC1088662AF45B - A0C00049CBCD6B00CFB18E979BAEF6C2 - - isa - PBXGroup - name - webp - sourceTree - <group> - - 048828C11D392FA5A13E60F5223762F8 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - PINCache.h - path - PINCache/PINCache.h - sourceTree - <group> - - 04ECC184692FC9A676106141D48F2EE3 - - children - - F59034D1B37659011B534E6DEF7D7F84 - D4A7AC7EC35C141AD8EC5E917486A3B1 - 368D6EE8BBF0E466D4CEF1736F59EF23 - F0587A92A6FDCDF7ED4C0AC2B6B7069D - - isa - PBXGroup - name - Products - sourceTree - <group> - - 05204CF01F096BC8F9A32C2C757533EA - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-PINRemoteImage-PINCache.xcconfig - sourceTree - <group> - - 0530DF53E50F23B58A6F04D802CFA9B0 - - fileRef - 103D6E913F66897CBC5AA2BAC1559C53 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 056272822D16293762F9F4B6B47C8A57 - - fileRef - 585541D65FCD3FEC57B9AF5CD13CD1E5 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 056A17AF5E589399B5500549916C964F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINRemoteImageProcessorTask.m - sourceTree - <group> - - 06655463DC05231AB09E5A504061E353 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINRemoteImageCallbacks.h - sourceTree - <group> - - 06F1FE6224968BE662E1143ADCF5D40F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINURLSessionManager.m - sourceTree - <group> - - 0708F88B696773C0A5227B28EC99A7F0 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - backward_references.h - path - src/enc/backward_references.h - sourceTree - <group> - - 0723546CB29E7CBB6EFC1088662AF45B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - mux_types.h - path - src/webp/mux_types.h - sourceTree - <group> - - 0759125F9B0A8FF4A7C7670AF9181C11 - - children - - F705D8BD26F0207F68990F2810C94492 - 8962BC3DCED6A56099C7E4251ED041A0 - B3C75AB1813564741ECF7F3D537569CA - 84C1B348CD730F4D14FEC257D6FE97F1 - 67406CC11BB9FE36BD868020640F58FA - E823AD90033331573401BDFE6AB93CCB - - isa - PBXGroup - name - Categories - path - Categories - sourceTree - <group> - - 0771434F429549DB1580F325FE7911FD - - baseConfigurationReference - 05204CF01F096BC8F9A32C2C757533EA - buildSettings - - ENABLE_STRICT_OBJC_MSGSEND - YES - EXECUTABLE_PREFIX - lib - GCC_PREFIX_HEADER - Target Support Files/Pods-PINRemoteImage-PINCache/Pods-PINRemoteImage-PINCache-prefix.pch - MACOSX_DEPLOYMENT_TARGET - 10.11 - MTL_ENABLE_DEBUG_INFO - YES - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRIVATE_HEADERS_FOLDER_PATH - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - - SDKROOT - macosx - - isa - XCBuildConfiguration - name - Debug - - 077F2A12C5BEE6866AD991528CB45AD6 - - fileRef - 48E463B6FDD17241DD3E1C3CF1F934A4 - isa - PBXBuildFile - - 07AC71A306E2361EB7056CB52E1C64D4 - - fileRef - CD41A5C9301EB06A7BA538065BEADCD4 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 07C66BB8FECEFB73FCCEF16D1352A2ED - - fileRef - 0E8222779199AC432EE5815423F43BCA - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 0811A435BCDE87F3F79D6E331F181DDB - - fileRef - 642415D3F112C6C096EC91FFAF924910 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 0839296EA88638F77315F77F49687A01 - - fileRef - 6E6950DAD97D897CF352F2FFD0BE0B41 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 08721ED67EA094F960FAEF205FAE47C0 - - isa - PBXTargetDependency - name - Pods-PINRemoteImage-PINCache - target - 54F27F7B6DBD02B3C1ABB03D547E1C0E - targetProxy - C13A607998BB556A4C9770538C826C06 - - 08B0859E25D0DF210E21239291ED01DF - - includeInIndex - 1 - isa - PBXFileReference - name - yuv_mips32.c - path - src/dsp/yuv_mips32.c - sourceTree - <group> - - 08D5D6CD76A31ABFA6E092502726BE9B - - fileRef - 67406CC11BB9FE36BD868020640F58FA - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 09AA62A51B4DA905E582E2AAF7D9B27B - - fileRef - 345C612CA023E9C9DA39708F28B69364 - isa - PBXBuildFile - - 0ADD8CAB9B5DD81C3744ED80567A2720 - - fileRef - 2E67890AF6FEFDF3B8842E6B1F1C8AEF - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 0B2545B7E15F58DE7D7857C1100F2E5F - - fileRef - 8962BC3DCED6A56099C7E4251ED041A0 - isa - PBXBuildFile - - 0B4022E490AE7D0C68357369C4CDFAA7 - - includeInIndex - 1 - isa - PBXFileReference - name - huffman_encode.c - path - src/utils/huffman_encode.c - sourceTree - <group> - - 0B43965EFDEAFAC0481542FF95374055 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - quant_levels.h - path - src/utils/quant_levels.h - sourceTree - <group> - - 0C33A0B2CA62D0A538C4071B126CF0B0 - - buildActionMask - 2147483647 - files - - F2401DC8EFDF9742AC607CF3D4A8495B - EBFDF03F22BC2CAE9696098C6E8BE8A7 - 6FF7A8804F9B6855BFF8FB792B2CAC7C - DBA70329D901B7929BA1974AB74F1B44 - 597EABFFF86A26555ACF60EF14695221 - 6B4EA5137E666D621A3B50D50FE1E19D - 7F8B27B7F4572B90427E90EDD6CE0278 - 3E8EBD4B83E9C54F53F004361C29DB42 - 5CEC4BBFC9D518A4FD8BC5A1362CF6E8 - CC26AE5B8B0709D14806614A187AF4D8 - 87D0CB66E7D297E3373B2E3947B35ED3 - 5C625F7142C8F808C946FDBB23B6E08F - F6614F7200CA7CFCF8A9CFF1BF80C7E7 - 13238AAE414C28744680FBB3371701BA - E430B4877504F51ABC452BCAF2BDA0AE - 3BC7BF5D12FA6079B4DCAF5DE2FE0942 - 2C3BB808565E82708384DBE2F928E259 - 2310584B1A349A2AECE50064336B8C01 - 7F1362EF05DAB36F93DAB1A5C736D7F5 - D0C0F1422A439355BF927294B61C21C0 - AD8FE2C6AD0CDB89DA2F149BED7A61C4 - 616906687440069E679BED18B66A3233 - D7F393F3B25273B25D31481A121E9ED8 - B07D21DBF6042F59ABF232E4FC67F3DA - 8805086DB01D26D4D721583A4D0B1600 - 8079C2382B7972F5FEB2C3C7D09592A2 - 2506AEAEA08053AC2DDAE6EFF67053EB - AF1368B6241655B6F8305E75A982AFE2 - 6E823A9FD8DD9685BD5195D154A6114F - 9676F64E06952A014CC3E763A1633682 - B05BC009CB931E4835D21011EA1BB53E - DA4CF6AA8B86FF316C8F7C8F75309261 - 574D0AB465DEE51656A2FAED9D40C311 - 68429D82C13F40EBAA7B8196131F5EA0 - A597BFE6B87B31BB6B653E99E9144602 - 546D1728881FEE40134C5590B2714AF9 - A2918F68A7A260336513C2D3DB44B9DD - B974D7A76F5A1DB6B3B873FE7C77FDC8 - C49060225E775882B26B37F8ECD6AC37 - 5D438E3783B022065CD9EB93BE9200BA - - isa - PBXHeadersBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 0C35CE5F643C47C3AF417B395748D79B - - includeInIndex - 1 - isa - PBXFileReference - name - cost.c - path - src/enc/cost.c - sourceTree - <group> - - 0C6BDAE9D7C739137B6D80FF57CF7DD1 - - isa - PBXFileReference - lastKnownFileType - wrapper.framework - name - Accelerate.framework - path - Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/Accelerate.framework - sourceTree - DEVELOPER_DIR - - 0CED3F531E83C3CBDBC261FE20EED9A0 - - includeInIndex - 1 - isa - PBXFileReference - name - analysis.c - path - src/enc/analysis.c - sourceTree - <group> - - 0DA7C28757B0C2EA3328CF99344DE4A7 - - isa - PBXFileReference - lastKnownFileType - wrapper.framework - name - Foundation.framework - path - Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/Foundation.framework - sourceTree - DEVELOPER_DIR - - 0E8222779199AC432EE5815423F43BCA - - includeInIndex - 1 - isa - PBXFileReference - name - dec_mips_dsp_r2.c - path - src/dsp/dec_mips_dsp_r2.c - sourceTree - <group> - - 0F917410D4EB6590E946692D160A4F5E - - includeInIndex - 1 - isa - PBXFileReference - name - webpenc.c - path - src/enc/webpenc.c - sourceTree - <group> - - 103D6E913F66897CBC5AA2BAC1559C53 - - includeInIndex - 1 - isa - PBXFileReference - name - tree.c - path - src/dec/tree.c - sourceTree - <group> - - 10742D6291172C33709408885657444B - - fileRef - F35E649D9FD9EBA610E53054A48244CE - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 10B2EE21B5D67EE2C819831CCC43832B - - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - CLANG_CXX_LANGUAGE_STANDARD - gnu++0x - CLANG_CXX_LIBRARY - libc++ - CLANG_ENABLE_MODULES - YES - CLANG_ENABLE_OBJC_ARC - YES - CLANG_WARN_BOOL_CONVERSION - YES - CLANG_WARN_CONSTANT_CONVERSION - YES - CLANG_WARN_DIRECT_OBJC_ISA_USAGE - YES - CLANG_WARN_EMPTY_BODY - YES - CLANG_WARN_ENUM_CONVERSION - YES - CLANG_WARN_INT_CONVERSION - YES - CLANG_WARN_OBJC_ROOT_CLASS - YES - CLANG_WARN_UNREACHABLE_CODE - YES - CLANG_WARN__DUPLICATE_METHOD_MATCH - YES - COPY_PHASE_STRIP - NO - GCC_C_LANGUAGE_STANDARD - gnu99 - GCC_DYNAMIC_NO_PIC - NO - GCC_OPTIMIZATION_LEVEL - 0 - GCC_PREPROCESSOR_DEFINITIONS - - DEBUG=1 - $(inherited) - - GCC_SYMBOLS_PRIVATE_EXTERN - NO - GCC_WARN_64_TO_32_BIT_CONVERSION - YES - GCC_WARN_ABOUT_RETURN_TYPE - YES - GCC_WARN_UNDECLARED_SELECTOR - YES - GCC_WARN_UNINITIALIZED_AUTOS - YES - GCC_WARN_UNUSED_FUNCTION - YES - GCC_WARN_UNUSED_VARIABLE - YES - MACOSX_DEPLOYMENT_TARGET - 10.11 - ONLY_ACTIVE_ARCH - YES - STRIP_INSTALLED_PRODUCT - NO - SYMROOT - ${SRCROOT}/../build - - isa - XCBuildConfiguration - name - Debug - - 1187943A8079A2835E378B9C7D227845 - - includeInIndex - 1 - isa - PBXFileReference - name - upsampling.c - path - src/dsp/upsampling.c - sourceTree - <group> - - 1254E5EA4410AD706C266B05B5BEB9D9 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - lossless.h - path - src/dsp/lossless.h - sourceTree - <group> - - 13238AAE414C28744680FBB3371701BA - - fileRef - B46C6B5F5186E6B2930248A79E4E25B3 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 13B20953F5F50AA7C21EE06EA988419B - - fileRef - 40E9A9B1442533BB506AA976BCAC68FA - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 14173E0FE6815CC17FBE637039CC32C7 - - fileRef - 3716FA451F6F4D28D103DB096A64670F - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 142141837F3BD87ACA4E9F0E4D15F0C1 - - fileRef - AEC044B0F76F511FA186E3719A2D7254 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 148B34B78792C8E391C04CF60FEE3548 - - fileRef - 0B4022E490AE7D0C68357369C4CDFAA7 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 15100ED6594D5097A6D6D6940738FC62 - - fileRef - E04359202406E39276DDCAD3D120BC31 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 1611E06E42073AE481AEEAFBACD45B76 - - fileRef - 390D2DDC2A0A49DD8394CBEE3E988302 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 162953E4F39E1792379941D154D1E1A4 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - Pods-PINRemoteImage-libwebp-dummy.m - sourceTree - <group> - - 1689FCB88270D158620C53BA268699CB - - fileRef - 842AEA4C593FCC23269637C63090CF9D - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 16ADB3861D9A0B9D5C491B35EDA654B3 - - includeInIndex - 1 - isa - PBXFileReference - name - histogram.c - path - src/enc/histogram.c - sourceTree - <group> - - 16AE3E97F8826CB59F3461CCE4C8D0A8 - - includeInIndex - 1 - isa - PBXFileReference - name - quant_levels_dec.c - path - src/utils/quant_levels_dec.c - sourceTree - <group> - - 178A06EC2705B46FE1BB38A02AAC7BBC - - children - - 59AABC1F754D2FC5DF89C547B78F7552 - - isa - PBXGroup - name - Frameworks - sourceTree - <group> - - 18B15F952128DD8DF6F1331A4263CB47 - - includeInIndex - 1 - isa - PBXFileReference - name - dec.c - path - src/dsp/dec.c - sourceTree - <group> - - 18E7BAAB882A7AA471B649263701AF42 - - includeInIndex - 1 - isa - PBXFileReference - name - vp8l.c - path - src/enc/vp8l.c - sourceTree - <group> - - 19CA21D4E473C742D1C8A16C68378AF6 - - fileRef - 4A5DDEDDF9AA6176B724AA21B3313574 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 1A7A91DDFAAB6930477A8A0BDCB9E403 - - includeInIndex - 1 - isa - PBXFileReference - name - picture_psnr.c - path - src/enc/picture_psnr.c - sourceTree - <group> - - 1AF7E5AACEEA90E9CBCD24A9DBC5F4EB - - includeInIndex - 1 - isa - PBXFileReference - name - quant.c - path - src/enc/quant.c - sourceTree - <group> - - 1B2BEA6928EEE8D8E93CF3346B8D4299 - - fileRef - 1A7A91DDFAAB6930477A8A0BDCB9E403 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 1BAA920F0E8A1454E03685EDFF2E1770 - - fileRef - 96ECBDF3CC7647F49CFD7843C639D5B6 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 1C62A009925C46A84BFA8DA6A64D96FD - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINRemoteImageCategoryManager.m - sourceTree - <group> - - 1DC8B0A40942437944A04BCEEC1EE669 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - utils.h - path - src/utils/utils.h - sourceTree - <group> - - 1E22FCADE80C38232EC200A47D23DE40 - - children - - 697F3EBB62E029994025C763402E8758 - F41B26725DCA5F24A5BCA3587600B423 - - isa - PBXGroup - name - Pods - sourceTree - <group> - - 1E79A2518AAF24762FE7D7A406618946 - - includeInIndex - 1 - isa - PBXFileReference - name - muxinternal.c - path - src/mux/muxinternal.c - sourceTree - <group> - - 1F00426785F865830F7BDC9352060EAE - - fileRef - A7D0CE377D79F0D63CB6EC7A83756E01 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 200CB87EBBE012F887B8C8483913709A - - fileRef - 378F2FEF47F92CF4C66FB72BEBAF495E - isa - PBXBuildFile - - 20271290BC3C4EBFEB6BF3413E48855F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - PINDiskCache.h - path - PINCache/PINDiskCache.h - sourceTree - <group> - - 20BC896ED7EC920A8F2E85AED94CD821 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - histogram.h - path - src/enc/histogram.h - sourceTree - <group> - - 20D0C1BEE694CD1889B151DBE94C9C1D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINURLSessionManager.h - sourceTree - <group> - - 21A5C5F154167D4633BFCC27A9B08C4D - - fileRef - 16AE3E97F8826CB59F3461CCE4C8D0A8 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 2310584B1A349A2AECE50064336B8C01 - - fileRef - B96F0796CF410388EC2CD6E630F4653B - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 234D58303ECAEAFE19646BBEDE05E61A - - fileRef - 73E90E16910BA96C9D4B3A48F7549621 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 25024AE072F0AF4E1074D34A2401B3CA - - includeInIndex - 1 - isa - PBXFileReference - name - filters.c - path - src/utils/filters.c - sourceTree - <group> - - 2506AEAEA08053AC2DDAE6EFF67053EB - - fileRef - 0314C236143A4F5C7DB88A7C63894C43 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 26F1B6705C6061C9BCC649D8C40F85E7 - - buildActionMask - 2147483647 - files - - 472A0B53991AB36C5CCF94987AA78B8C - C7E494F18D812C1D3AC4DD57FB199880 - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 272212045D7B928A9E34A493D9D9C818 - - includeInIndex - 1 - isa - PBXFileReference - name - picture_rescale.c - path - src/enc/picture_rescale.c - sourceTree - <group> - - 27F5A1DB1F55E010CB9B74F53EDB26C9 - - fileRef - 9E53B4B4CFB2A6A28E55991BF9E5D041 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 283FC0870DBA2C4A604649C455E72E99 - - fileRef - 8DD9CE62AAD6CABEDB42F03617A53104 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 288A12940DEF877778DDE2744116FCF6 - - children - - B8C78EA04207D7819734F983DDE86ABA - 162953E4F39E1792379941D154D1E1A4 - A299D5BFD07FEA9CE70BF808BE5BDFF8 - - isa - PBXGroup - name - Support Files - path - ../Target Support Files/Pods-PINRemoteImage-libwebp - sourceTree - <group> - - 2920D4CB7D46EC6195B0C496D72BA261 - - fileRef - 06655463DC05231AB09E5A504061E353 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 2929654B44ED7A72D38BBC18D01FFB02 - - includeInIndex - 1 - isa - PBXFileReference - name - yuv_sse2.c - path - src/dsp/yuv_sse2.c - sourceTree - <group> - - 292F6C517A2D16180FD0DCCB5DB0ABC0 - - fileRef - 9C4A8E9B0DE801ADA11ED1898E7A8A6D - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 2B2B19B78AF2E7588E1B3B4318FB50FC - - fileRef - B7D7872C876F23F1729EA5F43344F778 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 2C3BB808565E82708384DBE2F928E259 - - fileRef - 756BD2121E0F0D8E9C49AE5325DD4D17 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 2CE3094E5B3487B8F790A1AB07048B00 - - buildConfigurations - - 4EBE8E8BCCF6F9AEFACDC298F46EC2E4 - 8C537ACFFA79F07062A867B02531366B - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - 2D8E8EC45A3A1A1D94AE762CB5028504 - - buildConfigurations - - 10B2EE21B5D67EE2C819831CCC43832B - 7C07D96CC7C445E83983A6C6420BC692 - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - 2E67890AF6FEFDF3B8842E6B1F1C8AEF - - includeInIndex - 1 - isa - PBXFileReference - name - backward_references.c - path - src/enc/backward_references.c - sourceTree - <group> - - 2E97BB4B842D8F8CA2DD76A00F23121A - - includeInIndex - 1 - isa - PBXFileReference - name - lossless.c - path - src/dsp/lossless.c - sourceTree - <group> - - 3039F9D9A1DAC9F39D6DB58B09B1AC57 - - includeInIndex - 1 - isa - PBXFileReference - name - lossless_enc.c - path - src/dsp/lossless_enc.c - sourceTree - <group> - - 30A57367464071D62B010563275C7AC2 - - fileRef - 888402B5D2CE2BBE8209B8B695DE9393 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 315A9C171818CF7B69118BD1D0D92544 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINRemoteImageMacros.h - sourceTree - <group> - - 32EACBCF545009BAB3CD5773D01FFD94 - - includeInIndex - 1 - isa - PBXFileReference - name - cost.c - path - src/dsp/cost.c - sourceTree - <group> - - 33AB437571CE87D26286011AAC6A292C - - fileRef - C114D92B7121DAF36A8E5383F255628E - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 33B13B5D7FE4572197F432409430431A - - children - - EDF461A029F5B6A0F026DA7412A6FA1F - - isa - PBXGroup - name - Pod - path - Pod - sourceTree - <group> - - 34168FD6B0CD9AD8FFA4E89726E00453 - - fileRef - 3D6C21D96548B9777F46000FCF001A3D - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 345C612CA023E9C9DA39708F28B69364 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINRemoteImageDownloadTask.m - sourceTree - <group> - - 34AC264E10630A0EE65E62186A98D728 - - includeInIndex - 1 - isa - PBXFileReference - name - huffman.c - path - src/utils/huffman.c - sourceTree - <group> - - 34D86B8A97D344C21F8D1354F4C71F2D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINDataTaskOperation.h - sourceTree - <group> - - 3503A8952DA4B2B222976B1DEDC77EF7 - - fileRef - 0CED3F531E83C3CBDBC261FE20EED9A0 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 365B51C8299D8B0817E9BD1BF65C7554 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINAnimatedImageManager.m - sourceTree - <group> - - 368D6EE8BBF0E466D4CEF1736F59EF23 - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - name - libPods-PINRemoteImage-PINCache.a - path - libPods-PINRemoteImage-PINCache.a - sourceTree - BUILT_PRODUCTS_DIR - - 3716FA451F6F4D28D103DB096A64670F - - includeInIndex - 1 - isa - PBXFileReference - name - io.c - path - src/dec/io.c - sourceTree - <group> - - 378F2FEF47F92CF4C66FB72BEBAF495E - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - Pods-PINRemoteImage-PINCache-dummy.m - sourceTree - <group> - - 37C614990C90CF23E15689F30EA8A64C - - fileRef - 0C6BDAE9D7C739137B6D80FF57CF7DD1 - isa - PBXBuildFile - - 37F2AC2A4B62F2AA6E3C2EBBED317ADF - - fileRef - 552A2F354B2E2164512C4B6461DB86D1 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 386E7AA05B41C981817240E0227F9A50 - - fileRef - 20271290BC3C4EBFEB6BF3413E48855F - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 38B2A77EF210B5D9F4FE93D5099617EA - - includeInIndex - 1 - isa - PBXFileReference - name - iterator.c - path - src/enc/iterator.c - sourceTree - <group> - - 38EC6522B224E3B9AFFA0BFE85B73A68 - - includeInIndex - 1 - isa - PBXFileReference - name - frame.c - path - src/enc/frame.c - sourceTree - <group> - - 390D2DDC2A0A49DD8394CBEE3E988302 - - includeInIndex - 1 - isa - PBXFileReference - name - lossless_neon.c - path - src/dsp/lossless_neon.c - sourceTree - <group> - - 39D6E1353F8D8C8254631EBF0E76EA77 - - fileRef - 34AC264E10630A0EE65E62186A98D728 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 3A5F4F7C3333C6FE0E2EE6C882B8773F - - fileRef - 38B2A77EF210B5D9F4FE93D5099617EA - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 3AFC2945B51028C7AF4AB9AFA9648AC1 - - fileRef - 18B15F952128DD8DF6F1331A4263CB47 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 3BC7BF5D12FA6079B4DCAF5DE2FE0942 - - fileRef - E61017926E4C5B70D20FAB84E278EF7F - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 3D0A76433D4385B8BC2AC0D8B1912A8D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINRemoteImageCategoryManager.h - sourceTree - <group> - - 3D6C21D96548B9777F46000FCF001A3D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINRemoteImage.h - sourceTree - <group> - - 3D8B33A6AF105DD2D8441D4B2FF3D883 - - containerPortal - D41D8CD98F00B204E9800998ECF8427E - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - 49081F3E6842F3DE8A4F88EBA06D8A8E - remoteInfo - Pods-PINRemoteImage-PINRemoteImage - - 3DEDC6A08970CB839B8A6496B5DF86D0 - - includeInIndex - 1 - isa - PBXFileReference - name - idec.c - path - src/dec/idec.c - sourceTree - <group> - - 3E3F7624713164015E677B04C47497C2 - - fileRef - 0004A378FDCA54B7480AEB7987CB2FB3 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 3E8EBD4B83E9C54F53F004361C29DB42 - - fileRef - 5FE27926AD01A59DF7B2BDE36BEA9504 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 3E91A8F873C86625D273F773B59E0841 - - fileRef - 76C594138591E3BDBB952C30C5CFFEAC - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 3EF73C8C5306EAED6EF86F15C02988BD - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINRemoteImageManager.m - sourceTree - <group> - - 3F5D4923A703E4F27848B4B3D58519AA - - children - - 9D202149D857914BCC0C357CA6932404 - - isa - PBXGroup - name - Targets Support Files - sourceTree - <group> - - 3FFCFE58F080E6D67CC03344D296989D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - common.h - path - src/dec/common.h - sourceTree - <group> - - 3FFD642A2341AAD51DEB64FBD4D0D7D7 - - fileRef - 6F07C068332B44FDB57D1A4FF1D0A5EA - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -DOS_OBJECT_USE_OBJC=0 - - - 40E9A9B1442533BB506AA976BCAC68FA - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINRemoteLock.h - sourceTree - <group> - - 415D4C495C85355B34899D807E5C6382 - - fileRef - E759CDA4349301C1E0FC7BC0FC163C08 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 4295C947AD69FD429F982D216B4F4B0D - - buildConfigurationList - D8144AB855026636396D296E4B308EA0 - buildPhases - - DC19EA7EA64F59F5FB99EB76948468E9 - 60BCFD87B71B05976AC58226C7C557D5 - 0C33A0B2CA62D0A538C4071B126CF0B0 - - buildRules - - dependencies - - isa - PBXNativeTarget - name - Pods-PINRemoteImage-libwebp - productName - Pods-PINRemoteImage-libwebp - productReference - D4A7AC7EC35C141AD8EC5E917486A3B1 - productType - com.apple.product-type.library.static - - 42A036B7F9799D066AF14D99C9D45C4C - - fileRef - BF1A285EE60DBF42A27F701FF5468D27 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 45729E38DC1140595790D766491BB172 - - children - - 05204CF01F096BC8F9A32C2C757533EA - 378F2FEF47F92CF4C66FB72BEBAF495E - BE83F5A11DB5C1AE3E0466DFAE79E981 - - isa - PBXGroup - name - Support Files - path - ../Target Support Files/Pods-PINRemoteImage-PINCache - sourceTree - <group> - - 45B83322961CD0BEB3EE0C9040E3B540 - - fileRef - D3EC23657EF6F08E01619710D063377C - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 46F39C5FC2377469E26ED318F9AB6661 - - includeInIndex - 1 - isa - PBXFileReference - name - vp8.c - path - src/dec/vp8.c - sourceTree - <group> - - 472A0B53991AB36C5CCF94987AA78B8C - - fileRef - 65347844787A41A2F0E848FA51EA725B - isa - PBXBuildFile - - 484DF8F62E7B56D0A9FD722FE1FAF57E - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - delta_palettization.h - path - src/enc/delta_palettization.h - sourceTree - <group> - - 48E463B6FDD17241DD3E1C3CF1F934A4 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINImageView+PINRemoteImage.m - sourceTree - <group> - - 49081F3E6842F3DE8A4F88EBA06D8A8E - - buildConfigurationList - 2CE3094E5B3487B8F790A1AB07048B00 - buildPhases - - 571C9D8E7F88F7EBF564D39B195FEE02 - 5F0F36465FA7A6408971129BD0E17247 - A227350F4130C68087CA0CEB7E634CB8 - - buildRules - - dependencies - - E353EF26682110F0BB0765C319A49DD5 - ACFEDB5DFC5CC534D0453D764DCE9C06 - - isa - PBXNativeTarget - name - Pods-PINRemoteImage-PINRemoteImage - productName - Pods-PINRemoteImage-PINRemoteImage - productReference - F0587A92A6FDCDF7ED4C0AC2B6B7069D - productType - com.apple.product-type.library.static - - 4A5DDEDDF9AA6176B724AA21B3313574 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINAnimatedImage.h - sourceTree - <group> - - 4A89E1A4DE7F6463F8D966DAE4ABA260 - - fileRef - 5852602B68C0922C56FB3C398FF437CD - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 4BD43A29167C49AE58CF07672602859E - - fileRef - AB55F5014C44319B86624542851A6254 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 4CBF09EEE3843F3754524ED18E977730 - - includeInIndex - 1 - isa - PBXFileReference - name - thread.c - path - src/utils/thread.c - sourceTree - <group> - - 4CC35C87226E62666D521C5EB54E8EDB - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - muxi.h - path - src/mux/muxi.h - sourceTree - <group> - - 4D0FFF465E08FE5A6EB685BC9F8FAF8B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - bit_reader_inl.h - path - src/utils/bit_reader_inl.h - sourceTree - <group> - - 4DD2E84F640C1D82EFAEB930D10F4499 - - includeInIndex - 1 - isa - PBXFileReference - name - dec_sse41.c - path - src/dsp/dec_sse41.c - sourceTree - <group> - - 4EBE8E8BCCF6F9AEFACDC298F46EC2E4 - - baseConfigurationReference - 550AFC415EE4A735BEA4248F7F40E7D1 - buildSettings - - ENABLE_STRICT_OBJC_MSGSEND - YES - EXECUTABLE_PREFIX - lib - GCC_PREFIX_HEADER - Target Support Files/Pods-PINRemoteImage-PINRemoteImage/Pods-PINRemoteImage-PINRemoteImage-prefix.pch - MACOSX_DEPLOYMENT_TARGET - 10.11 - MTL_ENABLE_DEBUG_INFO - YES - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRIVATE_HEADERS_FOLDER_PATH - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - - SDKROOT - macosx - - isa - XCBuildConfiguration - name - Debug - - 5055130A4D4926609736E8141AC2D2C0 - - fileRef - DD6765CC87F0C7941BB608F3D360F10D - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 50CB7CB77AB80FC17B37C991711FE330 - - includeInIndex - 1 - isa - PBXFileReference - name - cpu.c - path - src/dsp/cpu.c - sourceTree - <group> - - 515272D2158D188DA1821C2D75FE69D0 - - fileRef - A4715947A8F78BE484203DD3902EBBC8 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 53B26F6779050EE7F14EBEA610331B56 - - children - - 33B13B5D7FE4572197F432409430431A - - isa - PBXGroup - name - Core - sourceTree - <group> - - 546D1728881FEE40134C5590B2714AF9 - - fileRef - 79898B5611196C60C85AE21343CDE299 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 54E7D833F175E7B87677C92E48919A74 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - webpi.h - path - src/dec/webpi.h - sourceTree - <group> - - 54F27F7B6DBD02B3C1ABB03D547E1C0E - - buildConfigurationList - 68AB40E1C361C8036348661A5205FAA8 - buildPhases - - DC138E767ECE3B27EC24765A880388E8 - 26F1B6705C6061C9BCC649D8C40F85E7 - 7311CA4BDE3DB5F713A42C68928AFE7A - - buildRules - - dependencies - - isa - PBXNativeTarget - name - Pods-PINRemoteImage-PINCache - productName - Pods-PINRemoteImage-PINCache - productReference - 368D6EE8BBF0E466D4CEF1736F59EF23 - productType - com.apple.product-type.library.static - - 550AFC415EE4A735BEA4248F7F40E7D1 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-PINRemoteImage-PINRemoteImage.xcconfig - sourceTree - <group> - - 552A2F354B2E2164512C4B6461DB86D1 - - includeInIndex - 1 - isa - PBXFileReference - name - color_cache.c - path - src/utils/color_cache.c - sourceTree - <group> - - 55D457194AAE2C98251B1CE16031F718 - - includeInIndex - 1 - isa - PBXFileReference - name - enc_avx2.c - path - src/dsp/enc_avx2.c - sourceTree - <group> - - 560212C23FE359FB73C6A993C66A326C - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - random.h - path - src/utils/random.h - sourceTree - <group> - - 561E890E632B37DF552812079980D5D0 - - children - - 9C4A8E9B0DE801ADA11ED1898E7A8A6D - 9F202CE74DED5002D40D9E4070B9A920 - 4CC35C87226E62666D521C5EB54E8EDB - 1E79A2518AAF24762FE7D7A406618946 - 7FE002DA500BD1E50B33903BDE4CB214 - - isa - PBXGroup - name - mux - sourceTree - <group> - - 5674395FB83A4783C842C89AB53A8851 - - fileRef - 272212045D7B928A9E34A493D9D9C818 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 568C04BE2B34B62D1FEC11694B9AAA5D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINProgressiveImage.m - sourceTree - <group> - - 56A79F15482DF888A6281346936408B7 - - fileRef - 2E97BB4B842D8F8CA2DD76A00F23121A - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 571C9D8E7F88F7EBF564D39B195FEE02 - - buildActionMask - 2147483647 - files - - 0B2545B7E15F58DE7D7857C1100F2E5F - 82B376FA899A48B08D535AF0496B0F63 - 6D683792B942CD60150C64460808080B - 8C701855176617805E77450393291F75 - 588BB2D4B672A9C683C52376DEDC58F9 - 978A97EA2A992B65B09FAF4F2F7C4223 - E44B88F2DFC6F097A47D503B76D923C5 - 7B766FC0B12D0DA825EB4EFD899814E6 - 077F2A12C5BEE6866AD991528CB45AD6 - F98A6FFF26897B0AC819DD3DB6669AB8 - 83DDA188F2B83C220C301358275C28A8 - 6B87898295103C7A765DC37937FC0097 - 09AA62A51B4DA905E582E2AAF7D9B27B - B8CD9A2C5F6E7EAD64BEF6DA081D7346 - 7E54B35F5D4B9D3B8B86AA0C14D30387 - 5BAC9D4E79D09C64B48094AF75F42820 - A4C9F1BE65219BC34FC0662AF6FB7651 - DD536A9B503A891F93DF8FA8A44713FA - C5A996455F5A5F5EE20A79B0F1269663 - D0206B2710197A30D3E82FB970037CAE - 87E29943241394445BE03E06EE8D7B54 - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 574D0AB465DEE51656A2FAED9D40C311 - - fileRef - A0C00049CBCD6B00CFB18E979BAEF6C2 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 57729752DF42EC63EC46736ED7815518 - - baseConfigurationReference - B8C78EA04207D7819734F983DDE86ABA - buildSettings - - DEBUG_INFORMATION_FORMAT - dwarf-with-dsym - ENABLE_STRICT_OBJC_MSGSEND - YES - EXECUTABLE_PREFIX - lib - GCC_PREFIX_HEADER - Target Support Files/Pods-PINRemoteImage-libwebp/Pods-PINRemoteImage-libwebp-prefix.pch - MACOSX_DEPLOYMENT_TARGET - 10.11 - MTL_ENABLE_DEBUG_INFO - NO - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRIVATE_HEADERS_FOLDER_PATH - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - - SDKROOT - macosx - - isa - XCBuildConfiguration - name - Release - - 5852602B68C0922C56FB3C398FF437CD - - includeInIndex - 1 - isa - PBXFileReference - name - lossless_enc_mips_dsp_r2.c - path - src/dsp/lossless_enc_mips_dsp_r2.c - sourceTree - <group> - - 585541D65FCD3FEC57B9AF5CD13CD1E5 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINRemoteImageProcessorTask.h - sourceTree - <group> - - 588BB2D4B672A9C683C52376DEDC58F9 - - fileRef - 7FA924048E3784670B1814740F2044EF - isa - PBXBuildFile - - 5962DD7238C4BBFCF261955C4651E8EE - - fileRef - DD0FFD7DBB393EC196E68670E37B5C6B - isa - PBXBuildFile - - 597EABFFF86A26555ACF60EF14695221 - - fileRef - F7F76726829C94536E7CCE02BB5F6273 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 598BE2B249C93D64AE8820885ECDD50A - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.script.sh - path - Pods-PINRemoteImage-frameworks.sh - sourceTree - <group> - - 59A8AFBD60EE84377C734A1AF1654E58 - - fileRef - D8D3C221D462BA09E4A62BCB567F8A2C - isa - PBXBuildFile - - 59AABC1F754D2FC5DF89C547B78F7552 - - children - - 0C6BDAE9D7C739137B6D80FF57CF7DD1 - 65347844787A41A2F0E848FA51EA725B - D8D3C221D462BA09E4A62BCB567F8A2C - 0DA7C28757B0C2EA3328CF99344DE4A7 - A070361A845B5F6BDAF19E3150E11A64 - - isa - PBXGroup - name - OS X - sourceTree - <group> - - 5B955F65D735F2CD9D1156233F596B19 - - fileRef - AD3D4855D31C5F1CECDAF2E4CE0EE5A1 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 5BAC9D4E79D09C64B48094AF75F42820 - - fileRef - D4873E4B41B03CCDFE653D3980CC089D - isa - PBXBuildFile - - 5C4F6DC4014902CE3AC38AD57D76C4F2 - - fileRef - 70FC5F3F16EDC8FF2240B65B226050C0 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 5C625F7142C8F808C946FDBB23B6E08F - - fileRef - E56EFC94FD15573B0B427C984A9AD0A7 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 5C67529B29D47327FFC4508DA0C5A5A5 - - fileRef - 25024AE072F0AF4E1074D34A2401B3CA - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 5CEC4BBFC9D518A4FD8BC5A1362CF6E8 - - fileRef - C7F4A899A302F13CEA24F45F292CAC1D - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 5D438E3783B022065CD9EB93BE9200BA - - fileRef - 97EBA7B57E58072FE1201383889B9E40 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 5E2DFD7569EF16E2F8B8841AC0EABAD3 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - vp8li.h - path - src/dec/vp8li.h - sourceTree - <group> - - 5EF76F77F6A44F2AA107FC8DA5B4A297 - - fileRef - 34D86B8A97D344C21F8D1354F4C71F2D - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 5F0F36465FA7A6408971129BD0E17247 - - buildActionMask - 2147483647 - files - - 37C614990C90CF23E15689F30EA8A64C - C3C84769FDAA224BA9047A2E7E227043 - 59A8AFBD60EE84377C734A1AF1654E58 - B20C5AF45B622660DCE6694119F1BE82 - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 5F83550406E29B081B693C0F416386BF - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - huffman.h - path - src/utils/huffman.h - sourceTree - <group> - - 5FCD43DDE3D1A4CB4ABCE3E2BED940C8 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - mips_macro.h - path - src/dsp/mips_macro.h - sourceTree - <group> - - 5FE27926AD01A59DF7B2BDE36BEA9504 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - cost.h - path - src/enc/cost.h - sourceTree - <group> - - 60BCFD87B71B05976AC58226C7C557D5 - - buildActionMask - 2147483647 - files - - E23D77FB173FD3685203C9258A188DB4 - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 61294653A45CA0017BB58CB3AEF0A5D4 - - fileRef - F705D8BD26F0207F68990F2810C94492 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 616906687440069E679BED18B66A3233 - - fileRef - 1254E5EA4410AD706C266B05B5BEB9D9 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 61B27E3DC140D91540D09398E02E7F10 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - endian_inl.h - path - src/utils/endian_inl.h - sourceTree - <group> - - 629E148921B121B07FD2841596FCFF1F - - includeInIndex - 1 - isa - PBXFileReference - name - argb_mips_dsp_r2.c - path - src/dsp/argb_mips_dsp_r2.c - sourceTree - <group> - - 62A26CD4C293A522500F0ABF37DF55E5 - - containerPortal - D41D8CD98F00B204E9800998ECF8427E - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - 54F27F7B6DBD02B3C1ABB03D547E1C0E - remoteInfo - Pods-PINRemoteImage-PINCache - - 6348F141C8AD20487BF355C6C04EC2E0 - - baseConfigurationReference - A125C4DC87748BD87EE04F19A2C5306B - buildSettings - - ENABLE_STRICT_OBJC_MSGSEND - YES - EXECUTABLE_PREFIX - lib - MACH_O_TYPE - staticlib - MACOSX_DEPLOYMENT_TARGET - 10.11 - MTL_ENABLE_DEBUG_INFO - YES - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PODS_ROOT - $(SRCROOT) - PRODUCT_NAME - $(TARGET_NAME) - SDKROOT - macosx - SKIP_INSTALL - YES - - isa - XCBuildConfiguration - name - Debug - - 6417C9204960876043FDEB1C9175915B - - fileRef - 048828C11D392FA5A13E60F5223762F8 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 642415D3F112C6C096EC91FFAF924910 - - includeInIndex - 1 - isa - PBXFileReference - name - upsampling_sse2.c - path - src/dsp/upsampling_sse2.c - sourceTree - <group> - - 64CCF9B39C036472FD45826766B43A00 - - includeInIndex - 1 - isa - PBXFileReference - name - alpha_processing_sse2.c - path - src/dsp/alpha_processing_sse2.c - sourceTree - <group> - - 65347844787A41A2F0E848FA51EA725B - - isa - PBXFileReference - lastKnownFileType - wrapper.framework - name - Cocoa.framework - path - Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/Cocoa.framework - sourceTree - DEVELOPER_DIR - - 6568C3274167E0B57D5E3EC72D7D34D5 - - fileRef - E9B0E6AF0B60FB459CC571631506971D - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 65C1015DB7B57B40D7043E24B6B8E1F7 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINRemoteLock.m - sourceTree - <group> - - 65ED19850B283DC46CFBD2BC4EFE0729 - - includeInIndex - 1 - isa - PBXFileReference - name - dec_sse2.c - path - src/dsp/dec_sse2.c - sourceTree - <group> - - 666EDF8661607BD5221D356F15F67A0F - - fileRef - A84DF9F56CB36717DCB0A0EF063267EA - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -DOS_OBJECT_USE_OBJC=0 - - - 66880E9B24C85F202A6E769B01093860 - - fileRef - 55D457194AAE2C98251B1CE16031F718 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 66B635E1C52712F16AEE410826E9ADA9 - - fileRef - 8C2FA0F3D184A8373CC2757262033311 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 67406CC11BB9FE36BD868020640F58FA - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINImage+WebP.h - sourceTree - <group> - - 6768645FDED7622000A01796971784E1 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-PINRemoteImage.release.xcconfig - sourceTree - <group> - - 68429D82C13F40EBAA7B8196131F5EA0 - - fileRef - 1DC8B0A40942437944A04BCEEC1EE669 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 68AB40E1C361C8036348661A5205FAA8 - - buildConfigurations - - 0771434F429549DB1580F325FE7911FD - C4DCC3F3334B4CC416143A86815EE363 - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - 697F3EBB62E029994025C763402E8758 - - children - - 6CBDB9A49F8417BC287449FC0173C8ED - 852724ADD7717B41EA1AA8B35B2F5347 - 561E890E632B37DF552812079980D5D0 - 288A12940DEF877778DDE2744116FCF6 - 03D76B1839E8B92203D849620D80659D - - isa - PBXGroup - name - libwebp - path - libwebp - sourceTree - <group> - - 6A4AC7853CC796EC2A019069268460A6 - - includeInIndex - 1 - isa - PBXFileReference - name - upsampling_mips_dsp_r2.c - path - src/dsp/upsampling_mips_dsp_r2.c - sourceTree - <group> - - 6A5A445AD47D71FE8A79972BB2049092 - - fileRef - 2929654B44ED7A72D38BBC18D01FFB02 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 6AB11F192A4CE1ECFEDD75974F80BB56 - - includeInIndex - 1 - isa - PBXFileReference - name - rescaler_sse2.c - path - src/dsp/rescaler_sse2.c - sourceTree - <group> - - 6B3D7DA068A8632A7BD386E9FF300B65 - - fileRef - CC79C76AF9A585EF3DB2BD3F0B8D3C4A - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 6B4EA5137E666D621A3B50D50FE1E19D - - fileRef - EF618625D10D27B3DB3B8DCBDDD55FE7 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 6B87898295103C7A765DC37937FC0097 - - fileRef - 1C62A009925C46A84BFA8DA6A64D96FD - isa - PBXBuildFile - - 6CBDB9A49F8417BC287449FC0173C8ED - - children - - 842AEA4C593FCC23269637C63090CF9D - C7790B50E03DCD85FD63A298F88406C9 - E04359202406E39276DDCAD3D120BC31 - AD8F412E11B54B10BBC8657E200C7692 - 64CCF9B39C036472FD45826766B43A00 - 83397620B5FCDC996DB5C56ADE4FF1F9 - A25EBA406D3B2465CBC05C69370DED9A - 0CED3F531E83C3CBDBC261FE20EED9A0 - 0004A378FDCA54B7480AEB7987CB2FB3 - 629E148921B121B07FD2841596FCFF1F - E759CDA4349301C1E0FC7BC0FC163C08 - 2E67890AF6FEFDF3B8842E6B1F1C8AEF - 0708F88B696773C0A5227B28EC99A7F0 - 760F5F3A3AB54AE54C0DC631B6613604 - C7F1A1C81A19E9FE065B5D711BE37AC1 - 4D0FFF465E08FE5A6EB685BC9F8FAF8B - 888402B5D2CE2BBE8209B8B695DE9393 - F7F76726829C94536E7CCE02BB5F6273 - 97C796AD72C43361972C7B8C7CEC7880 - 552A2F354B2E2164512C4B6461DB86D1 - EF618625D10D27B3DB3B8DCBDDD55FE7 - 3FFCFE58F080E6D67CC03344D296989D - ACE0481457BF0274EC90F9BE3CFECD58 - 32EACBCF545009BAB3CD5773D01FFD94 - 0C35CE5F643C47C3AF417B395748D79B - 5FE27926AD01A59DF7B2BDE36BEA9504 - C114D92B7121DAF36A8E5383F255628E - CD41A5C9301EB06A7BA538065BEADCD4 - FB5D8FEC1F4B45AC4E1F9F824E753A4C - 50CB7CB77AB80FC17B37C991711FE330 - 18B15F952128DD8DF6F1331A4263CB47 - AEC044B0F76F511FA186E3719A2D7254 - 8D95A8D8B5D14A3D0BDB9236279D887B - 0E8222779199AC432EE5815423F43BCA - E68A8BFCB9208DB7048EDCA39ED67CFE - 65ED19850B283DC46CFBD2BC4EFE0729 - 4DD2E84F640C1D82EFAEB930D10F4499 - 959671A41F010478CAB6B1EC43D8441D - CB8FF7C88A18D6F4251F5A40E94A521D - 484DF8F62E7B56D0A9FD722FE1FAF57E - B68CF83B26F463D56D967719370C49E9 - E9B0E6AF0B60FB459CC571631506971D - 55D457194AAE2C98251B1CE16031F718 - C7F6A3EA8780ED38A22717D7CF15D90A - 74A311B3E6310D04E94D0B5640A3CFA8 - FE5EFC80D9471840D669FC3BFC2F289C - CC79C76AF9A585EF3DB2BD3F0B8D3C4A - 8DD9CE62AAD6CABEDB42F03617A53104 - 61B27E3DC140D91540D09398E02E7F10 - FFDCC5F0ABFA0D7E719A1109B8BF09E9 - 25024AE072F0AF4E1074D34A2401B3CA - 88D57E6D945960FE467EE1D65E194657 - 756BD2121E0F0D8E9C49AE5325DD4D17 - 96ECBDF3CC7647F49CFD7843C639D5B6 - 96156DB8E0F9F37D62C22E540877ED46 - 96C37E85FD520F8DCE151AAFEB13F88B - 38EC6522B224E3B9AFFA0BFE85B73A68 - 16ADB3861D9A0B9D5C491B35EDA654B3 - 20BC896ED7EC920A8F2E85AED94CD821 - 34AC264E10630A0EE65E62186A98D728 - 5F83550406E29B081B693C0F416386BF - 0B4022E490AE7D0C68357369C4CDFAA7 - A09C277CA0ECD1D7958686DDF3E2635B - 3DEDC6A08970CB839B8A6496B5DF86D0 - 3716FA451F6F4D28D103DB096A64670F - 38B2A77EF210B5D9F4FE93D5099617EA - 2E97BB4B842D8F8CA2DD76A00F23121A - 1254E5EA4410AD706C266B05B5BEB9D9 - 3039F9D9A1DAC9F39D6DB58B09B1AC57 - D538FDF01692214B5EFEB1E24D2A43C3 - 5852602B68C0922C56FB3C398FF437CD - BF1A285EE60DBF42A27F701FF5468D27 - C345E6209766AB1E702BDB362FC87673 - DD6765CC87F0C7941BB608F3D360F10D - F35E649D9FD9EBA610E53054A48244CE - 390D2DDC2A0A49DD8394CBEE3E988302 - B79AE0FA1860BFFD6B25495007477FC1 - 5FCD43DDE3D1A4CB4ABCE3E2BED940C8 - 88F99FCFD19A6FD6BC17C3D0D8A2766C - 0314C236143A4F5C7DB88A7C63894C43 - E19FC2F669F3E194D36D2B9410024FF8 - D3EC23657EF6F08E01619710D063377C - 1A7A91DDFAAB6930477A8A0BDCB9E403 - 272212045D7B928A9E34A493D9D9C818 - 727ABA42CABB8ABDCA113B98B5E0150C - D212C0227D15A3285951BD8DC15D576D - 1AF7E5AACEEA90E9CBCD24A9DBC5F4EB - 91AE2309E9946328C1F57CC567FF32CD - 0B43965EFDEAFAC0481542FF95374055 - 16AE3E97F8826CB59F3461CCE4C8D0A8 - F788EF1E261A9857273D8789C00F4DD4 - FE4520AC8ED67F5B8E54F3689C81F27C - 560212C23FE359FB73C6A993C66A326C - A4715947A8F78BE484203DD3902EBBC8 - A7D0CE377D79F0D63CB6EC7A83756E01 - FF392DA14E62ADEDDAE707FCA4028EC9 - 8C2FA0F3D184A8373CC2757262033311 - E1B9C97C5E571C31D4FC6C18C2BDA277 - 953EFFCF40C4001355AA2BA478451219 - 6AB11F192A4CE1ECFEDD75974F80BB56 - E12712BE03D1C9D1E867561CB4675EAD - 4CBF09EEE3843F3754524ED18E977730 - C3A5CAB3F244F79545963B8402DDF8B6 - A5144EB69172BAF63CF0FD6CB654802A - 103D6E913F66897CBC5AA2BAC1559C53 - A5B0B158C327BC36C2CFBA2530F074DF - 1187943A8079A2835E378B9C7D227845 - 6A4AC7853CC796EC2A019069268460A6 - 70FC5F3F16EDC8FF2240B65B226050C0 - 642415D3F112C6C096EC91FFAF924910 - 7A4C4EA7929FC36063200A3E345491DE - 1DC8B0A40942437944A04BCEEC1EE669 - 46F39C5FC2377469E26ED318F9AB6661 - C02F0EC4332D93095124D3E6B1790A46 - 79898B5611196C60C85AE21343CDE299 - AB55F5014C44319B86624542851A6254 - 18E7BAAB882A7AA471B649263701AF42 - 5E2DFD7569EF16E2F8B8841AC0EABAD3 - 879D57D1C89338755EE755EA1EA78E7C - C91034D1B9A6DB74E32B988B6DD13431 - 0F917410D4EB6590E946692D160A4F5E - 54E7D833F175E7B87677C92E48919A74 - CDF5DF12D07104923EC83FFA1E652FA9 - 97EBA7B57E58072FE1201383889B9E40 - 08B0859E25D0DF210E21239291ED01DF - 9E53B4B4CFB2A6A28E55991BF9E5D041 - 2929654B44ED7A72D38BBC18D01FFB02 - - isa - PBXGroup - name - core - sourceTree - <group> - - 6D683792B942CD60150C64460808080B - - fileRef - B76335CB2C89D0B241162674CBE8F1BA - isa - PBXBuildFile - - 6D8D1E79BCFA8A046565E36701F75BB6 - - fileRef - A5144EB69172BAF63CF0FD6CB654802A - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 6E6950DAD97D897CF352F2FFD0BE0B41 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - PINMemoryCache.h - path - PINCache/PINMemoryCache.h - sourceTree - <group> - - 6E823A9FD8DD9685BD5195D154A6114F - - fileRef - F788EF1E261A9857273D8789C00F4DD4 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 6F07C068332B44FDB57D1A4FF1D0A5EA - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - PINMemoryCache.m - path - PINCache/PINMemoryCache.m - sourceTree - <group> - - 6FE5842D9003D47BD0F8052831F0A814 - - fileRef - 7A4C4EA7929FC36063200A3E345491DE - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 6FF7A8804F9B6855BFF8FB792B2CAC7C - - fileRef - C7F1A1C81A19E9FE065B5D711BE37AC1 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 70FC5F3F16EDC8FF2240B65B226050C0 - - includeInIndex - 1 - isa - PBXFileReference - name - upsampling_neon.c - path - src/dsp/upsampling_neon.c - sourceTree - <group> - - 71B8A507DA55CEE6074547BB00C43BE5 - - fileRef - E68A8BFCB9208DB7048EDCA39ED67CFE - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 72100D09068058FEEABFF54C4D58A63A - - fileRef - 0C35CE5F643C47C3AF417B395748D79B - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 727ABA42CABB8ABDCA113B98B5E0150C - - includeInIndex - 1 - isa - PBXFileReference - name - picture_tools.c - path - src/enc/picture_tools.c - sourceTree - <group> - - 729140BD068361446FC8B24AC931F070 - - fileRef - 1187943A8079A2835E378B9C7D227845 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 72E7B0ECB6D569AC70B080E21F1587A6 - - fileRef - C345E6209766AB1E702BDB362FC87673 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 730679DEA1B4A13DA684CD48E0AEC007 - - children - - 76C594138591E3BDBB952C30C5CFFEAC - 7FA924048E3784670B1814740F2044EF - 01D8C9CB03CD8E823A419412F9415111 - 48E463B6FDD17241DD3E1C3CF1F934A4 - - isa - PBXGroup - name - Image Categories - path - Image Categories - sourceTree - <group> - - 7311CA4BDE3DB5F713A42C68928AFE7A - - buildActionMask - 2147483647 - files - - 9988EDCDF778F7B6685EC9759251C27B - 6417C9204960876043FDEB1C9175915B - 386E7AA05B41C981817240E0227F9A50 - 0839296EA88638F77315F77F49687A01 - - isa - PBXHeadersBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 73E90E16910BA96C9D4B3A48F7549621 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINRemoteImageDownloadTask.h - sourceTree - <group> - - 74A311B3E6310D04E94D0B5640A3CFA8 - - includeInIndex - 1 - isa - PBXFileReference - name - enc_mips_dsp_r2.c - path - src/dsp/enc_mips_dsp_r2.c - sourceTree - <group> - - 756BD2121E0F0D8E9C49AE5325DD4D17 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - filters.h - path - src/utils/filters.h - sourceTree - <group> - - 75FF73D66A4FA5E783791D59AFB39A2F - - fileRef - 3039F9D9A1DAC9F39D6DB58B09B1AC57 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 760F5F3A3AB54AE54C0DC631B6613604 - - includeInIndex - 1 - isa - PBXFileReference - name - bit_reader.c - path - src/utils/bit_reader.c - sourceTree - <group> - - 76C594138591E3BDBB952C30C5CFFEAC - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINButton+PINRemoteImage.h - sourceTree - <group> - - 77A0D1BFA97789A761884AF14BF3ADB9 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINDataTaskOperation.m - sourceTree - <group> - - 7890C9E7CF0C51306C75202785872967 - - fileRef - C91034D1B9A6DB74E32B988B6DD13431 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 79898B5611196C60C85AE21343CDE299 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - vp8i.h - path - src/dec/vp8i.h - sourceTree - <group> - - 7A4C4EA7929FC36063200A3E345491DE - - includeInIndex - 1 - isa - PBXFileReference - name - utils.c - path - src/utils/utils.c - sourceTree - <group> - - 7AD18E9483A7E1DA16781D2974CF2AB3 - - fileRef - 1E79A2518AAF24762FE7D7A406618946 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 7B766FC0B12D0DA825EB4EFD899814E6 - - fileRef - E823AD90033331573401BDFE6AB93CCB - isa - PBXBuildFile - - 7C07D96CC7C445E83983A6C6420BC692 - - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - CLANG_CXX_LANGUAGE_STANDARD - gnu++0x - CLANG_CXX_LIBRARY - libc++ - CLANG_ENABLE_MODULES - YES - CLANG_ENABLE_OBJC_ARC - YES - CLANG_WARN_BOOL_CONVERSION - YES - CLANG_WARN_CONSTANT_CONVERSION - YES - CLANG_WARN_DIRECT_OBJC_ISA_USAGE - YES - CLANG_WARN_EMPTY_BODY - YES - CLANG_WARN_ENUM_CONVERSION - YES - CLANG_WARN_INT_CONVERSION - YES - CLANG_WARN_OBJC_ROOT_CLASS - YES - CLANG_WARN_UNREACHABLE_CODE - YES - CLANG_WARN__DUPLICATE_METHOD_MATCH - YES - COPY_PHASE_STRIP - YES - ENABLE_NS_ASSERTIONS - NO - GCC_C_LANGUAGE_STANDARD - gnu99 - GCC_PREPROCESSOR_DEFINITIONS - - RELEASE=1 - - GCC_WARN_64_TO_32_BIT_CONVERSION - YES - GCC_WARN_ABOUT_RETURN_TYPE - YES - GCC_WARN_UNDECLARED_SELECTOR - YES - GCC_WARN_UNINITIALIZED_AUTOS - YES - GCC_WARN_UNUSED_FUNCTION - YES - GCC_WARN_UNUSED_VARIABLE - YES - MACOSX_DEPLOYMENT_TARGET - 10.11 - STRIP_INSTALLED_PRODUCT - NO - SYMROOT - ${SRCROOT}/../build - VALIDATE_PRODUCT - YES - - isa - XCBuildConfiguration - name - Release - - 7DB346D0F39D3F0E887471402A8071AB - - children - - BA6428E9F66FD5A23C0A2E06ED26CD2F - B1A11A7DE699B711ECE8F5987072C1D1 - 178A06EC2705B46FE1BB38A02AAC7BBC - 1E22FCADE80C38232EC200A47D23DE40 - 04ECC184692FC9A676106141D48F2EE3 - 3F5D4923A703E4F27848B4B3D58519AA - - isa - PBXGroup - sourceTree - <group> - - 7E2E59D9702480FF4D6B419C151E869D - - buildActionMask - 2147483647 - files - - 5962DD7238C4BBFCF261955C4651E8EE - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 7E54B35F5D4B9D3B8B86AA0C14D30387 - - fileRef - F12FF4A476141AE96BFAAB268C6394A0 - isa - PBXBuildFile - - 7F1362EF05DAB36F93DAB1A5C736D7F5 - - fileRef - 20BC896ED7EC920A8F2E85AED94CD821 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 7F16A4084715FAAC9B03AFC5A76D74CD - - fileRef - ACE0481457BF0274EC90F9BE3CFECD58 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 7F8B27B7F4572B90427E90EDD6CE0278 - - fileRef - 3FFCFE58F080E6D67CC03344D296989D - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 7F8E6C29485F5A930E2C73320C3E3F49 - - fileRef - E12712BE03D1C9D1E867561CB4675EAD - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 7FA924048E3784670B1814740F2044EF - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINButton+PINRemoteImage.m - sourceTree - <group> - - 7FE002DA500BD1E50B33903BDE4CB214 - - includeInIndex - 1 - isa - PBXFileReference - name - muxread.c - path - src/mux/muxread.c - sourceTree - <group> - - 8079C2382B7972F5FEB2C3C7D09592A2 - - fileRef - 4CC35C87226E62666D521C5EB54E8EDB - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 80DF14201CA36FAD2A469B1E688BA203 - - fileRef - 50CB7CB77AB80FC17B37C991711FE330 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 81571B2373D35793BCE857249C8D61C5 - - fileRef - D212C0227D15A3285951BD8DC15D576D - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 82B376FA899A48B08D535AF0496B0F63 - - fileRef - D99F4EFAF0C186086E786CFED30E0C6F - isa - PBXBuildFile - - 82F712C6D7B19B4D0B48668BB0C32A4F - - fileRef - B0B935414267CF835EFBFA7548C531AF - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 83397620B5FCDC996DB5C56ADE4FF1F9 - - includeInIndex - 1 - isa - PBXFileReference - name - alpha_processing_sse41.c - path - src/dsp/alpha_processing_sse41.c - sourceTree - <group> - - 83DDA188F2B83C220C301358275C28A8 - - fileRef - B9214326F987BC91CA4A3826C11D186C - isa - PBXBuildFile - - 842AEA4C593FCC23269637C63090CF9D - - includeInIndex - 1 - isa - PBXFileReference - name - alpha.c - path - src/dec/alpha.c - sourceTree - <group> - - 84BF72C4C5B822EA1053B174CF730065 - - isa - PBXTargetDependency - name - Pods-PINRemoteImage-libwebp - target - 4295C947AD69FD429F982D216B4F4B0D - targetProxy - 89A7F2C20C62FB1B52D09DB0612F9D6E - - 84C028B26FFAE771F8B6D1B5A00C2DBC - - fileRef - F5609D1F6A761F296346723B5846872C - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -DOS_OBJECT_USE_OBJC=0 - - - 84C1B348CD730F4D14FEC257D6FE97F1 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINImage+DecodedImage.m - sourceTree - <group> - - 852724ADD7717B41EA1AA8B35B2F5347 - - children - - EDFE857B881B90821CD9E77B38B977FD - EE90AE58540DEA4276BE7CC8A1A49E50 - - isa - PBXGroup - name - demux - sourceTree - <group> - - 879D57D1C89338755EE755EA1EA78E7C - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - vp8li.h - path - src/enc/vp8li.h - sourceTree - <group> - - 87D0CB66E7D297E3373B2E3947B35ED3 - - fileRef - 484DF8F62E7B56D0A9FD722FE1FAF57E - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 87E29943241394445BE03E06EE8D7B54 - - fileRef - A52BEB5277D24E9FAD174A602DEA6FDC - isa - PBXBuildFile - - 8805086DB01D26D4D721583A4D0B1600 - - fileRef - 0723546CB29E7CBB6EFC1088662AF45B - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 888402B5D2CE2BBE8209B8B695DE9393 - - includeInIndex - 1 - isa - PBXFileReference - name - bit_writer.c - path - src/utils/bit_writer.c - sourceTree - <group> - - 88D57E6D945960FE467EE1D65E194657 - - includeInIndex - 1 - isa - PBXFileReference - name - filters.c - path - src/dsp/filters.c - sourceTree - <group> - - 88F99FCFD19A6FD6BC17C3D0D8A2766C - - includeInIndex - 1 - isa - PBXFileReference - name - near_lossless.c - path - src/enc/near_lossless.c - sourceTree - <group> - - 8962BC3DCED6A56099C7E4251ED041A0 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - NSData+ImageDetectors.m - sourceTree - <group> - - 89A7F2C20C62FB1B52D09DB0612F9D6E - - containerPortal - D41D8CD98F00B204E9800998ECF8427E - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - 4295C947AD69FD429F982D216B4F4B0D - remoteInfo - Pods-PINRemoteImage-libwebp - - 8A959A9BF9BE1D6380F86FC5B4EC474A - - baseConfigurationReference - 6768645FDED7622000A01796971784E1 - buildSettings - - DEBUG_INFORMATION_FORMAT - dwarf-with-dsym - ENABLE_STRICT_OBJC_MSGSEND - YES - EXECUTABLE_PREFIX - lib - MACH_O_TYPE - staticlib - MACOSX_DEPLOYMENT_TARGET - 10.11 - MTL_ENABLE_DEBUG_INFO - NO - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PODS_ROOT - $(SRCROOT) - PRODUCT_NAME - $(TARGET_NAME) - SDKROOT - macosx - SKIP_INSTALL - YES - - isa - XCBuildConfiguration - name - Release - - 8C2FA0F3D184A8373CC2757262033311 - - includeInIndex - 1 - isa - PBXFileReference - name - rescaler_mips32.c - path - src/dsp/rescaler_mips32.c - sourceTree - <group> - - 8C537ACFFA79F07062A867B02531366B - - baseConfigurationReference - 550AFC415EE4A735BEA4248F7F40E7D1 - buildSettings - - DEBUG_INFORMATION_FORMAT - dwarf-with-dsym - ENABLE_STRICT_OBJC_MSGSEND - YES - EXECUTABLE_PREFIX - lib - GCC_PREFIX_HEADER - Target Support Files/Pods-PINRemoteImage-PINRemoteImage/Pods-PINRemoteImage-PINRemoteImage-prefix.pch - MACOSX_DEPLOYMENT_TARGET - 10.11 - MTL_ENABLE_DEBUG_INFO - NO - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRIVATE_HEADERS_FOLDER_PATH - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - - SDKROOT - macosx - - isa - XCBuildConfiguration - name - Release - - 8C701855176617805E77450393291F75 - - fileRef - 365B51C8299D8B0817E9BD1BF65C7554 - isa - PBXBuildFile - - 8D95A8D8B5D14A3D0BDB9236279D887B - - includeInIndex - 1 - isa - PBXFileReference - name - dec_mips32.c - path - src/dsp/dec_mips32.c - sourceTree - <group> - - 8DD9CE62AAD6CABEDB42F03617A53104 - - includeInIndex - 1 - isa - PBXFileReference - name - enc_sse41.c - path - src/dsp/enc_sse41.c - sourceTree - <group> - - 90955DB5237070F75E50577201574746 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINRemoteImageTask.m - sourceTree - <group> - - 90CBD6B77DF1D6E995A51B91A1AAC1A4 - - fileRef - 727ABA42CABB8ABDCA113B98B5E0150C - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 91AE2309E9946328C1F57CC567FF32CD - - includeInIndex - 1 - isa - PBXFileReference - name - quant_levels.c - path - src/utils/quant_levels.c - sourceTree - <group> - - 9384157F74F3E1C89836B61F3376F257 - - fileRef - 91AE2309E9946328C1F57CC567FF32CD - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 94E7C2C94EC549215002024D975467CB - - children - - 53B26F6779050EE7F14EBEA610331B56 - B8492CECA2F297209BD33D36F4CE3F05 - - isa - PBXGroup - name - PINRemoteImage - path - ../.. - sourceTree - <group> - - 94F8FA6C7F323CAC5C561ABF83DF1CB0 - - fileRef - 315A9C171818CF7B69118BD1D0D92544 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 95242733D78E04F586EAA570FEE21A1C - - fileRef - 96C37E85FD520F8DCE151AAFEB13F88B - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 953EFFCF40C4001355AA2BA478451219 - - includeInIndex - 1 - isa - PBXFileReference - name - rescaler_neon.c - path - src/dsp/rescaler_neon.c - sourceTree - <group> - - 959671A41F010478CAB6B1EC43D8441D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - decode_vp8.h - path - src/dec/decode_vp8.h - sourceTree - <group> - - 96156DB8E0F9F37D62C22E540877ED46 - - includeInIndex - 1 - isa - PBXFileReference - name - filters_sse2.c - path - src/dsp/filters_sse2.c - sourceTree - <group> - - 96330677DABAA013E46967C3A62E62FE - - fileRef - E19FC2F669F3E194D36D2B9410024FF8 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 9676F64E06952A014CC3E763A1633682 - - fileRef - 560212C23FE359FB73C6A993C66A326C - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 96C37E85FD520F8DCE151AAFEB13F88B - - includeInIndex - 1 - isa - PBXFileReference - name - frame.c - path - src/dec/frame.c - sourceTree - <group> - - 96ECBDF3CC7647F49CFD7843C639D5B6 - - includeInIndex - 1 - isa - PBXFileReference - name - filters_mips_dsp_r2.c - path - src/dsp/filters_mips_dsp_r2.c - sourceTree - <group> - - 978A97EA2A992B65B09FAF4F2F7C4223 - - fileRef - 77A0D1BFA97789A761884AF14BF3ADB9 - isa - PBXBuildFile - - 97C796AD72C43361972C7B8C7CEC7880 - - includeInIndex - 1 - isa - PBXFileReference - name - buffer.c - path - src/dec/buffer.c - sourceTree - <group> - - 97EBA7B57E58072FE1201383889B9E40 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - yuv.h - path - src/dsp/yuv.h - sourceTree - <group> - - 9988EDCDF778F7B6685EC9759251C27B - - fileRef - C6514CE37D3EE0EDBA0A0552B2AE8363 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 9A175DD5D5380EF9C411AF10AD80B028 - - fileRef - 88D57E6D945960FE467EE1D65E194657 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 9A3F2BCCB510DBB197909E21A9252DDF - - fileRef - 9F202CE74DED5002D40D9E4070B9A920 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 9C4A8E9B0DE801ADA11ED1898E7A8A6D - - includeInIndex - 1 - isa - PBXFileReference - name - anim_encode.c - path - src/mux/anim_encode.c - sourceTree - <group> - - 9C9C5757E4E05A66410CC397C2C80538 - - buildActionMask - 2147483647 - files - - 022891CD3C29415D1572CB15581E9FC9 - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 9D202149D857914BCC0C357CA6932404 - - children - - FF102A6E7977A3906DD7C91B6D7DEDA0 - CF259E283490ADDFAB56DAE513DFAC7F - DD0FFD7DBB393EC196E68670E37B5C6B - 598BE2B249C93D64AE8820885ECDD50A - DC868C27032D99EFCEDEE502267DDDD6 - A125C4DC87748BD87EE04F19A2C5306B - 6768645FDED7622000A01796971784E1 - - isa - PBXGroup - name - Pods-PINRemoteImage - path - Target Support Files/Pods-PINRemoteImage - sourceTree - <group> - - 9E081C46E13555389FC66F52A15A2E0E - - fileRef - 08B0859E25D0DF210E21239291ED01DF - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - 9E53B4B4CFB2A6A28E55991BF9E5D041 - - includeInIndex - 1 - isa - PBXFileReference - name - yuv_mips_dsp_r2.c - path - src/dsp/yuv_mips_dsp_r2.c - sourceTree - <group> - - 9F202CE74DED5002D40D9E4070B9A920 - - includeInIndex - 1 - isa - PBXFileReference - name - muxedit.c - path - src/mux/muxedit.c - sourceTree - <group> - - A070361A845B5F6BDAF19E3150E11A64 - - isa - PBXFileReference - lastKnownFileType - wrapper.framework - name - ImageIO.framework - path - Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/ImageIO.framework - sourceTree - DEVELOPER_DIR - - A09C277CA0ECD1D7958686DDF3E2635B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - huffman_encode.h - path - src/utils/huffman_encode.h - sourceTree - <group> - - A0C00049CBCD6B00CFB18E979BAEF6C2 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - types.h - path - src/webp/types.h - sourceTree - <group> - - A125C4DC87748BD87EE04F19A2C5306B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-PINRemoteImage.debug.xcconfig - sourceTree - <group> - - A227350F4130C68087CA0CEB7E634CB8 - - buildActionMask - 2147483647 - files - - 61294653A45CA0017BB58CB3AEF0A5D4 - A72BF48BF8EC1FE8DFEEAF555503962B - 19CA21D4E473C742D1C8A16C68378AF6 - CE244CEF193D9BF0CEE12512AAB601AF - 3E91A8F873C86625D273F773B59E0841 - 5EF76F77F6A44F2AA107FC8DA5B4A297 - FA65978174B2A98AC19D5C33ED661FD0 - 08D5D6CD76A31ABFA6E092502726BE9B - C2D7ABA5C5115DB6523104EC9B6DCEF3 - B79E421A78B877FB423982AEEBE1BA22 - 34168FD6B0CD9AD8FFA4E89726E00453 - 2920D4CB7D46EC6195B0C496D72BA261 - F0DC3B2438333A7853152F7DBB224042 - 234D58303ECAEAFE19646BBEDE05E61A - 94F8FA6C7F323CAC5C561ABF83DF1CB0 - 2B2B19B78AF2E7588E1B3B4318FB50FC - 82F712C6D7B19B4D0B48668BB0C32A4F - 5B955F65D735F2CD9D1156233F596B19 - 056272822D16293762F9F4B6B47C8A57 - A37F22EB428786593AE461E80F0C3889 - 13B20953F5F50AA7C21EE06EA988419B - EF16E58EF853CCF02EB26BAEA03B6BC5 - - isa - PBXHeadersBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - A25EBA406D3B2465CBC05C69370DED9A - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - alphai.h - path - src/dec/alphai.h - sourceTree - <group> - - A2918F68A7A260336513C2D3DB44B9DD - - fileRef - 5E2DFD7569EF16E2F8B8841AC0EABAD3 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - A299D5BFD07FEA9CE70BF808BE5BDFF8 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - Pods-PINRemoteImage-libwebp-prefix.pch - sourceTree - <group> - - A3667E58E4E0A14B361F34D068724745 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINProgressiveImage.h - sourceTree - <group> - - A37F22EB428786593AE461E80F0C3889 - - fileRef - AB35BD9A85E83BB1480B2BD1649C5553 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - A4359EE8B8DF3244B9F72346B6E74882 - - fileRef - FFDCC5F0ABFA0D7E719A1109B8BF09E9 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - A4715947A8F78BE484203DD3902EBBC8 - - includeInIndex - 1 - isa - PBXFileReference - name - rescaler.c - path - src/utils/rescaler.c - sourceTree - <group> - - A4C9F1BE65219BC34FC0662AF6FB7651 - - fileRef - 056A17AF5E589399B5500549916C964F - isa - PBXBuildFile - - A5144EB69172BAF63CF0FD6CB654802A - - includeInIndex - 1 - isa - PBXFileReference - name - token.c - path - src/enc/token.c - sourceTree - <group> - - A52BEB5277D24E9FAD174A602DEA6FDC - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - Pods-PINRemoteImage-PINRemoteImage-dummy.m - sourceTree - <group> - - A597BFE6B87B31BB6B653E99E9144602 - - fileRef - C02F0EC4332D93095124D3E6B1790A46 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - A5B0B158C327BC36C2CFBA2530F074DF - - includeInIndex - 1 - isa - PBXFileReference - name - tree.c - path - src/enc/tree.c - sourceTree - <group> - - A72BF48BF8EC1FE8DFEEAF555503962B - - fileRef - D6001D25EE732A2486755053A0152248 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - A7D0CE377D79F0D63CB6EC7A83756E01 - - includeInIndex - 1 - isa - PBXFileReference - name - rescaler.c - path - src/dsp/rescaler.c - sourceTree - <group> - - A84DF9F56CB36717DCB0A0EF063267EA - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - PINDiskCache.m - path - PINCache/PINDiskCache.m - sourceTree - <group> - - A8AA31557BBEE3F8DDA6FC3A01A54B38 - - fileRef - EDFE857B881B90821CD9E77B38B977FD - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - AB35BD9A85E83BB1480B2BD1649C5553 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINRemoteImageTask.h - sourceTree - <group> - - AB55F5014C44319B86624542851A6254 - - includeInIndex - 1 - isa - PBXFileReference - name - vp8l.c - path - src/dec/vp8l.c - sourceTree - <group> - - ACE0481457BF0274EC90F9BE3CFECD58 - - includeInIndex - 1 - isa - PBXFileReference - name - config.c - path - src/enc/config.c - sourceTree - <group> - - ACFEDB5DFC5CC534D0453D764DCE9C06 - - isa - PBXTargetDependency - name - Pods-PINRemoteImage-libwebp - target - 4295C947AD69FD429F982D216B4F4B0D - targetProxy - F807ECB0D11647282E3BD0CC2C16EF5B - - AD3D4855D31C5F1CECDAF2E4CE0EE5A1 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINRemoteImageMemoryContainer.h - sourceTree - <group> - - AD821974AF5498048A69BC2524B1C934 - - fileRef - 4DD2E84F640C1D82EFAEB930D10F4499 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - AD8F412E11B54B10BBC8657E200C7692 - - includeInIndex - 1 - isa - PBXFileReference - name - alpha_processing_mips_dsp_r2.c - path - src/dsp/alpha_processing_mips_dsp_r2.c - sourceTree - <group> - - AD8FE2C6AD0CDB89DA2F149BED7A61C4 - - fileRef - A09C277CA0ECD1D7958686DDF3E2635B - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - AEC044B0F76F511FA186E3719A2D7254 - - includeInIndex - 1 - isa - PBXFileReference - name - dec_clip_tables.c - path - src/dsp/dec_clip_tables.c - sourceTree - <group> - - AEF9CC15864A4B75B2767B8727A21B42 - - fileRef - CDF5DF12D07104923EC83FFA1E652FA9 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - AF1368B6241655B6F8305E75A982AFE2 - - fileRef - 0B43965EFDEAFAC0481542FF95374055 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - AFFCB16B0E467933CBE72A5EA381D7E9 - - fileRef - 97C796AD72C43361972C7B8C7CEC7880 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - B05BC009CB931E4835D21011EA1BB53E - - fileRef - FF392DA14E62ADEDDAE707FCA4028EC9 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - B07D21DBF6042F59ABF232E4FC67F3DA - - fileRef - C716806CED5D85E3B92E3D16B2292A83 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - B0B935414267CF835EFBFA7548C531AF - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINRemoteImageManagerResult.h - sourceTree - <group> - - B1A11A7DE699B711ECE8F5987072C1D1 - - children - - 94E7C2C94EC549215002024D975467CB - - isa - PBXGroup - name - Development Pods - sourceTree - <group> - - B20C5AF45B622660DCE6694119F1BE82 - - fileRef - A070361A845B5F6BDAF19E3150E11A64 - isa - PBXBuildFile - - B30114FA69E34B23835898CE1D216DD0 - - fileRef - D538FDF01692214B5EFEB1E24D2A43C3 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - B3C75AB1813564741ECF7F3D537569CA - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINImage+DecodedImage.h - sourceTree - <group> - - B414271F5AD28427640B5CA2DBB478DD - - fileRef - 7FE002DA500BD1E50B33903BDE4CB214 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - B46C6B5F5186E6B2930248A79E4E25B3 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - encode.h - path - src/webp/encode.h - sourceTree - <group> - - B59399B9C8E67345C36E3E3EF690EB20 - - baseConfigurationReference - B8C78EA04207D7819734F983DDE86ABA - buildSettings - - ENABLE_STRICT_OBJC_MSGSEND - YES - EXECUTABLE_PREFIX - lib - GCC_PREFIX_HEADER - Target Support Files/Pods-PINRemoteImage-libwebp/Pods-PINRemoteImage-libwebp-prefix.pch - MACOSX_DEPLOYMENT_TARGET - 10.11 - MTL_ENABLE_DEBUG_INFO - YES - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRIVATE_HEADERS_FOLDER_PATH - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - - SDKROOT - macosx - - isa - XCBuildConfiguration - name - Debug - - B6564E50493B9364185CADB6FFAE36D7 - - fileRef - C7790B50E03DCD85FD63A298F88406C9 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - B68CF83B26F463D56D967719370C49E9 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - dsp.h - path - src/dsp/dsp.h - sourceTree - <group> - - B76335CB2C89D0B241162674CBE8F1BA - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINAnimatedImage.m - sourceTree - <group> - - B79AE0FA1860BFFD6B25495007477FC1 - - includeInIndex - 1 - isa - PBXFileReference - name - lossless_sse2.c - path - src/dsp/lossless_sse2.c - sourceTree - <group> - - B79E421A78B877FB423982AEEBE1BA22 - - fileRef - A3667E58E4E0A14B361F34D068724745 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - B7D7872C876F23F1729EA5F43344F778 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINRemoteImageManager.h - sourceTree - <group> - - B8492CECA2F297209BD33D36F4CE3F05 - - children - - 550AFC415EE4A735BEA4248F7F40E7D1 - A52BEB5277D24E9FAD174A602DEA6FDC - D78FC91F85C97871DC9341A80AA95734 - - isa - PBXGroup - name - Support Files - path - Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-PINRemoteImage - sourceTree - <group> - - B8C78EA04207D7819734F983DDE86ABA - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-PINRemoteImage-libwebp.xcconfig - sourceTree - <group> - - B8CD9A2C5F6E7EAD64BEF6DA081D7346 - - fileRef - 3EF73C8C5306EAED6EF86F15C02988BD - isa - PBXBuildFile - - B9214326F987BC91CA4A3826C11D186C - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINRemoteImageCallbacks.m - sourceTree - <group> - - B96F0796CF410388EC2CD6E630F4653B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - format_constants.h - path - src/webp/format_constants.h - sourceTree - <group> - - B974D7A76F5A1DB6B3B873FE7C77FDC8 - - fileRef - 879D57D1C89338755EE755EA1EA78E7C - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - B9FD53A3AE714DA3CCEB98844A97EE83 - - fileRef - E1B9C97C5E571C31D4FC6C18C2BDA277 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - BA6428E9F66FD5A23C0A2E06ED26CD2F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text - name - Podfile - path - ../Podfile - sourceTree - SOURCE_ROOT - xcLanguageSpecificationIdentifier - xcode.lang.ruby - - BE83F5A11DB5C1AE3E0466DFAE79E981 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - Pods-PINRemoteImage-PINCache-prefix.pch - sourceTree - <group> - - BF1A285EE60DBF42A27F701FF5468D27 - - includeInIndex - 1 - isa - PBXFileReference - name - lossless_enc_neon.c - path - src/dsp/lossless_enc_neon.c - sourceTree - <group> - - C02F0EC4332D93095124D3E6B1790A46 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - vp8enci.h - path - src/enc/vp8enci.h - sourceTree - <group> - - C114D92B7121DAF36A8E5383F255628E - - includeInIndex - 1 - isa - PBXFileReference - name - cost_mips32.c - path - src/dsp/cost_mips32.c - sourceTree - <group> - - C13A607998BB556A4C9770538C826C06 - - containerPortal - D41D8CD98F00B204E9800998ECF8427E - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - 54F27F7B6DBD02B3C1ABB03D547E1C0E - remoteInfo - Pods-PINRemoteImage-PINCache - - C17B863A1D95FC023F190C0ECC59B452 - - fileRef - 3DEDC6A08970CB839B8A6496B5DF86D0 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - C2D7ABA5C5115DB6523104EC9B6DCEF3 - - fileRef - 01D8C9CB03CD8E823A419412F9415111 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - C345E6209766AB1E702BDB362FC87673 - - includeInIndex - 1 - isa - PBXFileReference - name - lossless_enc_sse2.c - path - src/dsp/lossless_enc_sse2.c - sourceTree - <group> - - C3A5CAB3F244F79545963B8402DDF8B6 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - thread.h - path - src/utils/thread.h - sourceTree - <group> - - C3C84769FDAA224BA9047A2E7E227043 - - fileRef - 65347844787A41A2F0E848FA51EA725B - isa - PBXBuildFile - - C49060225E775882B26B37F8ECD6AC37 - - fileRef - 54E7D833F175E7B87677C92E48919A74 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - C4DCC3F3334B4CC416143A86815EE363 - - baseConfigurationReference - 05204CF01F096BC8F9A32C2C757533EA - buildSettings - - DEBUG_INFORMATION_FORMAT - dwarf-with-dsym - ENABLE_STRICT_OBJC_MSGSEND - YES - EXECUTABLE_PREFIX - lib - GCC_PREFIX_HEADER - Target Support Files/Pods-PINRemoteImage-PINCache/Pods-PINRemoteImage-PINCache-prefix.pch - MACOSX_DEPLOYMENT_TARGET - 10.11 - MTL_ENABLE_DEBUG_INFO - NO - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRIVATE_HEADERS_FOLDER_PATH - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - - SDKROOT - macosx - - isa - XCBuildConfiguration - name - Release - - C570B2B6167DFDD45562DA234ABC96B0 - - fileRef - 38EC6522B224E3B9AFFA0BFE85B73A68 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - C5A996455F5A5F5EE20A79B0F1269663 - - fileRef - 65C1015DB7B57B40D7043E24B6B8E1F7 - isa - PBXBuildFile - - C614CD1F2299FAE605449BA1D9894EB8 - - buildConfigurations - - 6348F141C8AD20487BF355C6C04EC2E0 - 8A959A9BF9BE1D6380F86FC5B4EC474A - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - C6514CE37D3EE0EDBA0A0552B2AE8363 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - Nullability.h - path - PINCache/Nullability.h - sourceTree - <group> - - C716806CED5D85E3B92E3D16B2292A83 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - mux.h - path - src/webp/mux.h - sourceTree - <group> - - C7790B50E03DCD85FD63A298F88406C9 - - includeInIndex - 1 - isa - PBXFileReference - name - alpha.c - path - src/enc/alpha.c - sourceTree - <group> - - C7E494F18D812C1D3AC4DD57FB199880 - - fileRef - 0DA7C28757B0C2EA3328CF99344DE4A7 - isa - PBXBuildFile - - C7F1A1C81A19E9FE065B5D711BE37AC1 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - bit_reader.h - path - src/utils/bit_reader.h - sourceTree - <group> - - C7F4A899A302F13CEA24F45F292CAC1D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - decode.h - path - src/webp/decode.h - sourceTree - <group> - - C7F6A3EA8780ED38A22717D7CF15D90A - - includeInIndex - 1 - isa - PBXFileReference - name - enc_mips32.c - path - src/dsp/enc_mips32.c - sourceTree - <group> - - C7FD2A26F681C73B3372964FEE50F3F7 - - fileRef - 953EFFCF40C4001355AA2BA478451219 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - C91034D1B9A6DB74E32B988B6DD13431 - - includeInIndex - 1 - isa - PBXFileReference - name - webp.c - path - src/dec/webp.c - sourceTree - <group> - - C92DCB80B0FC006C667B87961227D082 - - fileRef - C7F6A3EA8780ED38A22717D7CF15D90A - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - C9B1AF7BC99CC4448C07577EDAC72BDF - - isa - PBXTargetDependency - name - Pods-PINRemoteImage-PINRemoteImage - target - 49081F3E6842F3DE8A4F88EBA06D8A8E - targetProxy - 3D8B33A6AF105DD2D8441D4B2FF3D883 - - CAF7E195ED7F6F65645FF836081BBCFF - - buildConfigurationList - C614CD1F2299FAE605449BA1D9894EB8 - buildPhases - - 7E2E59D9702480FF4D6B419C151E869D - 9C9C5757E4E05A66410CC397C2C80538 - - buildRules - - dependencies - - 08721ED67EA094F960FAEF205FAE47C0 - C9B1AF7BC99CC4448C07577EDAC72BDF - 84BF72C4C5B822EA1053B174CF730065 - - isa - PBXNativeTarget - name - Pods-PINRemoteImage - productName - Pods-PINRemoteImage - productReference - F59034D1B37659011B534E6DEF7D7F84 - productType - com.apple.product-type.library.static - - CB0EADB499F60ADFC6562BCD874AA754 - - fileRef - 65ED19850B283DC46CFBD2BC4EFE0729 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - CB8FF7C88A18D6F4251F5A40E94A521D - - includeInIndex - 1 - isa - PBXFileReference - name - delta_palettization.c - path - src/enc/delta_palettization.c - sourceTree - <group> - - CC26AE5B8B0709D14806614A187AF4D8 - - fileRef - 959671A41F010478CAB6B1EC43D8441D - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - CC79C76AF9A585EF3DB2BD3F0B8D3C4A - - includeInIndex - 1 - isa - PBXFileReference - name - enc_sse2.c - path - src/dsp/enc_sse2.c - sourceTree - <group> - - CCDB7A6A179B0B5DDF44680164507489 - - fileRef - FB5D8FEC1F4B45AC4E1F9F824E753A4C - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - CD16137FAE7112695FCF50336C1B4969 - - fileRef - FE5EFC80D9471840D669FC3BFC2F289C - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - CD41A5C9301EB06A7BA538065BEADCD4 - - includeInIndex - 1 - isa - PBXFileReference - name - cost_mips_dsp_r2.c - path - src/dsp/cost_mips_dsp_r2.c - sourceTree - <group> - - CDF5DF12D07104923EC83FFA1E652FA9 - - includeInIndex - 1 - isa - PBXFileReference - name - yuv.c - path - src/dsp/yuv.c - sourceTree - <group> - - CE23D02F1951FFEAF4B5F2E704388A45 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINAnimatedImageManager.h - sourceTree - <group> - - CE244CEF193D9BF0CEE12512AAB601AF - - fileRef - CE23D02F1951FFEAF4B5F2E704388A45 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - CF259E283490ADDFAB56DAE513DFAC7F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.plist.xml - path - Pods-PINRemoteImage-acknowledgements.plist - sourceTree - <group> - - D0206B2710197A30D3E82FB970037CAE - - fileRef - 06F1FE6224968BE662E1143ADCF5D40F - isa - PBXBuildFile - - D0C0F1422A439355BF927294B61C21C0 - - fileRef - 5F83550406E29B081B693C0F416386BF - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - D212C0227D15A3285951BD8DC15D576D - - includeInIndex - 1 - isa - PBXFileReference - name - quant.c - path - src/dec/quant.c - sourceTree - <group> - - D24938702361B9ACFC70E266D21969A8 - - fileRef - 74A311B3E6310D04E94D0B5640A3CFA8 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - D3EC23657EF6F08E01619710D063377C - - includeInIndex - 1 - isa - PBXFileReference - name - picture_csp.c - path - src/enc/picture_csp.c - sourceTree - <group> - - D41D8CD98F00B204E9800998ECF8427E - - attributes - - LastSwiftUpdateCheck - 0700 - LastUpgradeCheck - 0700 - - buildConfigurationList - 2D8E8EC45A3A1A1D94AE762CB5028504 - compatibilityVersion - Xcode 3.2 - developmentRegion - English - hasScannedForEncodings - 0 - isa - PBXProject - knownRegions - - en - - mainGroup - 7DB346D0F39D3F0E887471402A8071AB - productRefGroup - 04ECC184692FC9A676106141D48F2EE3 - projectDirPath - - projectReferences - - projectRoot - - targets - - CAF7E195ED7F6F65645FF836081BBCFF - 4295C947AD69FD429F982D216B4F4B0D - 54F27F7B6DBD02B3C1ABB03D547E1C0E - 49081F3E6842F3DE8A4F88EBA06D8A8E - - - D4873E4B41B03CCDFE653D3980CC089D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINRemoteImageMemoryContainer.m - sourceTree - <group> - - D4A7AC7EC35C141AD8EC5E917486A3B1 - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - name - libPods-PINRemoteImage-libwebp.a - path - libPods-PINRemoteImage-libwebp.a - sourceTree - BUILT_PRODUCTS_DIR - - D5115B9528A623B800518F63A206E612 - - fileRef - AD8F412E11B54B10BBC8657E200C7692 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - D538FDF01692214B5EFEB1E24D2A43C3 - - includeInIndex - 1 - isa - PBXFileReference - name - lossless_enc_mips32.c - path - src/dsp/lossless_enc_mips32.c - sourceTree - <group> - - D6001D25EE732A2486755053A0152248 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINAlternateRepresentationProvider.h - sourceTree - <group> - - D6CD40299F470E5633B202022E055DAF - - fileRef - A5B0B158C327BC36C2CFBA2530F074DF - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - D78FC91F85C97871DC9341A80AA95734 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - Pods-PINRemoteImage-PINRemoteImage-prefix.pch - sourceTree - <group> - - D7F393F3B25273B25D31481A121E9ED8 - - fileRef - 5FCD43DDE3D1A4CB4ABCE3E2BED940C8 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - D8144AB855026636396D296E4B308EA0 - - buildConfigurations - - B59399B9C8E67345C36E3E3EF690EB20 - 57729752DF42EC63EC46736ED7815518 - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - D8D3C221D462BA09E4A62BCB567F8A2C - - isa - PBXFileReference - lastKnownFileType - wrapper.framework - name - CoreServices.framework - path - Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/CoreServices.framework - sourceTree - DEVELOPER_DIR - - D99F4EFAF0C186086E786CFED30E0C6F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINAlternateRepresentationProvider.m - sourceTree - <group> - - DA4CF6AA8B86FF316C8F7C8F75309261 - - fileRef - C3A5CAB3F244F79545963B8402DDF8B6 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - DBA70329D901B7929BA1974AB74F1B44 - - fileRef - 4D0FFF465E08FE5A6EB685BC9F8FAF8B - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - DBF11981941E346187E50DBB1A68DCDB - - fileRef - 64CCF9B39C036472FD45826766B43A00 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - DC138E767ECE3B27EC24765A880388E8 - - buildActionMask - 2147483647 - files - - 84C028B26FFAE771F8B6D1B5A00C2DBC - 666EDF8661607BD5221D356F15F67A0F - 3FFD642A2341AAD51DEB64FBD4D0D7D7 - 200CB87EBBE012F887B8C8483913709A - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - DC19EA7EA64F59F5FB99EB76948468E9 - - buildActionMask - 2147483647 - files - - B6564E50493B9364185CADB6FFAE36D7 - 1689FCB88270D158620C53BA268699CB - 15100ED6594D5097A6D6D6940738FC62 - D5115B9528A623B800518F63A206E612 - DBF11981941E346187E50DBB1A68DCDB - 0245A25FD1BCE61C6AAC2D5D5369778A - 3503A8952DA4B2B222976B1DEDC77EF7 - A8AA31557BBEE3F8DDA6FC3A01A54B38 - 292F6C517A2D16180FD0DCCB5DB0ABC0 - 3E3F7624713164015E677B04C47497C2 - E5740F3B61C38C9451598B1B785D4D16 - 415D4C495C85355B34899D807E5C6382 - 0ADD8CAB9B5DD81C3744ED80567A2720 - E33545CB3179F2A033B7B6EF8666CFE6 - 30A57367464071D62B010563275C7AC2 - AFFCB16B0E467933CBE72A5EA381D7E9 - 37F2AC2A4B62F2AA6E3C2EBBED317ADF - 7F16A4084715FAAC9B03AFC5A76D74CD - 72100D09068058FEEABFF54C4D58A63A - F7B958A45578551BE79E94729407AA2A - 33AB437571CE87D26286011AAC6A292C - 07AC71A306E2361EB7056CB52E1C64D4 - CCDB7A6A179B0B5DDF44680164507489 - 80DF14201CA36FAD2A469B1E688BA203 - 3AFC2945B51028C7AF4AB9AFA9648AC1 - 142141837F3BD87ACA4E9F0E4D15F0C1 - E6D9DE7704FC1D97F1DBF0D3DF480EC9 - 07C66BB8FECEFB73FCCEF16D1352A2ED - 71B8A507DA55CEE6074547BB00C43BE5 - CB0EADB499F60ADFC6562BCD874AA754 - AD821974AF5498048A69BC2524B1C934 - E671530DA226AAC0D76BCD124F47C208 - F2B4DD2CC7F837D9E5D58CA31D89123D - 6568C3274167E0B57D5E3EC72D7D34D5 - 66880E9B24C85F202A6E769B01093860 - C92DCB80B0FC006C667B87961227D082 - D24938702361B9ACFC70E266D21969A8 - CD16137FAE7112695FCF50336C1B4969 - 6B3D7DA068A8632A7BD386E9FF300B65 - 283FC0870DBA2C4A604649C455E72E99 - A4359EE8B8DF3244B9F72346B6E74882 - 5C67529B29D47327FFC4508DA0C5A5A5 - 9A175DD5D5380EF9C411AF10AD80B028 - 1BAA920F0E8A1454E03685EDFF2E1770 - F3C7CEBB7EB1723A978F8786E4235369 - 95242733D78E04F586EAA570FEE21A1C - C570B2B6167DFDD45562DA234ABC96B0 - EBDDBEEF58A1ACDB45CCF0F5DD6685BC - 39D6E1353F8D8C8254631EBF0E76EA77 - 148B34B78792C8E391C04CF60FEE3548 - C17B863A1D95FC023F190C0ECC59B452 - 14173E0FE6815CC17FBE637039CC32C7 - 3A5F4F7C3333C6FE0E2EE6C882B8773F - 56A79F15482DF888A6281346936408B7 - 75FF73D66A4FA5E783791D59AFB39A2F - B30114FA69E34B23835898CE1D216DD0 - 4A89E1A4DE7F6463F8D966DAE4ABA260 - 42A036B7F9799D066AF14D99C9D45C4C - 72E7B0ECB6D569AC70B080E21F1587A6 - 5055130A4D4926609736E8141AC2D2C0 - 10742D6291172C33709408885657444B - 1611E06E42073AE481AEEAFBACD45B76 - E770EF61FBA22D2977435F0740818131 - 9A3F2BCCB510DBB197909E21A9252DDF - 7AD18E9483A7E1DA16781D2974CF2AB3 - B414271F5AD28427640B5CA2DBB478DD - FDC1B6382DAD60CDC90B9656DDFC6BF6 - 96330677DABAA013E46967C3A62E62FE - 45B83322961CD0BEB3EE0C9040E3B540 - 1B2BEA6928EEE8D8E93CF3346B8D4299 - 5674395FB83A4783C842C89AB53A8851 - 90CBD6B77DF1D6E995A51B91A1AAC1A4 - F2E31F4DF94B56B207C86779CBB1F712 - 81571B2373D35793BCE857249C8D61C5 - F31FF5D8415EA5EEF97810F71DFA3C19 - 9384157F74F3E1C89836B61F3376F257 - 21A5C5F154167D4633BFCC27A9B08C4D - F7476375130BE9A7BD00B1957C2A5216 - 1F00426785F865830F7BDC9352060EAE - 515272D2158D188DA1821C2D75FE69D0 - 66B635E1C52712F16AEE410826E9ADA9 - B9FD53A3AE714DA3CCEB98844A97EE83 - C7FD2A26F681C73B3372964FEE50F3F7 - F50CB1BC57D6A80A1D7B8E55FC1C97A9 - 7F8E6C29485F5A930E2C73320C3E3F49 - F02578DE309FA6B5DE284795E2F15095 - 6D8D1E79BCFA8A046565E36701F75BB6 - D6CD40299F470E5633B202022E055DAF - 0530DF53E50F23B58A6F04D802CFA9B0 - 729140BD068361446FC8B24AC931F070 - EDDB27EA7F726B32758270984205B2B4 - 5C4F6DC4014902CE3AC38AD57D76C4F2 - 0811A435BCDE87F3F79D6E331F181DDB - 6FE5842D9003D47BD0F8052831F0A814 - FF8CD4D050C9B15112C81D0BA26D6F16 - F2AE247C472B928CE16DCC29F5EF9FA0 - 4BD43A29167C49AE58CF07672602859E - 7890C9E7CF0C51306C75202785872967 - FCAB324E03CC8A62DFEB5E8AB4A68D67 - AEF9CC15864A4B75B2767B8727A21B42 - 9E081C46E13555389FC66F52A15A2E0E - 27F5A1DB1F55E010CB9B74F53EDB26C9 - 6A5A445AD47D71FE8A79972BB2049092 - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - DC868C27032D99EFCEDEE502267DDDD6 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.script.sh - path - Pods-PINRemoteImage-resources.sh - sourceTree - <group> - - DD0FFD7DBB393EC196E68670E37B5C6B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - Pods-PINRemoteImage-dummy.m - sourceTree - <group> - - DD536A9B503A891F93DF8FA8A44713FA - - fileRef - 90955DB5237070F75E50577201574746 - isa - PBXBuildFile - - DD6765CC87F0C7941BB608F3D360F10D - - includeInIndex - 1 - isa - PBXFileReference - name - lossless_enc_sse41.c - path - src/dsp/lossless_enc_sse41.c - sourceTree - <group> - - E04359202406E39276DDCAD3D120BC31 - - includeInIndex - 1 - isa - PBXFileReference - name - alpha_processing.c - path - src/dsp/alpha_processing.c - sourceTree - <group> - - E12712BE03D1C9D1E867561CB4675EAD - - includeInIndex - 1 - isa - PBXFileReference - name - syntax.c - path - src/enc/syntax.c - sourceTree - <group> - - E19FC2F669F3E194D36D2B9410024FF8 - - includeInIndex - 1 - isa - PBXFileReference - name - picture.c - path - src/enc/picture.c - sourceTree - <group> - - E1B9C97C5E571C31D4FC6C18C2BDA277 - - includeInIndex - 1 - isa - PBXFileReference - name - rescaler_mips_dsp_r2.c - path - src/dsp/rescaler_mips_dsp_r2.c - sourceTree - <group> - - E23D77FB173FD3685203C9258A188DB4 - - fileRef - 65347844787A41A2F0E848FA51EA725B - isa - PBXBuildFile - - E33545CB3179F2A033B7B6EF8666CFE6 - - fileRef - 760F5F3A3AB54AE54C0DC631B6613604 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - E353EF26682110F0BB0765C319A49DD5 - - isa - PBXTargetDependency - name - Pods-PINRemoteImage-PINCache - target - 54F27F7B6DBD02B3C1ABB03D547E1C0E - targetProxy - 62A26CD4C293A522500F0ABF37DF55E5 - - E430B4877504F51ABC452BCAF2BDA0AE - - fileRef - 61B27E3DC140D91540D09398E02E7F10 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - E44B88F2DFC6F097A47D503B76D923C5 - - fileRef - 84C1B348CD730F4D14FEC257D6FE97F1 - isa - PBXBuildFile - - E56EFC94FD15573B0B427C984A9AD0A7 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - demux.h - path - src/webp/demux.h - sourceTree - <group> - - E5740F3B61C38C9451598B1B785D4D16 - - fileRef - 629E148921B121B07FD2841596FCFF1F - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - E61017926E4C5B70D20FAB84E278EF7F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - extras.h - path - src/webp/extras.h - sourceTree - <group> - - E671530DA226AAC0D76BCD124F47C208 - - fileRef - CB8FF7C88A18D6F4251F5A40E94A521D - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - E68A8BFCB9208DB7048EDCA39ED67CFE - - includeInIndex - 1 - isa - PBXFileReference - name - dec_neon.c - path - src/dsp/dec_neon.c - sourceTree - <group> - - E6D9DE7704FC1D97F1DBF0D3DF480EC9 - - fileRef - 8D95A8D8B5D14A3D0BDB9236279D887B - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - E759CDA4349301C1E0FC7BC0FC163C08 - - includeInIndex - 1 - isa - PBXFileReference - name - argb_sse2.c - path - src/dsp/argb_sse2.c - sourceTree - <group> - - E770EF61FBA22D2977435F0740818131 - - fileRef - B79AE0FA1860BFFD6B25495007477FC1 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - E823AD90033331573401BDFE6AB93CCB - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINImage+WebP.m - sourceTree - <group> - - E9B0E6AF0B60FB459CC571631506971D - - includeInIndex - 1 - isa - PBXFileReference - name - enc.c - path - src/dsp/enc.c - sourceTree - <group> - - EBDDBEEF58A1ACDB45CCF0F5DD6685BC - - fileRef - 16ADB3861D9A0B9D5C491B35EDA654B3 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - EBFDF03F22BC2CAE9696098C6E8BE8A7 - - fileRef - 0708F88B696773C0A5227B28EC99A7F0 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - EDDB27EA7F726B32758270984205B2B4 - - fileRef - 6A4AC7853CC796EC2A019069268460A6 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - EDF461A029F5B6A0F026DA7412A6FA1F - - children - - D6001D25EE732A2486755053A0152248 - D99F4EFAF0C186086E786CFED30E0C6F - 4A5DDEDDF9AA6176B724AA21B3313574 - B76335CB2C89D0B241162674CBE8F1BA - CE23D02F1951FFEAF4B5F2E704388A45 - 365B51C8299D8B0817E9BD1BF65C7554 - 34D86B8A97D344C21F8D1354F4C71F2D - 77A0D1BFA97789A761884AF14BF3ADB9 - A3667E58E4E0A14B361F34D068724745 - 568C04BE2B34B62D1FEC11694B9AAA5D - 3D6C21D96548B9777F46000FCF001A3D - 06655463DC05231AB09E5A504061E353 - B9214326F987BC91CA4A3826C11D186C - 3D0A76433D4385B8BC2AC0D8B1912A8D - 1C62A009925C46A84BFA8DA6A64D96FD - 73E90E16910BA96C9D4B3A48F7549621 - 345C612CA023E9C9DA39708F28B69364 - 315A9C171818CF7B69118BD1D0D92544 - B7D7872C876F23F1729EA5F43344F778 - 3EF73C8C5306EAED6EF86F15C02988BD - B0B935414267CF835EFBFA7548C531AF - F12FF4A476141AE96BFAAB268C6394A0 - AD3D4855D31C5F1CECDAF2E4CE0EE5A1 - D4873E4B41B03CCDFE653D3980CC089D - 585541D65FCD3FEC57B9AF5CD13CD1E5 - 056A17AF5E589399B5500549916C964F - AB35BD9A85E83BB1480B2BD1649C5553 - 90955DB5237070F75E50577201574746 - 40E9A9B1442533BB506AA976BCAC68FA - 65C1015DB7B57B40D7043E24B6B8E1F7 - 20D0C1BEE694CD1889B151DBE94C9C1D - 06F1FE6224968BE662E1143ADCF5D40F - 0759125F9B0A8FF4A7C7670AF9181C11 - 730679DEA1B4A13DA684CD48E0AEC007 - - isa - PBXGroup - name - Classes - path - Classes - sourceTree - <group> - - EDFE857B881B90821CD9E77B38B977FD - - includeInIndex - 1 - isa - PBXFileReference - name - anim_decode.c - path - src/demux/anim_decode.c - sourceTree - <group> - - EE90AE58540DEA4276BE7CC8A1A49E50 - - includeInIndex - 1 - isa - PBXFileReference - name - demux.c - path - src/demux/demux.c - sourceTree - <group> - - EF16E58EF853CCF02EB26BAEA03B6BC5 - - fileRef - 20D0C1BEE694CD1889B151DBE94C9C1D - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - EF618625D10D27B3DB3B8DCBDDD55FE7 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - color_cache.h - path - src/utils/color_cache.h - sourceTree - <group> - - F02578DE309FA6B5DE284795E2F15095 - - fileRef - 4CBF09EEE3843F3754524ED18E977730 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - F0587A92A6FDCDF7ED4C0AC2B6B7069D - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - name - libPods-PINRemoteImage-PINRemoteImage.a - path - libPods-PINRemoteImage-PINRemoteImage.a - sourceTree - BUILT_PRODUCTS_DIR - - F0DC3B2438333A7853152F7DBB224042 - - fileRef - 3D0A76433D4385B8BC2AC0D8B1912A8D - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - F12FF4A476141AE96BFAAB268C6394A0 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINRemoteImageManagerResult.m - sourceTree - <group> - - F2401DC8EFDF9742AC607CF3D4A8495B - - fileRef - A25EBA406D3B2465CBC05C69370DED9A - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - F2AE247C472B928CE16DCC29F5EF9FA0 - - fileRef - 18E7BAAB882A7AA471B649263701AF42 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - F2B4DD2CC7F837D9E5D58CA31D89123D - - fileRef - EE90AE58540DEA4276BE7CC8A1A49E50 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - F2E31F4DF94B56B207C86779CBB1F712 - - fileRef - 162953E4F39E1792379941D154D1E1A4 - isa - PBXBuildFile - - F31FF5D8415EA5EEF97810F71DFA3C19 - - fileRef - 1AF7E5AACEEA90E9CBCD24A9DBC5F4EB - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - F35E649D9FD9EBA610E53054A48244CE - - includeInIndex - 1 - isa - PBXFileReference - name - lossless_mips_dsp_r2.c - path - src/dsp/lossless_mips_dsp_r2.c - sourceTree - <group> - - F3C7CEBB7EB1723A978F8786E4235369 - - fileRef - 96156DB8E0F9F37D62C22E540877ED46 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - F41B26725DCA5F24A5BCA3587600B423 - - children - - C6514CE37D3EE0EDBA0A0552B2AE8363 - 048828C11D392FA5A13E60F5223762F8 - F5609D1F6A761F296346723B5846872C - 20271290BC3C4EBFEB6BF3413E48855F - A84DF9F56CB36717DCB0A0EF063267EA - 6E6950DAD97D897CF352F2FFD0BE0B41 - 6F07C068332B44FDB57D1A4FF1D0A5EA - 45729E38DC1140595790D766491BB172 - - isa - PBXGroup - name - PINCache - path - PINCache - sourceTree - <group> - - F50CB1BC57D6A80A1D7B8E55FC1C97A9 - - fileRef - 6AB11F192A4CE1ECFEDD75974F80BB56 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - F5609D1F6A761F296346723B5846872C - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - PINCache.m - path - PINCache/PINCache.m - sourceTree - <group> - - F59034D1B37659011B534E6DEF7D7F84 - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - name - libPods-PINRemoteImage.a - path - libPods-PINRemoteImage.a - sourceTree - BUILT_PRODUCTS_DIR - - F6614F7200CA7CFCF8A9CFF1BF80C7E7 - - fileRef - B68CF83B26F463D56D967719370C49E9 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - F705D8BD26F0207F68990F2810C94492 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - NSData+ImageDetectors.h - sourceTree - <group> - - F7476375130BE9A7BD00B1957C2A5216 - - fileRef - FE4520AC8ED67F5B8E54F3689C81F27C - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - F788EF1E261A9857273D8789C00F4DD4 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - quant_levels_dec.h - path - src/utils/quant_levels_dec.h - sourceTree - <group> - - F7B958A45578551BE79E94729407AA2A - - fileRef - 32EACBCF545009BAB3CD5773D01FFD94 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - F7F76726829C94536E7CCE02BB5F6273 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - bit_writer.h - path - src/utils/bit_writer.h - sourceTree - <group> - - F807ECB0D11647282E3BD0CC2C16EF5B - - containerPortal - D41D8CD98F00B204E9800998ECF8427E - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - 4295C947AD69FD429F982D216B4F4B0D - remoteInfo - Pods-PINRemoteImage-libwebp - - F98A6FFF26897B0AC819DD3DB6669AB8 - - fileRef - 568C04BE2B34B62D1FEC11694B9AAA5D - isa - PBXBuildFile - - FA65978174B2A98AC19D5C33ED661FD0 - - fileRef - B3C75AB1813564741ECF7F3D537569CA - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - FB5D8FEC1F4B45AC4E1F9F824E753A4C - - includeInIndex - 1 - isa - PBXFileReference - name - cost_sse2.c - path - src/dsp/cost_sse2.c - sourceTree - <group> - - FCAB324E03CC8A62DFEB5E8AB4A68D67 - - fileRef - 0F917410D4EB6590E946692D160A4F5E - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - FDC1B6382DAD60CDC90B9656DDFC6BF6 - - fileRef - 88F99FCFD19A6FD6BC17C3D0D8A2766C - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - FE4520AC8ED67F5B8E54F3689C81F27C - - includeInIndex - 1 - isa - PBXFileReference - name - random.c - path - src/utils/random.c - sourceTree - <group> - - FE5EFC80D9471840D669FC3BFC2F289C - - includeInIndex - 1 - isa - PBXFileReference - name - enc_neon.c - path - src/dsp/enc_neon.c - sourceTree - <group> - - FF102A6E7977A3906DD7C91B6D7DEDA0 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text - path - Pods-PINRemoteImage-acknowledgements.markdown - sourceTree - <group> - - FF392DA14E62ADEDDAE707FCA4028EC9 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - rescaler.h - path - src/utils/rescaler.h - sourceTree - <group> - - FF8CD4D050C9B15112C81D0BA26D6F16 - - fileRef - 46F39C5FC2377469E26ED318F9AB6661 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -D_THREAD_SAFE -fno-objc-arc - - - FFDCC5F0ABFA0D7E719A1109B8BF09E9 - - includeInIndex - 1 - isa - PBXFileReference - name - filter.c - path - src/enc/filter.c - sourceTree - <group> - - - rootObject - D41D8CD98F00B204E9800998ECF8427E - - diff --git a/Example-Mac/Pods/Pods.xcodeproj/xcshareddata/xcschemes/PINRemoteImage.xcscheme b/Example-Mac/Pods/Pods.xcodeproj/xcshareddata/xcschemes/PINRemoteImage.xcscheme deleted file mode 100644 index 5e404280..00000000 --- a/Example-Mac/Pods/Pods.xcodeproj/xcshareddata/xcschemes/PINRemoteImage.xcscheme +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Example-Mac/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-PINRemoteImage-PINRemoteImage.xcscheme b/Example-Mac/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-PINRemoteImage-PINRemoteImage.xcscheme deleted file mode 100644 index fd73ec2c..00000000 --- a/Example-Mac/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-PINRemoteImage-PINRemoteImage.xcscheme +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-PINCache/Pods-PINRemoteImage-PINCache-dummy.m b/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-PINCache/Pods-PINRemoteImage-PINCache-dummy.m deleted file mode 100644 index 794b3f80..00000000 --- a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-PINCache/Pods-PINRemoteImage-PINCache-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Pods_PINRemoteImage_PINCache : NSObject -@end -@implementation PodsDummy_Pods_PINRemoteImage_PINCache -@end diff --git a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-PINCache/Pods-PINRemoteImage-PINCache-prefix.pch b/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-PINCache/Pods-PINRemoteImage-PINCache-prefix.pch deleted file mode 100644 index 248b60d7..00000000 --- a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-PINCache/Pods-PINRemoteImage-PINCache-prefix.pch +++ /dev/null @@ -1,7 +0,0 @@ -#ifdef __OBJC__ -#import -#endif - -#ifndef TARGET_OS_WATCH - #define TARGET_OS_WATCH 0 -#endif diff --git a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-PINCache/Pods-PINRemoteImage-PINCache.xcconfig b/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-PINCache/Pods-PINRemoteImage-PINCache.xcconfig deleted file mode 100644 index 659d1e75..00000000 --- a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-PINCache/Pods-PINRemoteImage-PINCache.xcconfig +++ /dev/null @@ -1,5 +0,0 @@ -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/PINCache" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/PINCache" "${PODS_ROOT}/Headers/Public/PINRemoteImage" "${PODS_ROOT}/Headers/Public/libwebp" -OTHER_LDFLAGS = -framework "Foundation" -weak_framework "AppKit" -PODS_ROOT = ${SRCROOT} -SKIP_INSTALL = YES \ No newline at end of file diff --git a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-PINRemoteImage/Pods-PINRemoteImage-PINRemoteImage-dummy.m b/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-PINRemoteImage/Pods-PINRemoteImage-PINRemoteImage-dummy.m deleted file mode 100644 index e66eb23f..00000000 --- a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-PINRemoteImage/Pods-PINRemoteImage-PINRemoteImage-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Pods_PINRemoteImage_PINRemoteImage : NSObject -@end -@implementation PodsDummy_Pods_PINRemoteImage_PINRemoteImage -@end diff --git a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-PINRemoteImage/Pods-PINRemoteImage-PINRemoteImage-prefix.pch b/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-PINRemoteImage/Pods-PINRemoteImage-PINRemoteImage-prefix.pch deleted file mode 100644 index b9c163b4..00000000 --- a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-PINRemoteImage/Pods-PINRemoteImage-PINRemoteImage-prefix.pch +++ /dev/null @@ -1,4 +0,0 @@ -#ifdef __OBJC__ -#import -#endif - diff --git a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-PINRemoteImage/Pods-PINRemoteImage-PINRemoteImage.xcconfig b/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-PINRemoteImage/Pods-PINRemoteImage-PINRemoteImage.xcconfig deleted file mode 100644 index cb2eb3a2..00000000 --- a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-PINRemoteImage/Pods-PINRemoteImage-PINRemoteImage.xcconfig +++ /dev/null @@ -1,5 +0,0 @@ -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PIN_WEBP=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/PINRemoteImage" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/PINCache" "${PODS_ROOT}/Headers/Public/PINRemoteImage" "${PODS_ROOT}/Headers/Public/libwebp" -OTHER_LDFLAGS = -framework "Accelerate" -framework "Cocoa" -framework "CoreServices" -framework "ImageIO" -PODS_ROOT = ${SRCROOT} -SKIP_INSTALL = YES \ No newline at end of file diff --git a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-libwebp/Pods-PINRemoteImage-libwebp-dummy.m b/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-libwebp/Pods-PINRemoteImage-libwebp-dummy.m deleted file mode 100644 index d538ff2f..00000000 --- a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-libwebp/Pods-PINRemoteImage-libwebp-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Pods_PINRemoteImage_libwebp : NSObject -@end -@implementation PodsDummy_Pods_PINRemoteImage_libwebp -@end diff --git a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-libwebp/Pods-PINRemoteImage-libwebp-prefix.pch b/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-libwebp/Pods-PINRemoteImage-libwebp-prefix.pch deleted file mode 100644 index b9c163b4..00000000 --- a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-libwebp/Pods-PINRemoteImage-libwebp-prefix.pch +++ /dev/null @@ -1,4 +0,0 @@ -#ifdef __OBJC__ -#import -#endif - diff --git a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-libwebp/Pods-PINRemoteImage-libwebp.xcconfig b/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-libwebp/Pods-PINRemoteImage-libwebp.xcconfig deleted file mode 100644 index de2e8a27..00000000 --- a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage-libwebp/Pods-PINRemoteImage-libwebp.xcconfig +++ /dev/null @@ -1,4 +0,0 @@ -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/libwebp" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/PINCache" "${PODS_ROOT}/Headers/Public/PINRemoteImage" "${PODS_ROOT}/Headers/Public/libwebp" -PODS_ROOT = ${SRCROOT} -SKIP_INSTALL = YES \ No newline at end of file diff --git a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-acknowledgements.markdown b/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-acknowledgements.markdown deleted file mode 100644 index bf5c389a..00000000 --- a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-acknowledgements.markdown +++ /dev/null @@ -1,259 +0,0 @@ -# Acknowledgements -This application makes use of the following third party libraries: - -## PINCache - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [2013] [Tumblr, Inc.] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - -## PINRemoteImage - -Copyright (c) 2015-2016 Pinterest, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - -## libwebp - -Copyright (c) 2010, Google Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of Google nor the names of its contributors may - be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -Generated by CocoaPods - http://cocoapods.org diff --git a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-acknowledgements.plist b/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-acknowledgements.plist deleted file mode 100644 index a40969c5..00000000 --- a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-acknowledgements.plist +++ /dev/null @@ -1,297 +0,0 @@ - - - - - PreferenceSpecifiers - - - FooterText - This application makes use of the following third party libraries: - Title - Acknowledgements - Type - PSGroupSpecifier - - - FooterText - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [2013] [Tumblr, Inc.] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - Title - PINCache - Type - PSGroupSpecifier - - - FooterText - Copyright (c) 2015-2016 Pinterest, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - Title - PINRemoteImage - Type - PSGroupSpecifier - - - FooterText - Copyright (c) 2010, Google Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of Google nor the names of its contributors may - be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - Title - libwebp - Type - PSGroupSpecifier - - - FooterText - Generated by CocoaPods - http://cocoapods.org - Title - - Type - PSGroupSpecifier - - - StringsTable - Acknowledgements - Title - Acknowledgements - - diff --git a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-dummy.m b/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-dummy.m deleted file mode 100644 index f17cca3c..00000000 --- a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Pods_PINRemoteImage : NSObject -@end -@implementation PodsDummy_Pods_PINRemoteImage -@end diff --git a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-frameworks.sh b/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-frameworks.sh deleted file mode 100755 index 6f763443..00000000 --- a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-frameworks.sh +++ /dev/null @@ -1,84 +0,0 @@ -#!/bin/sh -set -e - -echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" -mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - -SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" - -install_framework() -{ - if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then - local source="${BUILT_PRODUCTS_DIR}/$1" - elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then - local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" - elif [ -r "$1" ]; then - local source="$1" - fi - - local destination="${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - - if [ -L "${source}" ]; then - echo "Symlinked..." - source="$(readlink "${source}")" - fi - - # use filter instead of exclude so missing patterns dont' throw errors - echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" - rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" - - local basename - basename="$(basename -s .framework "$1")" - binary="${destination}/${basename}.framework/${basename}" - if ! [ -r "$binary" ]; then - binary="${destination}/${basename}" - fi - - # Strip invalid architectures so "fat" simulator / device frameworks work on device - if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then - strip_invalid_archs "$binary" - fi - - # Resign the code if required by the build settings to avoid unstable apps - code_sign_if_enabled "${destination}/$(basename "$1")" - - # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. - if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then - local swift_runtime_libs - swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) - for lib in $swift_runtime_libs; do - echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" - rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" - code_sign_if_enabled "${destination}/${lib}" - done - fi -} - -# Signs a framework with the provided identity -code_sign_if_enabled() { - if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then - # Use the current code_sign_identitiy - echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" - echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements \"$1\"" - /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements "$1" - fi -} - -# Strip invalid architectures -strip_invalid_archs() { - binary="$1" - # Get architectures for current file - archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" - stripped="" - for arch in $archs; do - if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then - # Strip non-valid architectures in-place - lipo -remove "$arch" -output "$binary" "$binary" || exit 1 - stripped="$stripped $arch" - fi - done - if [[ "$stripped" ]]; then - echo "Stripped $binary of architectures:$stripped" - fi -} - diff --git a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-resources.sh b/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-resources.sh deleted file mode 100755 index 16774fb4..00000000 --- a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-resources.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/bin/sh -set -e - -mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" - -RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt -> "$RESOURCES_TO_COPY" - -XCASSET_FILES=() - -realpath() { - DIRECTORY="$(cd "${1%/*}" && pwd)" - FILENAME="${1##*/}" - echo "$DIRECTORY/$FILENAME" -} - -install_resource() -{ - case $1 in - *.storyboard) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}" - ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" - ;; - *.xib) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}" - ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" - ;; - *.framework) - echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - ;; - *.xcdatamodel) - echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\"" - xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom" - ;; - *.xcdatamodeld) - echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\"" - xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd" - ;; - *.xcmappingmodel) - echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\"" - xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm" - ;; - *.xcassets) - ABSOLUTE_XCASSET_FILE=$(realpath "${PODS_ROOT}/$1") - XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") - ;; - /*) - echo "$1" - echo "$1" >> "$RESOURCES_TO_COPY" - ;; - *) - echo "${PODS_ROOT}/$1" - echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY" - ;; - esac -} - -mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then - mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" - rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -fi -rm -f "$RESOURCES_TO_COPY" - -if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] -then - case "${TARGETED_DEVICE_FAMILY}" in - 1,2) - TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" - ;; - 1) - TARGET_DEVICE_ARGS="--target-device iphone" - ;; - 2) - TARGET_DEVICE_ARGS="--target-device ipad" - ;; - *) - TARGET_DEVICE_ARGS="--target-device mac" - ;; - esac - - # Find all other xcassets (this unfortunately includes those of path pods and other targets). - OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) - while read line; do - if [[ $line != "`realpath $PODS_ROOT`*" ]]; then - XCASSET_FILES+=("$line") - fi - done <<<"$OTHER_XCASSETS" - - printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -fi diff --git a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage.debug.xcconfig b/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage.debug.xcconfig deleted file mode 100644 index 6c1ae9cb..00000000 --- a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage.debug.xcconfig +++ /dev/null @@ -1,5 +0,0 @@ -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PIN_WEBP=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/PINCache" "${PODS_ROOT}/Headers/Public/PINRemoteImage" "${PODS_ROOT}/Headers/Public/libwebp" -OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/PINCache" -isystem "${PODS_ROOT}/Headers/Public/PINRemoteImage" -isystem "${PODS_ROOT}/Headers/Public/libwebp" -OTHER_LDFLAGS = $(inherited) -ObjC -l"Pods-PINRemoteImage-PINCache" -l"Pods-PINRemoteImage-PINRemoteImage" -l"Pods-PINRemoteImage-libwebp" -framework "Accelerate" -framework "Cocoa" -framework "CoreServices" -framework "Foundation" -framework "ImageIO" -weak_framework "AppKit" -PODS_ROOT = ${SRCROOT}/Pods \ No newline at end of file diff --git a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage.release.xcconfig b/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage.release.xcconfig deleted file mode 100644 index 6c1ae9cb..00000000 --- a/Example-Mac/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage.release.xcconfig +++ /dev/null @@ -1,5 +0,0 @@ -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PIN_WEBP=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/PINCache" "${PODS_ROOT}/Headers/Public/PINRemoteImage" "${PODS_ROOT}/Headers/Public/libwebp" -OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/PINCache" -isystem "${PODS_ROOT}/Headers/Public/PINRemoteImage" -isystem "${PODS_ROOT}/Headers/Public/libwebp" -OTHER_LDFLAGS = $(inherited) -ObjC -l"Pods-PINRemoteImage-PINCache" -l"Pods-PINRemoteImage-PINRemoteImage" -l"Pods-PINRemoteImage-libwebp" -framework "Accelerate" -framework "Cocoa" -framework "CoreServices" -framework "Foundation" -framework "ImageIO" -weak_framework "AppKit" -PODS_ROOT = ${SRCROOT}/Pods \ No newline at end of file diff --git a/Example-Mac/Pods/libwebp/COPYING b/Example-Mac/Pods/libwebp/COPYING deleted file mode 100644 index 7a6f9954..00000000 --- a/Example-Mac/Pods/libwebp/COPYING +++ /dev/null @@ -1,30 +0,0 @@ -Copyright (c) 2010, Google Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of Google nor the names of its contributors may - be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/Example-Mac/Pods/libwebp/README b/Example-Mac/Pods/libwebp/README deleted file mode 100644 index 381b9270..00000000 --- a/Example-Mac/Pods/libwebp/README +++ /dev/null @@ -1,649 +0,0 @@ - __ __ ____ ____ ____ - / \\/ \/ _ \/ _ )/ _ \ - \ / __/ _ \ __/ - \__\__/\____/\_____/__/ ____ ___ - / _/ / \ \ / _ \/ _/ - / \_/ / / \ \ __/ \__ - \____/____/\_____/_____/____/v0.5.0 - -Description: -============ - -WebP codec: library to encode and decode images in WebP format. This package -contains the library that can be used in other programs to add WebP support, -as well as the command line tools 'cwebp' and 'dwebp'. - -See http://developers.google.com/speed/webp - -The latest source tree is available at -https://chromium.googlesource.com/webm/libwebp - -It is released under the same license as the WebM project. -See http://www.webmproject.org/license/software/ or the -file "COPYING" file for details. An additional intellectual -property rights grant can be found in the file PATENTS. - -Building: -========= - -Windows build: --------------- - -By running: - - nmake /f Makefile.vc CFG=release-static RTLIBCFG=static OBJDIR=output - -the directory output\release-static\(x64|x86)\bin will contain the tools -cwebp.exe and dwebp.exe. The directory output\release-static\(x64|x86)\lib will -contain the libwebp static library. -The target architecture (x86/x64) is detected by Makefile.vc from the Visual -Studio compiler (cl.exe) available in the system path. - -Unix build using makefile.unix: -------------------------------- - -On platforms with GNU tools installed (gcc and make), running - - make -f makefile.unix - -will build the binaries examples/cwebp and examples/dwebp, along -with the static library src/libwebp.a. No system-wide installation -is supplied, as this is a simple alternative to the full installation -system based on the autoconf tools (see below). -Please refer to makefile.unix for additional details and customizations. - -Using autoconf tools: ---------------------- -Prerequisites: -A compiler (e.g., gcc), make, autoconf, automake, libtool. -On a Debian-like system the following should install everything you need for a -minimal build: -$ sudo apt-get install gcc make autoconf automake libtool - -When building from git sources, you will need to run autogen.sh to generate the -configure script. - -./configure -make -make install - -should be all you need to have the following files - -/usr/local/include/webp/decode.h -/usr/local/include/webp/encode.h -/usr/local/include/webp/types.h -/usr/local/lib/libwebp.* -/usr/local/bin/cwebp -/usr/local/bin/dwebp - -installed. - -Note: A decode-only library, libwebpdecoder, is available using the -'--enable-libwebpdecoder' flag. The encode library is built separately and can -be installed independently using a minor modification in the corresponding -Makefile.am configure files (see comments there). See './configure --help' for -more options. - -SWIG bindings: --------------- - -To generate language bindings from swig/libwebp.swig at least swig-1.3 -(http://www.swig.org) is required. - -Currently the following functions are mapped: -Decode: - WebPGetDecoderVersion - WebPGetInfo - WebPDecodeRGBA - WebPDecodeARGB - WebPDecodeBGRA - WebPDecodeBGR - WebPDecodeRGB - -Encode: - WebPGetEncoderVersion - WebPEncodeRGBA - WebPEncodeBGRA - WebPEncodeRGB - WebPEncodeBGR - WebPEncodeLosslessRGBA - WebPEncodeLosslessBGRA - WebPEncodeLosslessRGB - WebPEncodeLosslessBGR - -See swig/README for more detailed build instructions. - -Java bindings: - -To build the swig-generated JNI wrapper code at least JDK-1.5 (or equivalent) -is necessary for enum support. The output is intended to be a shared object / -DLL that can be loaded via System.loadLibrary("webp_jni"). - -Python bindings: - -To build the swig-generated Python extension code at least Python 2.6 is -required. Python < 2.6 may build with some minor changes to libwebp.swig or the -generated code, but is untested. - -Encoding tool: -============== - -The examples/ directory contains tools for encoding (cwebp) and -decoding (dwebp) images. - -The easiest use should look like: - cwebp input.png -q 80 -o output.webp -which will convert the input file to a WebP file using a quality factor of 80 -on a 0->100 scale (0 being the lowest quality, 100 being the best. Default -value is 75). -You might want to try the -lossless flag too, which will compress the source -(in RGBA format) without any loss. The -q quality parameter will in this case -control the amount of processing time spent trying to make the output file as -small as possible. - -A longer list of options is available using the -longhelp command line flag: - -> cwebp -longhelp -Usage: - cwebp [-preset <...>] [options] in_file [-o out_file] - -If input size (-s) for an image is not specified, it is -assumed to be a PNG, JPEG, TIFF or WebP file. - -Options: - -h / -help ............ short help - -H / -longhelp ........ long help - -q ............. quality factor (0:small..100:big) - -alpha_q ......... transparency-compression quality (0..100) - -preset ....... preset setting, one of: - default, photo, picture, - drawing, icon, text - -preset must come first, as it overwrites other parameters - -z ............... activates lossless preset with given - level in [0:fast, ..., 9:slowest] - - -m ............... compression method (0=fast, 6=slowest) - -segments ........ number of segments to use (1..4) - -size ............ target size (in bytes) - -psnr .......... target PSNR (in dB. typically: 42) - - -s ......... input size (width x height) for YUV - -sns ............. spatial noise shaping (0:off, 100:max) - -f ............... filter strength (0=off..100) - -sharpness ....... filter sharpness (0:most .. 7:least sharp) - -strong ................ use strong filter instead of simple (default) - -nostrong .............. use simple filter instead of strong - -partition_limit . limit quality to fit the 512k limit on - the first partition (0=no degradation ... 100=full) - -pass ............ analysis pass number (1..10) - -crop .. crop picture with the given rectangle - -resize ........ resize picture (after any cropping) - -mt .................... use multi-threading if available - -low_memory ............ reduce memory usage (slower encoding) - -map ............. print map of extra info - -print_psnr ............ prints averaged PSNR distortion - -print_ssim ............ prints averaged SSIM distortion - -print_lsim ............ prints local-similarity distortion - -d .......... dump the compressed output (PGM file) - -alpha_method .... transparency-compression method (0..1) - -alpha_filter . predictive filtering for alpha plane, - one of: none, fast (default) or best - -exact ................. preserve RGB values in transparent area - -blend_alpha ..... blend colors against background color - expressed as RGB values written in - hexadecimal, e.g. 0xc0e0d0 for red=0xc0 - green=0xe0 and blue=0xd0 - -noalpha ............... discard any transparency information - -lossless .............. encode image losslessly - -near_lossless ... use near-lossless image - preprocessing (0..100=off) - -hint ......... specify image characteristics hint, - one of: photo, picture or graph - - -metadata ..... comma separated list of metadata to - copy from the input to the output if present. - Valid values: all, none (default), exif, icc, xmp - - -short ................. condense printed message - -quiet ................. don't print anything - -version ............... print version number and exit - -noasm ................. disable all assembly optimizations - -v ..................... verbose, e.g. print encoding/decoding times - -progress .............. report encoding progress - -Experimental Options: - -jpeg_like ............. roughly match expected JPEG size - -af .................... auto-adjust filter strength - -pre ............. pre-processing filter - -The main options you might want to try in order to further tune the -visual quality are: - -preset - -sns - -f - -m - -Namely: - * 'preset' will set up a default encoding configuration targeting a - particular type of input. It should appear first in the list of options, - so that subsequent options can take effect on top of this preset. - Default value is 'default'. - * 'sns' will progressively turn on (when going from 0 to 100) some additional - visual optimizations (like: segmentation map re-enforcement). This option - will balance the bit allocation differently. It tries to take bits from the - "easy" parts of the picture and use them in the "difficult" ones instead. - Usually, raising the sns value (at fixed -q value) leads to larger files, - but with better quality. - Typical value is around '75'. - * 'f' option directly links to the filtering strength used by the codec's - in-loop processing. The higher the value, the smoother the - highly-compressed area will look. This is particularly useful when aiming - at very small files. Typical values are around 20-30. Note that using the - option -strong/-nostrong will change the type of filtering. Use "-f 0" to - turn filtering off. - * 'm' controls the trade-off between encoding speed and quality. Default is 4. - You can try -m 5 or -m 6 to explore more (time-consuming) encoding - possibilities. A lower value will result in faster encoding at the expense - of quality. - -Decoding tool: -============== - -There is a decoding sample in examples/dwebp.c which will take -a .webp file and decode it to a PNG image file (amongst other formats). -This is simply to demonstrate the use of the API. You can verify the -file test.webp decodes to exactly the same as test_ref.ppm by using: - - cd examples - ./dwebp test.webp -ppm -o test.ppm - diff test.ppm test_ref.ppm - -The full list of options is available using -h: - -> dwebp -h -Usage: dwebp in_file [options] [-o out_file] - -Decodes the WebP image file to PNG format [Default] -Use following options to convert into alternate image formats: - -pam ......... save the raw RGBA samples as a color PAM - -ppm ......... save the raw RGB samples as a color PPM - -bmp ......... save as uncompressed BMP format - -tiff ........ save as uncompressed TIFF format - -pgm ......... save the raw YUV samples as a grayscale PGM - file with IMC4 layout - -yuv ......... save the raw YUV samples in flat layout - - Other options are: - -version .... print version number and exit - -nofancy ..... don't use the fancy YUV420 upscaler - -nofilter .... disable in-loop filtering - -nodither .... disable dithering - -dither .. dithering strength (in 0..100) - -alpha_dither use alpha-plane dithering if needed - -mt .......... use multi-threading - -crop ... crop output with the given rectangle - -resize ......... scale the output (*after* any cropping) - -flip ........ flip the output vertically - -alpha ....... only save the alpha plane - -incremental . use incremental decoding (useful for tests) - -h ....... this help message - -v ....... verbose (e.g. print encoding/decoding times) - -quiet ....... quiet mode, don't print anything - -noasm ....... disable all assembly optimizations - -Visualization tool: -=================== - -There's a little self-serve visualization tool called 'vwebp' under the -examples/ directory. It uses OpenGL to open a simple drawing window and show -a decoded WebP file. It's not yet integrated in the automake build system, but -you can try to manually compile it using the recommendations below. - -Usage: vwebp in_file [options] - -Decodes the WebP image file and visualize it using OpenGL -Options are: - -version .... print version number and exit - -noicc ....... don't use the icc profile if present - -nofancy ..... don't use the fancy YUV420 upscaler - -nofilter .... disable in-loop filtering - -dither dithering strength (0..100), default=50 - -noalphadither disable alpha plane dithering - -mt .......... use multi-threading - -info ........ print info - -h ....... this help message - -Keyboard shortcuts: - 'c' ................ toggle use of color profile - 'i' ................ overlay file information - 'q' / 'Q' / ESC .... quit - -Building: ---------- - -Prerequisites: -1) OpenGL & OpenGL Utility Toolkit (GLUT) - Linux: - $ sudo apt-get install freeglut3-dev mesa-common-dev - Mac + XCode: - - These libraries should be available in the OpenGL / GLUT frameworks. - Windows: - http://freeglut.sourceforge.net/index.php#download - -2) (Optional) qcms (Quick Color Management System) - i. Download qcms from Mozilla / Chromium: - http://hg.mozilla.org/mozilla-central/file/0e7639e3bdfb/gfx/qcms - http://src.chromium.org/viewvc/chrome/trunk/src/third_party/qcms - ii. Build and archive the source files as libqcms.a / qcms.lib - iii. Update makefile.unix / Makefile.vc - a) Define WEBP_HAVE_QCMS - b) Update include / library paths to reference the qcms directory. - -Build using makefile.unix / Makefile.vc: -$ make -f makefile.unix examples/vwebp -> nmake /f Makefile.vc CFG=release-static \ - ../obj/x64/release-static/bin/vwebp.exe - -Animated GIF conversion: -======================== -Animated GIF files can be converted to WebP files with animation using the -gif2webp utility available under examples/. The files can then be viewed using -vwebp. - -Usage: - gif2webp [options] gif_file -o webp_file -Options: - -h / -help ............ this help - -lossy ................. encode image using lossy compression - -mixed ................. for each frame in the image, pick lossy - or lossless compression heuristically - -q ............. quality factor (0:small..100:big) - -m ............... compression method (0=fast, 6=slowest) - -min_size .............. minimize output size (default:off) - lossless compression by default; can be - combined with -q, -m, -lossy or -mixed - options - -kmin ............ min distance between key frames - -kmax ............ max distance between key frames - -f ............... filter strength (0=off..100) - -metadata ..... comma separated list of metadata to - copy from the input to the output if present - Valid values: all, none, icc, xmp (default) - -mt .................... use multi-threading if available - - -version ............... print version number and exit - -v ..................... verbose - -quiet ................. don't print anything - -Building: ---------- -With the libgif development files installed, gif2webp can be built using -makefile.unix: -$ make -f makefile.unix examples/gif2webp - -or using autoconf: -$ ./configure --enable-everything -$ make - -Comparison of animated images: -============================== -Test utility anim_diff under examples/ can be used to compare two animated -images (each can be GIF or WebP). - -Usage: anim_diff [options] - -Options: - -dump_frames dump decoded frames in PAM format - -min_psnr ... minimum per-frame PSNR - -raw_comparison ..... if this flag is not used, RGB is - premultiplied before comparison - -Building: ---------- -With the libgif development files and a C++ compiler installed, anim_diff can -be built using makefile.unix: -$ make -f makefile.unix examples/anim_diff - -or using autoconf: -$ ./configure --enable-everything -$ make - -Encoding API: -============= - -The main encoding functions are available in the header src/webp/encode.h -The ready-to-use ones are: -size_t WebPEncodeRGB(const uint8_t* rgb, int width, int height, int stride, - float quality_factor, uint8_t** output); -size_t WebPEncodeBGR(const uint8_t* bgr, int width, int height, int stride, - float quality_factor, uint8_t** output); -size_t WebPEncodeRGBA(const uint8_t* rgba, int width, int height, int stride, - float quality_factor, uint8_t** output); -size_t WebPEncodeBGRA(const uint8_t* bgra, int width, int height, int stride, - float quality_factor, uint8_t** output); - -They will convert raw RGB samples to a WebP data. The only control supplied -is the quality factor. - -There are some variants for using the lossless format: - -size_t WebPEncodeLosslessRGB(const uint8_t* rgb, int width, int height, - int stride, uint8_t** output); -size_t WebPEncodeLosslessBGR(const uint8_t* bgr, int width, int height, - int stride, uint8_t** output); -size_t WebPEncodeLosslessRGBA(const uint8_t* rgba, int width, int height, - int stride, uint8_t** output); -size_t WebPEncodeLosslessBGRA(const uint8_t* bgra, int width, int height, - int stride, uint8_t** output); - -Of course in this case, no quality factor is needed since the compression -occurs without loss of the input values, at the expense of larger output sizes. - -Advanced encoding API: ----------------------- - -A more advanced API is based on the WebPConfig and WebPPicture structures. - -WebPConfig contains the encoding settings and is not tied to a particular -picture. -WebPPicture contains input data, on which some WebPConfig will be used for -compression. -The encoding flow looks like: - --------------------------------------- BEGIN PSEUDO EXAMPLE - -#include - - // Setup a config, starting form a preset and tuning some additional - // parameters - WebPConfig config; - if (!WebPConfigPreset(&config, WEBP_PRESET_PHOTO, quality_factor)) - return 0; // version error - } - // ... additional tuning - config.sns_strength = 90; - config.filter_sharpness = 6; - config_error = WebPValidateConfig(&config); // not mandatory, but useful - - // Setup the input data - WebPPicture pic; - if (!WebPPictureInit(&pic)) { - return 0; // version error - } - pic.width = width; - pic.height = height; - // allocated picture of dimension width x height - if (!WebPPictureAllocate(&pic)) { - return 0; // memory error - } - // at this point, 'pic' has been initialized as a container, - // and can receive the Y/U/V samples. - // Alternatively, one could use ready-made import functions like - // WebPPictureImportRGB(), which will take care of memory allocation. - // In any case, past this point, one will have to call - // WebPPictureFree(&pic) to reclaim memory. - - // Set up a byte-output write method. WebPMemoryWriter, for instance. - WebPMemoryWriter wrt; - WebPMemoryWriterInit(&wrt); // initialize 'wrt' - - pic.writer = MyFileWriter; - pic.custom_ptr = my_opaque_structure_to_make_MyFileWriter_work; - - // Compress! - int ok = WebPEncode(&config, &pic); // ok = 0 => error occurred! - WebPPictureFree(&pic); // must be called independently of the 'ok' result. - - // output data should have been handled by the writer at that point. - // -> compressed data is the memory buffer described by wrt.mem / wrt.size - - // deallocate the memory used by compressed data - WebPMemoryWriterClear(&wrt); - --------------------------------------- END PSEUDO EXAMPLE - -Decoding API: -============= - -This is mainly just one function to call: - -#include "webp/decode.h" -uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size, - int* width, int* height); - -Please have a look at the file src/webp/decode.h for the details. -There are variants for decoding in BGR/RGBA/ARGB/BGRA order, along with -decoding to raw Y'CbCr samples. One can also decode the image directly into a -pre-allocated buffer. - -To detect a WebP file and gather the picture's dimensions, the function: - int WebPGetInfo(const uint8_t* data, size_t data_size, - int* width, int* height); -is supplied. No decoding is involved when using it. - -Incremental decoding API: -========================= - -In the case when data is being progressively transmitted, pictures can still -be incrementally decoded using a slightly more complicated API. Decoder state -is stored into an instance of the WebPIDecoder object. This object can be -created with the purpose of decoding either RGB or Y'CbCr samples. -For instance: - - WebPDecBuffer buffer; - WebPInitDecBuffer(&buffer); - buffer.colorspace = MODE_BGR; - ... - WebPIDecoder* idec = WebPINewDecoder(&buffer); - -As data is made progressively available, this incremental-decoder object -can be used to decode the picture further. There are two (mutually exclusive) -ways to pass freshly arrived data: - -either by appending the fresh bytes: - - WebPIAppend(idec, fresh_data, size_of_fresh_data); - -or by just mentioning the new size of the transmitted data: - - WebPIUpdate(idec, buffer, size_of_transmitted_buffer); - -Note that 'buffer' can be modified between each call to WebPIUpdate, in -particular when the buffer is resized to accommodate larger data. - -These functions will return the decoding status: either VP8_STATUS_SUSPENDED if -decoding is not finished yet or VP8_STATUS_OK when decoding is done. Any other -status is an error condition. - -The 'idec' object must always be released (even upon an error condition) by -calling: WebPDelete(idec). - -To retrieve partially decoded picture samples, one must use the corresponding -method: WebPIDecGetRGB or WebPIDecGetYUVA. -It will return the last displayable pixel row. - -Lastly, note that decoding can also be performed into a pre-allocated pixel -buffer. This buffer must be passed when creating a WebPIDecoder, calling -WebPINewRGB() or WebPINewYUVA(). - -Please have a look at the src/webp/decode.h header for further details. - -Advanced Decoding API: -====================== - -WebP decoding supports an advanced API which provides on-the-fly cropping and -rescaling, something of great usefulness on memory-constrained environments like -mobile phones. Basically, the memory usage will scale with the output's size, -not the input's, when one only needs a quick preview or a zoomed in portion of -an otherwise too-large picture. Some CPU can be saved too, incidentally. - --------------------------------------- BEGIN PSEUDO EXAMPLE - // A) Init a configuration object - WebPDecoderConfig config; - CHECK(WebPInitDecoderConfig(&config)); - - // B) optional: retrieve the bitstream's features. - CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK); - - // C) Adjust 'config' options, if needed - config.options.no_fancy_upsampling = 1; - config.options.use_scaling = 1; - config.options.scaled_width = scaledWidth(); - config.options.scaled_height = scaledHeight(); - // etc. - - // D) Specify 'config' output options for specifying output colorspace. - // Optionally the external image decode buffer can also be specified. - config.output.colorspace = MODE_BGRA; - // Optionally, the config.output can be pointed to an external buffer as - // well for decoding the image. This externally supplied memory buffer - // should be big enough to store the decoded picture. - config.output.u.RGBA.rgba = (uint8_t*) memory_buffer; - config.output.u.RGBA.stride = scanline_stride; - config.output.u.RGBA.size = total_size_of_the_memory_buffer; - config.output.is_external_memory = 1; - - // E) Decode the WebP image. There are two variants w.r.t decoding image. - // The first one (E.1) decodes the full image and the second one (E.2) is - // used to incrementally decode the image using small input buffers. - // Any one of these steps can be used to decode the WebP image. - - // E.1) Decode full image. - CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK); - - // E.2) Decode image incrementally. - WebPIDecoder* const idec = WebPIDecode(NULL, NULL, &config); - CHECK(idec != NULL); - while (bytes_remaining > 0) { - VP8StatusCode status = WebPIAppend(idec, input, bytes_read); - if (status == VP8_STATUS_OK || status == VP8_STATUS_SUSPENDED) { - bytes_remaining -= bytes_read; - } else { - break; - } - } - WebPIDelete(idec); - - // F) Decoded image is now in config.output (and config.output.u.RGBA). - // It can be saved, displayed or otherwise processed. - - // G) Reclaim memory allocated in config's object. It's safe to call - // this function even if the memory is external and wasn't allocated - // by WebPDecode(). - WebPFreeDecBuffer(&config.output); - --------------------------------------- END PSEUDO EXAMPLE - -Bugs: -===== - -Please report all bugs to our issue tracker: - https://bugs.chromium.org/p/webp -Patches welcome! See this page to get started: - http://www.webmproject.org/code/contribute/submitting-patches/ - -Discuss: -======== - -Email: webp-discuss@webmproject.org -Web: http://groups.google.com/a/webmproject.org/group/webp-discuss diff --git a/Example-Mac/Pods/libwebp/README.mux b/Example-Mac/Pods/libwebp/README.mux deleted file mode 100644 index aa077e8d..00000000 --- a/Example-Mac/Pods/libwebp/README.mux +++ /dev/null @@ -1,210 +0,0 @@ - __ __ ____ ____ ____ __ __ _ __ __ - / \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\ - \ / __/ _ \ __/ / / (_/ /__ - \__\__/\_____/_____/__/ \__//_/\_____/__/___/v0.3.0 - - -Description: -============ - -WebPMux: set of two libraries 'Mux' and 'Demux' for creation, extraction and -manipulation of an extended format WebP file, which can have features like -color profile, metadata and animation. Reference command-line tools 'webpmux' -and 'vwebp' as well as the WebP container specification -'doc/webp-container-spec.txt' are also provided in this package. - -WebP Mux tool: -============== - -The examples/ directory contains a tool (webpmux) for manipulating WebP -files. The webpmux tool can be used to create an extended format WebP file and -also to extract or strip relevant data from such a file. - -A list of options is available using the -help command line flag: - -> webpmux -help -Usage: webpmux -get GET_OPTIONS INPUT -o OUTPUT - webpmux -set SET_OPTIONS INPUT -o OUTPUT - webpmux -strip STRIP_OPTIONS INPUT -o OUTPUT - webpmux -frame FRAME_OPTIONS [-frame...] [-loop LOOP_COUNT] - [-bgcolor BACKGROUND_COLOR] -o OUTPUT - webpmux -info INPUT - webpmux [-h|-help] - webpmux -version - -GET_OPTIONS: - Extract relevant data: - icc get ICC profile - exif get EXIF metadata - xmp get XMP metadata - frame n get nth frame - -SET_OPTIONS: - Set color profile/metadata: - icc file.icc set ICC profile - exif file.exif set EXIF metadata - xmp file.xmp set XMP metadata - where: 'file.icc' contains the ICC profile to be set, - 'file.exif' contains the EXIF metadata to be set - 'file.xmp' contains the XMP metadata to be set - -STRIP_OPTIONS: - Strip color profile/metadata: - icc strip ICC profile - exif strip EXIF metadata - xmp strip XMP metadata - -FRAME_OPTIONS(i): - Create animation: - file_i +di+[xi+yi[+mi[bi]]] - where: 'file_i' is the i'th animation frame (WebP format), - 'di' is the pause duration before next frame, - 'xi','yi' specify the image offset for this frame, - 'mi' is the dispose method for this frame (0 or 1), - 'bi' is the blending method for this frame (+b or -b) - -LOOP_COUNT: - Number of times to repeat the animation. - Valid range is 0 to 65535 [Default: 0 (infinite)]. - -BACKGROUND_COLOR: - Background color of the canvas. - A,R,G,B - where: 'A', 'R', 'G' and 'B' are integers in the range 0 to 255 specifying - the Alpha, Red, Green and Blue component values respectively - [Default: 255,255,255,255] - -INPUT & OUTPUT are in WebP format. - -Note: The nature of EXIF, XMP and ICC data is not checked and is assumed to be -valid. - -Visualization tool: -=================== - -The examples/ directory also contains a tool (vwebp) for viewing WebP files. -It decodes the image and visualizes it using OpenGL. See the libwebp README -for details on building and running this program. - -Mux API: -======== -The Mux API contains methods for adding data to and reading data from WebP -files. This API currently supports XMP/EXIF metadata, ICC profile and animation. -Other features may be added in subsequent releases. - -Example#1 (pseudo code): Creating a WebPMux object with image data, color -profile and XMP metadata. - - int copy_data = 0; - WebPMux* mux = WebPMuxNew(); - // ... (Prepare image data). - WebPMuxSetImage(mux, &image, copy_data); - // ... (Prepare ICC profile data). - WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data); - // ... (Prepare XMP metadata). - WebPMuxSetChunk(mux, "XMP ", &xmp, copy_data); - // Get data from mux in WebP RIFF format. - WebPMuxAssemble(mux, &output_data); - WebPMuxDelete(mux); - // ... (Consume output_data; e.g. write output_data.bytes to file). - WebPDataClear(&output_data); - - -Example#2 (pseudo code): Get image and color profile data from a WebP file. - - int copy_data = 0; - // ... (Read data from file). - WebPMux* mux = WebPMuxCreate(&data, copy_data); - WebPMuxGetFrame(mux, 1, &image); - // ... (Consume image; e.g. call WebPDecode() to decode the data). - WebPMuxGetChunk(mux, "ICCP", &icc_profile); - // ... (Consume icc_profile). - WebPMuxDelete(mux); - free(data); - - -For a detailed Mux API reference, please refer to the header file -(src/webp/mux.h). - -Demux API: -========== -The Demux API enables extraction of images and extended format data from -WebP files. This API currently supports reading of XMP/EXIF metadata, ICC -profile and animated images. Other features may be added in subsequent -releases. - -Code example: Demuxing WebP data to extract all the frames, ICC profile -and EXIF/XMP metadata. - - WebPDemuxer* demux = WebPDemux(&webp_data); - uint32_t width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH); - uint32_t height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT); - // ... (Get information about the features present in the WebP file). - uint32_t flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS); - - // ... (Iterate over all frames). - WebPIterator iter; - if (WebPDemuxGetFrame(demux, 1, &iter)) { - do { - // ... (Consume 'iter'; e.g. Decode 'iter.fragment' with WebPDecode(), - // ... and get other frame properties like width, height, offsets etc. - // ... see 'struct WebPIterator' below for more info). - } while (WebPDemuxNextFrame(&iter)); - WebPDemuxReleaseIterator(&iter); - } - - // ... (Extract metadata). - WebPChunkIterator chunk_iter; - if (flags & ICCP_FLAG) WebPDemuxGetChunk(demux, "ICCP", 1, &chunk_iter); - // ... (Consume the ICC profile in 'chunk_iter.chunk'). - WebPDemuxReleaseChunkIterator(&chunk_iter); - if (flags & EXIF_FLAG) WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter); - // ... (Consume the EXIF metadata in 'chunk_iter.chunk'). - WebPDemuxReleaseChunkIterator(&chunk_iter); - if (flags & XMP_FLAG) WebPDemuxGetChunk(demux, "XMP ", 1, &chunk_iter); - // ... (Consume the XMP metadata in 'chunk_iter.chunk'). - WebPDemuxReleaseChunkIterator(&chunk_iter); - WebPDemuxDelete(demux); - - -For a detailed Demux API reference, please refer to the header file -(src/webp/demux.h). - -AnimEncoder API: -================ -The AnimEncoder API can be used to create animated WebP images. - -Code example: - - WebPAnimEncoderOptions enc_options; - WebPAnimEncoderOptionsInit(&enc_options); - // ... (Tune 'enc_options' as needed). - WebPAnimEncoder* enc = WebPAnimEncoderNew(width, height, &enc_options); - while() { - WebPConfig config; - WebPConfigInit(&config); - // ... (Tune 'config' as needed). - WebPAnimEncoderAdd(enc, frame, duration, &config); - } - WebPAnimEncoderAssemble(enc, webp_data); - WebPAnimEncoderDelete(enc); - // ... (Write the 'webp_data' to a file, or re-mux it further). - - -For a detailed AnimEncoder API reference, please refer to the header file -(src/webp/mux.h). - - -Bugs: -===== - -Please report all bugs to our issue tracker: - https://bugs.chromium.org/p/webp -Patches welcome! See this page to get started: - http://www.webmproject.org/code/contribute/submitting-patches/ - -Discuss: -======== - -Email: webp-discuss@webmproject.org -Web: http://groups.google.com/a/webmproject.org/group/webp-discuss diff --git a/Example-Mac/Pods/libwebp/src/dec/alpha.c b/Example-Mac/Pods/libwebp/src/dec/alpha.c deleted file mode 100644 index 52216fc4..00000000 --- a/Example-Mac/Pods/libwebp/src/dec/alpha.c +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Alpha-plane decompression. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include "./alphai.h" -#include "./vp8i.h" -#include "./vp8li.h" -#include "../dsp/dsp.h" -#include "../utils/quant_levels_dec.h" -#include "../utils/utils.h" -#include "../webp/format_constants.h" - -//------------------------------------------------------------------------------ -// ALPHDecoder object. - -ALPHDecoder* ALPHNew(void) { - ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); - return dec; -} - -void ALPHDelete(ALPHDecoder* const dec) { - if (dec != NULL) { - VP8LDelete(dec->vp8l_dec_); - dec->vp8l_dec_ = NULL; - WebPSafeFree(dec); - } -} - -//------------------------------------------------------------------------------ -// Decoding. - -// Initialize alpha decoding by parsing the alpha header and decoding the image -// header for alpha data stored using lossless compression. -// Returns false in case of error in alpha header (data too short, invalid -// compression method or filter, error in lossless header data etc). -static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data, - size_t data_size, int width, int height, uint8_t* output) { - int ok = 0; - const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN; - const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN; - int rsrv; - - assert(width > 0 && height > 0); - assert(data != NULL && output != NULL); - - dec->width_ = width; - dec->height_ = height; - - if (data_size <= ALPHA_HEADER_LEN) { - return 0; - } - - dec->method_ = (data[0] >> 0) & 0x03; - dec->filter_ = (data[0] >> 2) & 0x03; - dec->pre_processing_ = (data[0] >> 4) & 0x03; - rsrv = (data[0] >> 6) & 0x03; - if (dec->method_ < ALPHA_NO_COMPRESSION || - dec->method_ > ALPHA_LOSSLESS_COMPRESSION || - dec->filter_ >= WEBP_FILTER_LAST || - dec->pre_processing_ > ALPHA_PREPROCESSED_LEVELS || - rsrv != 0) { - return 0; - } - - if (dec->method_ == ALPHA_NO_COMPRESSION) { - const size_t alpha_decoded_size = dec->width_ * dec->height_; - ok = (alpha_data_size >= alpha_decoded_size); - } else { - assert(dec->method_ == ALPHA_LOSSLESS_COMPRESSION); - ok = VP8LDecodeAlphaHeader(dec, alpha_data, alpha_data_size, output); - } - VP8FiltersInit(); - return ok; -} - -// Decodes, unfilters and dequantizes *at least* 'num_rows' rows of alpha -// starting from row number 'row'. It assumes that rows up to (row - 1) have -// already been decoded. -// Returns false in case of bitstream error. -static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) { - ALPHDecoder* const alph_dec = dec->alph_dec_; - const int width = alph_dec->width_; - const int height = alph_dec->height_; - WebPUnfilterFunc unfilter_func = WebPUnfilters[alph_dec->filter_]; - uint8_t* const output = dec->alpha_plane_; - if (alph_dec->method_ == ALPHA_NO_COMPRESSION) { - const size_t offset = row * width; - const size_t num_pixels = num_rows * width; - assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN + offset + num_pixels); - memcpy(dec->alpha_plane_ + offset, - dec->alpha_data_ + ALPHA_HEADER_LEN + offset, num_pixels); - } else { // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION - assert(alph_dec->vp8l_dec_ != NULL); - if (!VP8LDecodeAlphaImageStream(alph_dec, row + num_rows)) { - return 0; - } - } - - if (unfilter_func != NULL) { - unfilter_func(width, height, width, row, num_rows, output); - } - - if (row + num_rows == dec->pic_hdr_.height_) { - dec->is_alpha_decoded_ = 1; - } - return 1; -} - -//------------------------------------------------------------------------------ -// Main entry point. - -const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, - int row, int num_rows) { - const int width = dec->pic_hdr_.width_; - const int height = dec->pic_hdr_.height_; - - if (row < 0 || num_rows <= 0 || row + num_rows > height) { - return NULL; // sanity check. - } - - if (row == 0) { - // Initialize decoding. - assert(dec->alpha_plane_ != NULL); - dec->alph_dec_ = ALPHNew(); - if (dec->alph_dec_ == NULL) return NULL; - if (!ALPHInit(dec->alph_dec_, dec->alpha_data_, dec->alpha_data_size_, - width, height, dec->alpha_plane_)) { - ALPHDelete(dec->alph_dec_); - dec->alph_dec_ = NULL; - return NULL; - } - // if we allowed use of alpha dithering, check whether it's needed at all - if (dec->alph_dec_->pre_processing_ != ALPHA_PREPROCESSED_LEVELS) { - dec->alpha_dithering_ = 0; // disable dithering - } else { - num_rows = height; // decode everything in one pass - } - } - - if (!dec->is_alpha_decoded_) { - int ok = 0; - assert(dec->alph_dec_ != NULL); - ok = ALPHDecode(dec, row, num_rows); - if (ok && dec->alpha_dithering_ > 0) { - ok = WebPDequantizeLevels(dec->alpha_plane_, width, height, - dec->alpha_dithering_); - } - if (!ok || dec->is_alpha_decoded_) { - ALPHDelete(dec->alph_dec_); - dec->alph_dec_ = NULL; - } - if (!ok) return NULL; // Error. - } - - // Return a pointer to the current decoded row. - return dec->alpha_plane_ + row * width; -} diff --git a/Example-Mac/Pods/libwebp/src/dec/alphai.h b/Example-Mac/Pods/libwebp/src/dec/alphai.h deleted file mode 100644 index 5fa230ca..00000000 --- a/Example-Mac/Pods/libwebp/src/dec/alphai.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Alpha decoder: internal header. -// -// Author: Urvang (urvang@google.com) - -#ifndef WEBP_DEC_ALPHAI_H_ -#define WEBP_DEC_ALPHAI_H_ - -#include "./webpi.h" -#include "../utils/filters.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct VP8LDecoder; // Defined in dec/vp8li.h. - -typedef struct ALPHDecoder ALPHDecoder; -struct ALPHDecoder { - int width_; - int height_; - int method_; - WEBP_FILTER_TYPE filter_; - int pre_processing_; - struct VP8LDecoder* vp8l_dec_; - VP8Io io_; - int use_8b_decode; // Although alpha channel requires only 1 byte per - // pixel, sometimes VP8LDecoder may need to allocate - // 4 bytes per pixel internally during decode. -}; - -//------------------------------------------------------------------------------ -// internal functions. Not public. - -// Allocates a new alpha decoder instance. -ALPHDecoder* ALPHNew(void); - -// Clears and deallocates an alpha decoder instance. -void ALPHDelete(ALPHDecoder* const dec); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_DEC_ALPHAI_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/dec/buffer.c b/Example-Mac/Pods/libwebp/src/dec/buffer.c deleted file mode 100644 index 9ed2b3fe..00000000 --- a/Example-Mac/Pods/libwebp/src/dec/buffer.c +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Everything about WebPDecBuffer -// -// Author: Skal (pascal.massimino@gmail.com) - -#include - -#include "./vp8i.h" -#include "./webpi.h" -#include "../utils/utils.h" - -//------------------------------------------------------------------------------ -// WebPDecBuffer - -// Number of bytes per pixel for the different color-spaces. -static const int kModeBpp[MODE_LAST] = { - 3, 4, 3, 4, 4, 2, 2, - 4, 4, 4, 2, // pre-multiplied modes - 1, 1 }; - -// Check that webp_csp_mode is within the bounds of WEBP_CSP_MODE. -// Convert to an integer to handle both the unsigned/signed enum cases -// without the need for casting to remove type limit warnings. -static int IsValidColorspace(int webp_csp_mode) { - return (webp_csp_mode >= MODE_RGB && webp_csp_mode < MODE_LAST); -} - -// strictly speaking, the very last (or first, if flipped) row -// doesn't require padding. -#define MIN_BUFFER_SIZE(WIDTH, HEIGHT, STRIDE) \ - (uint64_t)(STRIDE) * ((HEIGHT) - 1) + (WIDTH) - -static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) { - int ok = 1; - const WEBP_CSP_MODE mode = buffer->colorspace; - const int width = buffer->width; - const int height = buffer->height; - if (!IsValidColorspace(mode)) { - ok = 0; - } else if (!WebPIsRGBMode(mode)) { // YUV checks - const WebPYUVABuffer* const buf = &buffer->u.YUVA; - const int uv_width = (width + 1) / 2; - const int uv_height = (height + 1) / 2; - const int y_stride = abs(buf->y_stride); - const int u_stride = abs(buf->u_stride); - const int v_stride = abs(buf->v_stride); - const int a_stride = abs(buf->a_stride); - const uint64_t y_size = MIN_BUFFER_SIZE(width, height, y_stride); - const uint64_t u_size = MIN_BUFFER_SIZE(uv_width, uv_height, u_stride); - const uint64_t v_size = MIN_BUFFER_SIZE(uv_width, uv_height, v_stride); - const uint64_t a_size = MIN_BUFFER_SIZE(width, height, a_stride); - ok &= (y_size <= buf->y_size); - ok &= (u_size <= buf->u_size); - ok &= (v_size <= buf->v_size); - ok &= (y_stride >= width); - ok &= (u_stride >= uv_width); - ok &= (v_stride >= uv_width); - ok &= (buf->y != NULL); - ok &= (buf->u != NULL); - ok &= (buf->v != NULL); - if (mode == MODE_YUVA) { - ok &= (a_stride >= width); - ok &= (a_size <= buf->a_size); - ok &= (buf->a != NULL); - } - } else { // RGB checks - const WebPRGBABuffer* const buf = &buffer->u.RGBA; - const int stride = abs(buf->stride); - const uint64_t size = MIN_BUFFER_SIZE(width, height, stride); - ok &= (size <= buf->size); - ok &= (stride >= width * kModeBpp[mode]); - ok &= (buf->rgba != NULL); - } - return ok ? VP8_STATUS_OK : VP8_STATUS_INVALID_PARAM; -} -#undef MIN_BUFFER_SIZE - -static VP8StatusCode AllocateBuffer(WebPDecBuffer* const buffer) { - const int w = buffer->width; - const int h = buffer->height; - const WEBP_CSP_MODE mode = buffer->colorspace; - - if (w <= 0 || h <= 0 || !IsValidColorspace(mode)) { - return VP8_STATUS_INVALID_PARAM; - } - - if (!buffer->is_external_memory && buffer->private_memory == NULL) { - uint8_t* output; - int uv_stride = 0, a_stride = 0; - uint64_t uv_size = 0, a_size = 0, total_size; - // We need memory and it hasn't been allocated yet. - // => initialize output buffer, now that dimensions are known. - const int stride = w * kModeBpp[mode]; - const uint64_t size = (uint64_t)stride * h; - - if (!WebPIsRGBMode(mode)) { - uv_stride = (w + 1) / 2; - uv_size = (uint64_t)uv_stride * ((h + 1) / 2); - if (mode == MODE_YUVA) { - a_stride = w; - a_size = (uint64_t)a_stride * h; - } - } - total_size = size + 2 * uv_size + a_size; - - // Security/sanity checks - output = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*output)); - if (output == NULL) { - return VP8_STATUS_OUT_OF_MEMORY; - } - buffer->private_memory = output; - - if (!WebPIsRGBMode(mode)) { // YUVA initialization - WebPYUVABuffer* const buf = &buffer->u.YUVA; - buf->y = output; - buf->y_stride = stride; - buf->y_size = (size_t)size; - buf->u = output + size; - buf->u_stride = uv_stride; - buf->u_size = (size_t)uv_size; - buf->v = output + size + uv_size; - buf->v_stride = uv_stride; - buf->v_size = (size_t)uv_size; - if (mode == MODE_YUVA) { - buf->a = output + size + 2 * uv_size; - } - buf->a_size = (size_t)a_size; - buf->a_stride = a_stride; - } else { // RGBA initialization - WebPRGBABuffer* const buf = &buffer->u.RGBA; - buf->rgba = output; - buf->stride = stride; - buf->size = (size_t)size; - } - } - return CheckDecBuffer(buffer); -} - -VP8StatusCode WebPFlipBuffer(WebPDecBuffer* const buffer) { - if (buffer == NULL) { - return VP8_STATUS_INVALID_PARAM; - } - if (WebPIsRGBMode(buffer->colorspace)) { - WebPRGBABuffer* const buf = &buffer->u.RGBA; - buf->rgba += (buffer->height - 1) * buf->stride; - buf->stride = -buf->stride; - } else { - WebPYUVABuffer* const buf = &buffer->u.YUVA; - const int H = buffer->height; - buf->y += (H - 1) * buf->y_stride; - buf->y_stride = -buf->y_stride; - buf->u += ((H - 1) >> 1) * buf->u_stride; - buf->u_stride = -buf->u_stride; - buf->v += ((H - 1) >> 1) * buf->v_stride; - buf->v_stride = -buf->v_stride; - if (buf->a != NULL) { - buf->a += (H - 1) * buf->a_stride; - buf->a_stride = -buf->a_stride; - } - } - return VP8_STATUS_OK; -} - -VP8StatusCode WebPAllocateDecBuffer(int w, int h, - const WebPDecoderOptions* const options, - WebPDecBuffer* const out) { - VP8StatusCode status; - if (out == NULL || w <= 0 || h <= 0) { - return VP8_STATUS_INVALID_PARAM; - } - if (options != NULL) { // First, apply options if there is any. - if (options->use_cropping) { - const int cw = options->crop_width; - const int ch = options->crop_height; - const int x = options->crop_left & ~1; - const int y = options->crop_top & ~1; - if (x < 0 || y < 0 || cw <= 0 || ch <= 0 || x + cw > w || y + ch > h) { - return VP8_STATUS_INVALID_PARAM; // out of frame boundary. - } - w = cw; - h = ch; - } - if (options->use_scaling) { - int scaled_width = options->scaled_width; - int scaled_height = options->scaled_height; - if (!WebPRescalerGetScaledDimensions( - w, h, &scaled_width, &scaled_height)) { - return VP8_STATUS_INVALID_PARAM; - } - w = scaled_width; - h = scaled_height; - } - } - out->width = w; - out->height = h; - - // Then, allocate buffer for real. - status = AllocateBuffer(out); - if (status != VP8_STATUS_OK) return status; - - // Use the stride trick if vertical flip is needed. - if (options != NULL && options->flip) { - status = WebPFlipBuffer(out); - } - return status; -} - -//------------------------------------------------------------------------------ -// constructors / destructors - -int WebPInitDecBufferInternal(WebPDecBuffer* buffer, int version) { - if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { - return 0; // version mismatch - } - if (buffer == NULL) return 0; - memset(buffer, 0, sizeof(*buffer)); - return 1; -} - -void WebPFreeDecBuffer(WebPDecBuffer* buffer) { - if (buffer != NULL) { - if (!buffer->is_external_memory) { - WebPSafeFree(buffer->private_memory); - } - buffer->private_memory = NULL; - } -} - -void WebPCopyDecBuffer(const WebPDecBuffer* const src, - WebPDecBuffer* const dst) { - if (src != NULL && dst != NULL) { - *dst = *src; - if (src->private_memory != NULL) { - dst->is_external_memory = 1; // dst buffer doesn't own the memory. - dst->private_memory = NULL; - } - } -} - -// Copy and transfer ownership from src to dst (beware of parameter order!) -void WebPGrabDecBuffer(WebPDecBuffer* const src, WebPDecBuffer* const dst) { - if (src != NULL && dst != NULL) { - *dst = *src; - if (src->private_memory != NULL) { - src->is_external_memory = 1; // src relinquishes ownership - src->private_memory = NULL; - } - } -} - -//------------------------------------------------------------------------------ - diff --git a/Example-Mac/Pods/libwebp/src/dec/common.h b/Example-Mac/Pods/libwebp/src/dec/common.h deleted file mode 100644 index 6961e224..00000000 --- a/Example-Mac/Pods/libwebp/src/dec/common.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Definitions and macros common to encoding and decoding -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_DEC_COMMON_H_ -#define WEBP_DEC_COMMON_H_ - -// intra prediction modes -enum { B_DC_PRED = 0, // 4x4 modes - B_TM_PRED = 1, - B_VE_PRED = 2, - B_HE_PRED = 3, - B_RD_PRED = 4, - B_VR_PRED = 5, - B_LD_PRED = 6, - B_VL_PRED = 7, - B_HD_PRED = 8, - B_HU_PRED = 9, - NUM_BMODES = B_HU_PRED + 1 - B_DC_PRED, // = 10 - - // Luma16 or UV modes - DC_PRED = B_DC_PRED, V_PRED = B_VE_PRED, - H_PRED = B_HE_PRED, TM_PRED = B_TM_PRED, - B_PRED = NUM_BMODES, // refined I4x4 mode - NUM_PRED_MODES = 4, - - // special modes - B_DC_PRED_NOTOP = 4, - B_DC_PRED_NOLEFT = 5, - B_DC_PRED_NOTOPLEFT = 6, - NUM_B_DC_MODES = 7 }; - -enum { MB_FEATURE_TREE_PROBS = 3, - NUM_MB_SEGMENTS = 4, - NUM_REF_LF_DELTAS = 4, - NUM_MODE_LF_DELTAS = 4, // I4x4, ZERO, *, SPLIT - MAX_NUM_PARTITIONS = 8, - // Probabilities - NUM_TYPES = 4, // 0: i16-AC, 1: i16-DC, 2:chroma-AC, 3:i4-AC - NUM_BANDS = 8, - NUM_CTX = 3, - NUM_PROBAS = 11 - }; - -#endif // WEBP_DEC_COMMON_H_ diff --git a/Example-Mac/Pods/libwebp/src/dec/decode_vp8.h b/Example-Mac/Pods/libwebp/src/dec/decode_vp8.h deleted file mode 100644 index b9337bbe..00000000 --- a/Example-Mac/Pods/libwebp/src/dec/decode_vp8.h +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Low-level API for VP8 decoder -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_WEBP_DECODE_VP8_H_ -#define WEBP_WEBP_DECODE_VP8_H_ - -#include "../webp/decode.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//------------------------------------------------------------------------------ -// Lower-level API -// -// These functions provide fine-grained control of the decoding process. -// The call flow should resemble: -// -// VP8Io io; -// VP8InitIo(&io); -// io.data = data; -// io.data_size = size; -// /* customize io's functions (setup()/put()/teardown()) if needed. */ -// -// VP8Decoder* dec = VP8New(); -// bool ok = VP8Decode(dec); -// if (!ok) printf("Error: %s\n", VP8StatusMessage(dec)); -// VP8Delete(dec); -// return ok; - -// Input / Output -typedef struct VP8Io VP8Io; -typedef int (*VP8IoPutHook)(const VP8Io* io); -typedef int (*VP8IoSetupHook)(VP8Io* io); -typedef void (*VP8IoTeardownHook)(const VP8Io* io); - -struct VP8Io { - // set by VP8GetHeaders() - int width, height; // picture dimensions, in pixels (invariable). - // These are the original, uncropped dimensions. - // The actual area passed to put() is stored - // in mb_w / mb_h fields. - - // set before calling put() - int mb_y; // position of the current rows (in pixels) - int mb_w; // number of columns in the sample - int mb_h; // number of rows in the sample - const uint8_t* y, *u, *v; // rows to copy (in yuv420 format) - int y_stride; // row stride for luma - int uv_stride; // row stride for chroma - - void* opaque; // user data - - // called when fresh samples are available. Currently, samples are in - // YUV420 format, and can be up to width x 24 in size (depending on the - // in-loop filtering level, e.g.). Should return false in case of error - // or abort request. The actual size of the area to update is mb_w x mb_h - // in size, taking cropping into account. - VP8IoPutHook put; - - // called just before starting to decode the blocks. - // Must return false in case of setup error, true otherwise. If false is - // returned, teardown() will NOT be called. But if the setup succeeded - // and true is returned, then teardown() will always be called afterward. - VP8IoSetupHook setup; - - // Called just after block decoding is finished (or when an error occurred - // during put()). Is NOT called if setup() failed. - VP8IoTeardownHook teardown; - - // this is a recommendation for the user-side yuv->rgb converter. This flag - // is set when calling setup() hook and can be overwritten by it. It then - // can be taken into consideration during the put() method. - int fancy_upsampling; - - // Input buffer. - size_t data_size; - const uint8_t* data; - - // If true, in-loop filtering will not be performed even if present in the - // bitstream. Switching off filtering may speed up decoding at the expense - // of more visible blocking. Note that output will also be non-compliant - // with the VP8 specifications. - int bypass_filtering; - - // Cropping parameters. - int use_cropping; - int crop_left, crop_right, crop_top, crop_bottom; - - // Scaling parameters. - int use_scaling; - int scaled_width, scaled_height; - - // If non NULL, pointer to the alpha data (if present) corresponding to the - // start of the current row (That is: it is pre-offset by mb_y and takes - // cropping into account). - const uint8_t* a; -}; - -// Internal, version-checked, entry point -int VP8InitIoInternal(VP8Io* const, int); - -// Set the custom IO function pointers and user-data. The setter for IO hooks -// should be called before initiating incremental decoding. Returns true if -// WebPIDecoder object is successfully modified, false otherwise. -int WebPISetIOHooks(WebPIDecoder* const idec, - VP8IoPutHook put, - VP8IoSetupHook setup, - VP8IoTeardownHook teardown, - void* user_data); - -// Main decoding object. This is an opaque structure. -typedef struct VP8Decoder VP8Decoder; - -// Create a new decoder object. -VP8Decoder* VP8New(void); - -// Must be called to make sure 'io' is initialized properly. -// Returns false in case of version mismatch. Upon such failure, no other -// decoding function should be called (VP8Decode, VP8GetHeaders, ...) -static WEBP_INLINE int VP8InitIo(VP8Io* const io) { - return VP8InitIoInternal(io, WEBP_DECODER_ABI_VERSION); -} - -// Decode the VP8 frame header. Returns true if ok. -// Note: 'io->data' must be pointing to the start of the VP8 frame header. -int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io); - -// Decode a picture. Will call VP8GetHeaders() if it wasn't done already. -// Returns false in case of error. -int VP8Decode(VP8Decoder* const dec, VP8Io* const io); - -// Return current status of the decoder: -VP8StatusCode VP8Status(VP8Decoder* const dec); - -// return readable string corresponding to the last status. -const char* VP8StatusMessage(VP8Decoder* const dec); - -// Resets the decoder in its initial state, reclaiming memory. -// Not a mandatory call between calls to VP8Decode(). -void VP8Clear(VP8Decoder* const dec); - -// Destroy the decoder object. -void VP8Delete(VP8Decoder* const dec); - -//------------------------------------------------------------------------------ -// Miscellaneous VP8/VP8L bitstream probing functions. - -// Returns true if the next 3 bytes in data contain the VP8 signature. -WEBP_EXTERN(int) VP8CheckSignature(const uint8_t* const data, size_t data_size); - -// Validates the VP8 data-header and retrieves basic header information viz -// width and height. Returns 0 in case of formatting error. *width/*height -// can be passed NULL. -WEBP_EXTERN(int) VP8GetInfo( - const uint8_t* data, - size_t data_size, // data available so far - size_t chunk_size, // total data size expected in the chunk - int* const width, int* const height); - -// Returns true if the next byte(s) in data is a VP8L signature. -WEBP_EXTERN(int) VP8LCheckSignature(const uint8_t* const data, size_t size); - -// Validates the VP8L data-header and retrieves basic header information viz -// width, height and alpha. Returns 0 in case of formatting error. -// width/height/has_alpha can be passed NULL. -WEBP_EXTERN(int) VP8LGetInfo( - const uint8_t* data, size_t data_size, // data available so far - int* const width, int* const height, int* const has_alpha); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_WEBP_DECODE_VP8_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/dec/frame.c b/Example-Mac/Pods/libwebp/src/dec/frame.c deleted file mode 100644 index b882133e..00000000 --- a/Example-Mac/Pods/libwebp/src/dec/frame.c +++ /dev/null @@ -1,822 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Frame-reconstruction function. Memory allocation. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include "./vp8i.h" -#include "../utils/utils.h" - -//------------------------------------------------------------------------------ -// Main reconstruction function. - -static const int kScan[16] = { - 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS, - 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS, - 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS, - 0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS -}; - -static int CheckMode(int mb_x, int mb_y, int mode) { - if (mode == B_DC_PRED) { - if (mb_x == 0) { - return (mb_y == 0) ? B_DC_PRED_NOTOPLEFT : B_DC_PRED_NOLEFT; - } else { - return (mb_y == 0) ? B_DC_PRED_NOTOP : B_DC_PRED; - } - } - return mode; -} - -static void Copy32b(uint8_t* const dst, const uint8_t* const src) { - memcpy(dst, src, 4); -} - -static WEBP_INLINE void DoTransform(uint32_t bits, const int16_t* const src, - uint8_t* const dst) { - switch (bits >> 30) { - case 3: - VP8Transform(src, dst, 0); - break; - case 2: - VP8TransformAC3(src, dst); - break; - case 1: - VP8TransformDC(src, dst); - break; - default: - break; - } -} - -static void DoUVTransform(uint32_t bits, const int16_t* const src, - uint8_t* const dst) { - if (bits & 0xff) { // any non-zero coeff at all? - if (bits & 0xaa) { // any non-zero AC coefficient? - VP8TransformUV(src, dst); // note we don't use the AC3 variant for U/V - } else { - VP8TransformDCUV(src, dst); - } - } -} - -static void ReconstructRow(const VP8Decoder* const dec, - const VP8ThreadContext* ctx) { - int j; - int mb_x; - const int mb_y = ctx->mb_y_; - const int cache_id = ctx->id_; - uint8_t* const y_dst = dec->yuv_b_ + Y_OFF; - uint8_t* const u_dst = dec->yuv_b_ + U_OFF; - uint8_t* const v_dst = dec->yuv_b_ + V_OFF; - - // Initialize left-most block. - for (j = 0; j < 16; ++j) { - y_dst[j * BPS - 1] = 129; - } - for (j = 0; j < 8; ++j) { - u_dst[j * BPS - 1] = 129; - v_dst[j * BPS - 1] = 129; - } - - // Init top-left sample on left column too. - if (mb_y > 0) { - y_dst[-1 - BPS] = u_dst[-1 - BPS] = v_dst[-1 - BPS] = 129; - } else { - // we only need to do this init once at block (0,0). - // Afterward, it remains valid for the whole topmost row. - memset(y_dst - BPS - 1, 127, 16 + 4 + 1); - memset(u_dst - BPS - 1, 127, 8 + 1); - memset(v_dst - BPS - 1, 127, 8 + 1); - } - - // Reconstruct one row. - for (mb_x = 0; mb_x < dec->mb_w_; ++mb_x) { - const VP8MBData* const block = ctx->mb_data_ + mb_x; - - // Rotate in the left samples from previously decoded block. We move four - // pixels at a time for alignment reason, and because of in-loop filter. - if (mb_x > 0) { - for (j = -1; j < 16; ++j) { - Copy32b(&y_dst[j * BPS - 4], &y_dst[j * BPS + 12]); - } - for (j = -1; j < 8; ++j) { - Copy32b(&u_dst[j * BPS - 4], &u_dst[j * BPS + 4]); - Copy32b(&v_dst[j * BPS - 4], &v_dst[j * BPS + 4]); - } - } - { - // bring top samples into the cache - VP8TopSamples* const top_yuv = dec->yuv_t_ + mb_x; - const int16_t* const coeffs = block->coeffs_; - uint32_t bits = block->non_zero_y_; - int n; - - if (mb_y > 0) { - memcpy(y_dst - BPS, top_yuv[0].y, 16); - memcpy(u_dst - BPS, top_yuv[0].u, 8); - memcpy(v_dst - BPS, top_yuv[0].v, 8); - } - - // predict and add residuals - if (block->is_i4x4_) { // 4x4 - uint32_t* const top_right = (uint32_t*)(y_dst - BPS + 16); - - if (mb_y > 0) { - if (mb_x >= dec->mb_w_ - 1) { // on rightmost border - memset(top_right, top_yuv[0].y[15], sizeof(*top_right)); - } else { - memcpy(top_right, top_yuv[1].y, sizeof(*top_right)); - } - } - // replicate the top-right pixels below - top_right[BPS] = top_right[2 * BPS] = top_right[3 * BPS] = top_right[0]; - - // predict and add residuals for all 4x4 blocks in turn. - for (n = 0; n < 16; ++n, bits <<= 2) { - uint8_t* const dst = y_dst + kScan[n]; - VP8PredLuma4[block->imodes_[n]](dst); - DoTransform(bits, coeffs + n * 16, dst); - } - } else { // 16x16 - const int pred_func = CheckMode(mb_x, mb_y, block->imodes_[0]); - VP8PredLuma16[pred_func](y_dst); - if (bits != 0) { - for (n = 0; n < 16; ++n, bits <<= 2) { - DoTransform(bits, coeffs + n * 16, y_dst + kScan[n]); - } - } - } - { - // Chroma - const uint32_t bits_uv = block->non_zero_uv_; - const int pred_func = CheckMode(mb_x, mb_y, block->uvmode_); - VP8PredChroma8[pred_func](u_dst); - VP8PredChroma8[pred_func](v_dst); - DoUVTransform(bits_uv >> 0, coeffs + 16 * 16, u_dst); - DoUVTransform(bits_uv >> 8, coeffs + 20 * 16, v_dst); - } - - // stash away top samples for next block - if (mb_y < dec->mb_h_ - 1) { - memcpy(top_yuv[0].y, y_dst + 15 * BPS, 16); - memcpy(top_yuv[0].u, u_dst + 7 * BPS, 8); - memcpy(top_yuv[0].v, v_dst + 7 * BPS, 8); - } - } - // Transfer reconstructed samples from yuv_b_ cache to final destination. - { - const int y_offset = cache_id * 16 * dec->cache_y_stride_; - const int uv_offset = cache_id * 8 * dec->cache_uv_stride_; - uint8_t* const y_out = dec->cache_y_ + mb_x * 16 + y_offset; - uint8_t* const u_out = dec->cache_u_ + mb_x * 8 + uv_offset; - uint8_t* const v_out = dec->cache_v_ + mb_x * 8 + uv_offset; - for (j = 0; j < 16; ++j) { - memcpy(y_out + j * dec->cache_y_stride_, y_dst + j * BPS, 16); - } - for (j = 0; j < 8; ++j) { - memcpy(u_out + j * dec->cache_uv_stride_, u_dst + j * BPS, 8); - memcpy(v_out + j * dec->cache_uv_stride_, v_dst + j * BPS, 8); - } - } - } -} - -//------------------------------------------------------------------------------ -// Filtering - -// kFilterExtraRows[] = How many extra lines are needed on the MB boundary -// for caching, given a filtering level. -// Simple filter: up to 2 luma samples are read and 1 is written. -// Complex filter: up to 4 luma samples are read and 3 are written. Same for -// U/V, so it's 8 samples total (because of the 2x upsampling). -static const uint8_t kFilterExtraRows[3] = { 0, 2, 8 }; - -static void DoFilter(const VP8Decoder* const dec, int mb_x, int mb_y) { - const VP8ThreadContext* const ctx = &dec->thread_ctx_; - const int cache_id = ctx->id_; - const int y_bps = dec->cache_y_stride_; - const VP8FInfo* const f_info = ctx->f_info_ + mb_x; - uint8_t* const y_dst = dec->cache_y_ + cache_id * 16 * y_bps + mb_x * 16; - const int ilevel = f_info->f_ilevel_; - const int limit = f_info->f_limit_; - if (limit == 0) { - return; - } - assert(limit >= 3); - if (dec->filter_type_ == 1) { // simple - if (mb_x > 0) { - VP8SimpleHFilter16(y_dst, y_bps, limit + 4); - } - if (f_info->f_inner_) { - VP8SimpleHFilter16i(y_dst, y_bps, limit); - } - if (mb_y > 0) { - VP8SimpleVFilter16(y_dst, y_bps, limit + 4); - } - if (f_info->f_inner_) { - VP8SimpleVFilter16i(y_dst, y_bps, limit); - } - } else { // complex - const int uv_bps = dec->cache_uv_stride_; - uint8_t* const u_dst = dec->cache_u_ + cache_id * 8 * uv_bps + mb_x * 8; - uint8_t* const v_dst = dec->cache_v_ + cache_id * 8 * uv_bps + mb_x * 8; - const int hev_thresh = f_info->hev_thresh_; - if (mb_x > 0) { - VP8HFilter16(y_dst, y_bps, limit + 4, ilevel, hev_thresh); - VP8HFilter8(u_dst, v_dst, uv_bps, limit + 4, ilevel, hev_thresh); - } - if (f_info->f_inner_) { - VP8HFilter16i(y_dst, y_bps, limit, ilevel, hev_thresh); - VP8HFilter8i(u_dst, v_dst, uv_bps, limit, ilevel, hev_thresh); - } - if (mb_y > 0) { - VP8VFilter16(y_dst, y_bps, limit + 4, ilevel, hev_thresh); - VP8VFilter8(u_dst, v_dst, uv_bps, limit + 4, ilevel, hev_thresh); - } - if (f_info->f_inner_) { - VP8VFilter16i(y_dst, y_bps, limit, ilevel, hev_thresh); - VP8VFilter8i(u_dst, v_dst, uv_bps, limit, ilevel, hev_thresh); - } - } -} - -// Filter the decoded macroblock row (if needed) -static void FilterRow(const VP8Decoder* const dec) { - int mb_x; - const int mb_y = dec->thread_ctx_.mb_y_; - assert(dec->thread_ctx_.filter_row_); - for (mb_x = dec->tl_mb_x_; mb_x < dec->br_mb_x_; ++mb_x) { - DoFilter(dec, mb_x, mb_y); - } -} - -//------------------------------------------------------------------------------ -// Precompute the filtering strength for each segment and each i4x4/i16x16 mode. - -static void PrecomputeFilterStrengths(VP8Decoder* const dec) { - if (dec->filter_type_ > 0) { - int s; - const VP8FilterHeader* const hdr = &dec->filter_hdr_; - for (s = 0; s < NUM_MB_SEGMENTS; ++s) { - int i4x4; - // First, compute the initial level - int base_level; - if (dec->segment_hdr_.use_segment_) { - base_level = dec->segment_hdr_.filter_strength_[s]; - if (!dec->segment_hdr_.absolute_delta_) { - base_level += hdr->level_; - } - } else { - base_level = hdr->level_; - } - for (i4x4 = 0; i4x4 <= 1; ++i4x4) { - VP8FInfo* const info = &dec->fstrengths_[s][i4x4]; - int level = base_level; - if (hdr->use_lf_delta_) { - level += hdr->ref_lf_delta_[0]; - if (i4x4) { - level += hdr->mode_lf_delta_[0]; - } - } - level = (level < 0) ? 0 : (level > 63) ? 63 : level; - if (level > 0) { - int ilevel = level; - if (hdr->sharpness_ > 0) { - if (hdr->sharpness_ > 4) { - ilevel >>= 2; - } else { - ilevel >>= 1; - } - if (ilevel > 9 - hdr->sharpness_) { - ilevel = 9 - hdr->sharpness_; - } - } - if (ilevel < 1) ilevel = 1; - info->f_ilevel_ = ilevel; - info->f_limit_ = 2 * level + ilevel; - info->hev_thresh_ = (level >= 40) ? 2 : (level >= 15) ? 1 : 0; - } else { - info->f_limit_ = 0; // no filtering - } - info->f_inner_ = i4x4; - } - } - } -} - -//------------------------------------------------------------------------------ -// Dithering - -#define DITHER_AMP_TAB_SIZE 12 -static const int kQuantToDitherAmp[DITHER_AMP_TAB_SIZE] = { - // roughly, it's dqm->uv_mat_[1] - 8, 7, 6, 4, 4, 2, 2, 2, 1, 1, 1, 1 -}; - -void VP8InitDithering(const WebPDecoderOptions* const options, - VP8Decoder* const dec) { - assert(dec != NULL); - if (options != NULL) { - const int d = options->dithering_strength; - const int max_amp = (1 << VP8_RANDOM_DITHER_FIX) - 1; - const int f = (d < 0) ? 0 : (d > 100) ? max_amp : (d * max_amp / 100); - if (f > 0) { - int s; - int all_amp = 0; - for (s = 0; s < NUM_MB_SEGMENTS; ++s) { - VP8QuantMatrix* const dqm = &dec->dqm_[s]; - if (dqm->uv_quant_ < DITHER_AMP_TAB_SIZE) { - // TODO(skal): should we specially dither more for uv_quant_ < 0? - const int idx = (dqm->uv_quant_ < 0) ? 0 : dqm->uv_quant_; - dqm->dither_ = (f * kQuantToDitherAmp[idx]) >> 3; - } - all_amp |= dqm->dither_; - } - if (all_amp != 0) { - VP8InitRandom(&dec->dithering_rg_, 1.0f); - dec->dither_ = 1; - } - } - // potentially allow alpha dithering - dec->alpha_dithering_ = options->alpha_dithering_strength; - if (dec->alpha_dithering_ > 100) { - dec->alpha_dithering_ = 100; - } else if (dec->alpha_dithering_ < 0) { - dec->alpha_dithering_ = 0; - } - } -} - -// minimal amp that will provide a non-zero dithering effect -#define MIN_DITHER_AMP 4 -#define DITHER_DESCALE 4 -#define DITHER_DESCALE_ROUNDER (1 << (DITHER_DESCALE - 1)) -#define DITHER_AMP_BITS 8 -#define DITHER_AMP_CENTER (1 << DITHER_AMP_BITS) - -static void Dither8x8(VP8Random* const rg, uint8_t* dst, int bps, int amp) { - int i, j; - for (j = 0; j < 8; ++j) { - for (i = 0; i < 8; ++i) { - // TODO: could be made faster with SSE2 - const int bits = - VP8RandomBits2(rg, DITHER_AMP_BITS + 1, amp) - DITHER_AMP_CENTER; - // Convert to range: [-2,2] for dither=50, [-4,4] for dither=100 - const int delta = (bits + DITHER_DESCALE_ROUNDER) >> DITHER_DESCALE; - const int v = (int)dst[i] + delta; - dst[i] = (v < 0) ? 0 : (v > 255) ? 255u : (uint8_t)v; - } - dst += bps; - } -} - -static void DitherRow(VP8Decoder* const dec) { - int mb_x; - assert(dec->dither_); - for (mb_x = dec->tl_mb_x_; mb_x < dec->br_mb_x_; ++mb_x) { - const VP8ThreadContext* const ctx = &dec->thread_ctx_; - const VP8MBData* const data = ctx->mb_data_ + mb_x; - const int cache_id = ctx->id_; - const int uv_bps = dec->cache_uv_stride_; - if (data->dither_ >= MIN_DITHER_AMP) { - uint8_t* const u_dst = dec->cache_u_ + cache_id * 8 * uv_bps + mb_x * 8; - uint8_t* const v_dst = dec->cache_v_ + cache_id * 8 * uv_bps + mb_x * 8; - Dither8x8(&dec->dithering_rg_, u_dst, uv_bps, data->dither_); - Dither8x8(&dec->dithering_rg_, v_dst, uv_bps, data->dither_); - } - } -} - -//------------------------------------------------------------------------------ -// This function is called after a row of macroblocks is finished decoding. -// It also takes into account the following restrictions: -// * In case of in-loop filtering, we must hold off sending some of the bottom -// pixels as they are yet unfiltered. They will be when the next macroblock -// row is decoded. Meanwhile, we must preserve them by rotating them in the -// cache area. This doesn't hold for the very bottom row of the uncropped -// picture of course. -// * we must clip the remaining pixels against the cropping area. The VP8Io -// struct must have the following fields set correctly before calling put(): - -#define MACROBLOCK_VPOS(mb_y) ((mb_y) * 16) // vertical position of a MB - -// Finalize and transmit a complete row. Return false in case of user-abort. -static int FinishRow(VP8Decoder* const dec, VP8Io* const io) { - int ok = 1; - const VP8ThreadContext* const ctx = &dec->thread_ctx_; - const int cache_id = ctx->id_; - const int extra_y_rows = kFilterExtraRows[dec->filter_type_]; - const int ysize = extra_y_rows * dec->cache_y_stride_; - const int uvsize = (extra_y_rows / 2) * dec->cache_uv_stride_; - const int y_offset = cache_id * 16 * dec->cache_y_stride_; - const int uv_offset = cache_id * 8 * dec->cache_uv_stride_; - uint8_t* const ydst = dec->cache_y_ - ysize + y_offset; - uint8_t* const udst = dec->cache_u_ - uvsize + uv_offset; - uint8_t* const vdst = dec->cache_v_ - uvsize + uv_offset; - const int mb_y = ctx->mb_y_; - const int is_first_row = (mb_y == 0); - const int is_last_row = (mb_y >= dec->br_mb_y_ - 1); - - if (dec->mt_method_ == 2) { - ReconstructRow(dec, ctx); - } - - if (ctx->filter_row_) { - FilterRow(dec); - } - - if (dec->dither_) { - DitherRow(dec); - } - - if (io->put != NULL) { - int y_start = MACROBLOCK_VPOS(mb_y); - int y_end = MACROBLOCK_VPOS(mb_y + 1); - if (!is_first_row) { - y_start -= extra_y_rows; - io->y = ydst; - io->u = udst; - io->v = vdst; - } else { - io->y = dec->cache_y_ + y_offset; - io->u = dec->cache_u_ + uv_offset; - io->v = dec->cache_v_ + uv_offset; - } - - if (!is_last_row) { - y_end -= extra_y_rows; - } - if (y_end > io->crop_bottom) { - y_end = io->crop_bottom; // make sure we don't overflow on last row. - } - io->a = NULL; - if (dec->alpha_data_ != NULL && y_start < y_end) { - // TODO(skal): testing presence of alpha with dec->alpha_data_ is not a - // good idea. - io->a = VP8DecompressAlphaRows(dec, y_start, y_end - y_start); - if (io->a == NULL) { - return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, - "Could not decode alpha data."); - } - } - if (y_start < io->crop_top) { - const int delta_y = io->crop_top - y_start; - y_start = io->crop_top; - assert(!(delta_y & 1)); - io->y += dec->cache_y_stride_ * delta_y; - io->u += dec->cache_uv_stride_ * (delta_y >> 1); - io->v += dec->cache_uv_stride_ * (delta_y >> 1); - if (io->a != NULL) { - io->a += io->width * delta_y; - } - } - if (y_start < y_end) { - io->y += io->crop_left; - io->u += io->crop_left >> 1; - io->v += io->crop_left >> 1; - if (io->a != NULL) { - io->a += io->crop_left; - } - io->mb_y = y_start - io->crop_top; - io->mb_w = io->crop_right - io->crop_left; - io->mb_h = y_end - y_start; - ok = io->put(io); - } - } - // rotate top samples if needed - if (cache_id + 1 == dec->num_caches_) { - if (!is_last_row) { - memcpy(dec->cache_y_ - ysize, ydst + 16 * dec->cache_y_stride_, ysize); - memcpy(dec->cache_u_ - uvsize, udst + 8 * dec->cache_uv_stride_, uvsize); - memcpy(dec->cache_v_ - uvsize, vdst + 8 * dec->cache_uv_stride_, uvsize); - } - } - - return ok; -} - -#undef MACROBLOCK_VPOS - -//------------------------------------------------------------------------------ - -int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io) { - int ok = 1; - VP8ThreadContext* const ctx = &dec->thread_ctx_; - const int filter_row = - (dec->filter_type_ > 0) && - (dec->mb_y_ >= dec->tl_mb_y_) && (dec->mb_y_ <= dec->br_mb_y_); - if (dec->mt_method_ == 0) { - // ctx->id_ and ctx->f_info_ are already set - ctx->mb_y_ = dec->mb_y_; - ctx->filter_row_ = filter_row; - ReconstructRow(dec, ctx); - ok = FinishRow(dec, io); - } else { - WebPWorker* const worker = &dec->worker_; - // Finish previous job *before* updating context - ok &= WebPGetWorkerInterface()->Sync(worker); - assert(worker->status_ == OK); - if (ok) { // spawn a new deblocking/output job - ctx->io_ = *io; - ctx->id_ = dec->cache_id_; - ctx->mb_y_ = dec->mb_y_; - ctx->filter_row_ = filter_row; - if (dec->mt_method_ == 2) { // swap macroblock data - VP8MBData* const tmp = ctx->mb_data_; - ctx->mb_data_ = dec->mb_data_; - dec->mb_data_ = tmp; - } else { - // perform reconstruction directly in main thread - ReconstructRow(dec, ctx); - } - if (filter_row) { // swap filter info - VP8FInfo* const tmp = ctx->f_info_; - ctx->f_info_ = dec->f_info_; - dec->f_info_ = tmp; - } - // (reconstruct)+filter in parallel - WebPGetWorkerInterface()->Launch(worker); - if (++dec->cache_id_ == dec->num_caches_) { - dec->cache_id_ = 0; - } - } - } - return ok; -} - -//------------------------------------------------------------------------------ -// Finish setting up the decoding parameter once user's setup() is called. - -VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io) { - // Call setup() first. This may trigger additional decoding features on 'io'. - // Note: Afterward, we must call teardown() no matter what. - if (io->setup != NULL && !io->setup(io)) { - VP8SetError(dec, VP8_STATUS_USER_ABORT, "Frame setup failed"); - return dec->status_; - } - - // Disable filtering per user request - if (io->bypass_filtering) { - dec->filter_type_ = 0; - } - // TODO(skal): filter type / strength / sharpness forcing - - // Define the area where we can skip in-loop filtering, in case of cropping. - // - // 'Simple' filter reads two luma samples outside of the macroblock - // and filters one. It doesn't filter the chroma samples. Hence, we can - // avoid doing the in-loop filtering before crop_top/crop_left position. - // For the 'Complex' filter, 3 samples are read and up to 3 are filtered. - // Means: there's a dependency chain that goes all the way up to the - // top-left corner of the picture (MB #0). We must filter all the previous - // macroblocks. - // TODO(skal): add an 'approximate_decoding' option, that won't produce - // a 1:1 bit-exactness for complex filtering? - { - const int extra_pixels = kFilterExtraRows[dec->filter_type_]; - if (dec->filter_type_ == 2) { - // For complex filter, we need to preserve the dependency chain. - dec->tl_mb_x_ = 0; - dec->tl_mb_y_ = 0; - } else { - // For simple filter, we can filter only the cropped region. - // We include 'extra_pixels' on the other side of the boundary, since - // vertical or horizontal filtering of the previous macroblock can - // modify some abutting pixels. - dec->tl_mb_x_ = (io->crop_left - extra_pixels) >> 4; - dec->tl_mb_y_ = (io->crop_top - extra_pixels) >> 4; - if (dec->tl_mb_x_ < 0) dec->tl_mb_x_ = 0; - if (dec->tl_mb_y_ < 0) dec->tl_mb_y_ = 0; - } - // We need some 'extra' pixels on the right/bottom. - dec->br_mb_y_ = (io->crop_bottom + 15 + extra_pixels) >> 4; - dec->br_mb_x_ = (io->crop_right + 15 + extra_pixels) >> 4; - if (dec->br_mb_x_ > dec->mb_w_) { - dec->br_mb_x_ = dec->mb_w_; - } - if (dec->br_mb_y_ > dec->mb_h_) { - dec->br_mb_y_ = dec->mb_h_; - } - } - PrecomputeFilterStrengths(dec); - return VP8_STATUS_OK; -} - -int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io) { - int ok = 1; - if (dec->mt_method_ > 0) { - ok = WebPGetWorkerInterface()->Sync(&dec->worker_); - } - - if (io->teardown != NULL) { - io->teardown(io); - } - return ok; -} - -//------------------------------------------------------------------------------ -// For multi-threaded decoding we need to use 3 rows of 16 pixels as delay line. -// -// Reason is: the deblocking filter cannot deblock the bottom horizontal edges -// immediately, and needs to wait for first few rows of the next macroblock to -// be decoded. Hence, deblocking is lagging behind by 4 or 8 pixels (depending -// on strength). -// With two threads, the vertical positions of the rows being decoded are: -// Decode: [ 0..15][16..31][32..47][48..63][64..79][... -// Deblock: [ 0..11][12..27][28..43][44..59][... -// If we use two threads and two caches of 16 pixels, the sequence would be: -// Decode: [ 0..15][16..31][ 0..15!!][16..31][ 0..15][... -// Deblock: [ 0..11][12..27!!][-4..11][12..27][... -// The problem occurs during row [12..15!!] that both the decoding and -// deblocking threads are writing simultaneously. -// With 3 cache lines, one get a safe write pattern: -// Decode: [ 0..15][16..31][32..47][ 0..15][16..31][32..47][0.. -// Deblock: [ 0..11][12..27][28..43][-4..11][12..27][28... -// Note that multi-threaded output _without_ deblocking can make use of two -// cache lines of 16 pixels only, since there's no lagging behind. The decoding -// and output process have non-concurrent writing: -// Decode: [ 0..15][16..31][ 0..15][16..31][... -// io->put: [ 0..15][16..31][ 0..15][... - -#define MT_CACHE_LINES 3 -#define ST_CACHE_LINES 1 // 1 cache row only for single-threaded case - -// Initialize multi/single-thread worker -static int InitThreadContext(VP8Decoder* const dec) { - dec->cache_id_ = 0; - if (dec->mt_method_ > 0) { - WebPWorker* const worker = &dec->worker_; - if (!WebPGetWorkerInterface()->Reset(worker)) { - return VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY, - "thread initialization failed."); - } - worker->data1 = dec; - worker->data2 = (void*)&dec->thread_ctx_.io_; - worker->hook = (WebPWorkerHook)FinishRow; - dec->num_caches_ = - (dec->filter_type_ > 0) ? MT_CACHE_LINES : MT_CACHE_LINES - 1; - } else { - dec->num_caches_ = ST_CACHE_LINES; - } - return 1; -} - -int VP8GetThreadMethod(const WebPDecoderOptions* const options, - const WebPHeaderStructure* const headers, - int width, int height) { - if (options == NULL || options->use_threads == 0) { - return 0; - } - (void)headers; - (void)width; - (void)height; - assert(headers == NULL || !headers->is_lossless); -#if defined(WEBP_USE_THREAD) - if (width < MIN_WIDTH_FOR_THREADS) return 0; - // TODO(skal): tune the heuristic further -#if 0 - if (height < 2 * width) return 2; -#endif - return 2; -#else // !WEBP_USE_THREAD - return 0; -#endif -} - -#undef MT_CACHE_LINES -#undef ST_CACHE_LINES - -//------------------------------------------------------------------------------ -// Memory setup - -static int AllocateMemory(VP8Decoder* const dec) { - const int num_caches = dec->num_caches_; - const int mb_w = dec->mb_w_; - // Note: we use 'size_t' when there's no overflow risk, uint64_t otherwise. - const size_t intra_pred_mode_size = 4 * mb_w * sizeof(uint8_t); - const size_t top_size = sizeof(VP8TopSamples) * mb_w; - const size_t mb_info_size = (mb_w + 1) * sizeof(VP8MB); - const size_t f_info_size = - (dec->filter_type_ > 0) ? - mb_w * (dec->mt_method_ > 0 ? 2 : 1) * sizeof(VP8FInfo) - : 0; - const size_t yuv_size = YUV_SIZE * sizeof(*dec->yuv_b_); - const size_t mb_data_size = - (dec->mt_method_ == 2 ? 2 : 1) * mb_w * sizeof(*dec->mb_data_); - const size_t cache_height = (16 * num_caches - + kFilterExtraRows[dec->filter_type_]) * 3 / 2; - const size_t cache_size = top_size * cache_height; - // alpha_size is the only one that scales as width x height. - const uint64_t alpha_size = (dec->alpha_data_ != NULL) ? - (uint64_t)dec->pic_hdr_.width_ * dec->pic_hdr_.height_ : 0ULL; - const uint64_t needed = (uint64_t)intra_pred_mode_size - + top_size + mb_info_size + f_info_size - + yuv_size + mb_data_size - + cache_size + alpha_size + WEBP_ALIGN_CST; - uint8_t* mem; - - if (needed != (size_t)needed) return 0; // check for overflow - if (needed > dec->mem_size_) { - WebPSafeFree(dec->mem_); - dec->mem_size_ = 0; - dec->mem_ = WebPSafeMalloc(needed, sizeof(uint8_t)); - if (dec->mem_ == NULL) { - return VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY, - "no memory during frame initialization."); - } - // down-cast is ok, thanks to WebPSafeAlloc() above. - dec->mem_size_ = (size_t)needed; - } - - mem = (uint8_t*)dec->mem_; - dec->intra_t_ = (uint8_t*)mem; - mem += intra_pred_mode_size; - - dec->yuv_t_ = (VP8TopSamples*)mem; - mem += top_size; - - dec->mb_info_ = ((VP8MB*)mem) + 1; - mem += mb_info_size; - - dec->f_info_ = f_info_size ? (VP8FInfo*)mem : NULL; - mem += f_info_size; - dec->thread_ctx_.id_ = 0; - dec->thread_ctx_.f_info_ = dec->f_info_; - if (dec->mt_method_ > 0) { - // secondary cache line. The deblocking process need to make use of the - // filtering strength from previous macroblock row, while the new ones - // are being decoded in parallel. We'll just swap the pointers. - dec->thread_ctx_.f_info_ += mb_w; - } - - mem = (uint8_t*)WEBP_ALIGN(mem); - assert((yuv_size & WEBP_ALIGN_CST) == 0); - dec->yuv_b_ = (uint8_t*)mem; - mem += yuv_size; - - dec->mb_data_ = (VP8MBData*)mem; - dec->thread_ctx_.mb_data_ = (VP8MBData*)mem; - if (dec->mt_method_ == 2) { - dec->thread_ctx_.mb_data_ += mb_w; - } - mem += mb_data_size; - - dec->cache_y_stride_ = 16 * mb_w; - dec->cache_uv_stride_ = 8 * mb_w; - { - const int extra_rows = kFilterExtraRows[dec->filter_type_]; - const int extra_y = extra_rows * dec->cache_y_stride_; - const int extra_uv = (extra_rows / 2) * dec->cache_uv_stride_; - dec->cache_y_ = ((uint8_t*)mem) + extra_y; - dec->cache_u_ = dec->cache_y_ - + 16 * num_caches * dec->cache_y_stride_ + extra_uv; - dec->cache_v_ = dec->cache_u_ - + 8 * num_caches * dec->cache_uv_stride_ + extra_uv; - dec->cache_id_ = 0; - } - mem += cache_size; - - // alpha plane - dec->alpha_plane_ = alpha_size ? (uint8_t*)mem : NULL; - mem += alpha_size; - assert(mem <= (uint8_t*)dec->mem_ + dec->mem_size_); - - // note: left/top-info is initialized once for all. - memset(dec->mb_info_ - 1, 0, mb_info_size); - VP8InitScanline(dec); // initialize left too. - - // initialize top - memset(dec->intra_t_, B_DC_PRED, intra_pred_mode_size); - - return 1; -} - -static void InitIo(VP8Decoder* const dec, VP8Io* io) { - // prepare 'io' - io->mb_y = 0; - io->y = dec->cache_y_; - io->u = dec->cache_u_; - io->v = dec->cache_v_; - io->y_stride = dec->cache_y_stride_; - io->uv_stride = dec->cache_uv_stride_; - io->a = NULL; -} - -int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io) { - if (!InitThreadContext(dec)) return 0; // call first. Sets dec->num_caches_. - if (!AllocateMemory(dec)) return 0; - InitIo(dec, io); - VP8DspInit(); // Init critical function pointers and look-up tables. - return 1; -} - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/dec/idec.c b/Example-Mac/Pods/libwebp/src/dec/idec.c deleted file mode 100644 index e0cf0c9c..00000000 --- a/Example-Mac/Pods/libwebp/src/dec/idec.c +++ /dev/null @@ -1,859 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Incremental decoding -// -// Author: somnath@google.com (Somnath Banerjee) - -#include -#include -#include - -#include "./alphai.h" -#include "./webpi.h" -#include "./vp8i.h" -#include "../utils/utils.h" - -// In append mode, buffer allocations increase as multiples of this value. -// Needs to be a power of 2. -#define CHUNK_SIZE 4096 -#define MAX_MB_SIZE 4096 - -//------------------------------------------------------------------------------ -// Data structures for memory and states - -// Decoding states. State normally flows as: -// WEBP_HEADER->VP8_HEADER->VP8_PARTS0->VP8_DATA->DONE for a lossy image, and -// WEBP_HEADER->VP8L_HEADER->VP8L_DATA->DONE for a lossless image. -// If there is any error the decoder goes into state ERROR. -typedef enum { - STATE_WEBP_HEADER, // All the data before that of the VP8/VP8L chunk. - STATE_VP8_HEADER, // The VP8 Frame header (within the VP8 chunk). - STATE_VP8_PARTS0, - STATE_VP8_DATA, - STATE_VP8L_HEADER, - STATE_VP8L_DATA, - STATE_DONE, - STATE_ERROR -} DecState; - -// Operating state for the MemBuffer -typedef enum { - MEM_MODE_NONE = 0, - MEM_MODE_APPEND, - MEM_MODE_MAP -} MemBufferMode; - -// storage for partition #0 and partial data (in a rolling fashion) -typedef struct { - MemBufferMode mode_; // Operation mode - size_t start_; // start location of the data to be decoded - size_t end_; // end location - size_t buf_size_; // size of the allocated buffer - uint8_t* buf_; // We don't own this buffer in case WebPIUpdate() - - size_t part0_size_; // size of partition #0 - const uint8_t* part0_buf_; // buffer to store partition #0 -} MemBuffer; - -struct WebPIDecoder { - DecState state_; // current decoding state - WebPDecParams params_; // Params to store output info - int is_lossless_; // for down-casting 'dec_'. - void* dec_; // either a VP8Decoder or a VP8LDecoder instance - VP8Io io_; - - MemBuffer mem_; // input memory buffer. - WebPDecBuffer output_; // output buffer (when no external one is supplied) - size_t chunk_size_; // Compressed VP8/VP8L size extracted from Header. - - int last_mb_y_; // last row reached for intra-mode decoding -}; - -// MB context to restore in case VP8DecodeMB() fails -typedef struct { - VP8MB left_; - VP8MB info_; - VP8BitReader token_br_; -} MBContext; - -//------------------------------------------------------------------------------ -// MemBuffer: incoming data handling - -static WEBP_INLINE size_t MemDataSize(const MemBuffer* mem) { - return (mem->end_ - mem->start_); -} - -// Check if we need to preserve the compressed alpha data, as it may not have -// been decoded yet. -static int NeedCompressedAlpha(const WebPIDecoder* const idec) { - if (idec->state_ == STATE_WEBP_HEADER) { - // We haven't parsed the headers yet, so we don't know whether the image is - // lossy or lossless. This also means that we haven't parsed the ALPH chunk. - return 0; - } - if (idec->is_lossless_) { - return 0; // ALPH chunk is not present for lossless images. - } else { - const VP8Decoder* const dec = (VP8Decoder*)idec->dec_; - assert(dec != NULL); // Must be true as idec->state_ != STATE_WEBP_HEADER. - return (dec->alpha_data_ != NULL) && !dec->is_alpha_decoded_; - } -} - -static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) { - MemBuffer* const mem = &idec->mem_; - const uint8_t* const new_base = mem->buf_ + mem->start_; - // note: for VP8, setting up idec->io_ is only really needed at the beginning - // of the decoding, till partition #0 is complete. - idec->io_.data = new_base; - idec->io_.data_size = MemDataSize(mem); - - if (idec->dec_ != NULL) { - if (!idec->is_lossless_) { - VP8Decoder* const dec = (VP8Decoder*)idec->dec_; - const int last_part = dec->num_parts_ - 1; - if (offset != 0) { - int p; - for (p = 0; p <= last_part; ++p) { - VP8RemapBitReader(dec->parts_ + p, offset); - } - // Remap partition #0 data pointer to new offset, but only in MAP - // mode (in APPEND mode, partition #0 is copied into a fixed memory). - if (mem->mode_ == MEM_MODE_MAP) { - VP8RemapBitReader(&dec->br_, offset); - } - } - { - const uint8_t* const last_start = dec->parts_[last_part].buf_; - assert(last_part >= 0); - VP8BitReaderSetBuffer(&dec->parts_[last_part], last_start, - mem->buf_ + mem->end_ - last_start); - } - if (NeedCompressedAlpha(idec)) { - ALPHDecoder* const alph_dec = dec->alph_dec_; - dec->alpha_data_ += offset; - if (alph_dec != NULL) { - if (alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION) { - VP8LDecoder* const alph_vp8l_dec = alph_dec->vp8l_dec_; - assert(alph_vp8l_dec != NULL); - assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN); - VP8LBitReaderSetBuffer(&alph_vp8l_dec->br_, - dec->alpha_data_ + ALPHA_HEADER_LEN, - dec->alpha_data_size_ - ALPHA_HEADER_LEN); - } else { // alph_dec->method_ == ALPHA_NO_COMPRESSION - // Nothing special to do in this case. - } - } - } - } else { // Resize lossless bitreader - VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; - VP8LBitReaderSetBuffer(&dec->br_, new_base, MemDataSize(mem)); - } - } -} - -// Appends data to the end of MemBuffer->buf_. It expands the allocated memory -// size if required and also updates VP8BitReader's if new memory is allocated. -static int AppendToMemBuffer(WebPIDecoder* const idec, - const uint8_t* const data, size_t data_size) { - VP8Decoder* const dec = (VP8Decoder*)idec->dec_; - MemBuffer* const mem = &idec->mem_; - const int need_compressed_alpha = NeedCompressedAlpha(idec); - const uint8_t* const old_start = mem->buf_ + mem->start_; - const uint8_t* const old_base = - need_compressed_alpha ? dec->alpha_data_ : old_start; - assert(mem->mode_ == MEM_MODE_APPEND); - if (data_size > MAX_CHUNK_PAYLOAD) { - // security safeguard: trying to allocate more than what the format - // allows for a chunk should be considered a smoke smell. - return 0; - } - - if (mem->end_ + data_size > mem->buf_size_) { // Need some free memory - const size_t new_mem_start = old_start - old_base; - const size_t current_size = MemDataSize(mem) + new_mem_start; - const uint64_t new_size = (uint64_t)current_size + data_size; - const uint64_t extra_size = (new_size + CHUNK_SIZE - 1) & ~(CHUNK_SIZE - 1); - uint8_t* const new_buf = - (uint8_t*)WebPSafeMalloc(extra_size, sizeof(*new_buf)); - if (new_buf == NULL) return 0; - memcpy(new_buf, old_base, current_size); - WebPSafeFree(mem->buf_); - mem->buf_ = new_buf; - mem->buf_size_ = (size_t)extra_size; - mem->start_ = new_mem_start; - mem->end_ = current_size; - } - - memcpy(mem->buf_ + mem->end_, data, data_size); - mem->end_ += data_size; - assert(mem->end_ <= mem->buf_size_); - - DoRemap(idec, mem->buf_ + mem->start_ - old_start); - return 1; -} - -static int RemapMemBuffer(WebPIDecoder* const idec, - const uint8_t* const data, size_t data_size) { - MemBuffer* const mem = &idec->mem_; - const uint8_t* const old_buf = mem->buf_; - const uint8_t* const old_start = old_buf + mem->start_; - assert(mem->mode_ == MEM_MODE_MAP); - - if (data_size < mem->buf_size_) return 0; // can't remap to a shorter buffer! - - mem->buf_ = (uint8_t*)data; - mem->end_ = mem->buf_size_ = data_size; - - DoRemap(idec, mem->buf_ + mem->start_ - old_start); - return 1; -} - -static void InitMemBuffer(MemBuffer* const mem) { - mem->mode_ = MEM_MODE_NONE; - mem->buf_ = NULL; - mem->buf_size_ = 0; - mem->part0_buf_ = NULL; - mem->part0_size_ = 0; -} - -static void ClearMemBuffer(MemBuffer* const mem) { - assert(mem); - if (mem->mode_ == MEM_MODE_APPEND) { - WebPSafeFree(mem->buf_); - WebPSafeFree((void*)mem->part0_buf_); - } -} - -static int CheckMemBufferMode(MemBuffer* const mem, MemBufferMode expected) { - if (mem->mode_ == MEM_MODE_NONE) { - mem->mode_ = expected; // switch to the expected mode - } else if (mem->mode_ != expected) { - return 0; // we mixed the modes => error - } - assert(mem->mode_ == expected); // mode is ok - return 1; -} - -// To be called last. -static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) { - const WebPDecoderOptions* const options = idec->params_.options; - WebPDecBuffer* const output = idec->params_.output; - - idec->state_ = STATE_DONE; - if (options != NULL && options->flip) { - return WebPFlipBuffer(output); - } else { - return VP8_STATUS_OK; - } -} - -//------------------------------------------------------------------------------ -// Macroblock-decoding contexts - -static void SaveContext(const VP8Decoder* dec, const VP8BitReader* token_br, - MBContext* const context) { - context->left_ = dec->mb_info_[-1]; - context->info_ = dec->mb_info_[dec->mb_x_]; - context->token_br_ = *token_br; -} - -static void RestoreContext(const MBContext* context, VP8Decoder* const dec, - VP8BitReader* const token_br) { - dec->mb_info_[-1] = context->left_; - dec->mb_info_[dec->mb_x_] = context->info_; - *token_br = context->token_br_; -} - -//------------------------------------------------------------------------------ - -static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) { - if (idec->state_ == STATE_VP8_DATA) { - VP8Io* const io = &idec->io_; - if (io->teardown != NULL) { - io->teardown(io); - } - } - idec->state_ = STATE_ERROR; - return error; -} - -static void ChangeState(WebPIDecoder* const idec, DecState new_state, - size_t consumed_bytes) { - MemBuffer* const mem = &idec->mem_; - idec->state_ = new_state; - mem->start_ += consumed_bytes; - assert(mem->start_ <= mem->end_); - idec->io_.data = mem->buf_ + mem->start_; - idec->io_.data_size = MemDataSize(mem); -} - -// Headers -static VP8StatusCode DecodeWebPHeaders(WebPIDecoder* const idec) { - MemBuffer* const mem = &idec->mem_; - const uint8_t* data = mem->buf_ + mem->start_; - size_t curr_size = MemDataSize(mem); - VP8StatusCode status; - WebPHeaderStructure headers; - - headers.data = data; - headers.data_size = curr_size; - headers.have_all_data = 0; - status = WebPParseHeaders(&headers); - if (status == VP8_STATUS_NOT_ENOUGH_DATA) { - return VP8_STATUS_SUSPENDED; // We haven't found a VP8 chunk yet. - } else if (status != VP8_STATUS_OK) { - return IDecError(idec, status); - } - - idec->chunk_size_ = headers.compressed_size; - idec->is_lossless_ = headers.is_lossless; - if (!idec->is_lossless_) { - VP8Decoder* const dec = VP8New(); - if (dec == NULL) { - return VP8_STATUS_OUT_OF_MEMORY; - } - idec->dec_ = dec; - dec->alpha_data_ = headers.alpha_data; - dec->alpha_data_size_ = headers.alpha_data_size; - ChangeState(idec, STATE_VP8_HEADER, headers.offset); - } else { - VP8LDecoder* const dec = VP8LNew(); - if (dec == NULL) { - return VP8_STATUS_OUT_OF_MEMORY; - } - idec->dec_ = dec; - ChangeState(idec, STATE_VP8L_HEADER, headers.offset); - } - return VP8_STATUS_OK; -} - -static VP8StatusCode DecodeVP8FrameHeader(WebPIDecoder* const idec) { - const uint8_t* data = idec->mem_.buf_ + idec->mem_.start_; - const size_t curr_size = MemDataSize(&idec->mem_); - int width, height; - uint32_t bits; - - if (curr_size < VP8_FRAME_HEADER_SIZE) { - // Not enough data bytes to extract VP8 Frame Header. - return VP8_STATUS_SUSPENDED; - } - if (!VP8GetInfo(data, curr_size, idec->chunk_size_, &width, &height)) { - return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); - } - - bits = data[0] | (data[1] << 8) | (data[2] << 16); - idec->mem_.part0_size_ = (bits >> 5) + VP8_FRAME_HEADER_SIZE; - - idec->io_.data = data; - idec->io_.data_size = curr_size; - idec->state_ = STATE_VP8_PARTS0; - return VP8_STATUS_OK; -} - -// Partition #0 -static VP8StatusCode CopyParts0Data(WebPIDecoder* const idec) { - VP8Decoder* const dec = (VP8Decoder*)idec->dec_; - VP8BitReader* const br = &dec->br_; - const size_t part_size = br->buf_end_ - br->buf_; - MemBuffer* const mem = &idec->mem_; - assert(!idec->is_lossless_); - assert(mem->part0_buf_ == NULL); - // the following is a format limitation, no need for runtime check: - assert(part_size <= mem->part0_size_); - if (part_size == 0) { // can't have zero-size partition #0 - return VP8_STATUS_BITSTREAM_ERROR; - } - if (mem->mode_ == MEM_MODE_APPEND) { - // We copy and grab ownership of the partition #0 data. - uint8_t* const part0_buf = (uint8_t*)WebPSafeMalloc(1ULL, part_size); - if (part0_buf == NULL) { - return VP8_STATUS_OUT_OF_MEMORY; - } - memcpy(part0_buf, br->buf_, part_size); - mem->part0_buf_ = part0_buf; - VP8BitReaderSetBuffer(br, part0_buf, part_size); - } else { - // Else: just keep pointers to the partition #0's data in dec_->br_. - } - mem->start_ += part_size; - return VP8_STATUS_OK; -} - -static VP8StatusCode DecodePartition0(WebPIDecoder* const idec) { - VP8Decoder* const dec = (VP8Decoder*)idec->dec_; - VP8Io* const io = &idec->io_; - const WebPDecParams* const params = &idec->params_; - WebPDecBuffer* const output = params->output; - - // Wait till we have enough data for the whole partition #0 - if (MemDataSize(&idec->mem_) < idec->mem_.part0_size_) { - return VP8_STATUS_SUSPENDED; - } - - if (!VP8GetHeaders(dec, io)) { - const VP8StatusCode status = dec->status_; - if (status == VP8_STATUS_SUSPENDED || - status == VP8_STATUS_NOT_ENOUGH_DATA) { - // treating NOT_ENOUGH_DATA as SUSPENDED state - return VP8_STATUS_SUSPENDED; - } - return IDecError(idec, status); - } - - // Allocate/Verify output buffer now - dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options, - output); - if (dec->status_ != VP8_STATUS_OK) { - return IDecError(idec, dec->status_); - } - // This change must be done before calling VP8InitFrame() - dec->mt_method_ = VP8GetThreadMethod(params->options, NULL, - io->width, io->height); - VP8InitDithering(params->options, dec); - - dec->status_ = CopyParts0Data(idec); - if (dec->status_ != VP8_STATUS_OK) { - return IDecError(idec, dec->status_); - } - - // Finish setting up the decoding parameters. Will call io->setup(). - if (VP8EnterCritical(dec, io) != VP8_STATUS_OK) { - return IDecError(idec, dec->status_); - } - - // Note: past this point, teardown() must always be called - // in case of error. - idec->state_ = STATE_VP8_DATA; - // Allocate memory and prepare everything. - if (!VP8InitFrame(dec, io)) { - return IDecError(idec, dec->status_); - } - return VP8_STATUS_OK; -} - -// Remaining partitions -static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) { - VP8Decoder* const dec = (VP8Decoder*)idec->dec_; - VP8Io* const io = &idec->io_; - - assert(dec->ready_); - for (; dec->mb_y_ < dec->mb_h_; ++dec->mb_y_) { - if (idec->last_mb_y_ != dec->mb_y_) { - if (!VP8ParseIntraModeRow(&dec->br_, dec)) { - // note: normally, error shouldn't occur since we already have the whole - // partition0 available here in DecodeRemaining(). Reaching EOF while - // reading intra modes really means a BITSTREAM_ERROR. - return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); - } - idec->last_mb_y_ = dec->mb_y_; - } - for (; dec->mb_x_ < dec->mb_w_; ++dec->mb_x_) { - VP8BitReader* const token_br = - &dec->parts_[dec->mb_y_ & (dec->num_parts_ - 1)]; - MBContext context; - SaveContext(dec, token_br, &context); - if (!VP8DecodeMB(dec, token_br)) { - // We shouldn't fail when MAX_MB data was available - if (dec->num_parts_ == 1 && MemDataSize(&idec->mem_) > MAX_MB_SIZE) { - return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); - } - RestoreContext(&context, dec, token_br); - return VP8_STATUS_SUSPENDED; - } - // Release buffer only if there is only one partition - if (dec->num_parts_ == 1) { - idec->mem_.start_ = token_br->buf_ - idec->mem_.buf_; - assert(idec->mem_.start_ <= idec->mem_.end_); - } - } - VP8InitScanline(dec); // Prepare for next scanline - - // Reconstruct, filter and emit the row. - if (!VP8ProcessRow(dec, io)) { - return IDecError(idec, VP8_STATUS_USER_ABORT); - } - } - // Synchronize the thread and check for errors. - if (!VP8ExitCritical(dec, io)) { - return IDecError(idec, VP8_STATUS_USER_ABORT); - } - dec->ready_ = 0; - return FinishDecoding(idec); -} - -static VP8StatusCode ErrorStatusLossless(WebPIDecoder* const idec, - VP8StatusCode status) { - if (status == VP8_STATUS_SUSPENDED || status == VP8_STATUS_NOT_ENOUGH_DATA) { - return VP8_STATUS_SUSPENDED; - } - return IDecError(idec, status); -} - -static VP8StatusCode DecodeVP8LHeader(WebPIDecoder* const idec) { - VP8Io* const io = &idec->io_; - VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; - const WebPDecParams* const params = &idec->params_; - WebPDecBuffer* const output = params->output; - size_t curr_size = MemDataSize(&idec->mem_); - assert(idec->is_lossless_); - - // Wait until there's enough data for decoding header. - if (curr_size < (idec->chunk_size_ >> 3)) { - dec->status_ = VP8_STATUS_SUSPENDED; - return ErrorStatusLossless(idec, dec->status_); - } - - if (!VP8LDecodeHeader(dec, io)) { - if (dec->status_ == VP8_STATUS_BITSTREAM_ERROR && - curr_size < idec->chunk_size_) { - dec->status_ = VP8_STATUS_SUSPENDED; - } - return ErrorStatusLossless(idec, dec->status_); - } - // Allocate/verify output buffer now. - dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options, - output); - if (dec->status_ != VP8_STATUS_OK) { - return IDecError(idec, dec->status_); - } - - idec->state_ = STATE_VP8L_DATA; - return VP8_STATUS_OK; -} - -static VP8StatusCode DecodeVP8LData(WebPIDecoder* const idec) { - VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; - const size_t curr_size = MemDataSize(&idec->mem_); - assert(idec->is_lossless_); - - // Switch to incremental decoding if we don't have all the bytes available. - dec->incremental_ = (curr_size < idec->chunk_size_); - - if (!VP8LDecodeImage(dec)) { - return ErrorStatusLossless(idec, dec->status_); - } - assert(dec->status_ == VP8_STATUS_OK || dec->status_ == VP8_STATUS_SUSPENDED); - return (dec->status_ == VP8_STATUS_SUSPENDED) ? dec->status_ - : FinishDecoding(idec); -} - - // Main decoding loop -static VP8StatusCode IDecode(WebPIDecoder* idec) { - VP8StatusCode status = VP8_STATUS_SUSPENDED; - - if (idec->state_ == STATE_WEBP_HEADER) { - status = DecodeWebPHeaders(idec); - } else { - if (idec->dec_ == NULL) { - return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder. - } - } - if (idec->state_ == STATE_VP8_HEADER) { - status = DecodeVP8FrameHeader(idec); - } - if (idec->state_ == STATE_VP8_PARTS0) { - status = DecodePartition0(idec); - } - if (idec->state_ == STATE_VP8_DATA) { - status = DecodeRemaining(idec); - } - if (idec->state_ == STATE_VP8L_HEADER) { - status = DecodeVP8LHeader(idec); - } - if (idec->state_ == STATE_VP8L_DATA) { - status = DecodeVP8LData(idec); - } - return status; -} - -//------------------------------------------------------------------------------ -// Public functions - -WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer) { - WebPIDecoder* idec = (WebPIDecoder*)WebPSafeCalloc(1ULL, sizeof(*idec)); - if (idec == NULL) { - return NULL; - } - - idec->state_ = STATE_WEBP_HEADER; - idec->chunk_size_ = 0; - - idec->last_mb_y_ = -1; - - InitMemBuffer(&idec->mem_); - WebPInitDecBuffer(&idec->output_); - VP8InitIo(&idec->io_); - - WebPResetDecParams(&idec->params_); - idec->params_.output = (output_buffer != NULL) ? output_buffer - : &idec->output_; - WebPInitCustomIo(&idec->params_, &idec->io_); // Plug the I/O functions. - - return idec; -} - -WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size, - WebPDecoderConfig* config) { - WebPIDecoder* idec; - - // Parse the bitstream's features, if requested: - if (data != NULL && data_size > 0 && config != NULL) { - if (WebPGetFeatures(data, data_size, &config->input) != VP8_STATUS_OK) { - return NULL; - } - } - // Create an instance of the incremental decoder - idec = WebPINewDecoder(config ? &config->output : NULL); - if (idec == NULL) { - return NULL; - } - // Finish initialization - if (config != NULL) { - idec->params_.options = &config->options; - } - return idec; -} - -void WebPIDelete(WebPIDecoder* idec) { - if (idec == NULL) return; - if (idec->dec_ != NULL) { - if (!idec->is_lossless_) { - if (idec->state_ == STATE_VP8_DATA) { - // Synchronize the thread, clean-up and check for errors. - VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_); - } - VP8Delete((VP8Decoder*)idec->dec_); - } else { - VP8LDelete((VP8LDecoder*)idec->dec_); - } - } - ClearMemBuffer(&idec->mem_); - WebPFreeDecBuffer(&idec->output_); - WebPSafeFree(idec); -} - -//------------------------------------------------------------------------------ -// Wrapper toward WebPINewDecoder - -WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE mode, uint8_t* output_buffer, - size_t output_buffer_size, int output_stride) { - const int is_external_memory = (output_buffer != NULL); - WebPIDecoder* idec; - - if (mode >= MODE_YUV) return NULL; - if (!is_external_memory) { // Overwrite parameters to sane values. - output_buffer_size = 0; - output_stride = 0; - } else { // A buffer was passed. Validate the other params. - if (output_stride == 0 || output_buffer_size == 0) { - return NULL; // invalid parameter. - } - } - idec = WebPINewDecoder(NULL); - if (idec == NULL) return NULL; - idec->output_.colorspace = mode; - idec->output_.is_external_memory = is_external_memory; - idec->output_.u.RGBA.rgba = output_buffer; - idec->output_.u.RGBA.stride = output_stride; - idec->output_.u.RGBA.size = output_buffer_size; - return idec; -} - -WebPIDecoder* WebPINewYUVA(uint8_t* luma, size_t luma_size, int luma_stride, - uint8_t* u, size_t u_size, int u_stride, - uint8_t* v, size_t v_size, int v_stride, - uint8_t* a, size_t a_size, int a_stride) { - const int is_external_memory = (luma != NULL); - WebPIDecoder* idec; - WEBP_CSP_MODE colorspace; - - if (!is_external_memory) { // Overwrite parameters to sane values. - luma_size = u_size = v_size = a_size = 0; - luma_stride = u_stride = v_stride = a_stride = 0; - u = v = a = NULL; - colorspace = MODE_YUVA; - } else { // A luma buffer was passed. Validate the other parameters. - if (u == NULL || v == NULL) return NULL; - if (luma_size == 0 || u_size == 0 || v_size == 0) return NULL; - if (luma_stride == 0 || u_stride == 0 || v_stride == 0) return NULL; - if (a != NULL) { - if (a_size == 0 || a_stride == 0) return NULL; - } - colorspace = (a == NULL) ? MODE_YUV : MODE_YUVA; - } - - idec = WebPINewDecoder(NULL); - if (idec == NULL) return NULL; - - idec->output_.colorspace = colorspace; - idec->output_.is_external_memory = is_external_memory; - idec->output_.u.YUVA.y = luma; - idec->output_.u.YUVA.y_stride = luma_stride; - idec->output_.u.YUVA.y_size = luma_size; - idec->output_.u.YUVA.u = u; - idec->output_.u.YUVA.u_stride = u_stride; - idec->output_.u.YUVA.u_size = u_size; - idec->output_.u.YUVA.v = v; - idec->output_.u.YUVA.v_stride = v_stride; - idec->output_.u.YUVA.v_size = v_size; - idec->output_.u.YUVA.a = a; - idec->output_.u.YUVA.a_stride = a_stride; - idec->output_.u.YUVA.a_size = a_size; - return idec; -} - -WebPIDecoder* WebPINewYUV(uint8_t* luma, size_t luma_size, int luma_stride, - uint8_t* u, size_t u_size, int u_stride, - uint8_t* v, size_t v_size, int v_stride) { - return WebPINewYUVA(luma, luma_size, luma_stride, - u, u_size, u_stride, - v, v_size, v_stride, - NULL, 0, 0); -} - -//------------------------------------------------------------------------------ - -static VP8StatusCode IDecCheckStatus(const WebPIDecoder* const idec) { - assert(idec); - if (idec->state_ == STATE_ERROR) { - return VP8_STATUS_BITSTREAM_ERROR; - } - if (idec->state_ == STATE_DONE) { - return VP8_STATUS_OK; - } - return VP8_STATUS_SUSPENDED; -} - -VP8StatusCode WebPIAppend(WebPIDecoder* idec, - const uint8_t* data, size_t data_size) { - VP8StatusCode status; - if (idec == NULL || data == NULL) { - return VP8_STATUS_INVALID_PARAM; - } - status = IDecCheckStatus(idec); - if (status != VP8_STATUS_SUSPENDED) { - return status; - } - // Check mixed calls between RemapMemBuffer and AppendToMemBuffer. - if (!CheckMemBufferMode(&idec->mem_, MEM_MODE_APPEND)) { - return VP8_STATUS_INVALID_PARAM; - } - // Append data to memory buffer - if (!AppendToMemBuffer(idec, data, data_size)) { - return VP8_STATUS_OUT_OF_MEMORY; - } - return IDecode(idec); -} - -VP8StatusCode WebPIUpdate(WebPIDecoder* idec, - const uint8_t* data, size_t data_size) { - VP8StatusCode status; - if (idec == NULL || data == NULL) { - return VP8_STATUS_INVALID_PARAM; - } - status = IDecCheckStatus(idec); - if (status != VP8_STATUS_SUSPENDED) { - return status; - } - // Check mixed calls between RemapMemBuffer and AppendToMemBuffer. - if (!CheckMemBufferMode(&idec->mem_, MEM_MODE_MAP)) { - return VP8_STATUS_INVALID_PARAM; - } - // Make the memory buffer point to the new buffer - if (!RemapMemBuffer(idec, data, data_size)) { - return VP8_STATUS_INVALID_PARAM; - } - return IDecode(idec); -} - -//------------------------------------------------------------------------------ - -static const WebPDecBuffer* GetOutputBuffer(const WebPIDecoder* const idec) { - if (idec == NULL || idec->dec_ == NULL) { - return NULL; - } - if (idec->state_ <= STATE_VP8_PARTS0) { - return NULL; - } - return idec->params_.output; -} - -const WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec, - int* left, int* top, - int* width, int* height) { - const WebPDecBuffer* const src = GetOutputBuffer(idec); - if (left != NULL) *left = 0; - if (top != NULL) *top = 0; - if (src) { - if (width != NULL) *width = src->width; - if (height != NULL) *height = idec->params_.last_y; - } else { - if (width != NULL) *width = 0; - if (height != NULL) *height = 0; - } - return src; -} - -uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y, - int* width, int* height, int* stride) { - const WebPDecBuffer* const src = GetOutputBuffer(idec); - if (src == NULL) return NULL; - if (src->colorspace >= MODE_YUV) { - return NULL; - } - - if (last_y != NULL) *last_y = idec->params_.last_y; - if (width != NULL) *width = src->width; - if (height != NULL) *height = src->height; - if (stride != NULL) *stride = src->u.RGBA.stride; - - return src->u.RGBA.rgba; -} - -uint8_t* WebPIDecGetYUVA(const WebPIDecoder* idec, int* last_y, - uint8_t** u, uint8_t** v, uint8_t** a, - int* width, int* height, - int* stride, int* uv_stride, int* a_stride) { - const WebPDecBuffer* const src = GetOutputBuffer(idec); - if (src == NULL) return NULL; - if (src->colorspace < MODE_YUV) { - return NULL; - } - - if (last_y != NULL) *last_y = idec->params_.last_y; - if (u != NULL) *u = src->u.YUVA.u; - if (v != NULL) *v = src->u.YUVA.v; - if (a != NULL) *a = src->u.YUVA.a; - if (width != NULL) *width = src->width; - if (height != NULL) *height = src->height; - if (stride != NULL) *stride = src->u.YUVA.y_stride; - if (uv_stride != NULL) *uv_stride = src->u.YUVA.u_stride; - if (a_stride != NULL) *a_stride = src->u.YUVA.a_stride; - - return src->u.YUVA.y; -} - -int WebPISetIOHooks(WebPIDecoder* const idec, - VP8IoPutHook put, - VP8IoSetupHook setup, - VP8IoTeardownHook teardown, - void* user_data) { - if (idec == NULL || idec->state_ > STATE_WEBP_HEADER) { - return 0; - } - - idec->io_.put = put; - idec->io_.setup = setup; - idec->io_.teardown = teardown; - idec->io_.opaque = user_data; - - return 1; -} diff --git a/Example-Mac/Pods/libwebp/src/dec/io.c b/Example-Mac/Pods/libwebp/src/dec/io.c deleted file mode 100644 index 13e469ab..00000000 --- a/Example-Mac/Pods/libwebp/src/dec/io.c +++ /dev/null @@ -1,614 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// functions for sample output. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include -#include "../dec/vp8i.h" -#include "./webpi.h" -#include "../dsp/dsp.h" -#include "../dsp/yuv.h" -#include "../utils/utils.h" - -//------------------------------------------------------------------------------ -// Main YUV<->RGB conversion functions - -static int EmitYUV(const VP8Io* const io, WebPDecParams* const p) { - WebPDecBuffer* output = p->output; - const WebPYUVABuffer* const buf = &output->u.YUVA; - uint8_t* const y_dst = buf->y + io->mb_y * buf->y_stride; - uint8_t* const u_dst = buf->u + (io->mb_y >> 1) * buf->u_stride; - uint8_t* const v_dst = buf->v + (io->mb_y >> 1) * buf->v_stride; - const int mb_w = io->mb_w; - const int mb_h = io->mb_h; - const int uv_w = (mb_w + 1) / 2; - const int uv_h = (mb_h + 1) / 2; - int j; - for (j = 0; j < mb_h; ++j) { - memcpy(y_dst + j * buf->y_stride, io->y + j * io->y_stride, mb_w); - } - for (j = 0; j < uv_h; ++j) { - memcpy(u_dst + j * buf->u_stride, io->u + j * io->uv_stride, uv_w); - memcpy(v_dst + j * buf->v_stride, io->v + j * io->uv_stride, uv_w); - } - return io->mb_h; -} - -// Point-sampling U/V sampler. -static int EmitSampledRGB(const VP8Io* const io, WebPDecParams* const p) { - WebPDecBuffer* const output = p->output; - WebPRGBABuffer* const buf = &output->u.RGBA; - uint8_t* const dst = buf->rgba + io->mb_y * buf->stride; - WebPSamplerProcessPlane(io->y, io->y_stride, - io->u, io->v, io->uv_stride, - dst, buf->stride, io->mb_w, io->mb_h, - WebPSamplers[output->colorspace]); - return io->mb_h; -} - -//------------------------------------------------------------------------------ -// Fancy upsampling - -#ifdef FANCY_UPSAMPLING -static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) { - int num_lines_out = io->mb_h; // a priori guess - const WebPRGBABuffer* const buf = &p->output->u.RGBA; - uint8_t* dst = buf->rgba + io->mb_y * buf->stride; - WebPUpsampleLinePairFunc upsample = WebPUpsamplers[p->output->colorspace]; - const uint8_t* cur_y = io->y; - const uint8_t* cur_u = io->u; - const uint8_t* cur_v = io->v; - const uint8_t* top_u = p->tmp_u; - const uint8_t* top_v = p->tmp_v; - int y = io->mb_y; - const int y_end = io->mb_y + io->mb_h; - const int mb_w = io->mb_w; - const int uv_w = (mb_w + 1) / 2; - - if (y == 0) { - // First line is special cased. We mirror the u/v samples at boundary. - upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, mb_w); - } else { - // We can finish the left-over line from previous call. - upsample(p->tmp_y, cur_y, top_u, top_v, cur_u, cur_v, - dst - buf->stride, dst, mb_w); - ++num_lines_out; - } - // Loop over each output pairs of row. - for (; y + 2 < y_end; y += 2) { - top_u = cur_u; - top_v = cur_v; - cur_u += io->uv_stride; - cur_v += io->uv_stride; - dst += 2 * buf->stride; - cur_y += 2 * io->y_stride; - upsample(cur_y - io->y_stride, cur_y, - top_u, top_v, cur_u, cur_v, - dst - buf->stride, dst, mb_w); - } - // move to last row - cur_y += io->y_stride; - if (io->crop_top + y_end < io->crop_bottom) { - // Save the unfinished samples for next call (as we're not done yet). - memcpy(p->tmp_y, cur_y, mb_w * sizeof(*p->tmp_y)); - memcpy(p->tmp_u, cur_u, uv_w * sizeof(*p->tmp_u)); - memcpy(p->tmp_v, cur_v, uv_w * sizeof(*p->tmp_v)); - // The fancy upsampler leaves a row unfinished behind - // (except for the very last row) - num_lines_out--; - } else { - // Process the very last row of even-sized picture - if (!(y_end & 1)) { - upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, - dst + buf->stride, NULL, mb_w); - } - } - return num_lines_out; -} - -#endif /* FANCY_UPSAMPLING */ - -//------------------------------------------------------------------------------ - -static int EmitAlphaYUV(const VP8Io* const io, WebPDecParams* const p, - int expected_num_lines_out) { - const uint8_t* alpha = io->a; - const WebPYUVABuffer* const buf = &p->output->u.YUVA; - const int mb_w = io->mb_w; - const int mb_h = io->mb_h; - uint8_t* dst = buf->a + io->mb_y * buf->a_stride; - int j; - (void)expected_num_lines_out; - assert(expected_num_lines_out == mb_h); - if (alpha != NULL) { - for (j = 0; j < mb_h; ++j) { - memcpy(dst, alpha, mb_w * sizeof(*dst)); - alpha += io->width; - dst += buf->a_stride; - } - } else if (buf->a != NULL) { - // the user requested alpha, but there is none, set it to opaque. - for (j = 0; j < mb_h; ++j) { - memset(dst, 0xff, mb_w * sizeof(*dst)); - dst += buf->a_stride; - } - } - return 0; -} - -static int GetAlphaSourceRow(const VP8Io* const io, - const uint8_t** alpha, int* const num_rows) { - int start_y = io->mb_y; - *num_rows = io->mb_h; - - // Compensate for the 1-line delay of the fancy upscaler. - // This is similar to EmitFancyRGB(). - if (io->fancy_upsampling) { - if (start_y == 0) { - // We don't process the last row yet. It'll be done during the next call. - --*num_rows; - } else { - --start_y; - // Fortunately, *alpha data is persistent, so we can go back - // one row and finish alpha blending, now that the fancy upscaler - // completed the YUV->RGB interpolation. - *alpha -= io->width; - } - if (io->crop_top + io->mb_y + io->mb_h == io->crop_bottom) { - // If it's the very last call, we process all the remaining rows! - *num_rows = io->crop_bottom - io->crop_top - start_y; - } - } - return start_y; -} - -static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p, - int expected_num_lines_out) { - const uint8_t* alpha = io->a; - if (alpha != NULL) { - const int mb_w = io->mb_w; - const WEBP_CSP_MODE colorspace = p->output->colorspace; - const int alpha_first = - (colorspace == MODE_ARGB || colorspace == MODE_Argb); - const WebPRGBABuffer* const buf = &p->output->u.RGBA; - int num_rows; - const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows); - uint8_t* const base_rgba = buf->rgba + start_y * buf->stride; - uint8_t* const dst = base_rgba + (alpha_first ? 0 : 3); - const int has_alpha = WebPDispatchAlpha(alpha, io->width, mb_w, - num_rows, dst, buf->stride); - (void)expected_num_lines_out; - assert(expected_num_lines_out == num_rows); - // has_alpha is true if there's non-trivial alpha to premultiply with. - if (has_alpha && WebPIsPremultipliedMode(colorspace)) { - WebPApplyAlphaMultiply(base_rgba, alpha_first, - mb_w, num_rows, buf->stride); - } - } - return 0; -} - -static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p, - int expected_num_lines_out) { - const uint8_t* alpha = io->a; - if (alpha != NULL) { - const int mb_w = io->mb_w; - const WEBP_CSP_MODE colorspace = p->output->colorspace; - const WebPRGBABuffer* const buf = &p->output->u.RGBA; - int num_rows; - const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows); - uint8_t* const base_rgba = buf->rgba + start_y * buf->stride; -#ifdef WEBP_SWAP_16BIT_CSP - uint8_t* alpha_dst = base_rgba; -#else - uint8_t* alpha_dst = base_rgba + 1; -#endif - uint32_t alpha_mask = 0x0f; - int i, j; - for (j = 0; j < num_rows; ++j) { - for (i = 0; i < mb_w; ++i) { - // Fill in the alpha value (converted to 4 bits). - const uint32_t alpha_value = alpha[i] >> 4; - alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value; - alpha_mask &= alpha_value; - } - alpha += io->width; - alpha_dst += buf->stride; - } - (void)expected_num_lines_out; - assert(expected_num_lines_out == num_rows); - if (alpha_mask != 0x0f && WebPIsPremultipliedMode(colorspace)) { - WebPApplyAlphaMultiply4444(base_rgba, mb_w, num_rows, buf->stride); - } - } - return 0; -} - -//------------------------------------------------------------------------------ -// YUV rescaling (no final RGB conversion needed) - -static int Rescale(const uint8_t* src, int src_stride, - int new_lines, WebPRescaler* const wrk) { - int num_lines_out = 0; - while (new_lines > 0) { // import new contributions of source rows. - const int lines_in = WebPRescalerImport(wrk, new_lines, src, src_stride); - src += lines_in * src_stride; - new_lines -= lines_in; - num_lines_out += WebPRescalerExport(wrk); // emit output row(s) - } - return num_lines_out; -} - -static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) { - const int mb_h = io->mb_h; - const int uv_mb_h = (mb_h + 1) >> 1; - WebPRescaler* const scaler = &p->scaler_y; - int num_lines_out = 0; - if (WebPIsAlphaMode(p->output->colorspace) && io->a != NULL) { - // Before rescaling, we premultiply the luma directly into the io->y - // internal buffer. This is OK since these samples are not used for - // intra-prediction (the top samples are saved in cache_y_/u_/v_). - // But we need to cast the const away, though. - WebPMultRows((uint8_t*)io->y, io->y_stride, - io->a, io->width, io->mb_w, mb_h, 0); - } - num_lines_out = Rescale(io->y, io->y_stride, mb_h, scaler); - Rescale(io->u, io->uv_stride, uv_mb_h, &p->scaler_u); - Rescale(io->v, io->uv_stride, uv_mb_h, &p->scaler_v); - return num_lines_out; -} - -static int EmitRescaledAlphaYUV(const VP8Io* const io, WebPDecParams* const p, - int expected_num_lines_out) { - if (io->a != NULL) { - const WebPYUVABuffer* const buf = &p->output->u.YUVA; - uint8_t* dst_y = buf->y + p->last_y * buf->y_stride; - const uint8_t* src_a = buf->a + p->last_y * buf->a_stride; - const int num_lines_out = Rescale(io->a, io->width, io->mb_h, &p->scaler_a); - (void)expected_num_lines_out; - assert(expected_num_lines_out == num_lines_out); - if (num_lines_out > 0) { // unmultiply the Y - WebPMultRows(dst_y, buf->y_stride, src_a, buf->a_stride, - p->scaler_a.dst_width, num_lines_out, 1); - } - } - return 0; -} - -static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) { - const int has_alpha = WebPIsAlphaMode(p->output->colorspace); - const WebPYUVABuffer* const buf = &p->output->u.YUVA; - const int out_width = io->scaled_width; - const int out_height = io->scaled_height; - const int uv_out_width = (out_width + 1) >> 1; - const int uv_out_height = (out_height + 1) >> 1; - const int uv_in_width = (io->mb_w + 1) >> 1; - const int uv_in_height = (io->mb_h + 1) >> 1; - const size_t work_size = 2 * out_width; // scratch memory for luma rescaler - const size_t uv_work_size = 2 * uv_out_width; // and for each u/v ones - size_t tmp_size; - rescaler_t* work; - - tmp_size = (work_size + 2 * uv_work_size) * sizeof(*work); - if (has_alpha) { - tmp_size += work_size * sizeof(*work); - } - p->memory = WebPSafeMalloc(1ULL, tmp_size); - if (p->memory == NULL) { - return 0; // memory error - } - work = (rescaler_t*)p->memory; - WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h, - buf->y, out_width, out_height, buf->y_stride, 1, - work); - WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height, - buf->u, uv_out_width, uv_out_height, buf->u_stride, 1, - work + work_size); - WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height, - buf->v, uv_out_width, uv_out_height, buf->v_stride, 1, - work + work_size + uv_work_size); - p->emit = EmitRescaledYUV; - - if (has_alpha) { - WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h, - buf->a, out_width, out_height, buf->a_stride, 1, - work + work_size + 2 * uv_work_size); - p->emit_alpha = EmitRescaledAlphaYUV; - WebPInitAlphaProcessing(); - } - return 1; -} - -//------------------------------------------------------------------------------ -// RGBA rescaling - -static int ExportRGB(WebPDecParams* const p, int y_pos) { - const WebPYUV444Converter convert = - WebPYUV444Converters[p->output->colorspace]; - const WebPRGBABuffer* const buf = &p->output->u.RGBA; - uint8_t* dst = buf->rgba + y_pos * buf->stride; - int num_lines_out = 0; - // For RGB rescaling, because of the YUV420, current scan position - // U/V can be +1/-1 line from the Y one. Hence the double test. - while (WebPRescalerHasPendingOutput(&p->scaler_y) && - WebPRescalerHasPendingOutput(&p->scaler_u)) { - assert(y_pos + num_lines_out < p->output->height); - assert(p->scaler_u.y_accum == p->scaler_v.y_accum); - WebPRescalerExportRow(&p->scaler_y); - WebPRescalerExportRow(&p->scaler_u); - WebPRescalerExportRow(&p->scaler_v); - convert(p->scaler_y.dst, p->scaler_u.dst, p->scaler_v.dst, - dst, p->scaler_y.dst_width); - dst += buf->stride; - ++num_lines_out; - } - return num_lines_out; -} - -static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) { - const int mb_h = io->mb_h; - const int uv_mb_h = (mb_h + 1) >> 1; - int j = 0, uv_j = 0; - int num_lines_out = 0; - while (j < mb_h) { - const int y_lines_in = - WebPRescalerImport(&p->scaler_y, mb_h - j, - io->y + j * io->y_stride, io->y_stride); - j += y_lines_in; - if (WebPRescaleNeededLines(&p->scaler_u, uv_mb_h - uv_j)) { - const int u_lines_in = - WebPRescalerImport(&p->scaler_u, uv_mb_h - uv_j, - io->u + uv_j * io->uv_stride, io->uv_stride); - const int v_lines_in = - WebPRescalerImport(&p->scaler_v, uv_mb_h - uv_j, - io->v + uv_j * io->uv_stride, io->uv_stride); - (void)v_lines_in; // remove a gcc warning - assert(u_lines_in == v_lines_in); - uv_j += u_lines_in; - } - num_lines_out += ExportRGB(p, p->last_y + num_lines_out); - } - return num_lines_out; -} - -static int ExportAlpha(WebPDecParams* const p, int y_pos, int max_lines_out) { - const WebPRGBABuffer* const buf = &p->output->u.RGBA; - uint8_t* const base_rgba = buf->rgba + y_pos * buf->stride; - const WEBP_CSP_MODE colorspace = p->output->colorspace; - const int alpha_first = - (colorspace == MODE_ARGB || colorspace == MODE_Argb); - uint8_t* dst = base_rgba + (alpha_first ? 0 : 3); - int num_lines_out = 0; - const int is_premult_alpha = WebPIsPremultipliedMode(colorspace); - uint32_t non_opaque = 0; - const int width = p->scaler_a.dst_width; - - while (WebPRescalerHasPendingOutput(&p->scaler_a) && - num_lines_out < max_lines_out) { - assert(y_pos + num_lines_out < p->output->height); - WebPRescalerExportRow(&p->scaler_a); - non_opaque |= WebPDispatchAlpha(p->scaler_a.dst, 0, width, 1, dst, 0); - dst += buf->stride; - ++num_lines_out; - } - if (is_premult_alpha && non_opaque) { - WebPApplyAlphaMultiply(base_rgba, alpha_first, - width, num_lines_out, buf->stride); - } - return num_lines_out; -} - -static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos, - int max_lines_out) { - const WebPRGBABuffer* const buf = &p->output->u.RGBA; - uint8_t* const base_rgba = buf->rgba + y_pos * buf->stride; -#ifdef WEBP_SWAP_16BIT_CSP - uint8_t* alpha_dst = base_rgba; -#else - uint8_t* alpha_dst = base_rgba + 1; -#endif - int num_lines_out = 0; - const WEBP_CSP_MODE colorspace = p->output->colorspace; - const int width = p->scaler_a.dst_width; - const int is_premult_alpha = WebPIsPremultipliedMode(colorspace); - uint32_t alpha_mask = 0x0f; - - while (WebPRescalerHasPendingOutput(&p->scaler_a) && - num_lines_out < max_lines_out) { - int i; - assert(y_pos + num_lines_out < p->output->height); - WebPRescalerExportRow(&p->scaler_a); - for (i = 0; i < width; ++i) { - // Fill in the alpha value (converted to 4 bits). - const uint32_t alpha_value = p->scaler_a.dst[i] >> 4; - alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value; - alpha_mask &= alpha_value; - } - alpha_dst += buf->stride; - ++num_lines_out; - } - if (is_premult_alpha && alpha_mask != 0x0f) { - WebPApplyAlphaMultiply4444(base_rgba, width, num_lines_out, buf->stride); - } - return num_lines_out; -} - -static int EmitRescaledAlphaRGB(const VP8Io* const io, WebPDecParams* const p, - int expected_num_out_lines) { - if (io->a != NULL) { - WebPRescaler* const scaler = &p->scaler_a; - int lines_left = expected_num_out_lines; - const int y_end = p->last_y + lines_left; - while (lines_left > 0) { - const int row_offset = scaler->src_y - io->mb_y; - WebPRescalerImport(scaler, io->mb_h + io->mb_y - scaler->src_y, - io->a + row_offset * io->width, io->width); - lines_left -= p->emit_alpha_row(p, y_end - lines_left, lines_left); - } - } - return 0; -} - -static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) { - const int has_alpha = WebPIsAlphaMode(p->output->colorspace); - const int out_width = io->scaled_width; - const int out_height = io->scaled_height; - const int uv_in_width = (io->mb_w + 1) >> 1; - const int uv_in_height = (io->mb_h + 1) >> 1; - const size_t work_size = 2 * out_width; // scratch memory for one rescaler - rescaler_t* work; // rescalers work area - uint8_t* tmp; // tmp storage for scaled YUV444 samples before RGB conversion - size_t tmp_size1, tmp_size2, total_size; - - tmp_size1 = 3 * work_size; - tmp_size2 = 3 * out_width; - if (has_alpha) { - tmp_size1 += work_size; - tmp_size2 += out_width; - } - total_size = tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp); - p->memory = WebPSafeMalloc(1ULL, total_size); - if (p->memory == NULL) { - return 0; // memory error - } - work = (rescaler_t*)p->memory; - tmp = (uint8_t*)(work + tmp_size1); - WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h, - tmp + 0 * out_width, out_width, out_height, 0, 1, - work + 0 * work_size); - WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height, - tmp + 1 * out_width, out_width, out_height, 0, 1, - work + 1 * work_size); - WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height, - tmp + 2 * out_width, out_width, out_height, 0, 1, - work + 2 * work_size); - p->emit = EmitRescaledRGB; - WebPInitYUV444Converters(); - - if (has_alpha) { - WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h, - tmp + 3 * out_width, out_width, out_height, 0, 1, - work + 3 * work_size); - p->emit_alpha = EmitRescaledAlphaRGB; - if (p->output->colorspace == MODE_RGBA_4444 || - p->output->colorspace == MODE_rgbA_4444) { - p->emit_alpha_row = ExportAlphaRGBA4444; - } else { - p->emit_alpha_row = ExportAlpha; - } - WebPInitAlphaProcessing(); - } - return 1; -} - -//------------------------------------------------------------------------------ -// Default custom functions - -static int CustomSetup(VP8Io* io) { - WebPDecParams* const p = (WebPDecParams*)io->opaque; - const WEBP_CSP_MODE colorspace = p->output->colorspace; - const int is_rgb = WebPIsRGBMode(colorspace); - const int is_alpha = WebPIsAlphaMode(colorspace); - - p->memory = NULL; - p->emit = NULL; - p->emit_alpha = NULL; - p->emit_alpha_row = NULL; - if (!WebPIoInitFromOptions(p->options, io, is_alpha ? MODE_YUV : MODE_YUVA)) { - return 0; - } - if (is_alpha && WebPIsPremultipliedMode(colorspace)) { - WebPInitUpsamplers(); - } - if (io->use_scaling) { - const int ok = is_rgb ? InitRGBRescaler(io, p) : InitYUVRescaler(io, p); - if (!ok) { - return 0; // memory error - } - } else { - if (is_rgb) { - WebPInitSamplers(); - p->emit = EmitSampledRGB; // default - if (io->fancy_upsampling) { -#ifdef FANCY_UPSAMPLING - const int uv_width = (io->mb_w + 1) >> 1; - p->memory = WebPSafeMalloc(1ULL, (size_t)(io->mb_w + 2 * uv_width)); - if (p->memory == NULL) { - return 0; // memory error. - } - p->tmp_y = (uint8_t*)p->memory; - p->tmp_u = p->tmp_y + io->mb_w; - p->tmp_v = p->tmp_u + uv_width; - p->emit = EmitFancyRGB; - WebPInitUpsamplers(); -#endif - } - } else { - p->emit = EmitYUV; - } - if (is_alpha) { // need transparency output - p->emit_alpha = - (colorspace == MODE_RGBA_4444 || colorspace == MODE_rgbA_4444) ? - EmitAlphaRGBA4444 - : is_rgb ? EmitAlphaRGB - : EmitAlphaYUV; - if (is_rgb) { - WebPInitAlphaProcessing(); - } - } - } - - if (is_rgb) { - VP8YUVInit(); - } - return 1; -} - -//------------------------------------------------------------------------------ - -static int CustomPut(const VP8Io* io) { - WebPDecParams* const p = (WebPDecParams*)io->opaque; - const int mb_w = io->mb_w; - const int mb_h = io->mb_h; - int num_lines_out; - assert(!(io->mb_y & 1)); - - if (mb_w <= 0 || mb_h <= 0) { - return 0; - } - num_lines_out = p->emit(io, p); - if (p->emit_alpha != NULL) { - p->emit_alpha(io, p, num_lines_out); - } - p->last_y += num_lines_out; - return 1; -} - -//------------------------------------------------------------------------------ - -static void CustomTeardown(const VP8Io* io) { - WebPDecParams* const p = (WebPDecParams*)io->opaque; - WebPSafeFree(p->memory); - p->memory = NULL; -} - -//------------------------------------------------------------------------------ -// Main entry point - -void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io) { - io->put = CustomPut; - io->setup = CustomSetup; - io->teardown = CustomTeardown; - io->opaque = params; -} - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/dec/quant.c b/Example-Mac/Pods/libwebp/src/dec/quant.c deleted file mode 100644 index 5b648f94..00000000 --- a/Example-Mac/Pods/libwebp/src/dec/quant.c +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Quantizer initialization -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./vp8i.h" - -static WEBP_INLINE int clip(int v, int M) { - return v < 0 ? 0 : v > M ? M : v; -} - -// Paragraph 14.1 -static const uint8_t kDcTable[128] = { - 4, 5, 6, 7, 8, 9, 10, 10, - 11, 12, 13, 14, 15, 16, 17, 17, - 18, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 25, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, - 37, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, - 91, 93, 95, 96, 98, 100, 101, 102, - 104, 106, 108, 110, 112, 114, 116, 118, - 122, 124, 126, 128, 130, 132, 134, 136, - 138, 140, 143, 145, 148, 151, 154, 157 -}; - -static const uint16_t kAcTable[128] = { - 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 60, - 62, 64, 66, 68, 70, 72, 74, 76, - 78, 80, 82, 84, 86, 88, 90, 92, - 94, 96, 98, 100, 102, 104, 106, 108, - 110, 112, 114, 116, 119, 122, 125, 128, - 131, 134, 137, 140, 143, 146, 149, 152, - 155, 158, 161, 164, 167, 170, 173, 177, - 181, 185, 189, 193, 197, 201, 205, 209, - 213, 217, 221, 225, 229, 234, 239, 245, - 249, 254, 259, 264, 269, 274, 279, 284 -}; - -//------------------------------------------------------------------------------ -// Paragraph 9.6 - -void VP8ParseQuant(VP8Decoder* const dec) { - VP8BitReader* const br = &dec->br_; - const int base_q0 = VP8GetValue(br, 7); - const int dqy1_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0; - const int dqy2_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0; - const int dqy2_ac = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0; - const int dquv_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0; - const int dquv_ac = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0; - - const VP8SegmentHeader* const hdr = &dec->segment_hdr_; - int i; - - for (i = 0; i < NUM_MB_SEGMENTS; ++i) { - int q; - if (hdr->use_segment_) { - q = hdr->quantizer_[i]; - if (!hdr->absolute_delta_) { - q += base_q0; - } - } else { - if (i > 0) { - dec->dqm_[i] = dec->dqm_[0]; - continue; - } else { - q = base_q0; - } - } - { - VP8QuantMatrix* const m = &dec->dqm_[i]; - m->y1_mat_[0] = kDcTable[clip(q + dqy1_dc, 127)]; - m->y1_mat_[1] = kAcTable[clip(q + 0, 127)]; - - m->y2_mat_[0] = kDcTable[clip(q + dqy2_dc, 127)] * 2; - // For all x in [0..284], x*155/100 is bitwise equal to (x*101581) >> 16. - // The smallest precision for that is '(x*6349) >> 12' but 16 is a good - // word size. - m->y2_mat_[1] = (kAcTable[clip(q + dqy2_ac, 127)] * 101581) >> 16; - if (m->y2_mat_[1] < 8) m->y2_mat_[1] = 8; - - m->uv_mat_[0] = kDcTable[clip(q + dquv_dc, 117)]; - m->uv_mat_[1] = kAcTable[clip(q + dquv_ac, 127)]; - - m->uv_quant_ = q + dquv_ac; // for dithering strength evaluation - } - } -} - -//------------------------------------------------------------------------------ - diff --git a/Example-Mac/Pods/libwebp/src/dec/tree.c b/Example-Mac/Pods/libwebp/src/dec/tree.c deleted file mode 100644 index c2007ea7..00000000 --- a/Example-Mac/Pods/libwebp/src/dec/tree.c +++ /dev/null @@ -1,525 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Coding trees and probas -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./vp8i.h" -#include "../utils/bit_reader_inl.h" - -#define USE_GENERIC_TREE - -#ifdef USE_GENERIC_TREE -static const int8_t kYModesIntra4[18] = { - -B_DC_PRED, 1, - -B_TM_PRED, 2, - -B_VE_PRED, 3, - 4, 6, - -B_HE_PRED, 5, - -B_RD_PRED, -B_VR_PRED, - -B_LD_PRED, 7, - -B_VL_PRED, 8, - -B_HD_PRED, -B_HU_PRED -}; -#endif - -//------------------------------------------------------------------------------ -// Default probabilities - -// Paragraph 13.5 -static const uint8_t - CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = { - { { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } - }, - { { 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128 }, - { 189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128 }, - { 106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128 } - }, - { { 1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128 }, - { 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128 }, - { 78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128 }, - }, - { { 1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128 }, - { 184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128 }, - { 77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128 }, - }, - { { 1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128 }, - { 170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128 }, - { 37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128 } - }, - { { 1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128 }, - { 207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128 }, - { 102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128 } - }, - { { 1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128 }, - { 177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128 }, - { 80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128 } - }, - { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } - } - }, - { { { 198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62 }, - { 131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1 }, - { 68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128 } - }, - { { 1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128 }, - { 184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128 }, - { 81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128 } - }, - { { 1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128 }, - { 99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128 }, - { 23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128 } - }, - { { 1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128 }, - { 109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128 }, - { 44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128 } - }, - { { 1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128 }, - { 94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128 }, - { 22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128 } - }, - { { 1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128 }, - { 124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128 }, - { 35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128 } - }, - { { 1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128 }, - { 121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128 }, - { 45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128 } - }, - { { 1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128 }, - { 203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128 } - } - }, - { { { 253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128 }, - { 175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128 }, - { 73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128 } - }, - { { 1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128 }, - { 239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128 }, - { 155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128 } - }, - { { 1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128 }, - { 201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128 }, - { 69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128 } - }, - { { 1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128 }, - { 141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128 } - }, - { { 1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128 }, - { 149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 } - }, - { { 1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128 } - }, - { { 1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128 } - }, - { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } - } - }, - { { { 202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255 }, - { 126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128 }, - { 61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128 } - }, - { { 1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128 }, - { 166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128 }, - { 39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128 } - }, - { { 1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128 }, - { 124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128 }, - { 24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128 } - }, - { { 1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128 }, - { 149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128 }, - { 28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128 } - }, - { { 1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128 }, - { 123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128 }, - { 20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128 } - }, - { { 1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128 }, - { 168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128 }, - { 47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128 } - }, - { { 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128 }, - { 141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128 }, - { 42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128 } - }, - { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 } - } - } -}; - -// Paragraph 11.5 -static const uint8_t kBModesProba[NUM_BMODES][NUM_BMODES][NUM_BMODES - 1] = { - { { 231, 120, 48, 89, 115, 113, 120, 152, 112 }, - { 152, 179, 64, 126, 170, 118, 46, 70, 95 }, - { 175, 69, 143, 80, 85, 82, 72, 155, 103 }, - { 56, 58, 10, 171, 218, 189, 17, 13, 152 }, - { 114, 26, 17, 163, 44, 195, 21, 10, 173 }, - { 121, 24, 80, 195, 26, 62, 44, 64, 85 }, - { 144, 71, 10, 38, 171, 213, 144, 34, 26 }, - { 170, 46, 55, 19, 136, 160, 33, 206, 71 }, - { 63, 20, 8, 114, 114, 208, 12, 9, 226 }, - { 81, 40, 11, 96, 182, 84, 29, 16, 36 } }, - { { 134, 183, 89, 137, 98, 101, 106, 165, 148 }, - { 72, 187, 100, 130, 157, 111, 32, 75, 80 }, - { 66, 102, 167, 99, 74, 62, 40, 234, 128 }, - { 41, 53, 9, 178, 241, 141, 26, 8, 107 }, - { 74, 43, 26, 146, 73, 166, 49, 23, 157 }, - { 65, 38, 105, 160, 51, 52, 31, 115, 128 }, - { 104, 79, 12, 27, 217, 255, 87, 17, 7 }, - { 87, 68, 71, 44, 114, 51, 15, 186, 23 }, - { 47, 41, 14, 110, 182, 183, 21, 17, 194 }, - { 66, 45, 25, 102, 197, 189, 23, 18, 22 } }, - { { 88, 88, 147, 150, 42, 46, 45, 196, 205 }, - { 43, 97, 183, 117, 85, 38, 35, 179, 61 }, - { 39, 53, 200, 87, 26, 21, 43, 232, 171 }, - { 56, 34, 51, 104, 114, 102, 29, 93, 77 }, - { 39, 28, 85, 171, 58, 165, 90, 98, 64 }, - { 34, 22, 116, 206, 23, 34, 43, 166, 73 }, - { 107, 54, 32, 26, 51, 1, 81, 43, 31 }, - { 68, 25, 106, 22, 64, 171, 36, 225, 114 }, - { 34, 19, 21, 102, 132, 188, 16, 76, 124 }, - { 62, 18, 78, 95, 85, 57, 50, 48, 51 } }, - { { 193, 101, 35, 159, 215, 111, 89, 46, 111 }, - { 60, 148, 31, 172, 219, 228, 21, 18, 111 }, - { 112, 113, 77, 85, 179, 255, 38, 120, 114 }, - { 40, 42, 1, 196, 245, 209, 10, 25, 109 }, - { 88, 43, 29, 140, 166, 213, 37, 43, 154 }, - { 61, 63, 30, 155, 67, 45, 68, 1, 209 }, - { 100, 80, 8, 43, 154, 1, 51, 26, 71 }, - { 142, 78, 78, 16, 255, 128, 34, 197, 171 }, - { 41, 40, 5, 102, 211, 183, 4, 1, 221 }, - { 51, 50, 17, 168, 209, 192, 23, 25, 82 } }, - { { 138, 31, 36, 171, 27, 166, 38, 44, 229 }, - { 67, 87, 58, 169, 82, 115, 26, 59, 179 }, - { 63, 59, 90, 180, 59, 166, 93, 73, 154 }, - { 40, 40, 21, 116, 143, 209, 34, 39, 175 }, - { 47, 15, 16, 183, 34, 223, 49, 45, 183 }, - { 46, 17, 33, 183, 6, 98, 15, 32, 183 }, - { 57, 46, 22, 24, 128, 1, 54, 17, 37 }, - { 65, 32, 73, 115, 28, 128, 23, 128, 205 }, - { 40, 3, 9, 115, 51, 192, 18, 6, 223 }, - { 87, 37, 9, 115, 59, 77, 64, 21, 47 } }, - { { 104, 55, 44, 218, 9, 54, 53, 130, 226 }, - { 64, 90, 70, 205, 40, 41, 23, 26, 57 }, - { 54, 57, 112, 184, 5, 41, 38, 166, 213 }, - { 30, 34, 26, 133, 152, 116, 10, 32, 134 }, - { 39, 19, 53, 221, 26, 114, 32, 73, 255 }, - { 31, 9, 65, 234, 2, 15, 1, 118, 73 }, - { 75, 32, 12, 51, 192, 255, 160, 43, 51 }, - { 88, 31, 35, 67, 102, 85, 55, 186, 85 }, - { 56, 21, 23, 111, 59, 205, 45, 37, 192 }, - { 55, 38, 70, 124, 73, 102, 1, 34, 98 } }, - { { 125, 98, 42, 88, 104, 85, 117, 175, 82 }, - { 95, 84, 53, 89, 128, 100, 113, 101, 45 }, - { 75, 79, 123, 47, 51, 128, 81, 171, 1 }, - { 57, 17, 5, 71, 102, 57, 53, 41, 49 }, - { 38, 33, 13, 121, 57, 73, 26, 1, 85 }, - { 41, 10, 67, 138, 77, 110, 90, 47, 114 }, - { 115, 21, 2, 10, 102, 255, 166, 23, 6 }, - { 101, 29, 16, 10, 85, 128, 101, 196, 26 }, - { 57, 18, 10, 102, 102, 213, 34, 20, 43 }, - { 117, 20, 15, 36, 163, 128, 68, 1, 26 } }, - { { 102, 61, 71, 37, 34, 53, 31, 243, 192 }, - { 69, 60, 71, 38, 73, 119, 28, 222, 37 }, - { 68, 45, 128, 34, 1, 47, 11, 245, 171 }, - { 62, 17, 19, 70, 146, 85, 55, 62, 70 }, - { 37, 43, 37, 154, 100, 163, 85, 160, 1 }, - { 63, 9, 92, 136, 28, 64, 32, 201, 85 }, - { 75, 15, 9, 9, 64, 255, 184, 119, 16 }, - { 86, 6, 28, 5, 64, 255, 25, 248, 1 }, - { 56, 8, 17, 132, 137, 255, 55, 116, 128 }, - { 58, 15, 20, 82, 135, 57, 26, 121, 40 } }, - { { 164, 50, 31, 137, 154, 133, 25, 35, 218 }, - { 51, 103, 44, 131, 131, 123, 31, 6, 158 }, - { 86, 40, 64, 135, 148, 224, 45, 183, 128 }, - { 22, 26, 17, 131, 240, 154, 14, 1, 209 }, - { 45, 16, 21, 91, 64, 222, 7, 1, 197 }, - { 56, 21, 39, 155, 60, 138, 23, 102, 213 }, - { 83, 12, 13, 54, 192, 255, 68, 47, 28 }, - { 85, 26, 85, 85, 128, 128, 32, 146, 171 }, - { 18, 11, 7, 63, 144, 171, 4, 4, 246 }, - { 35, 27, 10, 146, 174, 171, 12, 26, 128 } }, - { { 190, 80, 35, 99, 180, 80, 126, 54, 45 }, - { 85, 126, 47, 87, 176, 51, 41, 20, 32 }, - { 101, 75, 128, 139, 118, 146, 116, 128, 85 }, - { 56, 41, 15, 176, 236, 85, 37, 9, 62 }, - { 71, 30, 17, 119, 118, 255, 17, 18, 138 }, - { 101, 38, 60, 138, 55, 70, 43, 26, 142 }, - { 146, 36, 19, 30, 171, 255, 97, 27, 20 }, - { 138, 45, 61, 62, 219, 1, 81, 188, 64 }, - { 32, 41, 20, 117, 151, 142, 20, 21, 163 }, - { 112, 19, 12, 61, 195, 128, 48, 4, 24 } } -}; - -void VP8ResetProba(VP8Proba* const proba) { - memset(proba->segments_, 255u, sizeof(proba->segments_)); - // proba->bands_[][] is initialized later -} - -static void ParseIntraMode(VP8BitReader* const br, - VP8Decoder* const dec, int mb_x) { - uint8_t* const top = dec->intra_t_ + 4 * mb_x; - uint8_t* const left = dec->intra_l_; - VP8MBData* const block = dec->mb_data_ + mb_x; - - // Note: we don't save segment map (yet), as we don't expect - // to decode more than 1 keyframe. - if (dec->segment_hdr_.update_map_) { - // Hardcoded tree parsing - block->segment_ = !VP8GetBit(br, dec->proba_.segments_[0]) - ? VP8GetBit(br, dec->proba_.segments_[1]) - : 2 + VP8GetBit(br, dec->proba_.segments_[2]); - } else { - block->segment_ = 0; // default for intra - } - if (dec->use_skip_proba_) block->skip_ = VP8GetBit(br, dec->skip_p_); - - block->is_i4x4_ = !VP8GetBit(br, 145); // decide for B_PRED first - if (!block->is_i4x4_) { - // Hardcoded 16x16 intra-mode decision tree. - const int ymode = - VP8GetBit(br, 156) ? (VP8GetBit(br, 128) ? TM_PRED : H_PRED) - : (VP8GetBit(br, 163) ? V_PRED : DC_PRED); - block->imodes_[0] = ymode; - memset(top, ymode, 4 * sizeof(*top)); - memset(left, ymode, 4 * sizeof(*left)); - } else { - uint8_t* modes = block->imodes_; - int y; - for (y = 0; y < 4; ++y) { - int ymode = left[y]; - int x; - for (x = 0; x < 4; ++x) { - const uint8_t* const prob = kBModesProba[top[x]][ymode]; -#ifdef USE_GENERIC_TREE - // Generic tree-parsing - int i = kYModesIntra4[VP8GetBit(br, prob[0])]; - while (i > 0) { - i = kYModesIntra4[2 * i + VP8GetBit(br, prob[i])]; - } - ymode = -i; -#else - // Hardcoded tree parsing - ymode = !VP8GetBit(br, prob[0]) ? B_DC_PRED : - !VP8GetBit(br, prob[1]) ? B_TM_PRED : - !VP8GetBit(br, prob[2]) ? B_VE_PRED : - !VP8GetBit(br, prob[3]) ? - (!VP8GetBit(br, prob[4]) ? B_HE_PRED : - (!VP8GetBit(br, prob[5]) ? B_RD_PRED : B_VR_PRED)) : - (!VP8GetBit(br, prob[6]) ? B_LD_PRED : - (!VP8GetBit(br, prob[7]) ? B_VL_PRED : - (!VP8GetBit(br, prob[8]) ? B_HD_PRED : B_HU_PRED))); -#endif // USE_GENERIC_TREE - top[x] = ymode; - } - memcpy(modes, top, 4 * sizeof(*top)); - modes += 4; - left[y] = ymode; - } - } - // Hardcoded UVMode decision tree - block->uvmode_ = !VP8GetBit(br, 142) ? DC_PRED - : !VP8GetBit(br, 114) ? V_PRED - : VP8GetBit(br, 183) ? TM_PRED : H_PRED; -} - -int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec) { - int mb_x; - for (mb_x = 0; mb_x < dec->mb_w_; ++mb_x) { - ParseIntraMode(br, dec, mb_x); - } - return !dec->br_.eof_; -} - -//------------------------------------------------------------------------------ -// Paragraph 13 - -static const uint8_t - CoeffsUpdateProba[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = { - { { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255 }, - { 250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - } - }, - { { { 217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255 }, - { 234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255 } - }, - { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - } - }, - { { { 186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255 }, - { 251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255 } - }, - { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - } - }, - { { { 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255 }, - { 248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - } - } -}; - -// Paragraph 9.9 - -static const int kBands[16 + 1] = { - 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, - 0 // extra entry as sentinel -}; - -void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) { - VP8Proba* const proba = &dec->proba_; - int t, b, c, p; - for (t = 0; t < NUM_TYPES; ++t) { - for (b = 0; b < NUM_BANDS; ++b) { - for (c = 0; c < NUM_CTX; ++c) { - for (p = 0; p < NUM_PROBAS; ++p) { - const int v = VP8GetBit(br, CoeffsUpdateProba[t][b][c][p]) ? - VP8GetValue(br, 8) : CoeffsProba0[t][b][c][p]; - proba->bands_[t][b].probas_[c][p] = v; - } - } - } - for (b = 0; b < 16 + 1; ++b) { - proba->bands_ptr_[t][b] = &proba->bands_[t][kBands[b]]; - } - } - dec->use_skip_proba_ = VP8Get(br); - if (dec->use_skip_proba_) { - dec->skip_p_ = VP8GetValue(br, 8); - } -} - diff --git a/Example-Mac/Pods/libwebp/src/dec/vp8.c b/Example-Mac/Pods/libwebp/src/dec/vp8.c deleted file mode 100644 index d89eb1c5..00000000 --- a/Example-Mac/Pods/libwebp/src/dec/vp8.c +++ /dev/null @@ -1,662 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// main entry for the decoder -// -// Author: Skal (pascal.massimino@gmail.com) - -#include - -#include "./alphai.h" -#include "./vp8i.h" -#include "./vp8li.h" -#include "./webpi.h" -#include "../utils/bit_reader_inl.h" -#include "../utils/utils.h" - -//------------------------------------------------------------------------------ - -int WebPGetDecoderVersion(void) { - return (DEC_MAJ_VERSION << 16) | (DEC_MIN_VERSION << 8) | DEC_REV_VERSION; -} - -//------------------------------------------------------------------------------ -// VP8Decoder - -static void SetOk(VP8Decoder* const dec) { - dec->status_ = VP8_STATUS_OK; - dec->error_msg_ = "OK"; -} - -int VP8InitIoInternal(VP8Io* const io, int version) { - if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { - return 0; // mismatch error - } - if (io != NULL) { - memset(io, 0, sizeof(*io)); - } - return 1; -} - -VP8Decoder* VP8New(void) { - VP8Decoder* const dec = (VP8Decoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); - if (dec != NULL) { - SetOk(dec); - WebPGetWorkerInterface()->Init(&dec->worker_); - dec->ready_ = 0; - dec->num_parts_ = 1; - } - return dec; -} - -VP8StatusCode VP8Status(VP8Decoder* const dec) { - if (!dec) return VP8_STATUS_INVALID_PARAM; - return dec->status_; -} - -const char* VP8StatusMessage(VP8Decoder* const dec) { - if (dec == NULL) return "no object"; - if (!dec->error_msg_) return "OK"; - return dec->error_msg_; -} - -void VP8Delete(VP8Decoder* const dec) { - if (dec != NULL) { - VP8Clear(dec); - WebPSafeFree(dec); - } -} - -int VP8SetError(VP8Decoder* const dec, - VP8StatusCode error, const char* const msg) { - // The oldest error reported takes precedence over the new one. - if (dec->status_ == VP8_STATUS_OK) { - dec->status_ = error; - dec->error_msg_ = msg; - dec->ready_ = 0; - } - return 0; -} - -//------------------------------------------------------------------------------ - -int VP8CheckSignature(const uint8_t* const data, size_t data_size) { - return (data_size >= 3 && - data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a); -} - -int VP8GetInfo(const uint8_t* data, size_t data_size, size_t chunk_size, - int* const width, int* const height) { - if (data == NULL || data_size < VP8_FRAME_HEADER_SIZE) { - return 0; // not enough data - } - // check signature - if (!VP8CheckSignature(data + 3, data_size - 3)) { - return 0; // Wrong signature. - } else { - const uint32_t bits = data[0] | (data[1] << 8) | (data[2] << 16); - const int key_frame = !(bits & 1); - const int w = ((data[7] << 8) | data[6]) & 0x3fff; - const int h = ((data[9] << 8) | data[8]) & 0x3fff; - - if (!key_frame) { // Not a keyframe. - return 0; - } - - if (((bits >> 1) & 7) > 3) { - return 0; // unknown profile - } - if (!((bits >> 4) & 1)) { - return 0; // first frame is invisible! - } - if (((bits >> 5)) >= chunk_size) { // partition_length - return 0; // inconsistent size information. - } - if (w == 0 || h == 0) { - return 0; // We don't support both width and height to be zero. - } - - if (width) { - *width = w; - } - if (height) { - *height = h; - } - - return 1; - } -} - -//------------------------------------------------------------------------------ -// Header parsing - -static void ResetSegmentHeader(VP8SegmentHeader* const hdr) { - assert(hdr != NULL); - hdr->use_segment_ = 0; - hdr->update_map_ = 0; - hdr->absolute_delta_ = 1; - memset(hdr->quantizer_, 0, sizeof(hdr->quantizer_)); - memset(hdr->filter_strength_, 0, sizeof(hdr->filter_strength_)); -} - -// Paragraph 9.3 -static int ParseSegmentHeader(VP8BitReader* br, - VP8SegmentHeader* hdr, VP8Proba* proba) { - assert(br != NULL); - assert(hdr != NULL); - hdr->use_segment_ = VP8Get(br); - if (hdr->use_segment_) { - hdr->update_map_ = VP8Get(br); - if (VP8Get(br)) { // update data - int s; - hdr->absolute_delta_ = VP8Get(br); - for (s = 0; s < NUM_MB_SEGMENTS; ++s) { - hdr->quantizer_[s] = VP8Get(br) ? VP8GetSignedValue(br, 7) : 0; - } - for (s = 0; s < NUM_MB_SEGMENTS; ++s) { - hdr->filter_strength_[s] = VP8Get(br) ? VP8GetSignedValue(br, 6) : 0; - } - } - if (hdr->update_map_) { - int s; - for (s = 0; s < MB_FEATURE_TREE_PROBS; ++s) { - proba->segments_[s] = VP8Get(br) ? VP8GetValue(br, 8) : 255u; - } - } - } else { - hdr->update_map_ = 0; - } - return !br->eof_; -} - -// Paragraph 9.5 -// This function returns VP8_STATUS_SUSPENDED if we don't have all the -// necessary data in 'buf'. -// This case is not necessarily an error (for incremental decoding). -// Still, no bitreader is ever initialized to make it possible to read -// unavailable memory. -// If we don't even have the partitions' sizes, than VP8_STATUS_NOT_ENOUGH_DATA -// is returned, and this is an unrecoverable error. -// If the partitions were positioned ok, VP8_STATUS_OK is returned. -static VP8StatusCode ParsePartitions(VP8Decoder* const dec, - const uint8_t* buf, size_t size) { - VP8BitReader* const br = &dec->br_; - const uint8_t* sz = buf; - const uint8_t* buf_end = buf + size; - const uint8_t* part_start; - size_t size_left = size; - size_t last_part; - size_t p; - - dec->num_parts_ = 1 << VP8GetValue(br, 2); - last_part = dec->num_parts_ - 1; - if (size < 3 * last_part) { - // we can't even read the sizes with sz[]! That's a failure. - return VP8_STATUS_NOT_ENOUGH_DATA; - } - part_start = buf + last_part * 3; - size_left -= last_part * 3; - for (p = 0; p < last_part; ++p) { - size_t psize = sz[0] | (sz[1] << 8) | (sz[2] << 16); - if (psize > size_left) psize = size_left; - VP8InitBitReader(dec->parts_ + p, part_start, psize); - part_start += psize; - size_left -= psize; - sz += 3; - } - VP8InitBitReader(dec->parts_ + last_part, part_start, size_left); - return (part_start < buf_end) ? VP8_STATUS_OK : - VP8_STATUS_SUSPENDED; // Init is ok, but there's not enough data -} - -// Paragraph 9.4 -static int ParseFilterHeader(VP8BitReader* br, VP8Decoder* const dec) { - VP8FilterHeader* const hdr = &dec->filter_hdr_; - hdr->simple_ = VP8Get(br); - hdr->level_ = VP8GetValue(br, 6); - hdr->sharpness_ = VP8GetValue(br, 3); - hdr->use_lf_delta_ = VP8Get(br); - if (hdr->use_lf_delta_) { - if (VP8Get(br)) { // update lf-delta? - int i; - for (i = 0; i < NUM_REF_LF_DELTAS; ++i) { - if (VP8Get(br)) { - hdr->ref_lf_delta_[i] = VP8GetSignedValue(br, 6); - } - } - for (i = 0; i < NUM_MODE_LF_DELTAS; ++i) { - if (VP8Get(br)) { - hdr->mode_lf_delta_[i] = VP8GetSignedValue(br, 6); - } - } - } - } - dec->filter_type_ = (hdr->level_ == 0) ? 0 : hdr->simple_ ? 1 : 2; - return !br->eof_; -} - -// Topmost call -int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) { - const uint8_t* buf; - size_t buf_size; - VP8FrameHeader* frm_hdr; - VP8PictureHeader* pic_hdr; - VP8BitReader* br; - VP8StatusCode status; - - if (dec == NULL) { - return 0; - } - SetOk(dec); - if (io == NULL) { - return VP8SetError(dec, VP8_STATUS_INVALID_PARAM, - "null VP8Io passed to VP8GetHeaders()"); - } - buf = io->data; - buf_size = io->data_size; - if (buf_size < 4) { - return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, - "Truncated header."); - } - - // Paragraph 9.1 - { - const uint32_t bits = buf[0] | (buf[1] << 8) | (buf[2] << 16); - frm_hdr = &dec->frm_hdr_; - frm_hdr->key_frame_ = !(bits & 1); - frm_hdr->profile_ = (bits >> 1) & 7; - frm_hdr->show_ = (bits >> 4) & 1; - frm_hdr->partition_length_ = (bits >> 5); - if (frm_hdr->profile_ > 3) - return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, - "Incorrect keyframe parameters."); - if (!frm_hdr->show_) - return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE, - "Frame not displayable."); - buf += 3; - buf_size -= 3; - } - - pic_hdr = &dec->pic_hdr_; - if (frm_hdr->key_frame_) { - // Paragraph 9.2 - if (buf_size < 7) { - return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, - "cannot parse picture header"); - } - if (!VP8CheckSignature(buf, buf_size)) { - return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, - "Bad code word"); - } - pic_hdr->width_ = ((buf[4] << 8) | buf[3]) & 0x3fff; - pic_hdr->xscale_ = buf[4] >> 6; // ratio: 1, 5/4 5/3 or 2 - pic_hdr->height_ = ((buf[6] << 8) | buf[5]) & 0x3fff; - pic_hdr->yscale_ = buf[6] >> 6; - buf += 7; - buf_size -= 7; - - dec->mb_w_ = (pic_hdr->width_ + 15) >> 4; - dec->mb_h_ = (pic_hdr->height_ + 15) >> 4; - // Setup default output area (can be later modified during io->setup()) - io->width = pic_hdr->width_; - io->height = pic_hdr->height_; - io->use_scaling = 0; - io->use_cropping = 0; - io->crop_top = 0; - io->crop_left = 0; - io->crop_right = io->width; - io->crop_bottom = io->height; - io->mb_w = io->width; // sanity check - io->mb_h = io->height; // ditto - - VP8ResetProba(&dec->proba_); - ResetSegmentHeader(&dec->segment_hdr_); - } - - // Check if we have all the partition #0 available, and initialize dec->br_ - // to read this partition (and this partition only). - if (frm_hdr->partition_length_ > buf_size) { - return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, - "bad partition length"); - } - - br = &dec->br_; - VP8InitBitReader(br, buf, frm_hdr->partition_length_); - buf += frm_hdr->partition_length_; - buf_size -= frm_hdr->partition_length_; - - if (frm_hdr->key_frame_) { - pic_hdr->colorspace_ = VP8Get(br); - pic_hdr->clamp_type_ = VP8Get(br); - } - if (!ParseSegmentHeader(br, &dec->segment_hdr_, &dec->proba_)) { - return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, - "cannot parse segment header"); - } - // Filter specs - if (!ParseFilterHeader(br, dec)) { - return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, - "cannot parse filter header"); - } - status = ParsePartitions(dec, buf, buf_size); - if (status != VP8_STATUS_OK) { - return VP8SetError(dec, status, "cannot parse partitions"); - } - - // quantizer change - VP8ParseQuant(dec); - - // Frame buffer marking - if (!frm_hdr->key_frame_) { - return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE, - "Not a key frame."); - } - - VP8Get(br); // ignore the value of update_proba_ - - VP8ParseProba(br, dec); - - // sanitized state - dec->ready_ = 1; - return 1; -} - -//------------------------------------------------------------------------------ -// Residual decoding (Paragraph 13.2 / 13.3) - -static const uint8_t kCat3[] = { 173, 148, 140, 0 }; -static const uint8_t kCat4[] = { 176, 155, 140, 135, 0 }; -static const uint8_t kCat5[] = { 180, 157, 141, 134, 130, 0 }; -static const uint8_t kCat6[] = - { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0 }; -static const uint8_t* const kCat3456[] = { kCat3, kCat4, kCat5, kCat6 }; -static const uint8_t kZigzag[16] = { - 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 -}; - -// See section 13-2: http://tools.ietf.org/html/rfc6386#section-13.2 -static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) { - int v; - if (!VP8GetBit(br, p[3])) { - if (!VP8GetBit(br, p[4])) { - v = 2; - } else { - v = 3 + VP8GetBit(br, p[5]); - } - } else { - if (!VP8GetBit(br, p[6])) { - if (!VP8GetBit(br, p[7])) { - v = 5 + VP8GetBit(br, 159); - } else { - v = 7 + 2 * VP8GetBit(br, 165); - v += VP8GetBit(br, 145); - } - } else { - const uint8_t* tab; - const int bit1 = VP8GetBit(br, p[8]); - const int bit0 = VP8GetBit(br, p[9 + bit1]); - const int cat = 2 * bit1 + bit0; - v = 0; - for (tab = kCat3456[cat]; *tab; ++tab) { - v += v + VP8GetBit(br, *tab); - } - v += 3 + (8 << cat); - } - } - return v; -} - -// Returns the position of the last non-zero coeff plus one -static int GetCoeffs(VP8BitReader* const br, const VP8BandProbas* const prob[], - int ctx, const quant_t dq, int n, int16_t* out) { - const uint8_t* p = prob[n]->probas_[ctx]; - for (; n < 16; ++n) { - if (!VP8GetBit(br, p[0])) { - return n; // previous coeff was last non-zero coeff - } - while (!VP8GetBit(br, p[1])) { // sequence of zero coeffs - p = prob[++n]->probas_[0]; - if (n == 16) return 16; - } - { // non zero coeff - const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0]; - int v; - if (!VP8GetBit(br, p[2])) { - v = 1; - p = p_ctx[1]; - } else { - v = GetLargeValue(br, p); - p = p_ctx[2]; - } - out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0]; - } - } - return 16; -} - -static WEBP_INLINE uint32_t NzCodeBits(uint32_t nz_coeffs, int nz, int dc_nz) { - nz_coeffs <<= 2; - nz_coeffs |= (nz > 3) ? 3 : (nz > 1) ? 2 : dc_nz; - return nz_coeffs; -} - -static int ParseResiduals(VP8Decoder* const dec, - VP8MB* const mb, VP8BitReader* const token_br) { - const VP8BandProbas* (* const bands)[16 + 1] = dec->proba_.bands_ptr_; - const VP8BandProbas* const * ac_proba; - VP8MBData* const block = dec->mb_data_ + dec->mb_x_; - const VP8QuantMatrix* const q = &dec->dqm_[block->segment_]; - int16_t* dst = block->coeffs_; - VP8MB* const left_mb = dec->mb_info_ - 1; - uint8_t tnz, lnz; - uint32_t non_zero_y = 0; - uint32_t non_zero_uv = 0; - int x, y, ch; - uint32_t out_t_nz, out_l_nz; - int first; - - memset(dst, 0, 384 * sizeof(*dst)); - if (!block->is_i4x4_) { // parse DC - int16_t dc[16] = { 0 }; - const int ctx = mb->nz_dc_ + left_mb->nz_dc_; - const int nz = GetCoeffs(token_br, bands[1], ctx, q->y2_mat_, 0, dc); - mb->nz_dc_ = left_mb->nz_dc_ = (nz > 0); - if (nz > 1) { // more than just the DC -> perform the full transform - VP8TransformWHT(dc, dst); - } else { // only DC is non-zero -> inlined simplified transform - int i; - const int dc0 = (dc[0] + 3) >> 3; - for (i = 0; i < 16 * 16; i += 16) dst[i] = dc0; - } - first = 1; - ac_proba = bands[0]; - } else { - first = 0; - ac_proba = bands[3]; - } - - tnz = mb->nz_ & 0x0f; - lnz = left_mb->nz_ & 0x0f; - for (y = 0; y < 4; ++y) { - int l = lnz & 1; - uint32_t nz_coeffs = 0; - for (x = 0; x < 4; ++x) { - const int ctx = l + (tnz & 1); - const int nz = GetCoeffs(token_br, ac_proba, ctx, q->y1_mat_, first, dst); - l = (nz > first); - tnz = (tnz >> 1) | (l << 7); - nz_coeffs = NzCodeBits(nz_coeffs, nz, dst[0] != 0); - dst += 16; - } - tnz >>= 4; - lnz = (lnz >> 1) | (l << 7); - non_zero_y = (non_zero_y << 8) | nz_coeffs; - } - out_t_nz = tnz; - out_l_nz = lnz >> 4; - - for (ch = 0; ch < 4; ch += 2) { - uint32_t nz_coeffs = 0; - tnz = mb->nz_ >> (4 + ch); - lnz = left_mb->nz_ >> (4 + ch); - for (y = 0; y < 2; ++y) { - int l = lnz & 1; - for (x = 0; x < 2; ++x) { - const int ctx = l + (tnz & 1); - const int nz = GetCoeffs(token_br, bands[2], ctx, q->uv_mat_, 0, dst); - l = (nz > 0); - tnz = (tnz >> 1) | (l << 3); - nz_coeffs = NzCodeBits(nz_coeffs, nz, dst[0] != 0); - dst += 16; - } - tnz >>= 2; - lnz = (lnz >> 1) | (l << 5); - } - // Note: we don't really need the per-4x4 details for U/V blocks. - non_zero_uv |= nz_coeffs << (4 * ch); - out_t_nz |= (tnz << 4) << ch; - out_l_nz |= (lnz & 0xf0) << ch; - } - mb->nz_ = out_t_nz; - left_mb->nz_ = out_l_nz; - - block->non_zero_y_ = non_zero_y; - block->non_zero_uv_ = non_zero_uv; - - // We look at the mode-code of each block and check if some blocks have less - // than three non-zero coeffs (code < 2). This is to avoid dithering flat and - // empty blocks. - block->dither_ = (non_zero_uv & 0xaaaa) ? 0 : q->dither_; - - return !(non_zero_y | non_zero_uv); // will be used for further optimization -} - -//------------------------------------------------------------------------------ -// Main loop - -int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br) { - VP8MB* const left = dec->mb_info_ - 1; - VP8MB* const mb = dec->mb_info_ + dec->mb_x_; - VP8MBData* const block = dec->mb_data_ + dec->mb_x_; - int skip = dec->use_skip_proba_ ? block->skip_ : 0; - - if (!skip) { - skip = ParseResiduals(dec, mb, token_br); - } else { - left->nz_ = mb->nz_ = 0; - if (!block->is_i4x4_) { - left->nz_dc_ = mb->nz_dc_ = 0; - } - block->non_zero_y_ = 0; - block->non_zero_uv_ = 0; - block->dither_ = 0; - } - - if (dec->filter_type_ > 0) { // store filter info - VP8FInfo* const finfo = dec->f_info_ + dec->mb_x_; - *finfo = dec->fstrengths_[block->segment_][block->is_i4x4_]; - finfo->f_inner_ |= !skip; - } - - return !token_br->eof_; -} - -void VP8InitScanline(VP8Decoder* const dec) { - VP8MB* const left = dec->mb_info_ - 1; - left->nz_ = 0; - left->nz_dc_ = 0; - memset(dec->intra_l_, B_DC_PRED, sizeof(dec->intra_l_)); - dec->mb_x_ = 0; -} - -static int ParseFrame(VP8Decoder* const dec, VP8Io* io) { - for (dec->mb_y_ = 0; dec->mb_y_ < dec->br_mb_y_; ++dec->mb_y_) { - // Parse bitstream for this row. - VP8BitReader* const token_br = - &dec->parts_[dec->mb_y_ & (dec->num_parts_ - 1)]; - if (!VP8ParseIntraModeRow(&dec->br_, dec)) { - return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, - "Premature end-of-partition0 encountered."); - } - for (; dec->mb_x_ < dec->mb_w_; ++dec->mb_x_) { - if (!VP8DecodeMB(dec, token_br)) { - return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, - "Premature end-of-file encountered."); - } - } - VP8InitScanline(dec); // Prepare for next scanline - - // Reconstruct, filter and emit the row. - if (!VP8ProcessRow(dec, io)) { - return VP8SetError(dec, VP8_STATUS_USER_ABORT, "Output aborted."); - } - } - if (dec->mt_method_ > 0) { - if (!WebPGetWorkerInterface()->Sync(&dec->worker_)) return 0; - } - - return 1; -} - -// Main entry point -int VP8Decode(VP8Decoder* const dec, VP8Io* const io) { - int ok = 0; - if (dec == NULL) { - return 0; - } - if (io == NULL) { - return VP8SetError(dec, VP8_STATUS_INVALID_PARAM, - "NULL VP8Io parameter in VP8Decode()."); - } - - if (!dec->ready_) { - if (!VP8GetHeaders(dec, io)) { - return 0; - } - } - assert(dec->ready_); - - // Finish setting up the decoding parameter. Will call io->setup(). - ok = (VP8EnterCritical(dec, io) == VP8_STATUS_OK); - if (ok) { // good to go. - // Will allocate memory and prepare everything. - if (ok) ok = VP8InitFrame(dec, io); - - // Main decoding loop - if (ok) ok = ParseFrame(dec, io); - - // Exit. - ok &= VP8ExitCritical(dec, io); - } - - if (!ok) { - VP8Clear(dec); - return 0; - } - - dec->ready_ = 0; - return ok; -} - -void VP8Clear(VP8Decoder* const dec) { - if (dec == NULL) { - return; - } - WebPGetWorkerInterface()->End(&dec->worker_); - ALPHDelete(dec->alph_dec_); - dec->alph_dec_ = NULL; - WebPSafeFree(dec->mem_); - dec->mem_ = NULL; - dec->mem_size_ = 0; - memset(&dec->br_, 0, sizeof(dec->br_)); - dec->ready_ = 0; -} - -//------------------------------------------------------------------------------ - diff --git a/Example-Mac/Pods/libwebp/src/dec/vp8i.h b/Example-Mac/Pods/libwebp/src/dec/vp8i.h deleted file mode 100644 index 0104f255..00000000 --- a/Example-Mac/Pods/libwebp/src/dec/vp8i.h +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// VP8 decoder: internal header. -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_DEC_VP8I_H_ -#define WEBP_DEC_VP8I_H_ - -#include // for memcpy() -#include "./common.h" -#include "./vp8li.h" -#include "../utils/bit_reader.h" -#include "../utils/random.h" -#include "../utils/thread.h" -#include "../dsp/dsp.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//------------------------------------------------------------------------------ -// Various defines and enums - -// version numbers -#define DEC_MAJ_VERSION 0 -#define DEC_MIN_VERSION 5 -#define DEC_REV_VERSION 0 - -// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline). -// Constraints are: We need to store one 16x16 block of luma samples (y), -// and two 8x8 chroma blocks (u/v). These are better be 16-bytes aligned, -// in order to be SIMD-friendly. We also need to store the top, left and -// top-left samples (from previously decoded blocks), along with four -// extra top-right samples for luma (intra4x4 prediction only). -// One possible layout is, using 32 * (17 + 9) bytes: -// -// .+------ <- only 1 pixel high -// .|yyyyt. -// .|yyyyt. -// .|yyyyt. -// .|yyyy.. -// .+--.+-- <- only 1 pixel high -// .|uu.|vv -// .|uu.|vv -// -// Every character is a 4x4 block, with legend: -// '.' = unused -// 'y' = y-samples 'u' = u-samples 'v' = u-samples -// '|' = left sample, '-' = top sample, '+' = top-left sample -// 't' = extra top-right sample for 4x4 modes -#define YUV_SIZE (BPS * 17 + BPS * 9) -#define Y_SIZE (BPS * 17) -#define Y_OFF (BPS * 1 + 8) -#define U_OFF (Y_OFF + BPS * 16 + BPS) -#define V_OFF (U_OFF + 16) - -// minimal width under which lossy multi-threading is always disabled -#define MIN_WIDTH_FOR_THREADS 512 - -//------------------------------------------------------------------------------ -// Headers - -typedef struct { - uint8_t key_frame_; - uint8_t profile_; - uint8_t show_; - uint32_t partition_length_; -} VP8FrameHeader; - -typedef struct { - uint16_t width_; - uint16_t height_; - uint8_t xscale_; - uint8_t yscale_; - uint8_t colorspace_; // 0 = YCbCr - uint8_t clamp_type_; -} VP8PictureHeader; - -// segment features -typedef struct { - int use_segment_; - int update_map_; // whether to update the segment map or not - int absolute_delta_; // absolute or delta values for quantizer and filter - int8_t quantizer_[NUM_MB_SEGMENTS]; // quantization changes - int8_t filter_strength_[NUM_MB_SEGMENTS]; // filter strength for segments -} VP8SegmentHeader; - -// probas associated to one of the contexts -typedef uint8_t VP8ProbaArray[NUM_PROBAS]; - -typedef struct { // all the probas associated to one band - VP8ProbaArray probas_[NUM_CTX]; -} VP8BandProbas; - -// Struct collecting all frame-persistent probabilities. -typedef struct { - uint8_t segments_[MB_FEATURE_TREE_PROBS]; - // Type: 0:Intra16-AC 1:Intra16-DC 2:Chroma 3:Intra4 - VP8BandProbas bands_[NUM_TYPES][NUM_BANDS]; - const VP8BandProbas* bands_ptr_[NUM_TYPES][16 + 1]; -} VP8Proba; - -// Filter parameters -typedef struct { - int simple_; // 0=complex, 1=simple - int level_; // [0..63] - int sharpness_; // [0..7] - int use_lf_delta_; - int ref_lf_delta_[NUM_REF_LF_DELTAS]; - int mode_lf_delta_[NUM_MODE_LF_DELTAS]; -} VP8FilterHeader; - -//------------------------------------------------------------------------------ -// Informations about the macroblocks. - -typedef struct { // filter specs - uint8_t f_limit_; // filter limit in [3..189], or 0 if no filtering - uint8_t f_ilevel_; // inner limit in [1..63] - uint8_t f_inner_; // do inner filtering? - uint8_t hev_thresh_; // high edge variance threshold in [0..2] -} VP8FInfo; - -typedef struct { // Top/Left Contexts used for syntax-parsing - uint8_t nz_; // non-zero AC/DC coeffs (4bit for luma + 4bit for chroma) - uint8_t nz_dc_; // non-zero DC coeff (1bit) -} VP8MB; - -// Dequantization matrices -typedef int quant_t[2]; // [DC / AC]. Can be 'uint16_t[2]' too (~slower). -typedef struct { - quant_t y1_mat_, y2_mat_, uv_mat_; - - int uv_quant_; // U/V quantizer value - int dither_; // dithering amplitude (0 = off, max=255) -} VP8QuantMatrix; - -// Data needed to reconstruct a macroblock -typedef struct { - int16_t coeffs_[384]; // 384 coeffs = (16+4+4) * 4*4 - uint8_t is_i4x4_; // true if intra4x4 - uint8_t imodes_[16]; // one 16x16 mode (#0) or sixteen 4x4 modes - uint8_t uvmode_; // chroma prediction mode - // bit-wise info about the content of each sub-4x4 blocks (in decoding order). - // Each of the 4x4 blocks for y/u/v is associated with a 2b code according to: - // code=0 -> no coefficient - // code=1 -> only DC - // code=2 -> first three coefficients are non-zero - // code=3 -> more than three coefficients are non-zero - // This allows to call specialized transform functions. - uint32_t non_zero_y_; - uint32_t non_zero_uv_; - uint8_t dither_; // local dithering strength (deduced from non_zero_*) - uint8_t skip_; - uint8_t segment_; -} VP8MBData; - -// Persistent information needed by the parallel processing -typedef struct { - int id_; // cache row to process (in [0..2]) - int mb_y_; // macroblock position of the row - int filter_row_; // true if row-filtering is needed - VP8FInfo* f_info_; // filter strengths (swapped with dec->f_info_) - VP8MBData* mb_data_; // reconstruction data (swapped with dec->mb_data_) - VP8Io io_; // copy of the VP8Io to pass to put() -} VP8ThreadContext; - -// Saved top samples, per macroblock. Fits into a cache-line. -typedef struct { - uint8_t y[16], u[8], v[8]; -} VP8TopSamples; - -//------------------------------------------------------------------------------ -// VP8Decoder: the main opaque structure handed over to user - -struct VP8Decoder { - VP8StatusCode status_; - int ready_; // true if ready to decode a picture with VP8Decode() - const char* error_msg_; // set when status_ is not OK. - - // Main data source - VP8BitReader br_; - - // headers - VP8FrameHeader frm_hdr_; - VP8PictureHeader pic_hdr_; - VP8FilterHeader filter_hdr_; - VP8SegmentHeader segment_hdr_; - - // Worker - WebPWorker worker_; - int mt_method_; // multi-thread method: 0=off, 1=[parse+recon][filter] - // 2=[parse][recon+filter] - int cache_id_; // current cache row - int num_caches_; // number of cached rows of 16 pixels (1, 2 or 3) - VP8ThreadContext thread_ctx_; // Thread context - - // dimension, in macroblock units. - int mb_w_, mb_h_; - - // Macroblock to process/filter, depending on cropping and filter_type. - int tl_mb_x_, tl_mb_y_; // top-left MB that must be in-loop filtered - int br_mb_x_, br_mb_y_; // last bottom-right MB that must be decoded - - // number of partitions. - int num_parts_; - // per-partition boolean decoders. - VP8BitReader parts_[MAX_NUM_PARTITIONS]; - - // Dithering strength, deduced from decoding options - int dither_; // whether to use dithering or not - VP8Random dithering_rg_; // random generator for dithering - - // dequantization (one set of DC/AC dequant factor per segment) - VP8QuantMatrix dqm_[NUM_MB_SEGMENTS]; - - // probabilities - VP8Proba proba_; - int use_skip_proba_; - uint8_t skip_p_; - - // Boundary data cache and persistent buffers. - uint8_t* intra_t_; // top intra modes values: 4 * mb_w_ - uint8_t intra_l_[4]; // left intra modes values - - VP8TopSamples* yuv_t_; // top y/u/v samples - - VP8MB* mb_info_; // contextual macroblock info (mb_w_ + 1) - VP8FInfo* f_info_; // filter strength info - uint8_t* yuv_b_; // main block for Y/U/V (size = YUV_SIZE) - - uint8_t* cache_y_; // macroblock row for storing unfiltered samples - uint8_t* cache_u_; - uint8_t* cache_v_; - int cache_y_stride_; - int cache_uv_stride_; - - // main memory chunk for the above data. Persistent. - void* mem_; - size_t mem_size_; - - // Per macroblock non-persistent infos. - int mb_x_, mb_y_; // current position, in macroblock units - VP8MBData* mb_data_; // parsed reconstruction data - - // Filtering side-info - int filter_type_; // 0=off, 1=simple, 2=complex - VP8FInfo fstrengths_[NUM_MB_SEGMENTS][2]; // precalculated per-segment/type - - // Alpha - struct ALPHDecoder* alph_dec_; // alpha-plane decoder object - const uint8_t* alpha_data_; // compressed alpha data (if present) - size_t alpha_data_size_; - int is_alpha_decoded_; // true if alpha_data_ is decoded in alpha_plane_ - uint8_t* alpha_plane_; // output. Persistent, contains the whole data. - int alpha_dithering_; // derived from decoding options (0=off, 100=full). -}; - -//------------------------------------------------------------------------------ -// internal functions. Not public. - -// in vp8.c -int VP8SetError(VP8Decoder* const dec, - VP8StatusCode error, const char* const msg); - -// in tree.c -void VP8ResetProba(VP8Proba* const proba); -void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec); -// parses one row of intra mode data in partition 0, returns !eof -int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec); - -// in quant.c -void VP8ParseQuant(VP8Decoder* const dec); - -// in frame.c -int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io); -// Call io->setup() and finish setting up scan parameters. -// After this call returns, one must always call VP8ExitCritical() with the -// same parameters. Both functions should be used in pair. Returns VP8_STATUS_OK -// if ok, otherwise sets and returns the error status on *dec. -VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io); -// Must always be called in pair with VP8EnterCritical(). -// Returns false in case of error. -int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io); -// Return the multi-threading method to use (0=off), depending -// on options and bitstream size. Only for lossy decoding. -int VP8GetThreadMethod(const WebPDecoderOptions* const options, - const WebPHeaderStructure* const headers, - int width, int height); -// Initialize dithering post-process if needed. -void VP8InitDithering(const WebPDecoderOptions* const options, - VP8Decoder* const dec); -// Process the last decoded row (filtering + output). -int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io); -// To be called at the start of a new scanline, to initialize predictors. -void VP8InitScanline(VP8Decoder* const dec); -// Decode one macroblock. Returns false if there is not enough data. -int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br); - -// in alpha.c -const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, - int row, int num_rows); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_DEC_VP8I_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/dec/vp8l.c b/Example-Mac/Pods/libwebp/src/dec/vp8l.c deleted file mode 100644 index a76ad6a1..00000000 --- a/Example-Mac/Pods/libwebp/src/dec/vp8l.c +++ /dev/null @@ -1,1627 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// main entry for the decoder -// -// Authors: Vikas Arora (vikaas.arora@gmail.com) -// Jyrki Alakuijala (jyrki@google.com) - -#include - -#include "./alphai.h" -#include "./vp8li.h" -#include "../dsp/dsp.h" -#include "../dsp/lossless.h" -#include "../dsp/yuv.h" -#include "../utils/endian_inl.h" -#include "../utils/huffman.h" -#include "../utils/utils.h" - -#define NUM_ARGB_CACHE_ROWS 16 - -static const int kCodeLengthLiterals = 16; -static const int kCodeLengthRepeatCode = 16; -static const int kCodeLengthExtraBits[3] = { 2, 3, 7 }; -static const int kCodeLengthRepeatOffsets[3] = { 3, 3, 11 }; - -// ----------------------------------------------------------------------------- -// Five Huffman codes are used at each meta code: -// 1. green + length prefix codes + color cache codes, -// 2. alpha, -// 3. red, -// 4. blue, and, -// 5. distance prefix codes. -typedef enum { - GREEN = 0, - RED = 1, - BLUE = 2, - ALPHA = 3, - DIST = 4 -} HuffIndex; - -static const uint16_t kAlphabetSize[HUFFMAN_CODES_PER_META_CODE] = { - NUM_LITERAL_CODES + NUM_LENGTH_CODES, - NUM_LITERAL_CODES, NUM_LITERAL_CODES, NUM_LITERAL_CODES, - NUM_DISTANCE_CODES -}; - -static const uint8_t kLiteralMap[HUFFMAN_CODES_PER_META_CODE] = { - 0, 1, 1, 1, 0 -}; - -#define NUM_CODE_LENGTH_CODES 19 -static const uint8_t kCodeLengthCodeOrder[NUM_CODE_LENGTH_CODES] = { - 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 -}; - -#define CODE_TO_PLANE_CODES 120 -static const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = { - 0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a, - 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a, - 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b, - 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03, - 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c, - 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e, - 0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b, - 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f, - 0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b, - 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41, - 0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f, - 0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70 -}; - -// Memory needed for lookup tables of one Huffman tree group. Red, blue, alpha -// and distance alphabets are constant (256 for red, blue and alpha, 40 for -// distance) and lookup table sizes for them in worst case are 630 and 410 -// respectively. Size of green alphabet depends on color cache size and is equal -// to 256 (green component values) + 24 (length prefix values) -// + color_cache_size (between 0 and 2048). -// All values computed for 8-bit first level lookup with Mark Adler's tool: -// http://www.hdfgroup.org/ftp/lib-external/zlib/zlib-1.2.5/examples/enough.c -#define FIXED_TABLE_SIZE (630 * 3 + 410) -static const int kTableSize[12] = { - FIXED_TABLE_SIZE + 654, - FIXED_TABLE_SIZE + 656, - FIXED_TABLE_SIZE + 658, - FIXED_TABLE_SIZE + 662, - FIXED_TABLE_SIZE + 670, - FIXED_TABLE_SIZE + 686, - FIXED_TABLE_SIZE + 718, - FIXED_TABLE_SIZE + 782, - FIXED_TABLE_SIZE + 912, - FIXED_TABLE_SIZE + 1168, - FIXED_TABLE_SIZE + 1680, - FIXED_TABLE_SIZE + 2704 -}; - -static int DecodeImageStream(int xsize, int ysize, - int is_level0, - VP8LDecoder* const dec, - uint32_t** const decoded_data); - -//------------------------------------------------------------------------------ - -int VP8LCheckSignature(const uint8_t* const data, size_t size) { - return (size >= VP8L_FRAME_HEADER_SIZE && - data[0] == VP8L_MAGIC_BYTE && - (data[4] >> 5) == 0); // version -} - -static int ReadImageInfo(VP8LBitReader* const br, - int* const width, int* const height, - int* const has_alpha) { - if (VP8LReadBits(br, 8) != VP8L_MAGIC_BYTE) return 0; - *width = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1; - *height = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1; - *has_alpha = VP8LReadBits(br, 1); - if (VP8LReadBits(br, VP8L_VERSION_BITS) != 0) return 0; - return !br->eos_; -} - -int VP8LGetInfo(const uint8_t* data, size_t data_size, - int* const width, int* const height, int* const has_alpha) { - if (data == NULL || data_size < VP8L_FRAME_HEADER_SIZE) { - return 0; // not enough data - } else if (!VP8LCheckSignature(data, data_size)) { - return 0; // bad signature - } else { - int w, h, a; - VP8LBitReader br; - VP8LInitBitReader(&br, data, data_size); - if (!ReadImageInfo(&br, &w, &h, &a)) { - return 0; - } - if (width != NULL) *width = w; - if (height != NULL) *height = h; - if (has_alpha != NULL) *has_alpha = a; - return 1; - } -} - -//------------------------------------------------------------------------------ - -static WEBP_INLINE int GetCopyDistance(int distance_symbol, - VP8LBitReader* const br) { - int extra_bits, offset; - if (distance_symbol < 4) { - return distance_symbol + 1; - } - extra_bits = (distance_symbol - 2) >> 1; - offset = (2 + (distance_symbol & 1)) << extra_bits; - return offset + VP8LReadBits(br, extra_bits) + 1; -} - -static WEBP_INLINE int GetCopyLength(int length_symbol, - VP8LBitReader* const br) { - // Length and distance prefixes are encoded the same way. - return GetCopyDistance(length_symbol, br); -} - -static WEBP_INLINE int PlaneCodeToDistance(int xsize, int plane_code) { - if (plane_code > CODE_TO_PLANE_CODES) { - return plane_code - CODE_TO_PLANE_CODES; - } else { - const int dist_code = kCodeToPlane[plane_code - 1]; - const int yoffset = dist_code >> 4; - const int xoffset = 8 - (dist_code & 0xf); - const int dist = yoffset * xsize + xoffset; - return (dist >= 1) ? dist : 1; // dist<1 can happen if xsize is very small - } -} - -//------------------------------------------------------------------------------ -// Decodes the next Huffman code from bit-stream. -// FillBitWindow(br) needs to be called at minimum every second call -// to ReadSymbol, in order to pre-fetch enough bits. -static WEBP_INLINE int ReadSymbol(const HuffmanCode* table, - VP8LBitReader* const br) { - int nbits; - uint32_t val = VP8LPrefetchBits(br); - table += val & HUFFMAN_TABLE_MASK; - nbits = table->bits - HUFFMAN_TABLE_BITS; - if (nbits > 0) { - VP8LSetBitPos(br, br->bit_pos_ + HUFFMAN_TABLE_BITS); - val = VP8LPrefetchBits(br); - table += table->value; - table += val & ((1 << nbits) - 1); - } - VP8LSetBitPos(br, br->bit_pos_ + table->bits); - return table->value; -} - -// Reads packed symbol depending on GREEN channel -#define BITS_SPECIAL_MARKER 0x100 // something large enough (and a bit-mask) -#define PACKED_NON_LITERAL_CODE 0 // must be < NUM_LITERAL_CODES -static WEBP_INLINE int ReadPackedSymbols(const HTreeGroup* group, - VP8LBitReader* const br, - uint32_t* const dst) { - const uint32_t val = VP8LPrefetchBits(br) & (HUFFMAN_PACKED_TABLE_SIZE - 1); - const HuffmanCode32 code = group->packed_table[val]; - assert(group->use_packed_table); - if (code.bits < BITS_SPECIAL_MARKER) { - VP8LSetBitPos(br, br->bit_pos_ + code.bits); - *dst = code.value; - return PACKED_NON_LITERAL_CODE; - } else { - VP8LSetBitPos(br, br->bit_pos_ + code.bits - BITS_SPECIAL_MARKER); - assert(code.value >= NUM_LITERAL_CODES); - return code.value; - } -} - -static int AccumulateHCode(HuffmanCode hcode, int shift, - HuffmanCode32* const huff) { - huff->bits += hcode.bits; - huff->value |= (uint32_t)hcode.value << shift; - assert(huff->bits <= HUFFMAN_TABLE_BITS); - return hcode.bits; -} - -static void BuildPackedTable(HTreeGroup* const htree_group) { - uint32_t code; - for (code = 0; code < HUFFMAN_PACKED_TABLE_SIZE; ++code) { - uint32_t bits = code; - HuffmanCode32* const huff = &htree_group->packed_table[bits]; - HuffmanCode hcode = htree_group->htrees[GREEN][bits]; - if (hcode.value >= NUM_LITERAL_CODES) { - huff->bits = hcode.bits + BITS_SPECIAL_MARKER; - huff->value = hcode.value; - } else { - huff->bits = 0; - huff->value = 0; - bits >>= AccumulateHCode(hcode, 8, huff); - bits >>= AccumulateHCode(htree_group->htrees[RED][bits], 16, huff); - bits >>= AccumulateHCode(htree_group->htrees[BLUE][bits], 0, huff); - bits >>= AccumulateHCode(htree_group->htrees[ALPHA][bits], 24, huff); - (void)bits; - } - } -} - -static int ReadHuffmanCodeLengths( - VP8LDecoder* const dec, const int* const code_length_code_lengths, - int num_symbols, int* const code_lengths) { - int ok = 0; - VP8LBitReader* const br = &dec->br_; - int symbol; - int max_symbol; - int prev_code_len = DEFAULT_CODE_LENGTH; - HuffmanCode table[1 << LENGTHS_TABLE_BITS]; - - if (!VP8LBuildHuffmanTable(table, LENGTHS_TABLE_BITS, - code_length_code_lengths, - NUM_CODE_LENGTH_CODES)) { - goto End; - } - - if (VP8LReadBits(br, 1)) { // use length - const int length_nbits = 2 + 2 * VP8LReadBits(br, 3); - max_symbol = 2 + VP8LReadBits(br, length_nbits); - if (max_symbol > num_symbols) { - goto End; - } - } else { - max_symbol = num_symbols; - } - - symbol = 0; - while (symbol < num_symbols) { - const HuffmanCode* p; - int code_len; - if (max_symbol-- == 0) break; - VP8LFillBitWindow(br); - p = &table[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK]; - VP8LSetBitPos(br, br->bit_pos_ + p->bits); - code_len = p->value; - if (code_len < kCodeLengthLiterals) { - code_lengths[symbol++] = code_len; - if (code_len != 0) prev_code_len = code_len; - } else { - const int use_prev = (code_len == kCodeLengthRepeatCode); - const int slot = code_len - kCodeLengthLiterals; - const int extra_bits = kCodeLengthExtraBits[slot]; - const int repeat_offset = kCodeLengthRepeatOffsets[slot]; - int repeat = VP8LReadBits(br, extra_bits) + repeat_offset; - if (symbol + repeat > num_symbols) { - goto End; - } else { - const int length = use_prev ? prev_code_len : 0; - while (repeat-- > 0) code_lengths[symbol++] = length; - } - } - } - ok = 1; - - End: - if (!ok) dec->status_ = VP8_STATUS_BITSTREAM_ERROR; - return ok; -} - -// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman -// tree. -static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec, - int* const code_lengths, HuffmanCode* const table) { - int ok = 0; - int size = 0; - VP8LBitReader* const br = &dec->br_; - const int simple_code = VP8LReadBits(br, 1); - - memset(code_lengths, 0, alphabet_size * sizeof(*code_lengths)); - - if (simple_code) { // Read symbols, codes & code lengths directly. - const int num_symbols = VP8LReadBits(br, 1) + 1; - const int first_symbol_len_code = VP8LReadBits(br, 1); - // The first code is either 1 bit or 8 bit code. - int symbol = VP8LReadBits(br, (first_symbol_len_code == 0) ? 1 : 8); - code_lengths[symbol] = 1; - // The second code (if present), is always 8 bit long. - if (num_symbols == 2) { - symbol = VP8LReadBits(br, 8); - code_lengths[symbol] = 1; - } - ok = 1; - } else { // Decode Huffman-coded code lengths. - int i; - int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 }; - const int num_codes = VP8LReadBits(br, 4) + 4; - if (num_codes > NUM_CODE_LENGTH_CODES) { - dec->status_ = VP8_STATUS_BITSTREAM_ERROR; - return 0; - } - - for (i = 0; i < num_codes; ++i) { - code_length_code_lengths[kCodeLengthCodeOrder[i]] = VP8LReadBits(br, 3); - } - ok = ReadHuffmanCodeLengths(dec, code_length_code_lengths, alphabet_size, - code_lengths); - } - - ok = ok && !br->eos_; - if (ok) { - size = VP8LBuildHuffmanTable(table, HUFFMAN_TABLE_BITS, - code_lengths, alphabet_size); - } - if (!ok || size == 0) { - dec->status_ = VP8_STATUS_BITSTREAM_ERROR; - return 0; - } - return size; -} - -static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, - int color_cache_bits, int allow_recursion) { - int i, j; - VP8LBitReader* const br = &dec->br_; - VP8LMetadata* const hdr = &dec->hdr_; - uint32_t* huffman_image = NULL; - HTreeGroup* htree_groups = NULL; - HuffmanCode* huffman_tables = NULL; - HuffmanCode* next = NULL; - int num_htree_groups = 1; - int max_alphabet_size = 0; - int* code_lengths = NULL; - const int table_size = kTableSize[color_cache_bits]; - - if (allow_recursion && VP8LReadBits(br, 1)) { - // use meta Huffman codes. - const int huffman_precision = VP8LReadBits(br, 3) + 2; - const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision); - const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision); - const int huffman_pixs = huffman_xsize * huffman_ysize; - if (!DecodeImageStream(huffman_xsize, huffman_ysize, 0, dec, - &huffman_image)) { - goto Error; - } - hdr->huffman_subsample_bits_ = huffman_precision; - for (i = 0; i < huffman_pixs; ++i) { - // The huffman data is stored in red and green bytes. - const int group = (huffman_image[i] >> 8) & 0xffff; - huffman_image[i] = group; - if (group >= num_htree_groups) { - num_htree_groups = group + 1; - } - } - } - - if (br->eos_) goto Error; - - // Find maximum alphabet size for the htree group. - for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { - int alphabet_size = kAlphabetSize[j]; - if (j == 0 && color_cache_bits > 0) { - alphabet_size += 1 << color_cache_bits; - } - if (max_alphabet_size < alphabet_size) { - max_alphabet_size = alphabet_size; - } - } - - huffman_tables = (HuffmanCode*)WebPSafeMalloc(num_htree_groups * table_size, - sizeof(*huffman_tables)); - htree_groups = VP8LHtreeGroupsNew(num_htree_groups); - code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size, - sizeof(*code_lengths)); - - if (htree_groups == NULL || code_lengths == NULL || huffman_tables == NULL) { - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; - goto Error; - } - - next = huffman_tables; - for (i = 0; i < num_htree_groups; ++i) { - HTreeGroup* const htree_group = &htree_groups[i]; - HuffmanCode** const htrees = htree_group->htrees; - int size; - int total_size = 0; - int is_trivial_literal = 1; - int max_bits = 0; - for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { - int alphabet_size = kAlphabetSize[j]; - htrees[j] = next; - if (j == 0 && color_cache_bits > 0) { - alphabet_size += 1 << color_cache_bits; - } - size = ReadHuffmanCode(alphabet_size, dec, code_lengths, next); - if (size == 0) { - goto Error; - } - if (is_trivial_literal && kLiteralMap[j] == 1) { - is_trivial_literal = (next->bits == 0); - } - total_size += next->bits; - next += size; - if (j <= ALPHA) { - int local_max_bits = code_lengths[0]; - int k; - for (k = 1; k < alphabet_size; ++k) { - if (code_lengths[k] > local_max_bits) { - local_max_bits = code_lengths[k]; - } - } - max_bits += local_max_bits; - } - } - htree_group->is_trivial_literal = is_trivial_literal; - htree_group->is_trivial_code = 0; - if (is_trivial_literal) { - const int red = htrees[RED][0].value; - const int blue = htrees[BLUE][0].value; - const int alpha = htrees[ALPHA][0].value; - htree_group->literal_arb = - ((uint32_t)alpha << 24) | (red << 16) | blue; - if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) { - htree_group->is_trivial_code = 1; - htree_group->literal_arb |= htrees[GREEN][0].value << 8; - } - } - htree_group->use_packed_table = !htree_group->is_trivial_code && - (max_bits < HUFFMAN_PACKED_BITS); - if (htree_group->use_packed_table) BuildPackedTable(htree_group); - } - WebPSafeFree(code_lengths); - - // All OK. Finalize pointers and return. - hdr->huffman_image_ = huffman_image; - hdr->num_htree_groups_ = num_htree_groups; - hdr->htree_groups_ = htree_groups; - hdr->huffman_tables_ = huffman_tables; - return 1; - - Error: - WebPSafeFree(code_lengths); - WebPSafeFree(huffman_image); - WebPSafeFree(huffman_tables); - VP8LHtreeGroupsFree(htree_groups); - return 0; -} - -//------------------------------------------------------------------------------ -// Scaling. - -static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) { - const int num_channels = 4; - const int in_width = io->mb_w; - const int out_width = io->scaled_width; - const int in_height = io->mb_h; - const int out_height = io->scaled_height; - const uint64_t work_size = 2 * num_channels * (uint64_t)out_width; - rescaler_t* work; // Rescaler work area. - const uint64_t scaled_data_size = (uint64_t)out_width; - uint32_t* scaled_data; // Temporary storage for scaled BGRA data. - const uint64_t memory_size = sizeof(*dec->rescaler) + - work_size * sizeof(*work) + - scaled_data_size * sizeof(*scaled_data); - uint8_t* memory = (uint8_t*)WebPSafeMalloc(memory_size, sizeof(*memory)); - if (memory == NULL) { - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; - return 0; - } - assert(dec->rescaler_memory == NULL); - dec->rescaler_memory = memory; - - dec->rescaler = (WebPRescaler*)memory; - memory += sizeof(*dec->rescaler); - work = (rescaler_t*)memory; - memory += work_size * sizeof(*work); - scaled_data = (uint32_t*)memory; - - WebPRescalerInit(dec->rescaler, in_width, in_height, (uint8_t*)scaled_data, - out_width, out_height, 0, num_channels, work); - return 1; -} - -//------------------------------------------------------------------------------ -// Export to ARGB - -// We have special "export" function since we need to convert from BGRA -static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace, - int rgba_stride, uint8_t* const rgba) { - uint32_t* const src = (uint32_t*)rescaler->dst; - const int dst_width = rescaler->dst_width; - int num_lines_out = 0; - while (WebPRescalerHasPendingOutput(rescaler)) { - uint8_t* const dst = rgba + num_lines_out * rgba_stride; - WebPRescalerExportRow(rescaler); - WebPMultARGBRow(src, dst_width, 1); - VP8LConvertFromBGRA(src, dst_width, colorspace, dst); - ++num_lines_out; - } - return num_lines_out; -} - -// Emit scaled rows. -static int EmitRescaledRowsRGBA(const VP8LDecoder* const dec, - uint8_t* in, int in_stride, int mb_h, - uint8_t* const out, int out_stride) { - const WEBP_CSP_MODE colorspace = dec->output_->colorspace; - int num_lines_in = 0; - int num_lines_out = 0; - while (num_lines_in < mb_h) { - uint8_t* const row_in = in + num_lines_in * in_stride; - uint8_t* const row_out = out + num_lines_out * out_stride; - const int lines_left = mb_h - num_lines_in; - const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left); - assert(needed_lines > 0 && needed_lines <= lines_left); - WebPMultARGBRows(row_in, in_stride, - dec->rescaler->src_width, needed_lines, 0); - WebPRescalerImport(dec->rescaler, lines_left, row_in, in_stride); - num_lines_in += needed_lines; - num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out); - } - return num_lines_out; -} - -// Emit rows without any scaling. -static int EmitRows(WEBP_CSP_MODE colorspace, - const uint8_t* row_in, int in_stride, - int mb_w, int mb_h, - uint8_t* const out, int out_stride) { - int lines = mb_h; - uint8_t* row_out = out; - while (lines-- > 0) { - VP8LConvertFromBGRA((const uint32_t*)row_in, mb_w, colorspace, row_out); - row_in += in_stride; - row_out += out_stride; - } - return mb_h; // Num rows out == num rows in. -} - -//------------------------------------------------------------------------------ -// Export to YUVA - -static void ConvertToYUVA(const uint32_t* const src, int width, int y_pos, - const WebPDecBuffer* const output) { - const WebPYUVABuffer* const buf = &output->u.YUVA; - - // first, the luma plane - WebPConvertARGBToY(src, buf->y + y_pos * buf->y_stride, width); - - // then U/V planes - { - uint8_t* const u = buf->u + (y_pos >> 1) * buf->u_stride; - uint8_t* const v = buf->v + (y_pos >> 1) * buf->v_stride; - // even lines: store values - // odd lines: average with previous values - WebPConvertARGBToUV(src, u, v, width, !(y_pos & 1)); - } - // Lastly, store alpha if needed. - if (buf->a != NULL) { - uint8_t* const a = buf->a + y_pos * buf->a_stride; -#if defined(WORDS_BIGENDIAN) - WebPExtractAlpha((uint8_t*)src + 0, 0, width, 1, a, 0); -#else - WebPExtractAlpha((uint8_t*)src + 3, 0, width, 1, a, 0); -#endif - } -} - -static int ExportYUVA(const VP8LDecoder* const dec, int y_pos) { - WebPRescaler* const rescaler = dec->rescaler; - uint32_t* const src = (uint32_t*)rescaler->dst; - const int dst_width = rescaler->dst_width; - int num_lines_out = 0; - while (WebPRescalerHasPendingOutput(rescaler)) { - WebPRescalerExportRow(rescaler); - WebPMultARGBRow(src, dst_width, 1); - ConvertToYUVA(src, dst_width, y_pos, dec->output_); - ++y_pos; - ++num_lines_out; - } - return num_lines_out; -} - -static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec, - uint8_t* in, int in_stride, int mb_h) { - int num_lines_in = 0; - int y_pos = dec->last_out_row_; - while (num_lines_in < mb_h) { - const int lines_left = mb_h - num_lines_in; - const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left); - WebPMultARGBRows(in, in_stride, dec->rescaler->src_width, needed_lines, 0); - WebPRescalerImport(dec->rescaler, lines_left, in, in_stride); - num_lines_in += needed_lines; - in += needed_lines * in_stride; - y_pos += ExportYUVA(dec, y_pos); - } - return y_pos; -} - -static int EmitRowsYUVA(const VP8LDecoder* const dec, - const uint8_t* in, int in_stride, - int mb_w, int num_rows) { - int y_pos = dec->last_out_row_; - while (num_rows-- > 0) { - ConvertToYUVA((const uint32_t*)in, mb_w, y_pos, dec->output_); - in += in_stride; - ++y_pos; - } - return y_pos; -} - -//------------------------------------------------------------------------------ -// Cropping. - -// Sets io->mb_y, io->mb_h & io->mb_w according to start row, end row and -// crop options. Also updates the input data pointer, so that it points to the -// start of the cropped window. Note that pixels are in ARGB format even if -// 'in_data' is uint8_t*. -// Returns true if the crop window is not empty. -static int SetCropWindow(VP8Io* const io, int y_start, int y_end, - uint8_t** const in_data, int pixel_stride) { - assert(y_start < y_end); - assert(io->crop_left < io->crop_right); - if (y_end > io->crop_bottom) { - y_end = io->crop_bottom; // make sure we don't overflow on last row. - } - if (y_start < io->crop_top) { - const int delta = io->crop_top - y_start; - y_start = io->crop_top; - *in_data += delta * pixel_stride; - } - if (y_start >= y_end) return 0; // Crop window is empty. - - *in_data += io->crop_left * sizeof(uint32_t); - - io->mb_y = y_start - io->crop_top; - io->mb_w = io->crop_right - io->crop_left; - io->mb_h = y_end - y_start; - return 1; // Non-empty crop window. -} - -//------------------------------------------------------------------------------ - -static WEBP_INLINE int GetMetaIndex( - const uint32_t* const image, int xsize, int bits, int x, int y) { - if (bits == 0) return 0; - return image[xsize * (y >> bits) + (x >> bits)]; -} - -static WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr, - int x, int y) { - const int meta_index = GetMetaIndex(hdr->huffman_image_, hdr->huffman_xsize_, - hdr->huffman_subsample_bits_, x, y); - assert(meta_index < hdr->num_htree_groups_); - return hdr->htree_groups_ + meta_index; -} - -//------------------------------------------------------------------------------ -// Main loop, with custom row-processing function - -typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row); - -static void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows, - const uint32_t* const rows) { - int n = dec->next_transform_; - const int cache_pixs = dec->width_ * num_rows; - const int start_row = dec->last_row_; - const int end_row = start_row + num_rows; - const uint32_t* rows_in = rows; - uint32_t* const rows_out = dec->argb_cache_; - - // Inverse transforms. - // TODO: most transforms only need to operate on the cropped region only. - memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out)); - while (n-- > 0) { - VP8LTransform* const transform = &dec->transforms_[n]; - VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out); - rows_in = rows_out; - } -} - -// Special method for paletted alpha data. -static void ApplyInverseTransformsAlpha(VP8LDecoder* const dec, int num_rows, - const uint8_t* const rows) { - const int start_row = dec->last_row_; - const int end_row = start_row + num_rows; - const uint8_t* rows_in = rows; - uint8_t* rows_out = (uint8_t*)dec->io_->opaque + dec->io_->width * start_row; - VP8LTransform* const transform = &dec->transforms_[0]; - assert(dec->next_transform_ == 1); - assert(transform->type_ == COLOR_INDEXING_TRANSFORM); - VP8LColorIndexInverseTransformAlpha(transform, start_row, end_row, rows_in, - rows_out); -} - -// Processes (transforms, scales & color-converts) the rows decoded after the -// last call. -static void ProcessRows(VP8LDecoder* const dec, int row) { - const uint32_t* const rows = dec->pixels_ + dec->width_ * dec->last_row_; - const int num_rows = row - dec->last_row_; - - if (num_rows <= 0) return; // Nothing to be done. - ApplyInverseTransforms(dec, num_rows, rows); - - // Emit output. - { - VP8Io* const io = dec->io_; - uint8_t* rows_data = (uint8_t*)dec->argb_cache_; - const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA - if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) { - // Nothing to output (this time). - } else { - const WebPDecBuffer* const output = dec->output_; - if (WebPIsRGBMode(output->colorspace)) { // convert to RGBA - const WebPRGBABuffer* const buf = &output->u.RGBA; - uint8_t* const rgba = buf->rgba + dec->last_out_row_ * buf->stride; - const int num_rows_out = io->use_scaling ? - EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h, - rgba, buf->stride) : - EmitRows(output->colorspace, rows_data, in_stride, - io->mb_w, io->mb_h, rgba, buf->stride); - // Update 'last_out_row_'. - dec->last_out_row_ += num_rows_out; - } else { // convert to YUVA - dec->last_out_row_ = io->use_scaling ? - EmitRescaledRowsYUVA(dec, rows_data, in_stride, io->mb_h) : - EmitRowsYUVA(dec, rows_data, in_stride, io->mb_w, io->mb_h); - } - assert(dec->last_out_row_ <= output->height); - } - } - - // Update 'last_row_'. - dec->last_row_ = row; - assert(dec->last_row_ <= dec->height_); -} - -// Row-processing for the special case when alpha data contains only one -// transform (color indexing), and trivial non-green literals. -static int Is8bOptimizable(const VP8LMetadata* const hdr) { - int i; - if (hdr->color_cache_size_ > 0) return 0; - // When the Huffman tree contains only one symbol, we can skip the - // call to ReadSymbol() for red/blue/alpha channels. - for (i = 0; i < hdr->num_htree_groups_; ++i) { - HuffmanCode** const htrees = hdr->htree_groups_[i].htrees; - if (htrees[RED][0].bits > 0) return 0; - if (htrees[BLUE][0].bits > 0) return 0; - if (htrees[ALPHA][0].bits > 0) return 0; - } - return 1; -} - -static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int row) { - const int num_rows = row - dec->last_row_; - const uint8_t* const in = - (uint8_t*)dec->pixels_ + dec->width_ * dec->last_row_; - if (num_rows > 0) { - ApplyInverseTransformsAlpha(dec, num_rows, in); - } - dec->last_row_ = dec->last_out_row_ = row; -} - -//------------------------------------------------------------------------------ -// Helper functions for fast pattern copy (8b and 32b) - -// cyclic rotation of pattern word -static WEBP_INLINE uint32_t Rotate8b(uint32_t V) { -#if defined(WORDS_BIGENDIAN) - return ((V & 0xff000000u) >> 24) | (V << 8); -#else - return ((V & 0xffu) << 24) | (V >> 8); -#endif -} - -// copy 1, 2 or 4-bytes pattern -static WEBP_INLINE void CopySmallPattern8b(const uint8_t* src, uint8_t* dst, - int length, uint32_t pattern) { - int i; - // align 'dst' to 4-bytes boundary. Adjust the pattern along the way. - while ((uintptr_t)dst & 3) { - *dst++ = *src++; - pattern = Rotate8b(pattern); - --length; - } - // Copy the pattern 4 bytes at a time. - for (i = 0; i < (length >> 2); ++i) { - ((uint32_t*)dst)[i] = pattern; - } - // Finish with left-overs. 'pattern' is still correctly positioned, - // so no Rotate8b() call is needed. - for (i <<= 2; i < length; ++i) { - dst[i] = src[i]; - } -} - -static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) { - const uint8_t* src = dst - dist; - if (length >= 8) { - uint32_t pattern = 0; - switch (dist) { - case 1: - pattern = src[0]; -#if defined(__arm__) || defined(_M_ARM) // arm doesn't like multiply that much - pattern |= pattern << 8; - pattern |= pattern << 16; -#elif defined(WEBP_USE_MIPS_DSP_R2) - __asm__ volatile ("replv.qb %0, %0" : "+r"(pattern)); -#else - pattern = 0x01010101u * pattern; -#endif - break; - case 2: - memcpy(&pattern, src, sizeof(uint16_t)); -#if defined(__arm__) || defined(_M_ARM) - pattern |= pattern << 16; -#elif defined(WEBP_USE_MIPS_DSP_R2) - __asm__ volatile ("replv.ph %0, %0" : "+r"(pattern)); -#else - pattern = 0x00010001u * pattern; -#endif - break; - case 4: - memcpy(&pattern, src, sizeof(uint32_t)); - break; - default: - goto Copy; - break; - } - CopySmallPattern8b(src, dst, length, pattern); - return; - } - Copy: - if (dist >= length) { // no overlap -> use memcpy() - memcpy(dst, src, length * sizeof(*dst)); - } else { - int i; - for (i = 0; i < length; ++i) dst[i] = src[i]; - } -} - -// copy pattern of 1 or 2 uint32_t's -static WEBP_INLINE void CopySmallPattern32b(const uint32_t* src, - uint32_t* dst, - int length, uint64_t pattern) { - int i; - if ((uintptr_t)dst & 4) { // Align 'dst' to 8-bytes boundary. - *dst++ = *src++; - pattern = (pattern >> 32) | (pattern << 32); - --length; - } - assert(0 == ((uintptr_t)dst & 7)); - for (i = 0; i < (length >> 1); ++i) { - ((uint64_t*)dst)[i] = pattern; // Copy the pattern 8 bytes at a time. - } - if (length & 1) { // Finish with left-over. - dst[i << 1] = src[i << 1]; - } -} - -static WEBP_INLINE void CopyBlock32b(uint32_t* const dst, - int dist, int length) { - const uint32_t* const src = dst - dist; - if (dist <= 2 && length >= 4 && ((uintptr_t)dst & 3) == 0) { - uint64_t pattern; - if (dist == 1) { - pattern = (uint64_t)src[0]; - pattern |= pattern << 32; - } else { - memcpy(&pattern, src, sizeof(pattern)); - } - CopySmallPattern32b(src, dst, length, pattern); - } else if (dist >= length) { // no overlap - memcpy(dst, src, length * sizeof(*dst)); - } else { - int i; - for (i = 0; i < length; ++i) dst[i] = src[i]; - } -} - -//------------------------------------------------------------------------------ - -static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data, - int width, int height, int last_row) { - int ok = 1; - int row = dec->last_pixel_ / width; - int col = dec->last_pixel_ % width; - VP8LBitReader* const br = &dec->br_; - VP8LMetadata* const hdr = &dec->hdr_; - const HTreeGroup* htree_group = GetHtreeGroupForPos(hdr, col, row); - int pos = dec->last_pixel_; // current position - const int end = width * height; // End of data - const int last = width * last_row; // Last pixel to decode - const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES; - const int mask = hdr->huffman_mask_; - assert(htree_group != NULL); - assert(pos < end); - assert(last_row <= height); - assert(Is8bOptimizable(hdr)); - - while (!br->eos_ && pos < last) { - int code; - // Only update when changing tile. - if ((col & mask) == 0) { - htree_group = GetHtreeGroupForPos(hdr, col, row); - } - VP8LFillBitWindow(br); - code = ReadSymbol(htree_group->htrees[GREEN], br); - if (code < NUM_LITERAL_CODES) { // Literal - data[pos] = code; - ++pos; - ++col; - if (col >= width) { - col = 0; - ++row; - if (row % NUM_ARGB_CACHE_ROWS == 0) { - ExtractPalettedAlphaRows(dec, row); - } - } - } else if (code < len_code_limit) { // Backward reference - int dist_code, dist; - const int length_sym = code - NUM_LITERAL_CODES; - const int length = GetCopyLength(length_sym, br); - const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br); - VP8LFillBitWindow(br); - dist_code = GetCopyDistance(dist_symbol, br); - dist = PlaneCodeToDistance(width, dist_code); - if (pos >= dist && end - pos >= length) { - CopyBlock8b(data + pos, dist, length); - } else { - ok = 0; - goto End; - } - pos += length; - col += length; - while (col >= width) { - col -= width; - ++row; - if (row % NUM_ARGB_CACHE_ROWS == 0) { - ExtractPalettedAlphaRows(dec, row); - } - } - if (pos < last && (col & mask)) { - htree_group = GetHtreeGroupForPos(hdr, col, row); - } - } else { // Not reached - ok = 0; - goto End; - } - assert(br->eos_ == VP8LIsEndOfStream(br)); - } - // Process the remaining rows corresponding to last row-block. - ExtractPalettedAlphaRows(dec, row); - - End: - if (!ok || (br->eos_ && pos < end)) { - ok = 0; - dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED - : VP8_STATUS_BITSTREAM_ERROR; - } else { - dec->last_pixel_ = pos; - } - return ok; -} - -static void SaveState(VP8LDecoder* const dec, int last_pixel) { - assert(dec->incremental_); - dec->saved_br_ = dec->br_; - dec->saved_last_pixel_ = last_pixel; - if (dec->hdr_.color_cache_size_ > 0) { - VP8LColorCacheCopy(&dec->hdr_.color_cache_, &dec->hdr_.saved_color_cache_); - } -} - -static void RestoreState(VP8LDecoder* const dec) { - assert(dec->br_.eos_); - dec->status_ = VP8_STATUS_SUSPENDED; - dec->br_ = dec->saved_br_; - dec->last_pixel_ = dec->saved_last_pixel_; - if (dec->hdr_.color_cache_size_ > 0) { - VP8LColorCacheCopy(&dec->hdr_.saved_color_cache_, &dec->hdr_.color_cache_); - } -} - -#define SYNC_EVERY_N_ROWS 8 // minimum number of rows between check-points -static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, - int width, int height, int last_row, - ProcessRowsFunc process_func) { - int row = dec->last_pixel_ / width; - int col = dec->last_pixel_ % width; - VP8LBitReader* const br = &dec->br_; - VP8LMetadata* const hdr = &dec->hdr_; - HTreeGroup* htree_group = GetHtreeGroupForPos(hdr, col, row); - uint32_t* src = data + dec->last_pixel_; - uint32_t* last_cached = src; - uint32_t* const src_end = data + width * height; // End of data - uint32_t* const src_last = data + width * last_row; // Last pixel to decode - const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES; - const int color_cache_limit = len_code_limit + hdr->color_cache_size_; - int next_sync_row = dec->incremental_ ? row : 1 << 24; - VP8LColorCache* const color_cache = - (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL; - const int mask = hdr->huffman_mask_; - assert(htree_group != NULL); - assert(src < src_end); - assert(src_last <= src_end); - - while (src < src_last) { - int code; - if (row >= next_sync_row) { - SaveState(dec, (int)(src - data)); - next_sync_row = row + SYNC_EVERY_N_ROWS; - } - // Only update when changing tile. Note we could use this test: - // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed - // but that's actually slower and needs storing the previous col/row. - if ((col & mask) == 0) htree_group = GetHtreeGroupForPos(hdr, col, row); - if (htree_group->is_trivial_code) { - *src = htree_group->literal_arb; - goto AdvanceByOne; - } - VP8LFillBitWindow(br); - if (htree_group->use_packed_table) { - code = ReadPackedSymbols(htree_group, br, src); - if (code == PACKED_NON_LITERAL_CODE) goto AdvanceByOne; - } else { - code = ReadSymbol(htree_group->htrees[GREEN], br); - } - if (br->eos_) break; // early out - if (code < NUM_LITERAL_CODES) { // Literal - if (htree_group->is_trivial_literal) { - *src = htree_group->literal_arb | (code << 8); - } else { - int red, blue, alpha; - red = ReadSymbol(htree_group->htrees[RED], br); - VP8LFillBitWindow(br); - blue = ReadSymbol(htree_group->htrees[BLUE], br); - alpha = ReadSymbol(htree_group->htrees[ALPHA], br); - if (br->eos_) break; - *src = ((uint32_t)alpha << 24) | (red << 16) | (code << 8) | blue; - } - AdvanceByOne: - ++src; - ++col; - if (col >= width) { - col = 0; - ++row; - if ((row % NUM_ARGB_CACHE_ROWS == 0) && (process_func != NULL)) { - process_func(dec, row); - } - if (color_cache != NULL) { - while (last_cached < src) { - VP8LColorCacheInsert(color_cache, *last_cached++); - } - } - } - } else if (code < len_code_limit) { // Backward reference - int dist_code, dist; - const int length_sym = code - NUM_LITERAL_CODES; - const int length = GetCopyLength(length_sym, br); - const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br); - VP8LFillBitWindow(br); - dist_code = GetCopyDistance(dist_symbol, br); - dist = PlaneCodeToDistance(width, dist_code); - if (br->eos_) break; - if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) { - goto Error; - } else { - CopyBlock32b(src, dist, length); - } - src += length; - col += length; - while (col >= width) { - col -= width; - ++row; - if ((row % NUM_ARGB_CACHE_ROWS == 0) && (process_func != NULL)) { - process_func(dec, row); - } - } - // Because of the check done above (before 'src' was incremented by - // 'length'), the following holds true. - assert(src <= src_end); - if (col & mask) htree_group = GetHtreeGroupForPos(hdr, col, row); - if (color_cache != NULL) { - while (last_cached < src) { - VP8LColorCacheInsert(color_cache, *last_cached++); - } - } - } else if (code < color_cache_limit) { // Color cache - const int key = code - len_code_limit; - assert(color_cache != NULL); - while (last_cached < src) { - VP8LColorCacheInsert(color_cache, *last_cached++); - } - *src = VP8LColorCacheLookup(color_cache, key); - goto AdvanceByOne; - } else { // Not reached - goto Error; - } - assert(br->eos_ == VP8LIsEndOfStream(br)); - } - - if (dec->incremental_ && br->eos_ && src < src_end) { - RestoreState(dec); - } else if (!br->eos_) { - // Process the remaining rows corresponding to last row-block. - if (process_func != NULL) { - process_func(dec, row); - } - dec->status_ = VP8_STATUS_OK; - dec->last_pixel_ = (int)(src - data); // end-of-scan marker - } else { - // if not incremental, and we are past the end of buffer (eos_=1), then this - // is a real bitstream error. - goto Error; - } - return 1; - - Error: - dec->status_ = VP8_STATUS_BITSTREAM_ERROR; - return 0; -} - -// ----------------------------------------------------------------------------- -// VP8LTransform - -static void ClearTransform(VP8LTransform* const transform) { - WebPSafeFree(transform->data_); - transform->data_ = NULL; -} - -// For security reason, we need to remap the color map to span -// the total possible bundled values, and not just the num_colors. -static int ExpandColorMap(int num_colors, VP8LTransform* const transform) { - int i; - const int final_num_colors = 1 << (8 >> transform->bits_); - uint32_t* const new_color_map = - (uint32_t*)WebPSafeMalloc((uint64_t)final_num_colors, - sizeof(*new_color_map)); - if (new_color_map == NULL) { - return 0; - } else { - uint8_t* const data = (uint8_t*)transform->data_; - uint8_t* const new_data = (uint8_t*)new_color_map; - new_color_map[0] = transform->data_[0]; - for (i = 4; i < 4 * num_colors; ++i) { - // Equivalent to AddPixelEq(), on a byte-basis. - new_data[i] = (data[i] + new_data[i - 4]) & 0xff; - } - for (; i < 4 * final_num_colors; ++i) - new_data[i] = 0; // black tail. - WebPSafeFree(transform->data_); - transform->data_ = new_color_map; - } - return 1; -} - -static int ReadTransform(int* const xsize, int const* ysize, - VP8LDecoder* const dec) { - int ok = 1; - VP8LBitReader* const br = &dec->br_; - VP8LTransform* transform = &dec->transforms_[dec->next_transform_]; - const VP8LImageTransformType type = - (VP8LImageTransformType)VP8LReadBits(br, 2); - - // Each transform type can only be present once in the stream. - if (dec->transforms_seen_ & (1U << type)) { - return 0; // Already there, let's not accept the second same transform. - } - dec->transforms_seen_ |= (1U << type); - - transform->type_ = type; - transform->xsize_ = *xsize; - transform->ysize_ = *ysize; - transform->data_ = NULL; - ++dec->next_transform_; - assert(dec->next_transform_ <= NUM_TRANSFORMS); - - switch (type) { - case PREDICTOR_TRANSFORM: - case CROSS_COLOR_TRANSFORM: - transform->bits_ = VP8LReadBits(br, 3) + 2; - ok = DecodeImageStream(VP8LSubSampleSize(transform->xsize_, - transform->bits_), - VP8LSubSampleSize(transform->ysize_, - transform->bits_), - 0, dec, &transform->data_); - break; - case COLOR_INDEXING_TRANSFORM: { - const int num_colors = VP8LReadBits(br, 8) + 1; - const int bits = (num_colors > 16) ? 0 - : (num_colors > 4) ? 1 - : (num_colors > 2) ? 2 - : 3; - *xsize = VP8LSubSampleSize(transform->xsize_, bits); - transform->bits_ = bits; - ok = DecodeImageStream(num_colors, 1, 0, dec, &transform->data_); - ok = ok && ExpandColorMap(num_colors, transform); - break; - } - case SUBTRACT_GREEN: - break; - default: - assert(0); // can't happen - break; - } - - return ok; -} - -// ----------------------------------------------------------------------------- -// VP8LMetadata - -static void InitMetadata(VP8LMetadata* const hdr) { - assert(hdr != NULL); - memset(hdr, 0, sizeof(*hdr)); -} - -static void ClearMetadata(VP8LMetadata* const hdr) { - assert(hdr != NULL); - - WebPSafeFree(hdr->huffman_image_); - WebPSafeFree(hdr->huffman_tables_); - VP8LHtreeGroupsFree(hdr->htree_groups_); - VP8LColorCacheClear(&hdr->color_cache_); - VP8LColorCacheClear(&hdr->saved_color_cache_); - InitMetadata(hdr); -} - -// ----------------------------------------------------------------------------- -// VP8LDecoder - -VP8LDecoder* VP8LNew(void) { - VP8LDecoder* const dec = (VP8LDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); - if (dec == NULL) return NULL; - dec->status_ = VP8_STATUS_OK; - dec->state_ = READ_DIM; - - VP8LDspInit(); // Init critical function pointers. - - return dec; -} - -void VP8LClear(VP8LDecoder* const dec) { - int i; - if (dec == NULL) return; - ClearMetadata(&dec->hdr_); - - WebPSafeFree(dec->pixels_); - dec->pixels_ = NULL; - for (i = 0; i < dec->next_transform_; ++i) { - ClearTransform(&dec->transforms_[i]); - } - dec->next_transform_ = 0; - dec->transforms_seen_ = 0; - - WebPSafeFree(dec->rescaler_memory); - dec->rescaler_memory = NULL; - - dec->output_ = NULL; // leave no trace behind -} - -void VP8LDelete(VP8LDecoder* const dec) { - if (dec != NULL) { - VP8LClear(dec); - WebPSafeFree(dec); - } -} - -static void UpdateDecoder(VP8LDecoder* const dec, int width, int height) { - VP8LMetadata* const hdr = &dec->hdr_; - const int num_bits = hdr->huffman_subsample_bits_; - dec->width_ = width; - dec->height_ = height; - - hdr->huffman_xsize_ = VP8LSubSampleSize(width, num_bits); - hdr->huffman_mask_ = (num_bits == 0) ? ~0 : (1 << num_bits) - 1; -} - -static int DecodeImageStream(int xsize, int ysize, - int is_level0, - VP8LDecoder* const dec, - uint32_t** const decoded_data) { - int ok = 1; - int transform_xsize = xsize; - int transform_ysize = ysize; - VP8LBitReader* const br = &dec->br_; - VP8LMetadata* const hdr = &dec->hdr_; - uint32_t* data = NULL; - int color_cache_bits = 0; - - // Read the transforms (may recurse). - if (is_level0) { - while (ok && VP8LReadBits(br, 1)) { - ok = ReadTransform(&transform_xsize, &transform_ysize, dec); - } - } - - // Color cache - if (ok && VP8LReadBits(br, 1)) { - color_cache_bits = VP8LReadBits(br, 4); - ok = (color_cache_bits >= 1 && color_cache_bits <= MAX_CACHE_BITS); - if (!ok) { - dec->status_ = VP8_STATUS_BITSTREAM_ERROR; - goto End; - } - } - - // Read the Huffman codes (may recurse). - ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize, - color_cache_bits, is_level0); - if (!ok) { - dec->status_ = VP8_STATUS_BITSTREAM_ERROR; - goto End; - } - - // Finish setting up the color-cache - if (color_cache_bits > 0) { - hdr->color_cache_size_ = 1 << color_cache_bits; - if (!VP8LColorCacheInit(&hdr->color_cache_, color_cache_bits)) { - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; - ok = 0; - goto End; - } - } else { - hdr->color_cache_size_ = 0; - } - UpdateDecoder(dec, transform_xsize, transform_ysize); - - if (is_level0) { // level 0 complete - dec->state_ = READ_HDR; - goto End; - } - - { - const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize; - data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data)); - if (data == NULL) { - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; - ok = 0; - goto End; - } - } - - // Use the Huffman trees to decode the LZ77 encoded data. - ok = DecodeImageData(dec, data, transform_xsize, transform_ysize, - transform_ysize, NULL); - ok = ok && !br->eos_; - - End: - if (!ok) { - WebPSafeFree(data); - ClearMetadata(hdr); - } else { - if (decoded_data != NULL) { - *decoded_data = data; - } else { - // We allocate image data in this function only for transforms. At level 0 - // (that is: not the transforms), we shouldn't have allocated anything. - assert(data == NULL); - assert(is_level0); - } - dec->last_pixel_ = 0; // Reset for future DECODE_DATA_FUNC() calls. - if (!is_level0) ClearMetadata(hdr); // Clean up temporary data behind. - } - return ok; -} - -//------------------------------------------------------------------------------ -// Allocate internal buffers dec->pixels_ and dec->argb_cache_. -static int AllocateInternalBuffers32b(VP8LDecoder* const dec, int final_width) { - const uint64_t num_pixels = (uint64_t)dec->width_ * dec->height_; - // Scratch buffer corresponding to top-prediction row for transforming the - // first row in the row-blocks. Not needed for paletted alpha. - const uint64_t cache_top_pixels = (uint16_t)final_width; - // Scratch buffer for temporary BGRA storage. Not needed for paletted alpha. - const uint64_t cache_pixels = (uint64_t)final_width * NUM_ARGB_CACHE_ROWS; - const uint64_t total_num_pixels = - num_pixels + cache_top_pixels + cache_pixels; - - assert(dec->width_ <= final_width); - dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint32_t)); - if (dec->pixels_ == NULL) { - dec->argb_cache_ = NULL; // for sanity check - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; - return 0; - } - dec->argb_cache_ = dec->pixels_ + num_pixels + cache_top_pixels; - return 1; -} - -static int AllocateInternalBuffers8b(VP8LDecoder* const dec) { - const uint64_t total_num_pixels = (uint64_t)dec->width_ * dec->height_; - dec->argb_cache_ = NULL; // for sanity check - dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint8_t)); - if (dec->pixels_ == NULL) { - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; - return 0; - } - return 1; -} - -//------------------------------------------------------------------------------ - -// Special row-processing that only stores the alpha data. -static void ExtractAlphaRows(VP8LDecoder* const dec, int row) { - const int num_rows = row - dec->last_row_; - const uint32_t* const in = dec->pixels_ + dec->width_ * dec->last_row_; - - if (num_rows <= 0) return; // Nothing to be done. - ApplyInverseTransforms(dec, num_rows, in); - - // Extract alpha (which is stored in the green plane). - { - const int width = dec->io_->width; // the final width (!= dec->width_) - const int cache_pixs = width * num_rows; - uint8_t* const dst = (uint8_t*)dec->io_->opaque + width * dec->last_row_; - const uint32_t* const src = dec->argb_cache_; - int i; - for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff; - } - dec->last_row_ = dec->last_out_row_ = row; -} - -int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec, - const uint8_t* const data, size_t data_size, - uint8_t* const output) { - int ok = 0; - VP8LDecoder* dec; - VP8Io* io; - assert(alph_dec != NULL); - alph_dec->vp8l_dec_ = VP8LNew(); - if (alph_dec->vp8l_dec_ == NULL) return 0; - dec = alph_dec->vp8l_dec_; - - dec->width_ = alph_dec->width_; - dec->height_ = alph_dec->height_; - dec->io_ = &alph_dec->io_; - io = dec->io_; - - VP8InitIo(io); - WebPInitCustomIo(NULL, io); // Just a sanity Init. io won't be used. - io->opaque = output; - io->width = alph_dec->width_; - io->height = alph_dec->height_; - - dec->status_ = VP8_STATUS_OK; - VP8LInitBitReader(&dec->br_, data, data_size); - - if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, 1, dec, NULL)) { - goto Err; - } - - // Special case: if alpha data uses only the color indexing transform and - // doesn't use color cache (a frequent case), we will use DecodeAlphaData() - // method that only needs allocation of 1 byte per pixel (alpha channel). - if (dec->next_transform_ == 1 && - dec->transforms_[0].type_ == COLOR_INDEXING_TRANSFORM && - Is8bOptimizable(&dec->hdr_)) { - alph_dec->use_8b_decode = 1; - ok = AllocateInternalBuffers8b(dec); - } else { - // Allocate internal buffers (note that dec->width_ may have changed here). - alph_dec->use_8b_decode = 0; - ok = AllocateInternalBuffers32b(dec, alph_dec->width_); - } - - if (!ok) goto Err; - - return 1; - - Err: - VP8LDelete(alph_dec->vp8l_dec_); - alph_dec->vp8l_dec_ = NULL; - return 0; -} - -int VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) { - VP8LDecoder* const dec = alph_dec->vp8l_dec_; - assert(dec != NULL); - assert(last_row <= dec->height_); - - if (dec->last_pixel_ == dec->width_ * dec->height_) { - return 1; // done - } - - // Decode (with special row processing). - return alph_dec->use_8b_decode ? - DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_, - last_row) : - DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, - last_row, ExtractAlphaRows); -} - -//------------------------------------------------------------------------------ - -int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) { - int width, height, has_alpha; - - if (dec == NULL) return 0; - if (io == NULL) { - dec->status_ = VP8_STATUS_INVALID_PARAM; - return 0; - } - - dec->io_ = io; - dec->status_ = VP8_STATUS_OK; - VP8LInitBitReader(&dec->br_, io->data, io->data_size); - if (!ReadImageInfo(&dec->br_, &width, &height, &has_alpha)) { - dec->status_ = VP8_STATUS_BITSTREAM_ERROR; - goto Error; - } - dec->state_ = READ_DIM; - io->width = width; - io->height = height; - - if (!DecodeImageStream(width, height, 1, dec, NULL)) goto Error; - return 1; - - Error: - VP8LClear(dec); - assert(dec->status_ != VP8_STATUS_OK); - return 0; -} - -int VP8LDecodeImage(VP8LDecoder* const dec) { - VP8Io* io = NULL; - WebPDecParams* params = NULL; - - // Sanity checks. - if (dec == NULL) return 0; - - assert(dec->hdr_.huffman_tables_ != NULL); - assert(dec->hdr_.htree_groups_ != NULL); - assert(dec->hdr_.num_htree_groups_ > 0); - - io = dec->io_; - assert(io != NULL); - params = (WebPDecParams*)io->opaque; - assert(params != NULL); - - // Initialization. - if (dec->state_ != READ_DATA) { - dec->output_ = params->output; - assert(dec->output_ != NULL); - - if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) { - dec->status_ = VP8_STATUS_INVALID_PARAM; - goto Err; - } - - if (!AllocateInternalBuffers32b(dec, io->width)) goto Err; - - if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err; - - if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) { - // need the alpha-multiply functions for premultiplied output or rescaling - WebPInitAlphaProcessing(); - } - if (!WebPIsRGBMode(dec->output_->colorspace)) { - WebPInitConvertARGBToYUV(); - if (dec->output_->u.YUVA.a != NULL) WebPInitAlphaProcessing(); - } - if (dec->incremental_) { - if (dec->hdr_.color_cache_size_ > 0 && - dec->hdr_.saved_color_cache_.colors_ == NULL) { - if (!VP8LColorCacheInit(&dec->hdr_.saved_color_cache_, - dec->hdr_.color_cache_.hash_bits_)) { - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; - goto Err; - } - } - } - dec->state_ = READ_DATA; - } - - // Decode. - if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, - dec->height_, ProcessRows)) { - goto Err; - } - - params->last_y = dec->last_out_row_; - return 1; - - Err: - VP8LClear(dec); - assert(dec->status_ != VP8_STATUS_OK); - return 0; -} - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/dec/vp8li.h b/Example-Mac/Pods/libwebp/src/dec/vp8li.h deleted file mode 100644 index 8886e47f..00000000 --- a/Example-Mac/Pods/libwebp/src/dec/vp8li.h +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Lossless decoder: internal header. -// -// Author: Skal (pascal.massimino@gmail.com) -// Vikas Arora(vikaas.arora@gmail.com) - -#ifndef WEBP_DEC_VP8LI_H_ -#define WEBP_DEC_VP8LI_H_ - -#include // for memcpy() -#include "./webpi.h" -#include "../utils/bit_reader.h" -#include "../utils/color_cache.h" -#include "../utils/huffman.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - READ_DATA = 0, - READ_HDR = 1, - READ_DIM = 2 -} VP8LDecodeState; - -typedef struct VP8LTransform VP8LTransform; -struct VP8LTransform { - VP8LImageTransformType type_; // transform type. - int bits_; // subsampling bits defining transform window. - int xsize_; // transform window X index. - int ysize_; // transform window Y index. - uint32_t *data_; // transform data. -}; - -typedef struct { - int color_cache_size_; - VP8LColorCache color_cache_; - VP8LColorCache saved_color_cache_; // for incremental - - int huffman_mask_; - int huffman_subsample_bits_; - int huffman_xsize_; - uint32_t *huffman_image_; - int num_htree_groups_; - HTreeGroup *htree_groups_; - HuffmanCode *huffman_tables_; -} VP8LMetadata; - -typedef struct VP8LDecoder VP8LDecoder; -struct VP8LDecoder { - VP8StatusCode status_; - VP8LDecodeState state_; - VP8Io *io_; - - const WebPDecBuffer *output_; // shortcut to io->opaque->output - - uint32_t *pixels_; // Internal data: either uint8_t* for alpha - // or uint32_t* for BGRA. - uint32_t *argb_cache_; // Scratch buffer for temporary BGRA storage. - - VP8LBitReader br_; - int incremental_; // if true, incremental decoding is expected - VP8LBitReader saved_br_; // note: could be local variables too - int saved_last_pixel_; - - int width_; - int height_; - int last_row_; // last input row decoded so far. - int last_pixel_; // last pixel decoded so far. However, it may - // not be transformed, scaled and - // color-converted yet. - int last_out_row_; // last row output so far. - - VP8LMetadata hdr_; - - int next_transform_; - VP8LTransform transforms_[NUM_TRANSFORMS]; - // or'd bitset storing the transforms types. - uint32_t transforms_seen_; - - uint8_t *rescaler_memory; // Working memory for rescaling work. - WebPRescaler *rescaler; // Common rescaler for all channels. -}; - -//------------------------------------------------------------------------------ -// internal functions. Not public. - -struct ALPHDecoder; // Defined in dec/alphai.h. - -// in vp8l.c - -// Decodes image header for alpha data stored using lossless compression. -// Returns false in case of error. -int VP8LDecodeAlphaHeader(struct ALPHDecoder* const alph_dec, - const uint8_t* const data, size_t data_size, - uint8_t* const output); - -// Decodes *at least* 'last_row' rows of alpha. If some of the initial rows are -// already decoded in previous call(s), it will resume decoding from where it -// was paused. -// Returns false in case of bitstream error. -int VP8LDecodeAlphaImageStream(struct ALPHDecoder* const alph_dec, - int last_row); - -// Allocates and initialize a new lossless decoder instance. -VP8LDecoder* VP8LNew(void); - -// Decodes the image header. Returns false in case of error. -int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io); - -// Decodes an image. It's required to decode the lossless header before calling -// this function. Returns false in case of error, with updated dec->status_. -int VP8LDecodeImage(VP8LDecoder* const dec); - -// Resets the decoder in its initial state, reclaiming memory. -// Preserves the dec->status_ value. -void VP8LClear(VP8LDecoder* const dec); - -// Clears and deallocate a lossless decoder instance. -void VP8LDelete(VP8LDecoder* const dec); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_DEC_VP8LI_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/dec/webp.c b/Example-Mac/Pods/libwebp/src/dec/webp.c deleted file mode 100644 index 952178fa..00000000 --- a/Example-Mac/Pods/libwebp/src/dec/webp.c +++ /dev/null @@ -1,829 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Main decoding functions for WEBP images. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include - -#include "./vp8i.h" -#include "./vp8li.h" -#include "./webpi.h" -#include "../utils/utils.h" -#include "../webp/mux_types.h" // ALPHA_FLAG - -//------------------------------------------------------------------------------ -// RIFF layout is: -// Offset tag -// 0...3 "RIFF" 4-byte tag -// 4...7 size of image data (including metadata) starting at offset 8 -// 8...11 "WEBP" our form-type signature -// The RIFF container (12 bytes) is followed by appropriate chunks: -// 12..15 "VP8 ": 4-bytes tags, signaling the use of VP8 video format -// 16..19 size of the raw VP8 image data, starting at offset 20 -// 20.... the VP8 bytes -// Or, -// 12..15 "VP8L": 4-bytes tags, signaling the use of VP8L lossless format -// 16..19 size of the raw VP8L image data, starting at offset 20 -// 20.... the VP8L bytes -// Or, -// 12..15 "VP8X": 4-bytes tags, describing the extended-VP8 chunk. -// 16..19 size of the VP8X chunk starting at offset 20. -// 20..23 VP8X flags bit-map corresponding to the chunk-types present. -// 24..26 Width of the Canvas Image. -// 27..29 Height of the Canvas Image. -// There can be extra chunks after the "VP8X" chunk (ICCP, FRGM, ANMF, VP8, -// VP8L, XMP, EXIF ...) -// All sizes are in little-endian order. -// Note: chunk data size must be padded to multiple of 2 when written. - -// Validates the RIFF container (if detected) and skips over it. -// If a RIFF container is detected, returns: -// VP8_STATUS_BITSTREAM_ERROR for invalid header, -// VP8_STATUS_NOT_ENOUGH_DATA for truncated data if have_all_data is true, -// and VP8_STATUS_OK otherwise. -// In case there are not enough bytes (partial RIFF container), return 0 for -// *riff_size. Else return the RIFF size extracted from the header. -static VP8StatusCode ParseRIFF(const uint8_t** const data, - size_t* const data_size, int have_all_data, - size_t* const riff_size) { - assert(data != NULL); - assert(data_size != NULL); - assert(riff_size != NULL); - - *riff_size = 0; // Default: no RIFF present. - if (*data_size >= RIFF_HEADER_SIZE && !memcmp(*data, "RIFF", TAG_SIZE)) { - if (memcmp(*data + 8, "WEBP", TAG_SIZE)) { - return VP8_STATUS_BITSTREAM_ERROR; // Wrong image file signature. - } else { - const uint32_t size = GetLE32(*data + TAG_SIZE); - // Check that we have at least one chunk (i.e "WEBP" + "VP8?nnnn"). - if (size < TAG_SIZE + CHUNK_HEADER_SIZE) { - return VP8_STATUS_BITSTREAM_ERROR; - } - if (size > MAX_CHUNK_PAYLOAD) { - return VP8_STATUS_BITSTREAM_ERROR; - } - if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) { - return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream. - } - // We have a RIFF container. Skip it. - *riff_size = size; - *data += RIFF_HEADER_SIZE; - *data_size -= RIFF_HEADER_SIZE; - } - } - return VP8_STATUS_OK; -} - -// Validates the VP8X header and skips over it. -// Returns VP8_STATUS_BITSTREAM_ERROR for invalid VP8X header, -// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and -// VP8_STATUS_OK otherwise. -// If a VP8X chunk is found, found_vp8x is set to true and *width_ptr, -// *height_ptr and *flags_ptr are set to the corresponding values extracted -// from the VP8X chunk. -static VP8StatusCode ParseVP8X(const uint8_t** const data, - size_t* const data_size, - int* const found_vp8x, - int* const width_ptr, int* const height_ptr, - uint32_t* const flags_ptr) { - const uint32_t vp8x_size = CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE; - assert(data != NULL); - assert(data_size != NULL); - assert(found_vp8x != NULL); - - *found_vp8x = 0; - - if (*data_size < CHUNK_HEADER_SIZE) { - return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. - } - - if (!memcmp(*data, "VP8X", TAG_SIZE)) { - int width, height; - uint32_t flags; - const uint32_t chunk_size = GetLE32(*data + TAG_SIZE); - if (chunk_size != VP8X_CHUNK_SIZE) { - return VP8_STATUS_BITSTREAM_ERROR; // Wrong chunk size. - } - - // Verify if enough data is available to validate the VP8X chunk. - if (*data_size < vp8x_size) { - return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. - } - flags = GetLE32(*data + 8); - width = 1 + GetLE24(*data + 12); - height = 1 + GetLE24(*data + 15); - if (width * (uint64_t)height >= MAX_IMAGE_AREA) { - return VP8_STATUS_BITSTREAM_ERROR; // image is too large - } - - if (flags_ptr != NULL) *flags_ptr = flags; - if (width_ptr != NULL) *width_ptr = width; - if (height_ptr != NULL) *height_ptr = height; - // Skip over VP8X header bytes. - *data += vp8x_size; - *data_size -= vp8x_size; - *found_vp8x = 1; - } - return VP8_STATUS_OK; -} - -// Skips to the next VP8/VP8L chunk header in the data given the size of the -// RIFF chunk 'riff_size'. -// Returns VP8_STATUS_BITSTREAM_ERROR if any invalid chunk size is encountered, -// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and -// VP8_STATUS_OK otherwise. -// If an alpha chunk is found, *alpha_data and *alpha_size are set -// appropriately. -static VP8StatusCode ParseOptionalChunks(const uint8_t** const data, - size_t* const data_size, - size_t const riff_size, - const uint8_t** const alpha_data, - size_t* const alpha_size) { - const uint8_t* buf; - size_t buf_size; - uint32_t total_size = TAG_SIZE + // "WEBP". - CHUNK_HEADER_SIZE + // "VP8Xnnnn". - VP8X_CHUNK_SIZE; // data. - assert(data != NULL); - assert(data_size != NULL); - buf = *data; - buf_size = *data_size; - - assert(alpha_data != NULL); - assert(alpha_size != NULL); - *alpha_data = NULL; - *alpha_size = 0; - - while (1) { - uint32_t chunk_size; - uint32_t disk_chunk_size; // chunk_size with padding - - *data = buf; - *data_size = buf_size; - - if (buf_size < CHUNK_HEADER_SIZE) { // Insufficient data. - return VP8_STATUS_NOT_ENOUGH_DATA; - } - - chunk_size = GetLE32(buf + TAG_SIZE); - if (chunk_size > MAX_CHUNK_PAYLOAD) { - return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. - } - // For odd-sized chunk-payload, there's one byte padding at the end. - disk_chunk_size = (CHUNK_HEADER_SIZE + chunk_size + 1) & ~1; - total_size += disk_chunk_size; - - // Check that total bytes skipped so far does not exceed riff_size. - if (riff_size > 0 && (total_size > riff_size)) { - return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. - } - - // Start of a (possibly incomplete) VP8/VP8L chunk implies that we have - // parsed all the optional chunks. - // Note: This check must occur before the check 'buf_size < disk_chunk_size' - // below to allow incomplete VP8/VP8L chunks. - if (!memcmp(buf, "VP8 ", TAG_SIZE) || - !memcmp(buf, "VP8L", TAG_SIZE)) { - return VP8_STATUS_OK; - } - - if (buf_size < disk_chunk_size) { // Insufficient data. - return VP8_STATUS_NOT_ENOUGH_DATA; - } - - if (!memcmp(buf, "ALPH", TAG_SIZE)) { // A valid ALPH header. - *alpha_data = buf + CHUNK_HEADER_SIZE; - *alpha_size = chunk_size; - } - - // We have a full and valid chunk; skip it. - buf += disk_chunk_size; - buf_size -= disk_chunk_size; - } -} - -// Validates the VP8/VP8L Header ("VP8 nnnn" or "VP8L nnnn") and skips over it. -// Returns VP8_STATUS_BITSTREAM_ERROR for invalid (chunk larger than -// riff_size) VP8/VP8L header, -// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and -// VP8_STATUS_OK otherwise. -// If a VP8/VP8L chunk is found, *chunk_size is set to the total number of bytes -// extracted from the VP8/VP8L chunk header. -// The flag '*is_lossless' is set to 1 in case of VP8L chunk / raw VP8L data. -static VP8StatusCode ParseVP8Header(const uint8_t** const data_ptr, - size_t* const data_size, int have_all_data, - size_t riff_size, size_t* const chunk_size, - int* const is_lossless) { - const uint8_t* const data = *data_ptr; - const int is_vp8 = !memcmp(data, "VP8 ", TAG_SIZE); - const int is_vp8l = !memcmp(data, "VP8L", TAG_SIZE); - const uint32_t minimal_size = - TAG_SIZE + CHUNK_HEADER_SIZE; // "WEBP" + "VP8 nnnn" OR - // "WEBP" + "VP8Lnnnn" - assert(data != NULL); - assert(data_size != NULL); - assert(chunk_size != NULL); - assert(is_lossless != NULL); - - if (*data_size < CHUNK_HEADER_SIZE) { - return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. - } - - if (is_vp8 || is_vp8l) { - // Bitstream contains VP8/VP8L header. - const uint32_t size = GetLE32(data + TAG_SIZE); - if ((riff_size >= minimal_size) && (size > riff_size - minimal_size)) { - return VP8_STATUS_BITSTREAM_ERROR; // Inconsistent size information. - } - if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) { - return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream. - } - // Skip over CHUNK_HEADER_SIZE bytes from VP8/VP8L Header. - *chunk_size = size; - *data_ptr += CHUNK_HEADER_SIZE; - *data_size -= CHUNK_HEADER_SIZE; - *is_lossless = is_vp8l; - } else { - // Raw VP8/VP8L bitstream (no header). - *is_lossless = VP8LCheckSignature(data, *data_size); - *chunk_size = *data_size; - } - - return VP8_STATUS_OK; -} - -//------------------------------------------------------------------------------ - -// Fetch '*width', '*height', '*has_alpha' and fill out 'headers' based on -// 'data'. All the output parameters may be NULL. If 'headers' is NULL only the -// minimal amount will be read to fetch the remaining parameters. -// If 'headers' is non-NULL this function will attempt to locate both alpha -// data (with or without a VP8X chunk) and the bitstream chunk (VP8/VP8L). -// Note: The following chunk sequences (before the raw VP8/VP8L data) are -// considered valid by this function: -// RIFF + VP8(L) -// RIFF + VP8X + (optional chunks) + VP8(L) -// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose. -// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose. -static VP8StatusCode ParseHeadersInternal(const uint8_t* data, - size_t data_size, - int* const width, - int* const height, - int* const has_alpha, - int* const has_animation, - int* const format, - WebPHeaderStructure* const headers) { - int canvas_width = 0; - int canvas_height = 0; - int image_width = 0; - int image_height = 0; - int found_riff = 0; - int found_vp8x = 0; - int animation_present = 0; - int fragments_present = 0; - const int have_all_data = (headers != NULL) ? headers->have_all_data : 0; - - VP8StatusCode status; - WebPHeaderStructure hdrs; - - if (data == NULL || data_size < RIFF_HEADER_SIZE) { - return VP8_STATUS_NOT_ENOUGH_DATA; - } - memset(&hdrs, 0, sizeof(hdrs)); - hdrs.data = data; - hdrs.data_size = data_size; - - // Skip over RIFF header. - status = ParseRIFF(&data, &data_size, have_all_data, &hdrs.riff_size); - if (status != VP8_STATUS_OK) { - return status; // Wrong RIFF header / insufficient data. - } - found_riff = (hdrs.riff_size > 0); - - // Skip over VP8X. - { - uint32_t flags = 0; - status = ParseVP8X(&data, &data_size, &found_vp8x, - &canvas_width, &canvas_height, &flags); - if (status != VP8_STATUS_OK) { - return status; // Wrong VP8X / insufficient data. - } - animation_present = !!(flags & ANIMATION_FLAG); - fragments_present = !!(flags & FRAGMENTS_FLAG); - if (!found_riff && found_vp8x) { - // Note: This restriction may be removed in the future, if it becomes - // necessary to send VP8X chunk to the decoder. - return VP8_STATUS_BITSTREAM_ERROR; - } - if (has_alpha != NULL) *has_alpha = !!(flags & ALPHA_FLAG); - if (has_animation != NULL) *has_animation = animation_present; - if (format != NULL) *format = 0; // default = undefined - - image_width = canvas_width; - image_height = canvas_height; - if (found_vp8x && (animation_present || fragments_present) && - headers == NULL) { - status = VP8_STATUS_OK; - goto ReturnWidthHeight; // Just return features from VP8X header. - } - } - - if (data_size < TAG_SIZE) { - status = VP8_STATUS_NOT_ENOUGH_DATA; - goto ReturnWidthHeight; - } - - // Skip over optional chunks if data started with "RIFF + VP8X" or "ALPH". - if ((found_riff && found_vp8x) || - (!found_riff && !found_vp8x && !memcmp(data, "ALPH", TAG_SIZE))) { - status = ParseOptionalChunks(&data, &data_size, hdrs.riff_size, - &hdrs.alpha_data, &hdrs.alpha_data_size); - if (status != VP8_STATUS_OK) { - goto ReturnWidthHeight; // Invalid chunk size / insufficient data. - } - } - - // Skip over VP8/VP8L header. - status = ParseVP8Header(&data, &data_size, have_all_data, hdrs.riff_size, - &hdrs.compressed_size, &hdrs.is_lossless); - if (status != VP8_STATUS_OK) { - goto ReturnWidthHeight; // Wrong VP8/VP8L chunk-header / insufficient data. - } - if (hdrs.compressed_size > MAX_CHUNK_PAYLOAD) { - return VP8_STATUS_BITSTREAM_ERROR; - } - - if (format != NULL && !(animation_present || fragments_present)) { - *format = hdrs.is_lossless ? 2 : 1; - } - - if (!hdrs.is_lossless) { - if (data_size < VP8_FRAME_HEADER_SIZE) { - status = VP8_STATUS_NOT_ENOUGH_DATA; - goto ReturnWidthHeight; - } - // Validates raw VP8 data. - if (!VP8GetInfo(data, data_size, (uint32_t)hdrs.compressed_size, - &image_width, &image_height)) { - return VP8_STATUS_BITSTREAM_ERROR; - } - } else { - if (data_size < VP8L_FRAME_HEADER_SIZE) { - status = VP8_STATUS_NOT_ENOUGH_DATA; - goto ReturnWidthHeight; - } - // Validates raw VP8L data. - if (!VP8LGetInfo(data, data_size, &image_width, &image_height, has_alpha)) { - return VP8_STATUS_BITSTREAM_ERROR; - } - } - // Validates image size coherency. - if (found_vp8x) { - if (canvas_width != image_width || canvas_height != image_height) { - return VP8_STATUS_BITSTREAM_ERROR; - } - } - if (headers != NULL) { - *headers = hdrs; - headers->offset = data - headers->data; - assert((uint64_t)(data - headers->data) < MAX_CHUNK_PAYLOAD); - assert(headers->offset == headers->data_size - data_size); - } - ReturnWidthHeight: - if (status == VP8_STATUS_OK || - (status == VP8_STATUS_NOT_ENOUGH_DATA && found_vp8x && headers == NULL)) { - if (has_alpha != NULL) { - // If the data did not contain a VP8X/VP8L chunk the only definitive way - // to set this is by looking for alpha data (from an ALPH chunk). - *has_alpha |= (hdrs.alpha_data != NULL); - } - if (width != NULL) *width = image_width; - if (height != NULL) *height = image_height; - return VP8_STATUS_OK; - } else { - return status; - } -} - -VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers) { - VP8StatusCode status; - int has_animation = 0; - assert(headers != NULL); - // fill out headers, ignore width/height/has_alpha. - status = ParseHeadersInternal(headers->data, headers->data_size, - NULL, NULL, NULL, &has_animation, - NULL, headers); - if (status == VP8_STATUS_OK || status == VP8_STATUS_NOT_ENOUGH_DATA) { - // TODO(jzern): full support of animation frames will require API additions. - if (has_animation) { - status = VP8_STATUS_UNSUPPORTED_FEATURE; - } - } - return status; -} - -//------------------------------------------------------------------------------ -// WebPDecParams - -void WebPResetDecParams(WebPDecParams* const params) { - if (params != NULL) { - memset(params, 0, sizeof(*params)); - } -} - -//------------------------------------------------------------------------------ -// "Into" decoding variants - -// Main flow -static VP8StatusCode DecodeInto(const uint8_t* const data, size_t data_size, - WebPDecParams* const params) { - VP8StatusCode status; - VP8Io io; - WebPHeaderStructure headers; - - headers.data = data; - headers.data_size = data_size; - headers.have_all_data = 1; - status = WebPParseHeaders(&headers); // Process Pre-VP8 chunks. - if (status != VP8_STATUS_OK) { - return status; - } - - assert(params != NULL); - VP8InitIo(&io); - io.data = headers.data + headers.offset; - io.data_size = headers.data_size - headers.offset; - WebPInitCustomIo(params, &io); // Plug the I/O functions. - - if (!headers.is_lossless) { - VP8Decoder* const dec = VP8New(); - if (dec == NULL) { - return VP8_STATUS_OUT_OF_MEMORY; - } - dec->alpha_data_ = headers.alpha_data; - dec->alpha_data_size_ = headers.alpha_data_size; - - // Decode bitstream header, update io->width/io->height. - if (!VP8GetHeaders(dec, &io)) { - status = dec->status_; // An error occurred. Grab error status. - } else { - // Allocate/check output buffers. - status = WebPAllocateDecBuffer(io.width, io.height, params->options, - params->output); - if (status == VP8_STATUS_OK) { // Decode - // This change must be done before calling VP8Decode() - dec->mt_method_ = VP8GetThreadMethod(params->options, &headers, - io.width, io.height); - VP8InitDithering(params->options, dec); - if (!VP8Decode(dec, &io)) { - status = dec->status_; - } - } - } - VP8Delete(dec); - } else { - VP8LDecoder* const dec = VP8LNew(); - if (dec == NULL) { - return VP8_STATUS_OUT_OF_MEMORY; - } - if (!VP8LDecodeHeader(dec, &io)) { - status = dec->status_; // An error occurred. Grab error status. - } else { - // Allocate/check output buffers. - status = WebPAllocateDecBuffer(io.width, io.height, params->options, - params->output); - if (status == VP8_STATUS_OK) { // Decode - if (!VP8LDecodeImage(dec)) { - status = dec->status_; - } - } - } - VP8LDelete(dec); - } - - if (status != VP8_STATUS_OK) { - WebPFreeDecBuffer(params->output); - } - - if (params->options != NULL && params->options->flip) { - status = WebPFlipBuffer(params->output); - } - return status; -} - -// Helpers -static uint8_t* DecodeIntoRGBABuffer(WEBP_CSP_MODE colorspace, - const uint8_t* const data, - size_t data_size, - uint8_t* const rgba, - int stride, size_t size) { - WebPDecParams params; - WebPDecBuffer buf; - if (rgba == NULL) { - return NULL; - } - WebPInitDecBuffer(&buf); - WebPResetDecParams(¶ms); - params.output = &buf; - buf.colorspace = colorspace; - buf.u.RGBA.rgba = rgba; - buf.u.RGBA.stride = stride; - buf.u.RGBA.size = size; - buf.is_external_memory = 1; - if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { - return NULL; - } - return rgba; -} - -uint8_t* WebPDecodeRGBInto(const uint8_t* data, size_t data_size, - uint8_t* output, size_t size, int stride) { - return DecodeIntoRGBABuffer(MODE_RGB, data, data_size, output, stride, size); -} - -uint8_t* WebPDecodeRGBAInto(const uint8_t* data, size_t data_size, - uint8_t* output, size_t size, int stride) { - return DecodeIntoRGBABuffer(MODE_RGBA, data, data_size, output, stride, size); -} - -uint8_t* WebPDecodeARGBInto(const uint8_t* data, size_t data_size, - uint8_t* output, size_t size, int stride) { - return DecodeIntoRGBABuffer(MODE_ARGB, data, data_size, output, stride, size); -} - -uint8_t* WebPDecodeBGRInto(const uint8_t* data, size_t data_size, - uint8_t* output, size_t size, int stride) { - return DecodeIntoRGBABuffer(MODE_BGR, data, data_size, output, stride, size); -} - -uint8_t* WebPDecodeBGRAInto(const uint8_t* data, size_t data_size, - uint8_t* output, size_t size, int stride) { - return DecodeIntoRGBABuffer(MODE_BGRA, data, data_size, output, stride, size); -} - -uint8_t* WebPDecodeYUVInto(const uint8_t* data, size_t data_size, - uint8_t* luma, size_t luma_size, int luma_stride, - uint8_t* u, size_t u_size, int u_stride, - uint8_t* v, size_t v_size, int v_stride) { - WebPDecParams params; - WebPDecBuffer output; - if (luma == NULL) return NULL; - WebPInitDecBuffer(&output); - WebPResetDecParams(¶ms); - params.output = &output; - output.colorspace = MODE_YUV; - output.u.YUVA.y = luma; - output.u.YUVA.y_stride = luma_stride; - output.u.YUVA.y_size = luma_size; - output.u.YUVA.u = u; - output.u.YUVA.u_stride = u_stride; - output.u.YUVA.u_size = u_size; - output.u.YUVA.v = v; - output.u.YUVA.v_stride = v_stride; - output.u.YUVA.v_size = v_size; - output.is_external_memory = 1; - if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { - return NULL; - } - return luma; -} - -//------------------------------------------------------------------------------ - -static uint8_t* Decode(WEBP_CSP_MODE mode, const uint8_t* const data, - size_t data_size, int* const width, int* const height, - WebPDecBuffer* const keep_info) { - WebPDecParams params; - WebPDecBuffer output; - - WebPInitDecBuffer(&output); - WebPResetDecParams(¶ms); - params.output = &output; - output.colorspace = mode; - - // Retrieve (and report back) the required dimensions from bitstream. - if (!WebPGetInfo(data, data_size, &output.width, &output.height)) { - return NULL; - } - if (width != NULL) *width = output.width; - if (height != NULL) *height = output.height; - - // Decode - if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { - return NULL; - } - if (keep_info != NULL) { // keep track of the side-info - WebPCopyDecBuffer(&output, keep_info); - } - // return decoded samples (don't clear 'output'!) - return WebPIsRGBMode(mode) ? output.u.RGBA.rgba : output.u.YUVA.y; -} - -uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size, - int* width, int* height) { - return Decode(MODE_RGB, data, data_size, width, height, NULL); -} - -uint8_t* WebPDecodeRGBA(const uint8_t* data, size_t data_size, - int* width, int* height) { - return Decode(MODE_RGBA, data, data_size, width, height, NULL); -} - -uint8_t* WebPDecodeARGB(const uint8_t* data, size_t data_size, - int* width, int* height) { - return Decode(MODE_ARGB, data, data_size, width, height, NULL); -} - -uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size, - int* width, int* height) { - return Decode(MODE_BGR, data, data_size, width, height, NULL); -} - -uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size, - int* width, int* height) { - return Decode(MODE_BGRA, data, data_size, width, height, NULL); -} - -uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size, - int* width, int* height, uint8_t** u, uint8_t** v, - int* stride, int* uv_stride) { - WebPDecBuffer output; // only to preserve the side-infos - uint8_t* const out = Decode(MODE_YUV, data, data_size, - width, height, &output); - - if (out != NULL) { - const WebPYUVABuffer* const buf = &output.u.YUVA; - *u = buf->u; - *v = buf->v; - *stride = buf->y_stride; - *uv_stride = buf->u_stride; - assert(buf->u_stride == buf->v_stride); - } - return out; -} - -static void DefaultFeatures(WebPBitstreamFeatures* const features) { - assert(features != NULL); - memset(features, 0, sizeof(*features)); -} - -static VP8StatusCode GetFeatures(const uint8_t* const data, size_t data_size, - WebPBitstreamFeatures* const features) { - if (features == NULL || data == NULL) { - return VP8_STATUS_INVALID_PARAM; - } - DefaultFeatures(features); - - // Only parse enough of the data to retrieve the features. - return ParseHeadersInternal(data, data_size, - &features->width, &features->height, - &features->has_alpha, &features->has_animation, - &features->format, NULL); -} - -//------------------------------------------------------------------------------ -// WebPGetInfo() - -int WebPGetInfo(const uint8_t* data, size_t data_size, - int* width, int* height) { - WebPBitstreamFeatures features; - - if (GetFeatures(data, data_size, &features) != VP8_STATUS_OK) { - return 0; - } - - if (width != NULL) { - *width = features.width; - } - if (height != NULL) { - *height = features.height; - } - - return 1; -} - -//------------------------------------------------------------------------------ -// Advance decoding API - -int WebPInitDecoderConfigInternal(WebPDecoderConfig* config, - int version) { - if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { - return 0; // version mismatch - } - if (config == NULL) { - return 0; - } - memset(config, 0, sizeof(*config)); - DefaultFeatures(&config->input); - WebPInitDecBuffer(&config->output); - return 1; -} - -VP8StatusCode WebPGetFeaturesInternal(const uint8_t* data, size_t data_size, - WebPBitstreamFeatures* features, - int version) { - if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { - return VP8_STATUS_INVALID_PARAM; // version mismatch - } - if (features == NULL) { - return VP8_STATUS_INVALID_PARAM; - } - return GetFeatures(data, data_size, features); -} - -VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size, - WebPDecoderConfig* config) { - WebPDecParams params; - VP8StatusCode status; - - if (config == NULL) { - return VP8_STATUS_INVALID_PARAM; - } - - status = GetFeatures(data, data_size, &config->input); - if (status != VP8_STATUS_OK) { - if (status == VP8_STATUS_NOT_ENOUGH_DATA) { - return VP8_STATUS_BITSTREAM_ERROR; // Not-enough-data treated as error. - } - return status; - } - - WebPResetDecParams(¶ms); - params.output = &config->output; - params.options = &config->options; - status = DecodeInto(data, data_size, ¶ms); - - return status; -} - -//------------------------------------------------------------------------------ -// Cropping and rescaling. - -int WebPIoInitFromOptions(const WebPDecoderOptions* const options, - VP8Io* const io, WEBP_CSP_MODE src_colorspace) { - const int W = io->width; - const int H = io->height; - int x = 0, y = 0, w = W, h = H; - - // Cropping - io->use_cropping = (options != NULL) && (options->use_cropping > 0); - if (io->use_cropping) { - w = options->crop_width; - h = options->crop_height; - x = options->crop_left; - y = options->crop_top; - if (!WebPIsRGBMode(src_colorspace)) { // only snap for YUV420 - x &= ~1; - y &= ~1; - } - if (x < 0 || y < 0 || w <= 0 || h <= 0 || x + w > W || y + h > H) { - return 0; // out of frame boundary error - } - } - io->crop_left = x; - io->crop_top = y; - io->crop_right = x + w; - io->crop_bottom = y + h; - io->mb_w = w; - io->mb_h = h; - - // Scaling - io->use_scaling = (options != NULL) && (options->use_scaling > 0); - if (io->use_scaling) { - int scaled_width = options->scaled_width; - int scaled_height = options->scaled_height; - if (!WebPRescalerGetScaledDimensions(w, h, &scaled_width, &scaled_height)) { - return 0; - } - io->scaled_width = scaled_width; - io->scaled_height = scaled_height; - } - - // Filter - io->bypass_filtering = options && options->bypass_filtering; - - // Fancy upsampler -#ifdef FANCY_UPSAMPLING - io->fancy_upsampling = (options == NULL) || (!options->no_fancy_upsampling); -#endif - - if (io->use_scaling) { - // disable filter (only for large downscaling ratio). - io->bypass_filtering = (io->scaled_width < W * 3 / 4) && - (io->scaled_height < H * 3 / 4); - io->fancy_upsampling = 0; - } - return 1; -} - -//------------------------------------------------------------------------------ - diff --git a/Example-Mac/Pods/libwebp/src/dec/webpi.h b/Example-Mac/Pods/libwebp/src/dec/webpi.h deleted file mode 100644 index c75a2e4a..00000000 --- a/Example-Mac/Pods/libwebp/src/dec/webpi.h +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Internal header: WebP decoding parameters and custom IO on buffer -// -// Author: somnath@google.com (Somnath Banerjee) - -#ifndef WEBP_DEC_WEBPI_H_ -#define WEBP_DEC_WEBPI_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "../utils/rescaler.h" -#include "./decode_vp8.h" - -//------------------------------------------------------------------------------ -// WebPDecParams: Decoding output parameters. Transient internal object. - -typedef struct WebPDecParams WebPDecParams; -typedef int (*OutputFunc)(const VP8Io* const io, WebPDecParams* const p); -typedef int (*OutputAlphaFunc)(const VP8Io* const io, WebPDecParams* const p, - int expected_num_out_lines); -typedef int (*OutputRowFunc)(WebPDecParams* const p, int y_pos, - int max_out_lines); - -struct WebPDecParams { - WebPDecBuffer* output; // output buffer. - uint8_t* tmp_y, *tmp_u, *tmp_v; // cache for the fancy upsampler - // or used for tmp rescaling - - int last_y; // coordinate of the line that was last output - const WebPDecoderOptions* options; // if not NULL, use alt decoding features - // rescalers - WebPRescaler scaler_y, scaler_u, scaler_v, scaler_a; - void* memory; // overall scratch memory for the output work. - - OutputFunc emit; // output RGB or YUV samples - OutputAlphaFunc emit_alpha; // output alpha channel - OutputRowFunc emit_alpha_row; // output one line of rescaled alpha values -}; - -// Should be called first, before any use of the WebPDecParams object. -void WebPResetDecParams(WebPDecParams* const params); - -//------------------------------------------------------------------------------ -// Header parsing helpers - -// Structure storing a description of the RIFF headers. -typedef struct { - const uint8_t* data; // input buffer - size_t data_size; // input buffer size - int have_all_data; // true if all data is known to be available - size_t offset; // offset to main data chunk (VP8 or VP8L) - const uint8_t* alpha_data; // points to alpha chunk (if present) - size_t alpha_data_size; // alpha chunk size - size_t compressed_size; // VP8/VP8L compressed data size - size_t riff_size; // size of the riff payload (or 0 if absent) - int is_lossless; // true if a VP8L chunk is present -} WebPHeaderStructure; - -// Skips over all valid chunks prior to the first VP8/VP8L frame header. -// Returns: VP8_STATUS_OK, VP8_STATUS_BITSTREAM_ERROR (invalid header/chunk), -// VP8_STATUS_NOT_ENOUGH_DATA (partial input) or VP8_STATUS_UNSUPPORTED_FEATURE -// in the case of non-decodable features (animation for instance). -// In 'headers', compressed_size, offset, alpha_data, alpha_size, and lossless -// fields are updated appropriately upon success. -VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers); - -//------------------------------------------------------------------------------ -// Misc utils - -// Initializes VP8Io with custom setup, io and teardown functions. The default -// hooks will use the supplied 'params' as io->opaque handle. -void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io); - -// Setup crop_xxx fields, mb_w and mb_h in io. 'src_colorspace' refers -// to the *compressed* format, not the output one. -int WebPIoInitFromOptions(const WebPDecoderOptions* const options, - VP8Io* const io, WEBP_CSP_MODE src_colorspace); - -//------------------------------------------------------------------------------ -// Internal functions regarding WebPDecBuffer memory (in buffer.c). -// Don't really need to be externally visible for now. - -// Prepare 'buffer' with the requested initial dimensions width/height. -// If no external storage is supplied, initializes buffer by allocating output -// memory and setting up the stride information. Validate the parameters. Return -// an error code in case of problem (no memory, or invalid stride / size / -// dimension / etc.). If *options is not NULL, also verify that the options' -// parameters are valid and apply them to the width/height dimensions of the -// output buffer. This takes cropping / scaling / rotation into account. -// Also incorporates the options->flip flag to flip the buffer parameters if -// needed. -VP8StatusCode WebPAllocateDecBuffer(int width, int height, - const WebPDecoderOptions* const options, - WebPDecBuffer* const buffer); - -// Flip buffer vertically by negating the various strides. -VP8StatusCode WebPFlipBuffer(WebPDecBuffer* const buffer); - -// Copy 'src' into 'dst' buffer, making sure 'dst' is not marked as owner of the -// memory (still held by 'src'). -void WebPCopyDecBuffer(const WebPDecBuffer* const src, - WebPDecBuffer* const dst); - -// Copy and transfer ownership from src to dst (beware of parameter order!) -void WebPGrabDecBuffer(WebPDecBuffer* const src, WebPDecBuffer* const dst); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_DEC_WEBPI_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/demux/anim_decode.c b/Example-Mac/Pods/libwebp/src/demux/anim_decode.c deleted file mode 100644 index 1989eb4a..00000000 --- a/Example-Mac/Pods/libwebp/src/demux/anim_decode.c +++ /dev/null @@ -1,442 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// AnimDecoder implementation. -// - -#ifdef HAVE_CONFIG_H -#include "../webp/config.h" -#endif - -#include -#include - -#include "../utils/utils.h" -#include "../webp/decode.h" -#include "../webp/demux.h" - -#define NUM_CHANNELS 4 - -typedef void (*BlendRowFunc)(uint32_t* const, const uint32_t* const, int); -static void BlendPixelRowNonPremult(uint32_t* const src, - const uint32_t* const dst, int num_pixels); -static void BlendPixelRowPremult(uint32_t* const src, const uint32_t* const dst, - int num_pixels); - -struct WebPAnimDecoder { - WebPDemuxer* demux_; // Demuxer created from given WebP bitstream. - WebPDecoderConfig config_; // Decoder config. - // Note: we use a pointer to a function blending multiple pixels at a time to - // allow possible inlining of per-pixel blending function. - BlendRowFunc blend_func_; // Pointer to the chose blend row function. - WebPAnimInfo info_; // Global info about the animation. - uint8_t* curr_frame_; // Current canvas (not disposed). - uint8_t* prev_frame_disposed_; // Previous canvas (properly disposed). - int prev_frame_timestamp_; // Previous frame timestamp (milliseconds). - WebPIterator prev_iter_; // Iterator object for previous frame. - int prev_frame_was_keyframe_; // True if previous frame was a keyframe. - int next_frame_; // Index of the next frame to be decoded - // (starting from 1). -}; - -static void DefaultDecoderOptions(WebPAnimDecoderOptions* const dec_options) { - dec_options->color_mode = MODE_RGBA; - dec_options->use_threads = 0; -} - -int WebPAnimDecoderOptionsInitInternal(WebPAnimDecoderOptions* dec_options, - int abi_version) { - if (dec_options == NULL || - WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_DEMUX_ABI_VERSION)) { - return 0; - } - DefaultDecoderOptions(dec_options); - return 1; -} - -static int ApplyDecoderOptions(const WebPAnimDecoderOptions* const dec_options, - WebPAnimDecoder* const dec) { - WEBP_CSP_MODE mode; - WebPDecoderConfig* config = &dec->config_; - assert(dec_options != NULL); - - mode = dec_options->color_mode; - if (mode != MODE_RGBA && mode != MODE_BGRA && - mode != MODE_rgbA && mode != MODE_bgrA) { - return 0; - } - dec->blend_func_ = (mode == MODE_RGBA || mode == MODE_BGRA) - ? &BlendPixelRowNonPremult - : &BlendPixelRowPremult; - WebPInitDecoderConfig(config); - config->output.colorspace = mode; - config->output.is_external_memory = 1; - config->options.use_threads = dec_options->use_threads; - // Note: config->output.u.RGBA is set at the time of decoding each frame. - return 1; -} - -WebPAnimDecoder* WebPAnimDecoderNewInternal( - const WebPData* webp_data, const WebPAnimDecoderOptions* dec_options, - int abi_version) { - WebPAnimDecoderOptions options; - WebPAnimDecoder* dec = NULL; - if (webp_data == NULL || - WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_DEMUX_ABI_VERSION)) { - return NULL; - } - - // Note: calloc() so that the pointer members are initialized to NULL. - dec = (WebPAnimDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); - if (dec == NULL) goto Error; - - if (dec_options != NULL) { - options = *dec_options; - } else { - DefaultDecoderOptions(&options); - } - if (!ApplyDecoderOptions(&options, dec)) goto Error; - - dec->demux_ = WebPDemux(webp_data); - if (dec->demux_ == NULL) goto Error; - - dec->info_.canvas_width = WebPDemuxGetI(dec->demux_, WEBP_FF_CANVAS_WIDTH); - dec->info_.canvas_height = WebPDemuxGetI(dec->demux_, WEBP_FF_CANVAS_HEIGHT); - dec->info_.loop_count = WebPDemuxGetI(dec->demux_, WEBP_FF_LOOP_COUNT); - dec->info_.bgcolor = WebPDemuxGetI(dec->demux_, WEBP_FF_BACKGROUND_COLOR); - dec->info_.frame_count = WebPDemuxGetI(dec->demux_, WEBP_FF_FRAME_COUNT); - - { - const int canvas_bytes = - dec->info_.canvas_width * NUM_CHANNELS * dec->info_.canvas_height; - // Note: calloc() because we fill frame with zeroes as well. - dec->curr_frame_ = WebPSafeCalloc(1ULL, canvas_bytes); - if (dec->curr_frame_ == NULL) goto Error; - dec->prev_frame_disposed_ = WebPSafeCalloc(1ULL, canvas_bytes); - if (dec->prev_frame_disposed_ == NULL) goto Error; - } - - WebPAnimDecoderReset(dec); - - return dec; - - Error: - WebPAnimDecoderDelete(dec); - return NULL; -} - -int WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec, WebPAnimInfo* info) { - if (dec == NULL || info == NULL) return 0; - *info = dec->info_; - return 1; -} - -// Returns true if the frame covers the full canvas. -static int IsFullFrame(int width, int height, int canvas_width, - int canvas_height) { - return (width == canvas_width && height == canvas_height); -} - -// Clear the canvas to transparent. -static void ZeroFillCanvas(uint8_t* buf, uint32_t canvas_width, - uint32_t canvas_height) { - memset(buf, 0, canvas_width * NUM_CHANNELS * canvas_height); -} - -// Clear given frame rectangle to transparent. -static void ZeroFillFrameRect(uint8_t* buf, int buf_stride, int x_offset, - int y_offset, int width, int height) { - int j; - assert(width * NUM_CHANNELS <= buf_stride); - buf += y_offset * buf_stride + x_offset * NUM_CHANNELS; - for (j = 0; j < height; ++j) { - memset(buf, 0, width * NUM_CHANNELS); - buf += buf_stride; - } -} - -// Copy width * height pixels from 'src' to 'dst'. -static void CopyCanvas(const uint8_t* src, uint8_t* dst, - uint32_t width, uint32_t height) { - assert(src != NULL && dst != NULL); - memcpy(dst, src, width * NUM_CHANNELS * height); -} - -// Returns true if the current frame is a key-frame. -static int IsKeyFrame(const WebPIterator* const curr, - const WebPIterator* const prev, - int prev_frame_was_key_frame, - int canvas_width, int canvas_height) { - if (curr->frame_num == 1) { - return 1; - } else if ((!curr->has_alpha || curr->blend_method == WEBP_MUX_NO_BLEND) && - IsFullFrame(curr->width, curr->height, - canvas_width, canvas_height)) { - return 1; - } else { - return (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) && - (IsFullFrame(prev->width, prev->height, canvas_width, - canvas_height) || - prev_frame_was_key_frame); - } -} - - -// Blend a single channel of 'src' over 'dst', given their alpha channel values. -// 'src' and 'dst' are assumed to be NOT pre-multiplied by alpha. -static uint8_t BlendChannelNonPremult(uint32_t src, uint8_t src_a, - uint32_t dst, uint8_t dst_a, - uint32_t scale, int shift) { - const uint8_t src_channel = (src >> shift) & 0xff; - const uint8_t dst_channel = (dst >> shift) & 0xff; - const uint32_t blend_unscaled = src_channel * src_a + dst_channel * dst_a; - assert(blend_unscaled < (1ULL << 32) / scale); - return (blend_unscaled * scale) >> 24; -} - -// Blend 'src' over 'dst' assuming they are NOT pre-multiplied by alpha. -static uint32_t BlendPixelNonPremult(uint32_t src, uint32_t dst) { - const uint8_t src_a = (src >> 24) & 0xff; - - if (src_a == 0) { - return dst; - } else { - const uint8_t dst_a = (dst >> 24) & 0xff; - // This is the approximate integer arithmetic for the actual formula: - // dst_factor_a = (dst_a * (255 - src_a)) / 255. - const uint8_t dst_factor_a = (dst_a * (256 - src_a)) >> 8; - const uint8_t blend_a = src_a + dst_factor_a; - const uint32_t scale = (1UL << 24) / blend_a; - - const uint8_t blend_r = - BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 0); - const uint8_t blend_g = - BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 8); - const uint8_t blend_b = - BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 16); - assert(src_a + dst_factor_a < 256); - - return (blend_r << 0) | - (blend_g << 8) | - (blend_b << 16) | - ((uint32_t)blend_a << 24); - } -} - -// Blend 'num_pixels' in 'src' over 'dst' assuming they are NOT pre-multiplied -// by alpha. -static void BlendPixelRowNonPremult(uint32_t* const src, - const uint32_t* const dst, int num_pixels) { - int i; - for (i = 0; i < num_pixels; ++i) { - const uint8_t src_alpha = (src[i] >> 24) & 0xff; - if (src_alpha != 0xff) { - src[i] = BlendPixelNonPremult(src[i], dst[i]); - } - } -} - -// Individually multiply each channel in 'pix' by 'scale'. -static WEBP_INLINE uint32_t ChannelwiseMultiply(uint32_t pix, uint32_t scale) { - uint32_t mask = 0x00FF00FF; - uint32_t rb = ((pix & mask) * scale) >> 8; - uint32_t ag = ((pix >> 8) & mask) * scale; - return (rb & mask) | (ag & ~mask); -} - -// Blend 'src' over 'dst' assuming they are pre-multiplied by alpha. -static uint32_t BlendPixelPremult(uint32_t src, uint32_t dst) { - const uint8_t src_a = (src >> 24) & 0xff; - return src + ChannelwiseMultiply(dst, 256 - src_a); -} - -// Blend 'num_pixels' in 'src' over 'dst' assuming they are pre-multiplied by -// alpha. -static void BlendPixelRowPremult(uint32_t* const src, const uint32_t* const dst, - int num_pixels) { - int i; - for (i = 0; i < num_pixels; ++i) { - const uint8_t src_alpha = (src[i] >> 24) & 0xff; - if (src_alpha != 0xff) { - src[i] = BlendPixelPremult(src[i], dst[i]); - } - } -} - -// Returns two ranges ( pairs) at row 'canvas_y', that belong to -// 'src' but not 'dst'. A point range is empty if the corresponding width is 0. -static void FindBlendRangeAtRow(const WebPIterator* const src, - const WebPIterator* const dst, int canvas_y, - int* const left1, int* const width1, - int* const left2, int* const width2) { - const int src_max_x = src->x_offset + src->width; - const int dst_max_x = dst->x_offset + dst->width; - const int dst_max_y = dst->y_offset + dst->height; - assert(canvas_y >= src->y_offset && canvas_y < (src->y_offset + src->height)); - *left1 = -1; - *width1 = 0; - *left2 = -1; - *width2 = 0; - - if (canvas_y < dst->y_offset || canvas_y >= dst_max_y || - src->x_offset >= dst_max_x || src_max_x <= dst->x_offset) { - *left1 = src->x_offset; - *width1 = src->width; - return; - } - - if (src->x_offset < dst->x_offset) { - *left1 = src->x_offset; - *width1 = dst->x_offset - src->x_offset; - } - - if (src_max_x > dst_max_x) { - *left2 = dst_max_x; - *width2 = src_max_x - dst_max_x; - } -} - -int WebPAnimDecoderGetNext(WebPAnimDecoder* dec, - uint8_t** buf_ptr, int* timestamp_ptr) { - WebPIterator iter; - uint32_t width; - uint32_t height; - int is_key_frame; - int timestamp; - BlendRowFunc blend_row; - - if (dec == NULL || buf_ptr == NULL || timestamp_ptr == NULL) return 0; - if (!WebPAnimDecoderHasMoreFrames(dec)) return 0; - - width = dec->info_.canvas_width; - height = dec->info_.canvas_height; - blend_row = dec->blend_func_; - - // Get compressed frame. - if (!WebPDemuxGetFrame(dec->demux_, dec->next_frame_, &iter)) { - return 0; - } - timestamp = dec->prev_frame_timestamp_ + iter.duration; - - // Initialize. - is_key_frame = IsKeyFrame(&iter, &dec->prev_iter_, - dec->prev_frame_was_keyframe_, width, height); - if (is_key_frame) { - ZeroFillCanvas(dec->curr_frame_, width, height); - } else { - CopyCanvas(dec->prev_frame_disposed_, dec->curr_frame_, width, height); - } - - // Decode. - { - const uint8_t* in = iter.fragment.bytes; - const size_t in_size = iter.fragment.size; - const size_t out_offset = - (iter.y_offset * width + iter.x_offset) * NUM_CHANNELS; - WebPDecoderConfig* const config = &dec->config_; - WebPRGBABuffer* const buf = &config->output.u.RGBA; - buf->stride = NUM_CHANNELS * width; - buf->size = buf->stride * iter.height; - buf->rgba = dec->curr_frame_ + out_offset; - - if (WebPDecode(in, in_size, config) != VP8_STATUS_OK) { - goto Error; - } - } - - // During the decoding of current frame, we may have set some pixels to be - // transparent (i.e. alpha < 255). However, the value of each of these - // pixels should have been determined by blending it against the value of - // that pixel in the previous frame if blending method of is WEBP_MUX_BLEND. - if (iter.frame_num > 1 && iter.blend_method == WEBP_MUX_BLEND && - !is_key_frame) { - if (dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_NONE) { - int y; - // Blend transparent pixels with pixels in previous canvas. - for (y = 0; y < iter.height; ++y) { - const size_t offset = - (iter.y_offset + y) * width + iter.x_offset; - blend_row((uint32_t*)dec->curr_frame_ + offset, - (uint32_t*)dec->prev_frame_disposed_ + offset, iter.width); - } - } else { - int y; - assert(dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND); - // We need to blend a transparent pixel with its value just after - // initialization. That is, blend it with: - // * Fully transparent pixel if it belongs to prevRect <-- No-op. - // * The pixel in the previous canvas otherwise <-- Need alpha-blending. - for (y = 0; y < iter.height; ++y) { - const int canvas_y = iter.y_offset + y; - int left1, width1, left2, width2; - FindBlendRangeAtRow(&iter, &dec->prev_iter_, canvas_y, &left1, &width1, - &left2, &width2); - if (width1 > 0) { - const size_t offset1 = canvas_y * width + left1; - blend_row((uint32_t*)dec->curr_frame_ + offset1, - (uint32_t*)dec->prev_frame_disposed_ + offset1, width1); - } - if (width2 > 0) { - const size_t offset2 = canvas_y * width + left2; - blend_row((uint32_t*)dec->curr_frame_ + offset2, - (uint32_t*)dec->prev_frame_disposed_ + offset2, width2); - } - } - } - } - - // Update info of the previous frame and dispose it for the next iteration. - dec->prev_frame_timestamp_ = timestamp; - dec->prev_iter_ = iter; - dec->prev_frame_was_keyframe_ = is_key_frame; - CopyCanvas(dec->curr_frame_, dec->prev_frame_disposed_, width, height); - if (dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { - ZeroFillFrameRect(dec->prev_frame_disposed_, width * NUM_CHANNELS, - dec->prev_iter_.x_offset, dec->prev_iter_.y_offset, - dec->prev_iter_.width, dec->prev_iter_.height); - } - ++dec->next_frame_; - - // All OK, fill in the values. - *buf_ptr = dec->curr_frame_; - *timestamp_ptr = timestamp; - return 1; - - Error: - WebPDemuxReleaseIterator(&iter); - return 0; -} - -int WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec) { - if (dec == NULL) return 0; - return (dec->next_frame_ <= (int)dec->info_.frame_count); -} - -void WebPAnimDecoderReset(WebPAnimDecoder* dec) { - if (dec != NULL) { - dec->prev_frame_timestamp_ = 0; - memset(&dec->prev_iter_, 0, sizeof(dec->prev_iter_)); - dec->prev_frame_was_keyframe_ = 0; - dec->next_frame_ = 1; - } -} - -const WebPDemuxer* WebPAnimDecoderGetDemuxer(const WebPAnimDecoder* dec) { - if (dec == NULL) return NULL; - return dec->demux_; -} - -void WebPAnimDecoderDelete(WebPAnimDecoder* dec) { - if (dec != NULL) { - WebPDemuxDelete(dec->demux_); - WebPSafeFree(dec->curr_frame_); - WebPSafeFree(dec->prev_frame_disposed_); - WebPSafeFree(dec); - } -} diff --git a/Example-Mac/Pods/libwebp/src/demux/demux.c b/Example-Mac/Pods/libwebp/src/demux/demux.c deleted file mode 100644 index 0d2989f6..00000000 --- a/Example-Mac/Pods/libwebp/src/demux/demux.c +++ /dev/null @@ -1,966 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// WebP container demux. -// - -#ifdef HAVE_CONFIG_H -#include "../webp/config.h" -#endif - -#include -#include -#include - -#include "../utils/utils.h" -#include "../webp/decode.h" // WebPGetFeatures -#include "../webp/demux.h" -#include "../webp/format_constants.h" - -#define DMUX_MAJ_VERSION 0 -#define DMUX_MIN_VERSION 3 -#define DMUX_REV_VERSION 0 - -typedef struct { - size_t start_; // start location of the data - size_t end_; // end location - size_t riff_end_; // riff chunk end location, can be > end_. - size_t buf_size_; // size of the buffer - const uint8_t* buf_; -} MemBuffer; - -typedef struct { - size_t offset_; - size_t size_; -} ChunkData; - -typedef struct Frame { - int x_offset_, y_offset_; - int width_, height_; - int has_alpha_; - int duration_; - WebPMuxAnimDispose dispose_method_; - WebPMuxAnimBlend blend_method_; - int frame_num_; - int complete_; // img_components_ contains a full image. - ChunkData img_components_[2]; // 0=VP8{,L} 1=ALPH - struct Frame* next_; -} Frame; - -typedef struct Chunk { - ChunkData data_; - struct Chunk* next_; -} Chunk; - -struct WebPDemuxer { - MemBuffer mem_; - WebPDemuxState state_; - int is_ext_format_; - uint32_t feature_flags_; - int canvas_width_, canvas_height_; - int loop_count_; - uint32_t bgcolor_; - int num_frames_; - Frame* frames_; - Frame** frames_tail_; - Chunk* chunks_; // non-image chunks - Chunk** chunks_tail_; -}; - -typedef enum { - PARSE_OK, - PARSE_NEED_MORE_DATA, - PARSE_ERROR -} ParseStatus; - -typedef struct ChunkParser { - uint8_t id[4]; - ParseStatus (*parse)(WebPDemuxer* const dmux); - int (*valid)(const WebPDemuxer* const dmux); -} ChunkParser; - -static ParseStatus ParseSingleImage(WebPDemuxer* const dmux); -static ParseStatus ParseVP8X(WebPDemuxer* const dmux); -static int IsValidSimpleFormat(const WebPDemuxer* const dmux); -static int IsValidExtendedFormat(const WebPDemuxer* const dmux); - -static const ChunkParser kMasterChunks[] = { - { { 'V', 'P', '8', ' ' }, ParseSingleImage, IsValidSimpleFormat }, - { { 'V', 'P', '8', 'L' }, ParseSingleImage, IsValidSimpleFormat }, - { { 'V', 'P', '8', 'X' }, ParseVP8X, IsValidExtendedFormat }, - { { '0', '0', '0', '0' }, NULL, NULL }, -}; - -//------------------------------------------------------------------------------ - -int WebPGetDemuxVersion(void) { - return (DMUX_MAJ_VERSION << 16) | (DMUX_MIN_VERSION << 8) | DMUX_REV_VERSION; -} - -// ----------------------------------------------------------------------------- -// MemBuffer - -static int RemapMemBuffer(MemBuffer* const mem, - const uint8_t* data, size_t size) { - if (size < mem->buf_size_) return 0; // can't remap to a shorter buffer! - - mem->buf_ = data; - mem->end_ = mem->buf_size_ = size; - return 1; -} - -static int InitMemBuffer(MemBuffer* const mem, - const uint8_t* data, size_t size) { - memset(mem, 0, sizeof(*mem)); - return RemapMemBuffer(mem, data, size); -} - -// Return the remaining data size available in 'mem'. -static WEBP_INLINE size_t MemDataSize(const MemBuffer* const mem) { - return (mem->end_ - mem->start_); -} - -// Return true if 'size' exceeds the end of the RIFF chunk. -static WEBP_INLINE int SizeIsInvalid(const MemBuffer* const mem, size_t size) { - return (size > mem->riff_end_ - mem->start_); -} - -static WEBP_INLINE void Skip(MemBuffer* const mem, size_t size) { - mem->start_ += size; -} - -static WEBP_INLINE void Rewind(MemBuffer* const mem, size_t size) { - mem->start_ -= size; -} - -static WEBP_INLINE const uint8_t* GetBuffer(MemBuffer* const mem) { - return mem->buf_ + mem->start_; -} - -// Read from 'mem' and skip the read bytes. -static WEBP_INLINE uint8_t ReadByte(MemBuffer* const mem) { - const uint8_t byte = mem->buf_[mem->start_]; - Skip(mem, 1); - return byte; -} - -static WEBP_INLINE int ReadLE16s(MemBuffer* const mem) { - const uint8_t* const data = mem->buf_ + mem->start_; - const int val = GetLE16(data); - Skip(mem, 2); - return val; -} - -static WEBP_INLINE int ReadLE24s(MemBuffer* const mem) { - const uint8_t* const data = mem->buf_ + mem->start_; - const int val = GetLE24(data); - Skip(mem, 3); - return val; -} - -static WEBP_INLINE uint32_t ReadLE32(MemBuffer* const mem) { - const uint8_t* const data = mem->buf_ + mem->start_; - const uint32_t val = GetLE32(data); - Skip(mem, 4); - return val; -} - -// ----------------------------------------------------------------------------- -// Secondary chunk parsing - -static void AddChunk(WebPDemuxer* const dmux, Chunk* const chunk) { - *dmux->chunks_tail_ = chunk; - chunk->next_ = NULL; - dmux->chunks_tail_ = &chunk->next_; -} - -// Add a frame to the end of the list, ensuring the last frame is complete. -// Returns true on success, false otherwise. -static int AddFrame(WebPDemuxer* const dmux, Frame* const frame) { - const Frame* const last_frame = *dmux->frames_tail_; - if (last_frame != NULL && !last_frame->complete_) return 0; - - *dmux->frames_tail_ = frame; - frame->next_ = NULL; - dmux->frames_tail_ = &frame->next_; - return 1; -} - -static void SetFrameInfo(size_t start_offset, size_t size, - int frame_num, int complete, - const WebPBitstreamFeatures* const features, - Frame* const frame) { - frame->img_components_[0].offset_ = start_offset; - frame->img_components_[0].size_ = size; - frame->width_ = features->width; - frame->height_ = features->height; - frame->has_alpha_ |= features->has_alpha; - frame->frame_num_ = frame_num; - frame->complete_ = complete; -} - -// Store image bearing chunks to 'frame'. -static ParseStatus StoreFrame(int frame_num, uint32_t min_size, - MemBuffer* const mem, Frame* const frame) { - int alpha_chunks = 0; - int image_chunks = 0; - int done = (MemDataSize(mem) < min_size); - ParseStatus status = PARSE_OK; - - if (done) return PARSE_NEED_MORE_DATA; - - do { - const size_t chunk_start_offset = mem->start_; - const uint32_t fourcc = ReadLE32(mem); - const uint32_t payload_size = ReadLE32(mem); - const uint32_t payload_size_padded = payload_size + (payload_size & 1); - const size_t payload_available = (payload_size_padded > MemDataSize(mem)) - ? MemDataSize(mem) : payload_size_padded; - const size_t chunk_size = CHUNK_HEADER_SIZE + payload_available; - - if (payload_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; - if (SizeIsInvalid(mem, payload_size_padded)) return PARSE_ERROR; - if (payload_size_padded > MemDataSize(mem)) status = PARSE_NEED_MORE_DATA; - - switch (fourcc) { - case MKFOURCC('A', 'L', 'P', 'H'): - if (alpha_chunks == 0) { - ++alpha_chunks; - frame->img_components_[1].offset_ = chunk_start_offset; - frame->img_components_[1].size_ = chunk_size; - frame->has_alpha_ = 1; - frame->frame_num_ = frame_num; - Skip(mem, payload_available); - } else { - goto Done; - } - break; - case MKFOURCC('V', 'P', '8', 'L'): - if (alpha_chunks > 0) return PARSE_ERROR; // VP8L has its own alpha - // fall through - case MKFOURCC('V', 'P', '8', ' '): - if (image_chunks == 0) { - // Extract the bitstream features, tolerating failures when the data - // is incomplete. - WebPBitstreamFeatures features; - const VP8StatusCode vp8_status = - WebPGetFeatures(mem->buf_ + chunk_start_offset, chunk_size, - &features); - if (status == PARSE_NEED_MORE_DATA && - vp8_status == VP8_STATUS_NOT_ENOUGH_DATA) { - return PARSE_NEED_MORE_DATA; - } else if (vp8_status != VP8_STATUS_OK) { - // We have enough data, and yet WebPGetFeatures() failed. - return PARSE_ERROR; - } - ++image_chunks; - SetFrameInfo(chunk_start_offset, chunk_size, frame_num, - status == PARSE_OK, &features, frame); - Skip(mem, payload_available); - } else { - goto Done; - } - break; - Done: - default: - // Restore fourcc/size when moving up one level in parsing. - Rewind(mem, CHUNK_HEADER_SIZE); - done = 1; - break; - } - - if (mem->start_ == mem->riff_end_) { - done = 1; - } else if (MemDataSize(mem) < CHUNK_HEADER_SIZE) { - status = PARSE_NEED_MORE_DATA; - } - } while (!done && status == PARSE_OK); - - return status; -} - -// Creates a new Frame if 'actual_size' is within bounds and 'mem' contains -// enough data ('min_size') to parse the payload. -// Returns PARSE_OK on success with *frame pointing to the new Frame. -// Returns PARSE_NEED_MORE_DATA with insufficient data, PARSE_ERROR otherwise. -static ParseStatus NewFrame(const MemBuffer* const mem, - uint32_t min_size, uint32_t actual_size, - Frame** frame) { - if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR; - if (actual_size < min_size) return PARSE_ERROR; - if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA; - - *frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(**frame)); - return (*frame == NULL) ? PARSE_ERROR : PARSE_OK; -} - -// Parse a 'ANMF' chunk and any image bearing chunks that immediately follow. -// 'frame_chunk_size' is the previously validated, padded chunk size. -static ParseStatus ParseAnimationFrame( - WebPDemuxer* const dmux, uint32_t frame_chunk_size) { - const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG); - const uint32_t anmf_payload_size = frame_chunk_size - ANMF_CHUNK_SIZE; - int added_frame = 0; - int bits; - MemBuffer* const mem = &dmux->mem_; - Frame* frame; - ParseStatus status = - NewFrame(mem, ANMF_CHUNK_SIZE, frame_chunk_size, &frame); - if (status != PARSE_OK) return status; - - frame->x_offset_ = 2 * ReadLE24s(mem); - frame->y_offset_ = 2 * ReadLE24s(mem); - frame->width_ = 1 + ReadLE24s(mem); - frame->height_ = 1 + ReadLE24s(mem); - frame->duration_ = ReadLE24s(mem); - bits = ReadByte(mem); - frame->dispose_method_ = - (bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE; - frame->blend_method_ = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND; - if (frame->width_ * (uint64_t)frame->height_ >= MAX_IMAGE_AREA) { - WebPSafeFree(frame); - return PARSE_ERROR; - } - - // Store a frame only if the animation flag is set there is some data for - // this frame is available. - status = StoreFrame(dmux->num_frames_ + 1, anmf_payload_size, mem, frame); - if (status != PARSE_ERROR && is_animation && frame->frame_num_ > 0) { - added_frame = AddFrame(dmux, frame); - if (added_frame) { - ++dmux->num_frames_; - } else { - status = PARSE_ERROR; - } - } - - if (!added_frame) WebPSafeFree(frame); - return status; -} - -// General chunk storage, starting with the header at 'start_offset', allowing -// the user to request the payload via a fourcc string. 'size' includes the -// header and the unpadded payload size. -// Returns true on success, false otherwise. -static int StoreChunk(WebPDemuxer* const dmux, - size_t start_offset, uint32_t size) { - Chunk* const chunk = (Chunk*)WebPSafeCalloc(1ULL, sizeof(*chunk)); - if (chunk == NULL) return 0; - - chunk->data_.offset_ = start_offset; - chunk->data_.size_ = size; - AddChunk(dmux, chunk); - return 1; -} - -// ----------------------------------------------------------------------------- -// Primary chunk parsing - -static ParseStatus ReadHeader(MemBuffer* const mem) { - const size_t min_size = RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE; - uint32_t riff_size; - - // Basic file level validation. - if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA; - if (memcmp(GetBuffer(mem), "RIFF", CHUNK_SIZE_BYTES) || - memcmp(GetBuffer(mem) + CHUNK_HEADER_SIZE, "WEBP", CHUNK_SIZE_BYTES)) { - return PARSE_ERROR; - } - - riff_size = GetLE32(GetBuffer(mem) + TAG_SIZE); - if (riff_size < CHUNK_HEADER_SIZE) return PARSE_ERROR; - if (riff_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; - - // There's no point in reading past the end of the RIFF chunk - mem->riff_end_ = riff_size + CHUNK_HEADER_SIZE; - if (mem->buf_size_ > mem->riff_end_) { - mem->buf_size_ = mem->end_ = mem->riff_end_; - } - - Skip(mem, RIFF_HEADER_SIZE); - return PARSE_OK; -} - -static ParseStatus ParseSingleImage(WebPDemuxer* const dmux) { - const size_t min_size = CHUNK_HEADER_SIZE; - MemBuffer* const mem = &dmux->mem_; - Frame* frame; - ParseStatus status; - int image_added = 0; - - if (dmux->frames_ != NULL) return PARSE_ERROR; - if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR; - if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA; - - frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame)); - if (frame == NULL) return PARSE_ERROR; - - // For the single image case we allow parsing of a partial frame, but we need - // at least CHUNK_HEADER_SIZE for parsing. - status = StoreFrame(1, CHUNK_HEADER_SIZE, &dmux->mem_, frame); - if (status != PARSE_ERROR) { - const int has_alpha = !!(dmux->feature_flags_ & ALPHA_FLAG); - // Clear any alpha when the alpha flag is missing. - if (!has_alpha && frame->img_components_[1].size_ > 0) { - frame->img_components_[1].offset_ = 0; - frame->img_components_[1].size_ = 0; - frame->has_alpha_ = 0; - } - - // Use the frame width/height as the canvas values for non-vp8x files. - // Also, set ALPHA_FLAG if this is a lossless image with alpha. - if (!dmux->is_ext_format_ && frame->width_ > 0 && frame->height_ > 0) { - dmux->state_ = WEBP_DEMUX_PARSED_HEADER; - dmux->canvas_width_ = frame->width_; - dmux->canvas_height_ = frame->height_; - dmux->feature_flags_ |= frame->has_alpha_ ? ALPHA_FLAG : 0; - } - if (!AddFrame(dmux, frame)) { - status = PARSE_ERROR; // last frame was left incomplete - } else { - image_added = 1; - dmux->num_frames_ = 1; - } - } - - if (!image_added) WebPSafeFree(frame); - return status; -} - -static ParseStatus ParseVP8XChunks(WebPDemuxer* const dmux) { - const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG); - MemBuffer* const mem = &dmux->mem_; - int anim_chunks = 0; - ParseStatus status = PARSE_OK; - - do { - int store_chunk = 1; - const size_t chunk_start_offset = mem->start_; - const uint32_t fourcc = ReadLE32(mem); - const uint32_t chunk_size = ReadLE32(mem); - const uint32_t chunk_size_padded = chunk_size + (chunk_size & 1); - - if (chunk_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; - if (SizeIsInvalid(mem, chunk_size_padded)) return PARSE_ERROR; - - switch (fourcc) { - case MKFOURCC('V', 'P', '8', 'X'): { - return PARSE_ERROR; - } - case MKFOURCC('A', 'L', 'P', 'H'): - case MKFOURCC('V', 'P', '8', ' '): - case MKFOURCC('V', 'P', '8', 'L'): { - // check that this isn't an animation (all frames should be in an ANMF). - if (anim_chunks > 0 || is_animation) return PARSE_ERROR; - - Rewind(mem, CHUNK_HEADER_SIZE); - status = ParseSingleImage(dmux); - break; - } - case MKFOURCC('A', 'N', 'I', 'M'): { - if (chunk_size_padded < ANIM_CHUNK_SIZE) return PARSE_ERROR; - - if (MemDataSize(mem) < chunk_size_padded) { - status = PARSE_NEED_MORE_DATA; - } else if (anim_chunks == 0) { - ++anim_chunks; - dmux->bgcolor_ = ReadLE32(mem); - dmux->loop_count_ = ReadLE16s(mem); - Skip(mem, chunk_size_padded - ANIM_CHUNK_SIZE); - } else { - store_chunk = 0; - goto Skip; - } - break; - } - case MKFOURCC('A', 'N', 'M', 'F'): { - if (anim_chunks == 0) return PARSE_ERROR; // 'ANIM' precedes frames. - status = ParseAnimationFrame(dmux, chunk_size_padded); - break; - } - case MKFOURCC('I', 'C', 'C', 'P'): { - store_chunk = !!(dmux->feature_flags_ & ICCP_FLAG); - goto Skip; - } - case MKFOURCC('E', 'X', 'I', 'F'): { - store_chunk = !!(dmux->feature_flags_ & EXIF_FLAG); - goto Skip; - } - case MKFOURCC('X', 'M', 'P', ' '): { - store_chunk = !!(dmux->feature_flags_ & XMP_FLAG); - goto Skip; - } - Skip: - default: { - if (chunk_size_padded <= MemDataSize(mem)) { - if (store_chunk) { - // Store only the chunk header and unpadded size as only the payload - // will be returned to the user. - if (!StoreChunk(dmux, chunk_start_offset, - CHUNK_HEADER_SIZE + chunk_size)) { - return PARSE_ERROR; - } - } - Skip(mem, chunk_size_padded); - } else { - status = PARSE_NEED_MORE_DATA; - } - } - } - - if (mem->start_ == mem->riff_end_) { - break; - } else if (MemDataSize(mem) < CHUNK_HEADER_SIZE) { - status = PARSE_NEED_MORE_DATA; - } - } while (status == PARSE_OK); - - return status; -} - -static ParseStatus ParseVP8X(WebPDemuxer* const dmux) { - MemBuffer* const mem = &dmux->mem_; - uint32_t vp8x_size; - - if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA; - - dmux->is_ext_format_ = 1; - Skip(mem, TAG_SIZE); // VP8X - vp8x_size = ReadLE32(mem); - if (vp8x_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; - if (vp8x_size < VP8X_CHUNK_SIZE) return PARSE_ERROR; - vp8x_size += vp8x_size & 1; - if (SizeIsInvalid(mem, vp8x_size)) return PARSE_ERROR; - if (MemDataSize(mem) < vp8x_size) return PARSE_NEED_MORE_DATA; - - dmux->feature_flags_ = ReadByte(mem); - Skip(mem, 3); // Reserved. - dmux->canvas_width_ = 1 + ReadLE24s(mem); - dmux->canvas_height_ = 1 + ReadLE24s(mem); - if (dmux->canvas_width_ * (uint64_t)dmux->canvas_height_ >= MAX_IMAGE_AREA) { - return PARSE_ERROR; // image final dimension is too large - } - Skip(mem, vp8x_size - VP8X_CHUNK_SIZE); // skip any trailing data. - dmux->state_ = WEBP_DEMUX_PARSED_HEADER; - - if (SizeIsInvalid(mem, CHUNK_HEADER_SIZE)) return PARSE_ERROR; - if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA; - - return ParseVP8XChunks(dmux); -} - -// ----------------------------------------------------------------------------- -// Format validation - -static int IsValidSimpleFormat(const WebPDemuxer* const dmux) { - const Frame* const frame = dmux->frames_; - if (dmux->state_ == WEBP_DEMUX_PARSING_HEADER) return 1; - - if (dmux->canvas_width_ <= 0 || dmux->canvas_height_ <= 0) return 0; - if (dmux->state_ == WEBP_DEMUX_DONE && frame == NULL) return 0; - - if (frame->width_ <= 0 || frame->height_ <= 0) return 0; - return 1; -} - -// If 'exact' is true, check that the image resolution matches the canvas. -// If 'exact' is false, check that the x/y offsets do not exceed the canvas. -static int CheckFrameBounds(const Frame* const frame, int exact, - int canvas_width, int canvas_height) { - if (exact) { - if (frame->x_offset_ != 0 || frame->y_offset_ != 0) { - return 0; - } - if (frame->width_ != canvas_width || frame->height_ != canvas_height) { - return 0; - } - } else { - if (frame->x_offset_ < 0 || frame->y_offset_ < 0) return 0; - if (frame->width_ + frame->x_offset_ > canvas_width) return 0; - if (frame->height_ + frame->y_offset_ > canvas_height) return 0; - } - return 1; -} - -static int IsValidExtendedFormat(const WebPDemuxer* const dmux) { - const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG); - const int is_fragmented = !!(dmux->feature_flags_ & FRAGMENTS_FLAG); - const Frame* f = dmux->frames_; - - if (dmux->state_ == WEBP_DEMUX_PARSING_HEADER) return 1; - - if (dmux->canvas_width_ <= 0 || dmux->canvas_height_ <= 0) return 0; - if (dmux->loop_count_ < 0) return 0; - if (dmux->state_ == WEBP_DEMUX_DONE && dmux->frames_ == NULL) return 0; - if (is_fragmented) return 0; - - while (f != NULL) { - const int cur_frame_set = f->frame_num_; - int frame_count = 0; - - // Check frame properties. - for (; f != NULL && f->frame_num_ == cur_frame_set; f = f->next_) { - const ChunkData* const image = f->img_components_; - const ChunkData* const alpha = f->img_components_ + 1; - - if (!is_animation && f->frame_num_ > 1) return 0; - - if (f->complete_) { - if (alpha->size_ == 0 && image->size_ == 0) return 0; - // Ensure alpha precedes image bitstream. - if (alpha->size_ > 0 && alpha->offset_ > image->offset_) { - return 0; - } - - if (f->width_ <= 0 || f->height_ <= 0) return 0; - } else { - // There shouldn't be a partial frame in a complete file. - if (dmux->state_ == WEBP_DEMUX_DONE) return 0; - - // Ensure alpha precedes image bitstream. - if (alpha->size_ > 0 && image->size_ > 0 && - alpha->offset_ > image->offset_) { - return 0; - } - // There shouldn't be any frames after an incomplete one. - if (f->next_ != NULL) return 0; - } - - if (f->width_ > 0 && f->height_ > 0 && - !CheckFrameBounds(f, !is_animation, - dmux->canvas_width_, dmux->canvas_height_)) { - return 0; - } - - ++frame_count; - } - } - return 1; -} - -// ----------------------------------------------------------------------------- -// WebPDemuxer object - -static void InitDemux(WebPDemuxer* const dmux, const MemBuffer* const mem) { - dmux->state_ = WEBP_DEMUX_PARSING_HEADER; - dmux->loop_count_ = 1; - dmux->bgcolor_ = 0xFFFFFFFF; // White background by default. - dmux->canvas_width_ = -1; - dmux->canvas_height_ = -1; - dmux->frames_tail_ = &dmux->frames_; - dmux->chunks_tail_ = &dmux->chunks_; - dmux->mem_ = *mem; -} - -static ParseStatus CreateRawImageDemuxer(MemBuffer* const mem, - WebPDemuxer** demuxer) { - WebPBitstreamFeatures features; - const VP8StatusCode status = - WebPGetFeatures(mem->buf_, mem->buf_size_, &features); - *demuxer = NULL; - if (status != VP8_STATUS_OK) { - return (status == VP8_STATUS_NOT_ENOUGH_DATA) ? PARSE_NEED_MORE_DATA - : PARSE_ERROR; - } - - { - WebPDemuxer* const dmux = (WebPDemuxer*)WebPSafeCalloc(1ULL, sizeof(*dmux)); - Frame* const frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame)); - if (dmux == NULL || frame == NULL) goto Error; - InitDemux(dmux, mem); - SetFrameInfo(0, mem->buf_size_, 1 /*frame_num*/, 1 /*complete*/, &features, - frame); - if (!AddFrame(dmux, frame)) goto Error; - dmux->state_ = WEBP_DEMUX_DONE; - dmux->canvas_width_ = frame->width_; - dmux->canvas_height_ = frame->height_; - dmux->feature_flags_ |= frame->has_alpha_ ? ALPHA_FLAG : 0; - dmux->num_frames_ = 1; - assert(IsValidSimpleFormat(dmux)); - *demuxer = dmux; - return PARSE_OK; - - Error: - WebPSafeFree(dmux); - WebPSafeFree(frame); - return PARSE_ERROR; - } -} - -WebPDemuxer* WebPDemuxInternal(const WebPData* data, int allow_partial, - WebPDemuxState* state, int version) { - const ChunkParser* parser; - int partial; - ParseStatus status = PARSE_ERROR; - MemBuffer mem; - WebPDemuxer* dmux; - - if (state != NULL) *state = WEBP_DEMUX_PARSE_ERROR; - - if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DEMUX_ABI_VERSION)) return NULL; - if (data == NULL || data->bytes == NULL || data->size == 0) return NULL; - - if (!InitMemBuffer(&mem, data->bytes, data->size)) return NULL; - status = ReadHeader(&mem); - if (status != PARSE_OK) { - // If parsing of the webp file header fails attempt to handle a raw - // VP8/VP8L frame. Note 'allow_partial' is ignored in this case. - if (status == PARSE_ERROR) { - status = CreateRawImageDemuxer(&mem, &dmux); - if (status == PARSE_OK) { - if (state != NULL) *state = WEBP_DEMUX_DONE; - return dmux; - } - } - if (state != NULL) { - *state = (status == PARSE_NEED_MORE_DATA) ? WEBP_DEMUX_PARSING_HEADER - : WEBP_DEMUX_PARSE_ERROR; - } - return NULL; - } - - partial = (mem.buf_size_ < mem.riff_end_); - if (!allow_partial && partial) return NULL; - - dmux = (WebPDemuxer*)WebPSafeCalloc(1ULL, sizeof(*dmux)); - if (dmux == NULL) return NULL; - InitDemux(dmux, &mem); - - status = PARSE_ERROR; - for (parser = kMasterChunks; parser->parse != NULL; ++parser) { - if (!memcmp(parser->id, GetBuffer(&dmux->mem_), TAG_SIZE)) { - status = parser->parse(dmux); - if (status == PARSE_OK) dmux->state_ = WEBP_DEMUX_DONE; - if (status == PARSE_NEED_MORE_DATA && !partial) status = PARSE_ERROR; - if (status != PARSE_ERROR && !parser->valid(dmux)) status = PARSE_ERROR; - if (status == PARSE_ERROR) dmux->state_ = WEBP_DEMUX_PARSE_ERROR; - break; - } - } - if (state != NULL) *state = dmux->state_; - - if (status == PARSE_ERROR) { - WebPDemuxDelete(dmux); - return NULL; - } - return dmux; -} - -void WebPDemuxDelete(WebPDemuxer* dmux) { - Chunk* c; - Frame* f; - if (dmux == NULL) return; - - for (f = dmux->frames_; f != NULL;) { - Frame* const cur_frame = f; - f = f->next_; - WebPSafeFree(cur_frame); - } - for (c = dmux->chunks_; c != NULL;) { - Chunk* const cur_chunk = c; - c = c->next_; - WebPSafeFree(cur_chunk); - } - WebPSafeFree(dmux); -} - -// ----------------------------------------------------------------------------- - -uint32_t WebPDemuxGetI(const WebPDemuxer* dmux, WebPFormatFeature feature) { - if (dmux == NULL) return 0; - - switch (feature) { - case WEBP_FF_FORMAT_FLAGS: return dmux->feature_flags_; - case WEBP_FF_CANVAS_WIDTH: return (uint32_t)dmux->canvas_width_; - case WEBP_FF_CANVAS_HEIGHT: return (uint32_t)dmux->canvas_height_; - case WEBP_FF_LOOP_COUNT: return (uint32_t)dmux->loop_count_; - case WEBP_FF_BACKGROUND_COLOR: return dmux->bgcolor_; - case WEBP_FF_FRAME_COUNT: return (uint32_t)dmux->num_frames_; - } - return 0; -} - -// ----------------------------------------------------------------------------- -// Frame iteration - -static const Frame* GetFrame(const WebPDemuxer* const dmux, int frame_num) { - const Frame* f; - for (f = dmux->frames_; f != NULL; f = f->next_) { - if (frame_num == f->frame_num_) break; - } - return f; -} - -static const uint8_t* GetFramePayload(const uint8_t* const mem_buf, - const Frame* const frame, - size_t* const data_size) { - *data_size = 0; - if (frame != NULL) { - const ChunkData* const image = frame->img_components_; - const ChunkData* const alpha = frame->img_components_ + 1; - size_t start_offset = image->offset_; - *data_size = image->size_; - - // if alpha exists it precedes image, update the size allowing for - // intervening chunks. - if (alpha->size_ > 0) { - const size_t inter_size = (image->offset_ > 0) - ? image->offset_ - (alpha->offset_ + alpha->size_) - : 0; - start_offset = alpha->offset_; - *data_size += alpha->size_ + inter_size; - } - return mem_buf + start_offset; - } - return NULL; -} - -// Create a whole 'frame' from VP8 (+ alpha) or lossless. -static int SynthesizeFrame(const WebPDemuxer* const dmux, - const Frame* const frame, - WebPIterator* const iter) { - const uint8_t* const mem_buf = dmux->mem_.buf_; - size_t payload_size = 0; - const uint8_t* const payload = GetFramePayload(mem_buf, frame, &payload_size); - if (payload == NULL) return 0; - assert(frame != NULL); - - iter->frame_num = frame->frame_num_; - iter->num_frames = dmux->num_frames_; - iter->x_offset = frame->x_offset_; - iter->y_offset = frame->y_offset_; - iter->width = frame->width_; - iter->height = frame->height_; - iter->has_alpha = frame->has_alpha_; - iter->duration = frame->duration_; - iter->dispose_method = frame->dispose_method_; - iter->blend_method = frame->blend_method_; - iter->complete = frame->complete_; - iter->fragment.bytes = payload; - iter->fragment.size = payload_size; - return 1; -} - -static int SetFrame(int frame_num, WebPIterator* const iter) { - const Frame* frame; - const WebPDemuxer* const dmux = (WebPDemuxer*)iter->private_; - if (dmux == NULL || frame_num < 0) return 0; - if (frame_num > dmux->num_frames_) return 0; - if (frame_num == 0) frame_num = dmux->num_frames_; - - frame = GetFrame(dmux, frame_num); - if (frame == NULL) return 0; - - return SynthesizeFrame(dmux, frame, iter); -} - -int WebPDemuxGetFrame(const WebPDemuxer* dmux, int frame, WebPIterator* iter) { - if (iter == NULL) return 0; - - memset(iter, 0, sizeof(*iter)); - iter->private_ = (void*)dmux; - return SetFrame(frame, iter); -} - -int WebPDemuxNextFrame(WebPIterator* iter) { - if (iter == NULL) return 0; - return SetFrame(iter->frame_num + 1, iter); -} - -int WebPDemuxPrevFrame(WebPIterator* iter) { - if (iter == NULL) return 0; - if (iter->frame_num <= 1) return 0; - return SetFrame(iter->frame_num - 1, iter); -} - -void WebPDemuxReleaseIterator(WebPIterator* iter) { - (void)iter; -} - -// ----------------------------------------------------------------------------- -// Chunk iteration - -static int ChunkCount(const WebPDemuxer* const dmux, const char fourcc[4]) { - const uint8_t* const mem_buf = dmux->mem_.buf_; - const Chunk* c; - int count = 0; - for (c = dmux->chunks_; c != NULL; c = c->next_) { - const uint8_t* const header = mem_buf + c->data_.offset_; - if (!memcmp(header, fourcc, TAG_SIZE)) ++count; - } - return count; -} - -static const Chunk* GetChunk(const WebPDemuxer* const dmux, - const char fourcc[4], int chunk_num) { - const uint8_t* const mem_buf = dmux->mem_.buf_; - const Chunk* c; - int count = 0; - for (c = dmux->chunks_; c != NULL; c = c->next_) { - const uint8_t* const header = mem_buf + c->data_.offset_; - if (!memcmp(header, fourcc, TAG_SIZE)) ++count; - if (count == chunk_num) break; - } - return c; -} - -static int SetChunk(const char fourcc[4], int chunk_num, - WebPChunkIterator* const iter) { - const WebPDemuxer* const dmux = (WebPDemuxer*)iter->private_; - int count; - - if (dmux == NULL || fourcc == NULL || chunk_num < 0) return 0; - count = ChunkCount(dmux, fourcc); - if (count == 0) return 0; - if (chunk_num == 0) chunk_num = count; - - if (chunk_num <= count) { - const uint8_t* const mem_buf = dmux->mem_.buf_; - const Chunk* const chunk = GetChunk(dmux, fourcc, chunk_num); - iter->chunk.bytes = mem_buf + chunk->data_.offset_ + CHUNK_HEADER_SIZE; - iter->chunk.size = chunk->data_.size_ - CHUNK_HEADER_SIZE; - iter->num_chunks = count; - iter->chunk_num = chunk_num; - return 1; - } - return 0; -} - -int WebPDemuxGetChunk(const WebPDemuxer* dmux, - const char fourcc[4], int chunk_num, - WebPChunkIterator* iter) { - if (iter == NULL) return 0; - - memset(iter, 0, sizeof(*iter)); - iter->private_ = (void*)dmux; - return SetChunk(fourcc, chunk_num, iter); -} - -int WebPDemuxNextChunk(WebPChunkIterator* iter) { - if (iter != NULL) { - const char* const fourcc = - (const char*)iter->chunk.bytes - CHUNK_HEADER_SIZE; - return SetChunk(fourcc, iter->chunk_num + 1, iter); - } - return 0; -} - -int WebPDemuxPrevChunk(WebPChunkIterator* iter) { - if (iter != NULL && iter->chunk_num > 1) { - const char* const fourcc = - (const char*)iter->chunk.bytes - CHUNK_HEADER_SIZE; - return SetChunk(fourcc, iter->chunk_num - 1, iter); - } - return 0; -} - -void WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter) { - (void)iter; -} - diff --git a/Example-Mac/Pods/libwebp/src/dsp/alpha_processing.c b/Example-Mac/Pods/libwebp/src/dsp/alpha_processing.c deleted file mode 100644 index 1716cace..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/alpha_processing.c +++ /dev/null @@ -1,383 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Utilities for processing transparent channel. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include "./dsp.h" - -// Tables can be faster on some platform but incur some extra binary size (~2k). -// #define USE_TABLES_FOR_ALPHA_MULT - -// ----------------------------------------------------------------------------- - -#define MFIX 24 // 24bit fixed-point arithmetic -#define HALF ((1u << MFIX) >> 1) -#define KINV_255 ((1u << MFIX) / 255u) - -static uint32_t Mult(uint8_t x, uint32_t mult) { - const uint32_t v = (x * mult + HALF) >> MFIX; - assert(v <= 255); // <- 24bit precision is enough to ensure that. - return v; -} - -#ifdef USE_TABLES_FOR_ALPHA_MULT - -static const uint32_t kMultTables[2][256] = { - { // (255u << MFIX) / alpha - 0x00000000, 0xff000000, 0x7f800000, 0x55000000, 0x3fc00000, 0x33000000, - 0x2a800000, 0x246db6db, 0x1fe00000, 0x1c555555, 0x19800000, 0x172e8ba2, - 0x15400000, 0x139d89d8, 0x1236db6d, 0x11000000, 0x0ff00000, 0x0f000000, - 0x0e2aaaaa, 0x0d6bca1a, 0x0cc00000, 0x0c249249, 0x0b9745d1, 0x0b1642c8, - 0x0aa00000, 0x0a333333, 0x09cec4ec, 0x0971c71c, 0x091b6db6, 0x08cb08d3, - 0x08800000, 0x0839ce73, 0x07f80000, 0x07ba2e8b, 0x07800000, 0x07492492, - 0x07155555, 0x06e45306, 0x06b5e50d, 0x0689d89d, 0x06600000, 0x063831f3, - 0x06124924, 0x05ee23b8, 0x05cba2e8, 0x05aaaaaa, 0x058b2164, 0x056cefa8, - 0x05500000, 0x05343eb1, 0x05199999, 0x05000000, 0x04e76276, 0x04cfb2b7, - 0x04b8e38e, 0x04a2e8ba, 0x048db6db, 0x0479435e, 0x04658469, 0x045270d0, - 0x04400000, 0x042e29f7, 0x041ce739, 0x040c30c3, 0x03fc0000, 0x03ec4ec4, - 0x03dd1745, 0x03ce540f, 0x03c00000, 0x03b21642, 0x03a49249, 0x03976fc6, - 0x038aaaaa, 0x037e3f1f, 0x03722983, 0x03666666, 0x035af286, 0x034fcace, - 0x0344ec4e, 0x033a5440, 0x03300000, 0x0325ed09, 0x031c18f9, 0x0312818a, - 0x03092492, 0x03000000, 0x02f711dc, 0x02ee5846, 0x02e5d174, 0x02dd7baf, - 0x02d55555, 0x02cd5cd5, 0x02c590b2, 0x02bdef7b, 0x02b677d4, 0x02af286b, - 0x02a80000, 0x02a0fd5c, 0x029a1f58, 0x029364d9, 0x028ccccc, 0x0286562d, - 0x02800000, 0x0279c952, 0x0273b13b, 0x026db6db, 0x0267d95b, 0x026217ec, - 0x025c71c7, 0x0256e62a, 0x0251745d, 0x024c1bac, 0x0246db6d, 0x0241b2f9, - 0x023ca1af, 0x0237a6f4, 0x0232c234, 0x022df2df, 0x02293868, 0x02249249, - 0x02200000, 0x021b810e, 0x021714fb, 0x0212bb51, 0x020e739c, 0x020a3d70, - 0x02061861, 0x02020408, 0x01fe0000, 0x01fa0be8, 0x01f62762, 0x01f25213, - 0x01ee8ba2, 0x01ead3ba, 0x01e72a07, 0x01e38e38, 0x01e00000, 0x01dc7f10, - 0x01d90b21, 0x01d5a3e9, 0x01d24924, 0x01cefa8d, 0x01cbb7e3, 0x01c880e5, - 0x01c55555, 0x01c234f7, 0x01bf1f8f, 0x01bc14e5, 0x01b914c1, 0x01b61eed, - 0x01b33333, 0x01b05160, 0x01ad7943, 0x01aaaaaa, 0x01a7e567, 0x01a5294a, - 0x01a27627, 0x019fcbd2, 0x019d2a20, 0x019a90e7, 0x01980000, 0x01957741, - 0x0192f684, 0x01907da4, 0x018e0c7c, 0x018ba2e8, 0x018940c5, 0x0186e5f0, - 0x01849249, 0x018245ae, 0x01800000, 0x017dc11f, 0x017b88ee, 0x0179574e, - 0x01772c23, 0x01750750, 0x0172e8ba, 0x0170d045, 0x016ebdd7, 0x016cb157, - 0x016aaaaa, 0x0168a9b9, 0x0166ae6a, 0x0164b8a7, 0x0162c859, 0x0160dd67, - 0x015ef7bd, 0x015d1745, 0x015b3bea, 0x01596596, 0x01579435, 0x0155c7b4, - 0x01540000, 0x01523d03, 0x01507eae, 0x014ec4ec, 0x014d0fac, 0x014b5edc, - 0x0149b26c, 0x01480a4a, 0x01466666, 0x0144c6af, 0x01432b16, 0x0141938b, - 0x01400000, 0x013e7063, 0x013ce4a9, 0x013b5cc0, 0x0139d89d, 0x01385830, - 0x0136db6d, 0x01356246, 0x0133ecad, 0x01327a97, 0x01310bf6, 0x012fa0be, - 0x012e38e3, 0x012cd459, 0x012b7315, 0x012a150a, 0x0128ba2e, 0x01276276, - 0x01260dd6, 0x0124bc44, 0x01236db6, 0x01222222, 0x0120d97c, 0x011f93bc, - 0x011e50d7, 0x011d10c4, 0x011bd37a, 0x011a98ef, 0x0119611a, 0x01182bf2, - 0x0116f96f, 0x0115c988, 0x01149c34, 0x0113716a, 0x01124924, 0x01112358, - 0x01100000, 0x010edf12, 0x010dc087, 0x010ca458, 0x010b8a7d, 0x010a72f0, - 0x01095da8, 0x01084a9f, 0x010739ce, 0x01062b2e, 0x01051eb8, 0x01041465, - 0x01030c30, 0x01020612, 0x01010204, 0x01000000 }, - { // alpha * KINV_255 - 0x00000000, 0x00010101, 0x00020202, 0x00030303, 0x00040404, 0x00050505, - 0x00060606, 0x00070707, 0x00080808, 0x00090909, 0x000a0a0a, 0x000b0b0b, - 0x000c0c0c, 0x000d0d0d, 0x000e0e0e, 0x000f0f0f, 0x00101010, 0x00111111, - 0x00121212, 0x00131313, 0x00141414, 0x00151515, 0x00161616, 0x00171717, - 0x00181818, 0x00191919, 0x001a1a1a, 0x001b1b1b, 0x001c1c1c, 0x001d1d1d, - 0x001e1e1e, 0x001f1f1f, 0x00202020, 0x00212121, 0x00222222, 0x00232323, - 0x00242424, 0x00252525, 0x00262626, 0x00272727, 0x00282828, 0x00292929, - 0x002a2a2a, 0x002b2b2b, 0x002c2c2c, 0x002d2d2d, 0x002e2e2e, 0x002f2f2f, - 0x00303030, 0x00313131, 0x00323232, 0x00333333, 0x00343434, 0x00353535, - 0x00363636, 0x00373737, 0x00383838, 0x00393939, 0x003a3a3a, 0x003b3b3b, - 0x003c3c3c, 0x003d3d3d, 0x003e3e3e, 0x003f3f3f, 0x00404040, 0x00414141, - 0x00424242, 0x00434343, 0x00444444, 0x00454545, 0x00464646, 0x00474747, - 0x00484848, 0x00494949, 0x004a4a4a, 0x004b4b4b, 0x004c4c4c, 0x004d4d4d, - 0x004e4e4e, 0x004f4f4f, 0x00505050, 0x00515151, 0x00525252, 0x00535353, - 0x00545454, 0x00555555, 0x00565656, 0x00575757, 0x00585858, 0x00595959, - 0x005a5a5a, 0x005b5b5b, 0x005c5c5c, 0x005d5d5d, 0x005e5e5e, 0x005f5f5f, - 0x00606060, 0x00616161, 0x00626262, 0x00636363, 0x00646464, 0x00656565, - 0x00666666, 0x00676767, 0x00686868, 0x00696969, 0x006a6a6a, 0x006b6b6b, - 0x006c6c6c, 0x006d6d6d, 0x006e6e6e, 0x006f6f6f, 0x00707070, 0x00717171, - 0x00727272, 0x00737373, 0x00747474, 0x00757575, 0x00767676, 0x00777777, - 0x00787878, 0x00797979, 0x007a7a7a, 0x007b7b7b, 0x007c7c7c, 0x007d7d7d, - 0x007e7e7e, 0x007f7f7f, 0x00808080, 0x00818181, 0x00828282, 0x00838383, - 0x00848484, 0x00858585, 0x00868686, 0x00878787, 0x00888888, 0x00898989, - 0x008a8a8a, 0x008b8b8b, 0x008c8c8c, 0x008d8d8d, 0x008e8e8e, 0x008f8f8f, - 0x00909090, 0x00919191, 0x00929292, 0x00939393, 0x00949494, 0x00959595, - 0x00969696, 0x00979797, 0x00989898, 0x00999999, 0x009a9a9a, 0x009b9b9b, - 0x009c9c9c, 0x009d9d9d, 0x009e9e9e, 0x009f9f9f, 0x00a0a0a0, 0x00a1a1a1, - 0x00a2a2a2, 0x00a3a3a3, 0x00a4a4a4, 0x00a5a5a5, 0x00a6a6a6, 0x00a7a7a7, - 0x00a8a8a8, 0x00a9a9a9, 0x00aaaaaa, 0x00ababab, 0x00acacac, 0x00adadad, - 0x00aeaeae, 0x00afafaf, 0x00b0b0b0, 0x00b1b1b1, 0x00b2b2b2, 0x00b3b3b3, - 0x00b4b4b4, 0x00b5b5b5, 0x00b6b6b6, 0x00b7b7b7, 0x00b8b8b8, 0x00b9b9b9, - 0x00bababa, 0x00bbbbbb, 0x00bcbcbc, 0x00bdbdbd, 0x00bebebe, 0x00bfbfbf, - 0x00c0c0c0, 0x00c1c1c1, 0x00c2c2c2, 0x00c3c3c3, 0x00c4c4c4, 0x00c5c5c5, - 0x00c6c6c6, 0x00c7c7c7, 0x00c8c8c8, 0x00c9c9c9, 0x00cacaca, 0x00cbcbcb, - 0x00cccccc, 0x00cdcdcd, 0x00cecece, 0x00cfcfcf, 0x00d0d0d0, 0x00d1d1d1, - 0x00d2d2d2, 0x00d3d3d3, 0x00d4d4d4, 0x00d5d5d5, 0x00d6d6d6, 0x00d7d7d7, - 0x00d8d8d8, 0x00d9d9d9, 0x00dadada, 0x00dbdbdb, 0x00dcdcdc, 0x00dddddd, - 0x00dedede, 0x00dfdfdf, 0x00e0e0e0, 0x00e1e1e1, 0x00e2e2e2, 0x00e3e3e3, - 0x00e4e4e4, 0x00e5e5e5, 0x00e6e6e6, 0x00e7e7e7, 0x00e8e8e8, 0x00e9e9e9, - 0x00eaeaea, 0x00ebebeb, 0x00ececec, 0x00ededed, 0x00eeeeee, 0x00efefef, - 0x00f0f0f0, 0x00f1f1f1, 0x00f2f2f2, 0x00f3f3f3, 0x00f4f4f4, 0x00f5f5f5, - 0x00f6f6f6, 0x00f7f7f7, 0x00f8f8f8, 0x00f9f9f9, 0x00fafafa, 0x00fbfbfb, - 0x00fcfcfc, 0x00fdfdfd, 0x00fefefe, 0x00ffffff } -}; - -static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) { - return kMultTables[!inverse][a]; -} - -#else - -static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) { - return inverse ? (255u << MFIX) / a : a * KINV_255; -} - -#endif // USE_TABLES_FOR_ALPHA_MULT - -void WebPMultARGBRowC(uint32_t* const ptr, int width, int inverse) { - int x; - for (x = 0; x < width; ++x) { - const uint32_t argb = ptr[x]; - if (argb < 0xff000000u) { // alpha < 255 - if (argb <= 0x00ffffffu) { // alpha == 0 - ptr[x] = 0; - } else { - const uint32_t alpha = (argb >> 24) & 0xff; - const uint32_t scale = GetScale(alpha, inverse); - uint32_t out = argb & 0xff000000u; - out |= Mult(argb >> 0, scale) << 0; - out |= Mult(argb >> 8, scale) << 8; - out |= Mult(argb >> 16, scale) << 16; - ptr[x] = out; - } - } - } -} - -void WebPMultRowC(uint8_t* const ptr, const uint8_t* const alpha, - int width, int inverse) { - int x; - for (x = 0; x < width; ++x) { - const uint32_t a = alpha[x]; - if (a != 255) { - if (a == 0) { - ptr[x] = 0; - } else { - const uint32_t scale = GetScale(a, inverse); - ptr[x] = Mult(ptr[x], scale); - } - } - } -} - -#undef KINV_255 -#undef HALF -#undef MFIX - -void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse); -void (*WebPMultRow)(uint8_t* const ptr, const uint8_t* const alpha, - int width, int inverse); - -//------------------------------------------------------------------------------ -// Generic per-plane calls - -void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows, - int inverse) { - int n; - for (n = 0; n < num_rows; ++n) { - WebPMultARGBRow((uint32_t*)ptr, width, inverse); - ptr += stride; - } -} - -void WebPMultRows(uint8_t* ptr, int stride, - const uint8_t* alpha, int alpha_stride, - int width, int num_rows, int inverse) { - int n; - for (n = 0; n < num_rows; ++n) { - WebPMultRow(ptr, alpha, width, inverse); - ptr += stride; - alpha += alpha_stride; - } -} - -//------------------------------------------------------------------------------ -// Premultiplied modes - -// non dithered-modes - -// (x * a * 32897) >> 23 is bit-wise equivalent to (int)(x * a / 255.) -// for all 8bit x or a. For bit-wise equivalence to (int)(x * a / 255. + .5), -// one can use instead: (x * a * 65793 + (1 << 23)) >> 24 -#if 1 // (int)(x * a / 255.) -#define MULTIPLIER(a) ((a) * 32897U) -#define PREMULTIPLY(x, m) (((x) * (m)) >> 23) -#else // (int)(x * a / 255. + .5) -#define MULTIPLIER(a) ((a) * 65793U) -#define PREMULTIPLY(x, m) (((x) * (m) + (1U << 23)) >> 24) -#endif - -static void ApplyAlphaMultiply(uint8_t* rgba, int alpha_first, - int w, int h, int stride) { - while (h-- > 0) { - uint8_t* const rgb = rgba + (alpha_first ? 1 : 0); - const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3); - int i; - for (i = 0; i < w; ++i) { - const uint32_t a = alpha[4 * i]; - if (a != 0xff) { - const uint32_t mult = MULTIPLIER(a); - rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult); - rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult); - rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult); - } - } - rgba += stride; - } -} -#undef MULTIPLIER -#undef PREMULTIPLY - -// rgbA4444 - -#define MULTIPLIER(a) ((a) * 0x1111) // 0x1111 ~= (1 << 16) / 15 - -static WEBP_INLINE uint8_t dither_hi(uint8_t x) { - return (x & 0xf0) | (x >> 4); -} - -static WEBP_INLINE uint8_t dither_lo(uint8_t x) { - return (x & 0x0f) | (x << 4); -} - -static WEBP_INLINE uint8_t multiply(uint8_t x, uint32_t m) { - return (x * m) >> 16; -} - -static WEBP_INLINE void ApplyAlphaMultiply4444(uint8_t* rgba4444, - int w, int h, int stride, - int rg_byte_pos /* 0 or 1 */) { - while (h-- > 0) { - int i; - for (i = 0; i < w; ++i) { - const uint32_t rg = rgba4444[2 * i + rg_byte_pos]; - const uint32_t ba = rgba4444[2 * i + (rg_byte_pos ^ 1)]; - const uint8_t a = ba & 0x0f; - const uint32_t mult = MULTIPLIER(a); - const uint8_t r = multiply(dither_hi(rg), mult); - const uint8_t g = multiply(dither_lo(rg), mult); - const uint8_t b = multiply(dither_hi(ba), mult); - rgba4444[2 * i + rg_byte_pos] = (r & 0xf0) | ((g >> 4) & 0x0f); - rgba4444[2 * i + (rg_byte_pos ^ 1)] = (b & 0xf0) | a; - } - rgba4444 += stride; - } -} -#undef MULTIPLIER - -static void ApplyAlphaMultiply_16b(uint8_t* rgba4444, - int w, int h, int stride) { -#ifdef WEBP_SWAP_16BIT_CSP - ApplyAlphaMultiply4444(rgba4444, w, h, stride, 1); -#else - ApplyAlphaMultiply4444(rgba4444, w, h, stride, 0); -#endif -} - -static int DispatchAlpha(const uint8_t* alpha, int alpha_stride, - int width, int height, - uint8_t* dst, int dst_stride) { - uint32_t alpha_mask = 0xff; - int i, j; - - for (j = 0; j < height; ++j) { - for (i = 0; i < width; ++i) { - const uint32_t alpha_value = alpha[i]; - dst[4 * i] = alpha_value; - alpha_mask &= alpha_value; - } - alpha += alpha_stride; - dst += dst_stride; - } - - return (alpha_mask != 0xff); -} - -static void DispatchAlphaToGreen(const uint8_t* alpha, int alpha_stride, - int width, int height, - uint32_t* dst, int dst_stride) { - int i, j; - for (j = 0; j < height; ++j) { - for (i = 0; i < width; ++i) { - dst[i] = alpha[i] << 8; // leave A/R/B channels zero'd. - } - alpha += alpha_stride; - dst += dst_stride; - } -} - -static int ExtractAlpha(const uint8_t* argb, int argb_stride, - int width, int height, - uint8_t* alpha, int alpha_stride) { - uint8_t alpha_mask = 0xff; - int i, j; - - for (j = 0; j < height; ++j) { - for (i = 0; i < width; ++i) { - const uint8_t alpha_value = argb[4 * i]; - alpha[i] = alpha_value; - alpha_mask &= alpha_value; - } - argb += argb_stride; - alpha += alpha_stride; - } - return (alpha_mask == 0xff); -} - -void (*WebPApplyAlphaMultiply)(uint8_t*, int, int, int, int); -void (*WebPApplyAlphaMultiply4444)(uint8_t*, int, int, int); -int (*WebPDispatchAlpha)(const uint8_t*, int, int, int, uint8_t*, int); -void (*WebPDispatchAlphaToGreen)(const uint8_t*, int, int, int, uint32_t*, int); -int (*WebPExtractAlpha)(const uint8_t*, int, int, int, uint8_t*, int); - -//------------------------------------------------------------------------------ -// Init function - -extern void WebPInitAlphaProcessingMIPSdspR2(void); -extern void WebPInitAlphaProcessingSSE2(void); -extern void WebPInitAlphaProcessingSSE41(void); - -static volatile VP8CPUInfo alpha_processing_last_cpuinfo_used = - (VP8CPUInfo)&alpha_processing_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessing(void) { - if (alpha_processing_last_cpuinfo_used == VP8GetCPUInfo) return; - - WebPMultARGBRow = WebPMultARGBRowC; - WebPMultRow = WebPMultRowC; - WebPApplyAlphaMultiply = ApplyAlphaMultiply; - WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b; - WebPDispatchAlpha = DispatchAlpha; - WebPDispatchAlphaToGreen = DispatchAlphaToGreen; - WebPExtractAlpha = ExtractAlpha; - - // If defined, use CPUInfo() to overwrite some pointers with faster versions. - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - WebPInitAlphaProcessingSSE2(); -#if defined(WEBP_USE_SSE41) - if (VP8GetCPUInfo(kSSE4_1)) { - WebPInitAlphaProcessingSSE41(); - } -#endif - } -#endif -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - WebPInitAlphaProcessingMIPSdspR2(); - } -#endif - } - alpha_processing_last_cpuinfo_used = VP8GetCPUInfo; -} diff --git a/Example-Mac/Pods/libwebp/src/dsp/alpha_processing_mips_dsp_r2.c b/Example-Mac/Pods/libwebp/src/dsp/alpha_processing_mips_dsp_r2.c deleted file mode 100644 index c631d789..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/alpha_processing_mips_dsp_r2.c +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Utilities for processing transparent channel. -// -// Author(s): Branimir Vasic (branimir.vasic@imgtec.com) -// Djordje Pesut (djordje.pesut@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS_DSP_R2) - -static int DispatchAlpha(const uint8_t* alpha, int alpha_stride, - int width, int height, - uint8_t* dst, int dst_stride) { - uint32_t alpha_mask = 0xffffffff; - int i, j, temp0; - - for (j = 0; j < height; ++j) { - uint8_t* pdst = dst; - const uint8_t* palpha = alpha; - for (i = 0; i < (width >> 2); ++i) { - int temp1, temp2, temp3; - - __asm__ volatile ( - "ulw %[temp0], 0(%[palpha]) \n\t" - "addiu %[palpha], %[palpha], 4 \n\t" - "addiu %[pdst], %[pdst], 16 \n\t" - "srl %[temp1], %[temp0], 8 \n\t" - "srl %[temp2], %[temp0], 16 \n\t" - "srl %[temp3], %[temp0], 24 \n\t" - "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t" - "sb %[temp0], -16(%[pdst]) \n\t" - "sb %[temp1], -12(%[pdst]) \n\t" - "sb %[temp2], -8(%[pdst]) \n\t" - "sb %[temp3], -4(%[pdst]) \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [palpha]"+r"(palpha), [pdst]"+r"(pdst), - [alpha_mask]"+r"(alpha_mask) - : - : "memory" - ); - } - - for (i = 0; i < (width & 3); ++i) { - __asm__ volatile ( - "lbu %[temp0], 0(%[palpha]) \n\t" - "addiu %[palpha], %[palpha], 1 \n\t" - "sb %[temp0], 0(%[pdst]) \n\t" - "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t" - "addiu %[pdst], %[pdst], 4 \n\t" - : [temp0]"=&r"(temp0), [palpha]"+r"(palpha), [pdst]"+r"(pdst), - [alpha_mask]"+r"(alpha_mask) - : - : "memory" - ); - } - alpha += alpha_stride; - dst += dst_stride; - } - - __asm__ volatile ( - "ext %[temp0], %[alpha_mask], 0, 16 \n\t" - "srl %[alpha_mask], %[alpha_mask], 16 \n\t" - "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t" - "ext %[temp0], %[alpha_mask], 0, 8 \n\t" - "srl %[alpha_mask], %[alpha_mask], 8 \n\t" - "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t" - : [temp0]"=&r"(temp0), [alpha_mask]"+r"(alpha_mask) - : - ); - - return (alpha_mask != 0xff); -} - -static void MultARGBRow(uint32_t* const ptr, int width, int inverse) { - int x; - const uint32_t c_00ffffff = 0x00ffffffu; - const uint32_t c_ff000000 = 0xff000000u; - const uint32_t c_8000000 = 0x00800000u; - const uint32_t c_8000080 = 0x00800080u; - for (x = 0; x < width; ++x) { - const uint32_t argb = ptr[x]; - if (argb < 0xff000000u) { // alpha < 255 - if (argb <= 0x00ffffffu) { // alpha == 0 - ptr[x] = 0; - } else { - int temp0, temp1, temp2, temp3, alpha; - __asm__ volatile ( - "srl %[alpha], %[argb], 24 \n\t" - "replv.qb %[temp0], %[alpha] \n\t" - "and %[temp0], %[temp0], %[c_00ffffff] \n\t" - "beqz %[inverse], 0f \n\t" - "divu $zero, %[c_ff000000], %[alpha] \n\t" - "mflo %[temp0] \n\t" - "0: \n\t" - "andi %[temp1], %[argb], 0xff \n\t" - "ext %[temp2], %[argb], 8, 8 \n\t" - "ext %[temp3], %[argb], 16, 8 \n\t" - "mul %[temp1], %[temp1], %[temp0] \n\t" - "mul %[temp2], %[temp2], %[temp0] \n\t" - "mul %[temp3], %[temp3], %[temp0] \n\t" - "precrq.ph.w %[temp1], %[temp2], %[temp1] \n\t" - "addu %[temp3], %[temp3], %[c_8000000] \n\t" - "addu %[temp1], %[temp1], %[c_8000080] \n\t" - "precrq.ph.w %[temp3], %[argb], %[temp3] \n\t" - "precrq.qb.ph %[temp1], %[temp3], %[temp1] \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [alpha]"=&r"(alpha) - : [inverse]"r"(inverse), [c_00ffffff]"r"(c_00ffffff), - [c_8000000]"r"(c_8000000), [c_8000080]"r"(c_8000080), - [c_ff000000]"r"(c_ff000000), [argb]"r"(argb) - : "memory", "hi", "lo" - ); - ptr[x] = temp1; - } - } - } -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void WebPInitAlphaProcessingMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingMIPSdspR2(void) { - WebPDispatchAlpha = DispatchAlpha; - WebPMultARGBRow = MultARGBRow; -} - -#else // !WEBP_USE_MIPS_DSP_R2 - -WEBP_DSP_INIT_STUB(WebPInitAlphaProcessingMIPSdspR2) - -#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/Example-Mac/Pods/libwebp/src/dsp/alpha_processing_sse2.c b/Example-Mac/Pods/libwebp/src/dsp/alpha_processing_sse2.c deleted file mode 100644 index 5acb481d..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/alpha_processing_sse2.c +++ /dev/null @@ -1,298 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Utilities for processing transparent channel. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE2) -#include - -//------------------------------------------------------------------------------ - -static int DispatchAlpha(const uint8_t* alpha, int alpha_stride, - int width, int height, - uint8_t* dst, int dst_stride) { - // alpha_and stores an 'and' operation of all the alpha[] values. The final - // value is not 0xff if any of the alpha[] is not equal to 0xff. - uint32_t alpha_and = 0xff; - int i, j; - const __m128i zero = _mm_setzero_si128(); - const __m128i rgb_mask = _mm_set1_epi32(0xffffff00u); // to preserve RGB - const __m128i all_0xff = _mm_set_epi32(0, 0, ~0u, ~0u); - __m128i all_alphas = all_0xff; - - // We must be able to access 3 extra bytes after the last written byte - // 'dst[4 * width - 4]', because we don't know if alpha is the first or the - // last byte of the quadruplet. - const int limit = (width - 1) & ~7; - - for (j = 0; j < height; ++j) { - __m128i* out = (__m128i*)dst; - for (i = 0; i < limit; i += 8) { - // load 8 alpha bytes - const __m128i a0 = _mm_loadl_epi64((const __m128i*)&alpha[i]); - const __m128i a1 = _mm_unpacklo_epi8(a0, zero); - const __m128i a2_lo = _mm_unpacklo_epi16(a1, zero); - const __m128i a2_hi = _mm_unpackhi_epi16(a1, zero); - // load 8 dst pixels (32 bytes) - const __m128i b0_lo = _mm_loadu_si128(out + 0); - const __m128i b0_hi = _mm_loadu_si128(out + 1); - // mask dst alpha values - const __m128i b1_lo = _mm_and_si128(b0_lo, rgb_mask); - const __m128i b1_hi = _mm_and_si128(b0_hi, rgb_mask); - // combine - const __m128i b2_lo = _mm_or_si128(b1_lo, a2_lo); - const __m128i b2_hi = _mm_or_si128(b1_hi, a2_hi); - // store - _mm_storeu_si128(out + 0, b2_lo); - _mm_storeu_si128(out + 1, b2_hi); - // accumulate eight alpha 'and' in parallel - all_alphas = _mm_and_si128(all_alphas, a0); - out += 2; - } - for (; i < width; ++i) { - const uint32_t alpha_value = alpha[i]; - dst[4 * i] = alpha_value; - alpha_and &= alpha_value; - } - alpha += alpha_stride; - dst += dst_stride; - } - // Combine the eight alpha 'and' into a 8-bit mask. - alpha_and &= _mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas, all_0xff)); - return (alpha_and != 0xff); -} - -static void DispatchAlphaToGreen(const uint8_t* alpha, int alpha_stride, - int width, int height, - uint32_t* dst, int dst_stride) { - int i, j; - const __m128i zero = _mm_setzero_si128(); - const int limit = width & ~15; - for (j = 0; j < height; ++j) { - for (i = 0; i < limit; i += 16) { // process 16 alpha bytes - const __m128i a0 = _mm_loadu_si128((const __m128i*)&alpha[i]); - const __m128i a1 = _mm_unpacklo_epi8(zero, a0); // note the 'zero' first! - const __m128i b1 = _mm_unpackhi_epi8(zero, a0); - const __m128i a2_lo = _mm_unpacklo_epi16(a1, zero); - const __m128i b2_lo = _mm_unpacklo_epi16(b1, zero); - const __m128i a2_hi = _mm_unpackhi_epi16(a1, zero); - const __m128i b2_hi = _mm_unpackhi_epi16(b1, zero); - _mm_storeu_si128((__m128i*)&dst[i + 0], a2_lo); - _mm_storeu_si128((__m128i*)&dst[i + 4], a2_hi); - _mm_storeu_si128((__m128i*)&dst[i + 8], b2_lo); - _mm_storeu_si128((__m128i*)&dst[i + 12], b2_hi); - } - for (; i < width; ++i) dst[i] = alpha[i] << 8; - alpha += alpha_stride; - dst += dst_stride; - } -} - -static int ExtractAlpha(const uint8_t* argb, int argb_stride, - int width, int height, - uint8_t* alpha, int alpha_stride) { - // alpha_and stores an 'and' operation of all the alpha[] values. The final - // value is not 0xff if any of the alpha[] is not equal to 0xff. - uint32_t alpha_and = 0xff; - int i, j; - const __m128i a_mask = _mm_set1_epi32(0xffu); // to preserve alpha - const __m128i all_0xff = _mm_set_epi32(0, 0, ~0u, ~0u); - __m128i all_alphas = all_0xff; - - // We must be able to access 3 extra bytes after the last written byte - // 'src[4 * width - 4]', because we don't know if alpha is the first or the - // last byte of the quadruplet. - const int limit = (width - 1) & ~7; - - for (j = 0; j < height; ++j) { - const __m128i* src = (const __m128i*)argb; - for (i = 0; i < limit; i += 8) { - // load 32 argb bytes - const __m128i a0 = _mm_loadu_si128(src + 0); - const __m128i a1 = _mm_loadu_si128(src + 1); - const __m128i b0 = _mm_and_si128(a0, a_mask); - const __m128i b1 = _mm_and_si128(a1, a_mask); - const __m128i c0 = _mm_packs_epi32(b0, b1); - const __m128i d0 = _mm_packus_epi16(c0, c0); - // store - _mm_storel_epi64((__m128i*)&alpha[i], d0); - // accumulate eight alpha 'and' in parallel - all_alphas = _mm_and_si128(all_alphas, d0); - src += 2; - } - for (; i < width; ++i) { - const uint32_t alpha_value = argb[4 * i]; - alpha[i] = alpha_value; - alpha_and &= alpha_value; - } - argb += argb_stride; - alpha += alpha_stride; - } - // Combine the eight alpha 'and' into a 8-bit mask. - alpha_and &= _mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas, all_0xff)); - return (alpha_and == 0xff); -} - -//------------------------------------------------------------------------------ -// Non-dither premultiplied modes - -#define MULTIPLIER(a) ((a) * 0x8081) -#define PREMULTIPLY(x, m) (((x) * (m)) >> 23) - -// We can't use a 'const int' for the SHUFFLE value, because it has to be an -// immediate in the _mm_shufflexx_epi16() instruction. We really a macro here. -#define APPLY_ALPHA(RGBX, SHUFFLE, MASK, MULT) do { \ - const __m128i argb0 = _mm_loadl_epi64((__m128i*)&(RGBX)); \ - const __m128i argb1 = _mm_unpacklo_epi8(argb0, zero); \ - const __m128i alpha0 = _mm_and_si128(argb1, MASK); \ - const __m128i alpha1 = _mm_shufflelo_epi16(alpha0, SHUFFLE); \ - const __m128i alpha2 = _mm_shufflehi_epi16(alpha1, SHUFFLE); \ - /* alpha2 = [0 a0 a0 a0][0 a1 a1 a1] */ \ - const __m128i scale0 = _mm_mullo_epi16(alpha2, MULT); \ - const __m128i scale1 = _mm_mulhi_epu16(alpha2, MULT); \ - const __m128i argb2 = _mm_mulhi_epu16(argb1, scale0); \ - const __m128i argb3 = _mm_mullo_epi16(argb1, scale1); \ - const __m128i argb4 = _mm_adds_epu16(argb2, argb3); \ - const __m128i argb5 = _mm_srli_epi16(argb4, 7); \ - const __m128i argb6 = _mm_or_si128(argb5, alpha0); \ - const __m128i argb7 = _mm_packus_epi16(argb6, zero); \ - _mm_storel_epi64((__m128i*)&(RGBX), argb7); \ -} while (0) - -static void ApplyAlphaMultiply(uint8_t* rgba, int alpha_first, - int w, int h, int stride) { - const __m128i zero = _mm_setzero_si128(); - const int kSpan = 2; - const int w2 = w & ~(kSpan - 1); - while (h-- > 0) { - uint32_t* const rgbx = (uint32_t*)rgba; - int i; - if (!alpha_first) { - const __m128i kMask = _mm_set_epi16(0xff, 0, 0, 0, 0xff, 0, 0, 0); - const __m128i kMult = - _mm_set_epi16(0, 0x8081, 0x8081, 0x8081, 0, 0x8081, 0x8081, 0x8081); - for (i = 0; i < w2; i += kSpan) { - APPLY_ALPHA(rgbx[i], _MM_SHUFFLE(0, 3, 3, 3), kMask, kMult); - } - } else { - const __m128i kMask = _mm_set_epi16(0, 0, 0, 0xff, 0, 0, 0, 0xff); - const __m128i kMult = - _mm_set_epi16(0x8081, 0x8081, 0x8081, 0, 0x8081, 0x8081, 0x8081, 0); - for (i = 0; i < w2; i += kSpan) { - APPLY_ALPHA(rgbx[i], _MM_SHUFFLE(0, 0, 0, 3), kMask, kMult); - } - } - // Finish with left-overs. - for (; i < w; ++i) { - uint8_t* const rgb = rgba + (alpha_first ? 1 : 0); - const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3); - const uint32_t a = alpha[4 * i]; - if (a != 0xff) { - const uint32_t mult = MULTIPLIER(a); - rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult); - rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult); - rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult); - } - } - rgba += stride; - } -} -#undef MULTIPLIER -#undef PREMULTIPLY - -// ----------------------------------------------------------------------------- -// Apply alpha value to rows - -// We use: kINV255 = (1 << 24) / 255 = 0x010101 -// So: a * kINV255 = (a << 16) | [(a << 8) | a] -// -> _mm_mulhi_epu16() takes care of the (a<<16) part, -// and _mm_mullo_epu16(a * 0x0101,...) takes care of the "(a << 8) | a" one. - -static void MultARGBRow(uint32_t* const ptr, int width, int inverse) { - int x = 0; - if (!inverse) { - const int kSpan = 2; - const __m128i zero = _mm_setzero_si128(); - const __m128i kRound = - _mm_set_epi16(0, 1 << 7, 1 << 7, 1 << 7, 0, 1 << 7, 1 << 7, 1 << 7); - const __m128i kMult = - _mm_set_epi16(0, 0x0101, 0x0101, 0x0101, 0, 0x0101, 0x0101, 0x0101); - const __m128i kOne64 = _mm_set_epi16(1u << 8, 0, 0, 0, 1u << 8, 0, 0, 0); - const int w2 = width & ~(kSpan - 1); - for (x = 0; x < w2; x += kSpan) { - const __m128i argb0 = _mm_loadl_epi64((__m128i*)&ptr[x]); - const __m128i argb1 = _mm_unpacklo_epi8(argb0, zero); - const __m128i tmp0 = _mm_shufflelo_epi16(argb1, _MM_SHUFFLE(3, 3, 3, 3)); - const __m128i tmp1 = _mm_shufflehi_epi16(tmp0, _MM_SHUFFLE(3, 3, 3, 3)); - const __m128i tmp2 = _mm_srli_epi64(tmp1, 16); - const __m128i scale0 = _mm_mullo_epi16(tmp1, kMult); - const __m128i scale1 = _mm_or_si128(tmp2, kOne64); - const __m128i argb2 = _mm_mulhi_epu16(argb1, scale0); - const __m128i argb3 = _mm_mullo_epi16(argb1, scale1); - const __m128i argb4 = _mm_adds_epu16(argb2, argb3); - const __m128i argb5 = _mm_adds_epu16(argb4, kRound); - const __m128i argb6 = _mm_srli_epi16(argb5, 8); - const __m128i argb7 = _mm_packus_epi16(argb6, zero); - _mm_storel_epi64((__m128i*)&ptr[x], argb7); - } - } - width -= x; - if (width > 0) WebPMultARGBRowC(ptr + x, width, inverse); -} - -static void MultRow(uint8_t* const ptr, const uint8_t* const alpha, - int width, int inverse) { - int x = 0; - if (!inverse) { - const int kSpan = 8; - const __m128i zero = _mm_setzero_si128(); - const __m128i kRound = _mm_set1_epi16(1 << 7); - const int w2 = width & ~(kSpan - 1); - for (x = 0; x < w2; x += kSpan) { - const __m128i v0 = _mm_loadl_epi64((__m128i*)&ptr[x]); - const __m128i v1 = _mm_unpacklo_epi8(v0, zero); - const __m128i alpha0 = _mm_loadl_epi64((const __m128i*)&alpha[x]); - const __m128i alpha1 = _mm_unpacklo_epi8(alpha0, zero); - const __m128i alpha2 = _mm_unpacklo_epi8(alpha0, alpha0); - const __m128i v2 = _mm_mulhi_epu16(v1, alpha2); - const __m128i v3 = _mm_mullo_epi16(v1, alpha1); - const __m128i v4 = _mm_adds_epu16(v2, v3); - const __m128i v5 = _mm_adds_epu16(v4, kRound); - const __m128i v6 = _mm_srli_epi16(v5, 8); - const __m128i v7 = _mm_packus_epi16(v6, zero); - _mm_storel_epi64((__m128i*)&ptr[x], v7); - } - } - width -= x; - if (width > 0) WebPMultRowC(ptr + x, alpha + x, width, inverse); -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void WebPInitAlphaProcessingSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingSSE2(void) { - WebPMultARGBRow = MultARGBRow; - WebPMultRow = MultRow; - WebPApplyAlphaMultiply = ApplyAlphaMultiply; - WebPDispatchAlpha = DispatchAlpha; - WebPDispatchAlphaToGreen = DispatchAlphaToGreen; - WebPExtractAlpha = ExtractAlpha; -} - -#else // !WEBP_USE_SSE2 - -WEBP_DSP_INIT_STUB(WebPInitAlphaProcessingSSE2) - -#endif // WEBP_USE_SSE2 diff --git a/Example-Mac/Pods/libwebp/src/dsp/alpha_processing_sse41.c b/Example-Mac/Pods/libwebp/src/dsp/alpha_processing_sse41.c deleted file mode 100644 index 986fde94..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/alpha_processing_sse41.c +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Utilities for processing transparent channel, SSE4.1 variant. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE41) - -#include - -//------------------------------------------------------------------------------ - -static int ExtractAlpha(const uint8_t* argb, int argb_stride, - int width, int height, - uint8_t* alpha, int alpha_stride) { - // alpha_and stores an 'and' operation of all the alpha[] values. The final - // value is not 0xff if any of the alpha[] is not equal to 0xff. - uint32_t alpha_and = 0xff; - int i, j; - const __m128i all_0xff = _mm_set1_epi32(~0u); - __m128i all_alphas = all_0xff; - - // We must be able to access 3 extra bytes after the last written byte - // 'src[4 * width - 4]', because we don't know if alpha is the first or the - // last byte of the quadruplet. - const int limit = (width - 1) & ~15; - const __m128i kCstAlpha0 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 12, 8, 4, 0); - const __m128i kCstAlpha1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, - 12, 8, 4, 0, -1, -1, -1, -1); - const __m128i kCstAlpha2 = _mm_set_epi8(-1, -1, -1, -1, 12, 8, 4, 0, - -1, -1, -1, -1, -1, -1, -1, -1); - const __m128i kCstAlpha3 = _mm_set_epi8(12, 8, 4, 0, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1); - for (j = 0; j < height; ++j) { - const __m128i* src = (const __m128i*)argb; - for (i = 0; i < limit; i += 16) { - // load 64 argb bytes - const __m128i a0 = _mm_loadu_si128(src + 0); - const __m128i a1 = _mm_loadu_si128(src + 1); - const __m128i a2 = _mm_loadu_si128(src + 2); - const __m128i a3 = _mm_loadu_si128(src + 3); - const __m128i b0 = _mm_shuffle_epi8(a0, kCstAlpha0); - const __m128i b1 = _mm_shuffle_epi8(a1, kCstAlpha1); - const __m128i b2 = _mm_shuffle_epi8(a2, kCstAlpha2); - const __m128i b3 = _mm_shuffle_epi8(a3, kCstAlpha3); - const __m128i c0 = _mm_or_si128(b0, b1); - const __m128i c1 = _mm_or_si128(b2, b3); - const __m128i d0 = _mm_or_si128(c0, c1); - // store - _mm_storeu_si128((__m128i*)&alpha[i], d0); - // accumulate sixteen alpha 'and' in parallel - all_alphas = _mm_and_si128(all_alphas, d0); - src += 4; - } - for (; i < width; ++i) { - const uint32_t alpha_value = argb[4 * i]; - alpha[i] = alpha_value; - alpha_and &= alpha_value; - } - argb += argb_stride; - alpha += alpha_stride; - } - // Combine the sixteen alpha 'and' into an 8-bit mask. - alpha_and |= 0xff00u; // pretend the upper bits [8..15] were tested ok. - alpha_and &= _mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas, all_0xff)); - return (alpha_and == 0xffffu); -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void WebPInitAlphaProcessingSSE41(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingSSE41(void) { - WebPExtractAlpha = ExtractAlpha; -} - -#else // !WEBP_USE_SSE41 - -WEBP_DSP_INIT_STUB(WebPInitAlphaProcessingSSE41) - -#endif // WEBP_USE_SSE41 diff --git a/Example-Mac/Pods/libwebp/src/dsp/argb.c b/Example-Mac/Pods/libwebp/src/dsp/argb.c deleted file mode 100644 index cc1f9a96..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/argb.c +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// ARGB making functions. -// -// Author: Djordje Pesut (djordje.pesut@imgtec.com) - -#include "./dsp.h" - -static WEBP_INLINE uint32_t MakeARGB32(int a, int r, int g, int b) { - return (((uint32_t)a << 24) | (r << 16) | (g << 8) | b); -} - -static void PackARGB(const uint8_t* a, const uint8_t* r, const uint8_t* g, - const uint8_t* b, int len, uint32_t* out) { - int i; - for (i = 0; i < len; ++i) { - out[i] = MakeARGB32(a[4 * i], r[4 * i], g[4 * i], b[4 * i]); - } -} - -static void PackRGB(const uint8_t* r, const uint8_t* g, const uint8_t* b, - int len, int step, uint32_t* out) { - int i, offset = 0; - for (i = 0; i < len; ++i) { - out[i] = MakeARGB32(0xff, r[offset], g[offset], b[offset]); - offset += step; - } -} - -void (*VP8PackARGB)(const uint8_t*, const uint8_t*, const uint8_t*, - const uint8_t*, int, uint32_t*); -void (*VP8PackRGB)(const uint8_t*, const uint8_t*, const uint8_t*, - int, int, uint32_t*); - -extern void VP8EncDspARGBInitMIPSdspR2(void); -extern void VP8EncDspARGBInitSSE2(void); - -static volatile VP8CPUInfo argb_last_cpuinfo_used = - (VP8CPUInfo)&argb_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspARGBInit(void) { - if (argb_last_cpuinfo_used == VP8GetCPUInfo) return; - - VP8PackARGB = PackARGB; - VP8PackRGB = PackRGB; - - // If defined, use CPUInfo() to overwrite some pointers with faster versions. - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - VP8EncDspARGBInitSSE2(); - } -#endif -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - VP8EncDspARGBInitMIPSdspR2(); - } -#endif - } - argb_last_cpuinfo_used = VP8GetCPUInfo; -} diff --git a/Example-Mac/Pods/libwebp/src/dsp/argb_mips_dsp_r2.c b/Example-Mac/Pods/libwebp/src/dsp/argb_mips_dsp_r2.c deleted file mode 100644 index af65acb8..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/argb_mips_dsp_r2.c +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// ARGB making functions (mips version). -// -// Author: Djordje Pesut (djordje.pesut@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS_DSP_R2) - -static void PackARGB(const uint8_t* a, const uint8_t* r, const uint8_t* g, - const uint8_t* b, int len, uint32_t* out) { - int temp0, temp1, temp2, temp3, offset; - const int rest = len & 1; - const uint32_t* const loop_end = out + len - rest; - const int step = 4; - __asm__ volatile ( - "xor %[offset], %[offset], %[offset] \n\t" - "beq %[loop_end], %[out], 0f \n\t" - "2: \n\t" - "lbux %[temp0], %[offset](%[a]) \n\t" - "lbux %[temp1], %[offset](%[r]) \n\t" - "lbux %[temp2], %[offset](%[g]) \n\t" - "lbux %[temp3], %[offset](%[b]) \n\t" - "ins %[temp1], %[temp0], 16, 16 \n\t" - "ins %[temp3], %[temp2], 16, 16 \n\t" - "addiu %[out], %[out], 4 \n\t" - "precr.qb.ph %[temp0], %[temp1], %[temp3] \n\t" - "sw %[temp0], -4(%[out]) \n\t" - "addu %[offset], %[offset], %[step] \n\t" - "bne %[loop_end], %[out], 2b \n\t" - "0: \n\t" - "beq %[rest], $zero, 1f \n\t" - "lbux %[temp0], %[offset](%[a]) \n\t" - "lbux %[temp1], %[offset](%[r]) \n\t" - "lbux %[temp2], %[offset](%[g]) \n\t" - "lbux %[temp3], %[offset](%[b]) \n\t" - "ins %[temp1], %[temp0], 16, 16 \n\t" - "ins %[temp3], %[temp2], 16, 16 \n\t" - "precr.qb.ph %[temp0], %[temp1], %[temp3] \n\t" - "sw %[temp0], 0(%[out]) \n\t" - "1: \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [offset]"=&r"(offset), [out]"+&r"(out) - : [a]"r"(a), [r]"r"(r), [g]"r"(g), [b]"r"(b), [step]"r"(step), - [loop_end]"r"(loop_end), [rest]"r"(rest) - : "memory" - ); -} - -static void PackRGB(const uint8_t* r, const uint8_t* g, const uint8_t* b, - int len, int step, uint32_t* out) { - int temp0, temp1, temp2, offset; - const int rest = len & 1; - const int a = 0xff; - const uint32_t* const loop_end = out + len - rest; - __asm__ volatile ( - "xor %[offset], %[offset], %[offset] \n\t" - "beq %[loop_end], %[out], 0f \n\t" - "2: \n\t" - "lbux %[temp0], %[offset](%[r]) \n\t" - "lbux %[temp1], %[offset](%[g]) \n\t" - "lbux %[temp2], %[offset](%[b]) \n\t" - "ins %[temp0], %[a], 16, 16 \n\t" - "ins %[temp2], %[temp1], 16, 16 \n\t" - "addiu %[out], %[out], 4 \n\t" - "precr.qb.ph %[temp0], %[temp0], %[temp2] \n\t" - "sw %[temp0], -4(%[out]) \n\t" - "addu %[offset], %[offset], %[step] \n\t" - "bne %[loop_end], %[out], 2b \n\t" - "0: \n\t" - "beq %[rest], $zero, 1f \n\t" - "lbux %[temp0], %[offset](%[r]) \n\t" - "lbux %[temp1], %[offset](%[g]) \n\t" - "lbux %[temp2], %[offset](%[b]) \n\t" - "ins %[temp0], %[a], 16, 16 \n\t" - "ins %[temp2], %[temp1], 16, 16 \n\t" - "precr.qb.ph %[temp0], %[temp0], %[temp2] \n\t" - "sw %[temp0], 0(%[out]) \n\t" - "1: \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [offset]"=&r"(offset), [out]"+&r"(out) - : [a]"r"(a), [r]"r"(r), [g]"r"(g), [b]"r"(b), [step]"r"(step), - [loop_end]"r"(loop_end), [rest]"r"(rest) - : "memory" - ); -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8EncDspARGBInitMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspARGBInitMIPSdspR2(void) { - VP8PackARGB = PackARGB; - VP8PackRGB = PackRGB; -} - -#else // !WEBP_USE_MIPS_DSP_R2 - -WEBP_DSP_INIT_STUB(VP8EncDspARGBInitMIPSdspR2) - -#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/Example-Mac/Pods/libwebp/src/dsp/argb_sse2.c b/Example-Mac/Pods/libwebp/src/dsp/argb_sse2.c deleted file mode 100644 index afcb1957..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/argb_sse2.c +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// ARGB making functions (SSE2 version). -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE2) - -#include -#include -#include - -static WEBP_INLINE uint32_t MakeARGB32(int a, int r, int g, int b) { - return (((uint32_t)a << 24) | (r << 16) | (g << 8) | b); -} - -static void PackARGB(const uint8_t* a, const uint8_t* r, const uint8_t* g, - const uint8_t* b, int len, uint32_t* out) { - if (g == r + 1) { // RGBA input order. Need to swap R and B. - int i = 0; - const int len_max = len & ~3; // max length processed in main loop - const __m128i red_blue_mask = _mm_set1_epi32(0x00ff00ffu); - assert(b == r + 2); - assert(a == r + 3); - for (; i < len_max; i += 4) { - const __m128i A = _mm_loadu_si128((const __m128i*)(r + 4 * i)); - const __m128i B = _mm_and_si128(A, red_blue_mask); // R 0 B 0 - const __m128i C = _mm_andnot_si128(red_blue_mask, A); // 0 G 0 A - const __m128i D = _mm_shufflelo_epi16(B, _MM_SHUFFLE(2, 3, 0, 1)); - const __m128i E = _mm_shufflehi_epi16(D, _MM_SHUFFLE(2, 3, 0, 1)); - const __m128i F = _mm_or_si128(E, C); - _mm_storeu_si128((__m128i*)(out + i), F); - } - for (; i < len; ++i) { - out[i] = MakeARGB32(a[4 * i], r[4 * i], g[4 * i], b[4 * i]); - } - } else { - assert(g == b + 1); - assert(r == b + 2); - assert(a == b + 3); - memcpy(out, b, len * 4); - } -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8EncDspARGBInitSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspARGBInitSSE2(void) { - VP8PackARGB = PackARGB; -} - -#else // !WEBP_USE_SSE2 - -WEBP_DSP_INIT_STUB(VP8EncDspARGBInitSSE2) - -#endif // WEBP_USE_SSE2 diff --git a/Example-Mac/Pods/libwebp/src/dsp/cost.c b/Example-Mac/Pods/libwebp/src/dsp/cost.c deleted file mode 100644 index fe72d26e..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/cost.c +++ /dev/null @@ -1,412 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" -#include "../enc/cost.h" - -//------------------------------------------------------------------------------ -// Boolean-cost cost table - -const uint16_t VP8EntropyCost[256] = { - 1792, 1792, 1792, 1536, 1536, 1408, 1366, 1280, 1280, 1216, - 1178, 1152, 1110, 1076, 1061, 1024, 1024, 992, 968, 951, - 939, 911, 896, 878, 871, 854, 838, 820, 811, 794, - 786, 768, 768, 752, 740, 732, 720, 709, 704, 690, - 683, 672, 666, 655, 647, 640, 631, 622, 615, 607, - 598, 592, 586, 576, 572, 564, 559, 555, 547, 541, - 534, 528, 522, 512, 512, 504, 500, 494, 488, 483, - 477, 473, 467, 461, 458, 452, 448, 443, 438, 434, - 427, 424, 419, 415, 410, 406, 403, 399, 394, 390, - 384, 384, 377, 374, 370, 366, 362, 359, 355, 351, - 347, 342, 342, 336, 333, 330, 326, 323, 320, 316, - 312, 308, 305, 302, 299, 296, 293, 288, 287, 283, - 280, 277, 274, 272, 268, 266, 262, 256, 256, 256, - 251, 248, 245, 242, 240, 237, 234, 232, 228, 226, - 223, 221, 218, 216, 214, 211, 208, 205, 203, 201, - 198, 196, 192, 191, 188, 187, 183, 181, 179, 176, - 175, 171, 171, 168, 165, 163, 160, 159, 156, 154, - 152, 150, 148, 146, 144, 142, 139, 138, 135, 133, - 131, 128, 128, 125, 123, 121, 119, 117, 115, 113, - 111, 110, 107, 105, 103, 102, 100, 98, 96, 94, - 92, 91, 89, 86, 86, 83, 82, 80, 77, 76, - 74, 73, 71, 69, 67, 66, 64, 63, 61, 59, - 57, 55, 54, 52, 51, 49, 47, 46, 44, 43, - 41, 40, 38, 36, 35, 33, 32, 30, 29, 27, - 25, 24, 22, 21, 19, 18, 16, 15, 13, 12, - 10, 9, 7, 6, 4, 3 -}; - -//------------------------------------------------------------------------------ -// Level cost tables - -// fixed costs for coding levels, deduce from the coding tree. -// This is only the part that doesn't depend on the probability state. -const uint16_t VP8LevelFixedCosts[MAX_LEVEL + 1] = { - 0, 256, 256, 256, 256, 432, 618, 630, - 731, 640, 640, 828, 901, 948, 1021, 1101, - 1174, 1221, 1294, 1042, 1085, 1115, 1158, 1202, - 1245, 1275, 1318, 1337, 1380, 1410, 1453, 1497, - 1540, 1570, 1613, 1280, 1295, 1317, 1332, 1358, - 1373, 1395, 1410, 1454, 1469, 1491, 1506, 1532, - 1547, 1569, 1584, 1601, 1616, 1638, 1653, 1679, - 1694, 1716, 1731, 1775, 1790, 1812, 1827, 1853, - 1868, 1890, 1905, 1727, 1733, 1742, 1748, 1759, - 1765, 1774, 1780, 1800, 1806, 1815, 1821, 1832, - 1838, 1847, 1853, 1878, 1884, 1893, 1899, 1910, - 1916, 1925, 1931, 1951, 1957, 1966, 1972, 1983, - 1989, 1998, 2004, 2027, 2033, 2042, 2048, 2059, - 2065, 2074, 2080, 2100, 2106, 2115, 2121, 2132, - 2138, 2147, 2153, 2178, 2184, 2193, 2199, 2210, - 2216, 2225, 2231, 2251, 2257, 2266, 2272, 2283, - 2289, 2298, 2304, 2168, 2174, 2183, 2189, 2200, - 2206, 2215, 2221, 2241, 2247, 2256, 2262, 2273, - 2279, 2288, 2294, 2319, 2325, 2334, 2340, 2351, - 2357, 2366, 2372, 2392, 2398, 2407, 2413, 2424, - 2430, 2439, 2445, 2468, 2474, 2483, 2489, 2500, - 2506, 2515, 2521, 2541, 2547, 2556, 2562, 2573, - 2579, 2588, 2594, 2619, 2625, 2634, 2640, 2651, - 2657, 2666, 2672, 2692, 2698, 2707, 2713, 2724, - 2730, 2739, 2745, 2540, 2546, 2555, 2561, 2572, - 2578, 2587, 2593, 2613, 2619, 2628, 2634, 2645, - 2651, 2660, 2666, 2691, 2697, 2706, 2712, 2723, - 2729, 2738, 2744, 2764, 2770, 2779, 2785, 2796, - 2802, 2811, 2817, 2840, 2846, 2855, 2861, 2872, - 2878, 2887, 2893, 2913, 2919, 2928, 2934, 2945, - 2951, 2960, 2966, 2991, 2997, 3006, 3012, 3023, - 3029, 3038, 3044, 3064, 3070, 3079, 3085, 3096, - 3102, 3111, 3117, 2981, 2987, 2996, 3002, 3013, - 3019, 3028, 3034, 3054, 3060, 3069, 3075, 3086, - 3092, 3101, 3107, 3132, 3138, 3147, 3153, 3164, - 3170, 3179, 3185, 3205, 3211, 3220, 3226, 3237, - 3243, 3252, 3258, 3281, 3287, 3296, 3302, 3313, - 3319, 3328, 3334, 3354, 3360, 3369, 3375, 3386, - 3392, 3401, 3407, 3432, 3438, 3447, 3453, 3464, - 3470, 3479, 3485, 3505, 3511, 3520, 3526, 3537, - 3543, 3552, 3558, 2816, 2822, 2831, 2837, 2848, - 2854, 2863, 2869, 2889, 2895, 2904, 2910, 2921, - 2927, 2936, 2942, 2967, 2973, 2982, 2988, 2999, - 3005, 3014, 3020, 3040, 3046, 3055, 3061, 3072, - 3078, 3087, 3093, 3116, 3122, 3131, 3137, 3148, - 3154, 3163, 3169, 3189, 3195, 3204, 3210, 3221, - 3227, 3236, 3242, 3267, 3273, 3282, 3288, 3299, - 3305, 3314, 3320, 3340, 3346, 3355, 3361, 3372, - 3378, 3387, 3393, 3257, 3263, 3272, 3278, 3289, - 3295, 3304, 3310, 3330, 3336, 3345, 3351, 3362, - 3368, 3377, 3383, 3408, 3414, 3423, 3429, 3440, - 3446, 3455, 3461, 3481, 3487, 3496, 3502, 3513, - 3519, 3528, 3534, 3557, 3563, 3572, 3578, 3589, - 3595, 3604, 3610, 3630, 3636, 3645, 3651, 3662, - 3668, 3677, 3683, 3708, 3714, 3723, 3729, 3740, - 3746, 3755, 3761, 3781, 3787, 3796, 3802, 3813, - 3819, 3828, 3834, 3629, 3635, 3644, 3650, 3661, - 3667, 3676, 3682, 3702, 3708, 3717, 3723, 3734, - 3740, 3749, 3755, 3780, 3786, 3795, 3801, 3812, - 3818, 3827, 3833, 3853, 3859, 3868, 3874, 3885, - 3891, 3900, 3906, 3929, 3935, 3944, 3950, 3961, - 3967, 3976, 3982, 4002, 4008, 4017, 4023, 4034, - 4040, 4049, 4055, 4080, 4086, 4095, 4101, 4112, - 4118, 4127, 4133, 4153, 4159, 4168, 4174, 4185, - 4191, 4200, 4206, 4070, 4076, 4085, 4091, 4102, - 4108, 4117, 4123, 4143, 4149, 4158, 4164, 4175, - 4181, 4190, 4196, 4221, 4227, 4236, 4242, 4253, - 4259, 4268, 4274, 4294, 4300, 4309, 4315, 4326, - 4332, 4341, 4347, 4370, 4376, 4385, 4391, 4402, - 4408, 4417, 4423, 4443, 4449, 4458, 4464, 4475, - 4481, 4490, 4496, 4521, 4527, 4536, 4542, 4553, - 4559, 4568, 4574, 4594, 4600, 4609, 4615, 4626, - 4632, 4641, 4647, 3515, 3521, 3530, 3536, 3547, - 3553, 3562, 3568, 3588, 3594, 3603, 3609, 3620, - 3626, 3635, 3641, 3666, 3672, 3681, 3687, 3698, - 3704, 3713, 3719, 3739, 3745, 3754, 3760, 3771, - 3777, 3786, 3792, 3815, 3821, 3830, 3836, 3847, - 3853, 3862, 3868, 3888, 3894, 3903, 3909, 3920, - 3926, 3935, 3941, 3966, 3972, 3981, 3987, 3998, - 4004, 4013, 4019, 4039, 4045, 4054, 4060, 4071, - 4077, 4086, 4092, 3956, 3962, 3971, 3977, 3988, - 3994, 4003, 4009, 4029, 4035, 4044, 4050, 4061, - 4067, 4076, 4082, 4107, 4113, 4122, 4128, 4139, - 4145, 4154, 4160, 4180, 4186, 4195, 4201, 4212, - 4218, 4227, 4233, 4256, 4262, 4271, 4277, 4288, - 4294, 4303, 4309, 4329, 4335, 4344, 4350, 4361, - 4367, 4376, 4382, 4407, 4413, 4422, 4428, 4439, - 4445, 4454, 4460, 4480, 4486, 4495, 4501, 4512, - 4518, 4527, 4533, 4328, 4334, 4343, 4349, 4360, - 4366, 4375, 4381, 4401, 4407, 4416, 4422, 4433, - 4439, 4448, 4454, 4479, 4485, 4494, 4500, 4511, - 4517, 4526, 4532, 4552, 4558, 4567, 4573, 4584, - 4590, 4599, 4605, 4628, 4634, 4643, 4649, 4660, - 4666, 4675, 4681, 4701, 4707, 4716, 4722, 4733, - 4739, 4748, 4754, 4779, 4785, 4794, 4800, 4811, - 4817, 4826, 4832, 4852, 4858, 4867, 4873, 4884, - 4890, 4899, 4905, 4769, 4775, 4784, 4790, 4801, - 4807, 4816, 4822, 4842, 4848, 4857, 4863, 4874, - 4880, 4889, 4895, 4920, 4926, 4935, 4941, 4952, - 4958, 4967, 4973, 4993, 4999, 5008, 5014, 5025, - 5031, 5040, 5046, 5069, 5075, 5084, 5090, 5101, - 5107, 5116, 5122, 5142, 5148, 5157, 5163, 5174, - 5180, 5189, 5195, 5220, 5226, 5235, 5241, 5252, - 5258, 5267, 5273, 5293, 5299, 5308, 5314, 5325, - 5331, 5340, 5346, 4604, 4610, 4619, 4625, 4636, - 4642, 4651, 4657, 4677, 4683, 4692, 4698, 4709, - 4715, 4724, 4730, 4755, 4761, 4770, 4776, 4787, - 4793, 4802, 4808, 4828, 4834, 4843, 4849, 4860, - 4866, 4875, 4881, 4904, 4910, 4919, 4925, 4936, - 4942, 4951, 4957, 4977, 4983, 4992, 4998, 5009, - 5015, 5024, 5030, 5055, 5061, 5070, 5076, 5087, - 5093, 5102, 5108, 5128, 5134, 5143, 5149, 5160, - 5166, 5175, 5181, 5045, 5051, 5060, 5066, 5077, - 5083, 5092, 5098, 5118, 5124, 5133, 5139, 5150, - 5156, 5165, 5171, 5196, 5202, 5211, 5217, 5228, - 5234, 5243, 5249, 5269, 5275, 5284, 5290, 5301, - 5307, 5316, 5322, 5345, 5351, 5360, 5366, 5377, - 5383, 5392, 5398, 5418, 5424, 5433, 5439, 5450, - 5456, 5465, 5471, 5496, 5502, 5511, 5517, 5528, - 5534, 5543, 5549, 5569, 5575, 5584, 5590, 5601, - 5607, 5616, 5622, 5417, 5423, 5432, 5438, 5449, - 5455, 5464, 5470, 5490, 5496, 5505, 5511, 5522, - 5528, 5537, 5543, 5568, 5574, 5583, 5589, 5600, - 5606, 5615, 5621, 5641, 5647, 5656, 5662, 5673, - 5679, 5688, 5694, 5717, 5723, 5732, 5738, 5749, - 5755, 5764, 5770, 5790, 5796, 5805, 5811, 5822, - 5828, 5837, 5843, 5868, 5874, 5883, 5889, 5900, - 5906, 5915, 5921, 5941, 5947, 5956, 5962, 5973, - 5979, 5988, 5994, 5858, 5864, 5873, 5879, 5890, - 5896, 5905, 5911, 5931, 5937, 5946, 5952, 5963, - 5969, 5978, 5984, 6009, 6015, 6024, 6030, 6041, - 6047, 6056, 6062, 6082, 6088, 6097, 6103, 6114, - 6120, 6129, 6135, 6158, 6164, 6173, 6179, 6190, - 6196, 6205, 6211, 6231, 6237, 6246, 6252, 6263, - 6269, 6278, 6284, 6309, 6315, 6324, 6330, 6341, - 6347, 6356, 6362, 6382, 6388, 6397, 6403, 6414, - 6420, 6429, 6435, 3515, 3521, 3530, 3536, 3547, - 3553, 3562, 3568, 3588, 3594, 3603, 3609, 3620, - 3626, 3635, 3641, 3666, 3672, 3681, 3687, 3698, - 3704, 3713, 3719, 3739, 3745, 3754, 3760, 3771, - 3777, 3786, 3792, 3815, 3821, 3830, 3836, 3847, - 3853, 3862, 3868, 3888, 3894, 3903, 3909, 3920, - 3926, 3935, 3941, 3966, 3972, 3981, 3987, 3998, - 4004, 4013, 4019, 4039, 4045, 4054, 4060, 4071, - 4077, 4086, 4092, 3956, 3962, 3971, 3977, 3988, - 3994, 4003, 4009, 4029, 4035, 4044, 4050, 4061, - 4067, 4076, 4082, 4107, 4113, 4122, 4128, 4139, - 4145, 4154, 4160, 4180, 4186, 4195, 4201, 4212, - 4218, 4227, 4233, 4256, 4262, 4271, 4277, 4288, - 4294, 4303, 4309, 4329, 4335, 4344, 4350, 4361, - 4367, 4376, 4382, 4407, 4413, 4422, 4428, 4439, - 4445, 4454, 4460, 4480, 4486, 4495, 4501, 4512, - 4518, 4527, 4533, 4328, 4334, 4343, 4349, 4360, - 4366, 4375, 4381, 4401, 4407, 4416, 4422, 4433, - 4439, 4448, 4454, 4479, 4485, 4494, 4500, 4511, - 4517, 4526, 4532, 4552, 4558, 4567, 4573, 4584, - 4590, 4599, 4605, 4628, 4634, 4643, 4649, 4660, - 4666, 4675, 4681, 4701, 4707, 4716, 4722, 4733, - 4739, 4748, 4754, 4779, 4785, 4794, 4800, 4811, - 4817, 4826, 4832, 4852, 4858, 4867, 4873, 4884, - 4890, 4899, 4905, 4769, 4775, 4784, 4790, 4801, - 4807, 4816, 4822, 4842, 4848, 4857, 4863, 4874, - 4880, 4889, 4895, 4920, 4926, 4935, 4941, 4952, - 4958, 4967, 4973, 4993, 4999, 5008, 5014, 5025, - 5031, 5040, 5046, 5069, 5075, 5084, 5090, 5101, - 5107, 5116, 5122, 5142, 5148, 5157, 5163, 5174, - 5180, 5189, 5195, 5220, 5226, 5235, 5241, 5252, - 5258, 5267, 5273, 5293, 5299, 5308, 5314, 5325, - 5331, 5340, 5346, 4604, 4610, 4619, 4625, 4636, - 4642, 4651, 4657, 4677, 4683, 4692, 4698, 4709, - 4715, 4724, 4730, 4755, 4761, 4770, 4776, 4787, - 4793, 4802, 4808, 4828, 4834, 4843, 4849, 4860, - 4866, 4875, 4881, 4904, 4910, 4919, 4925, 4936, - 4942, 4951, 4957, 4977, 4983, 4992, 4998, 5009, - 5015, 5024, 5030, 5055, 5061, 5070, 5076, 5087, - 5093, 5102, 5108, 5128, 5134, 5143, 5149, 5160, - 5166, 5175, 5181, 5045, 5051, 5060, 5066, 5077, - 5083, 5092, 5098, 5118, 5124, 5133, 5139, 5150, - 5156, 5165, 5171, 5196, 5202, 5211, 5217, 5228, - 5234, 5243, 5249, 5269, 5275, 5284, 5290, 5301, - 5307, 5316, 5322, 5345, 5351, 5360, 5366, 5377, - 5383, 5392, 5398, 5418, 5424, 5433, 5439, 5450, - 5456, 5465, 5471, 5496, 5502, 5511, 5517, 5528, - 5534, 5543, 5549, 5569, 5575, 5584, 5590, 5601, - 5607, 5616, 5622, 5417, 5423, 5432, 5438, 5449, - 5455, 5464, 5470, 5490, 5496, 5505, 5511, 5522, - 5528, 5537, 5543, 5568, 5574, 5583, 5589, 5600, - 5606, 5615, 5621, 5641, 5647, 5656, 5662, 5673, - 5679, 5688, 5694, 5717, 5723, 5732, 5738, 5749, - 5755, 5764, 5770, 5790, 5796, 5805, 5811, 5822, - 5828, 5837, 5843, 5868, 5874, 5883, 5889, 5900, - 5906, 5915, 5921, 5941, 5947, 5956, 5962, 5973, - 5979, 5988, 5994, 5858, 5864, 5873, 5879, 5890, - 5896, 5905, 5911, 5931, 5937, 5946, 5952, 5963, - 5969, 5978, 5984, 6009, 6015, 6024, 6030, 6041, - 6047, 6056, 6062, 6082, 6088, 6097, 6103, 6114, - 6120, 6129, 6135, 6158, 6164, 6173, 6179, 6190, - 6196, 6205, 6211, 6231, 6237, 6246, 6252, 6263, - 6269, 6278, 6284, 6309, 6315, 6324, 6330, 6341, - 6347, 6356, 6362, 6382, 6388, 6397, 6403, 6414, - 6420, 6429, 6435, 5303, 5309, 5318, 5324, 5335, - 5341, 5350, 5356, 5376, 5382, 5391, 5397, 5408, - 5414, 5423, 5429, 5454, 5460, 5469, 5475, 5486, - 5492, 5501, 5507, 5527, 5533, 5542, 5548, 5559, - 5565, 5574, 5580, 5603, 5609, 5618, 5624, 5635, - 5641, 5650, 5656, 5676, 5682, 5691, 5697, 5708, - 5714, 5723, 5729, 5754, 5760, 5769, 5775, 5786, - 5792, 5801, 5807, 5827, 5833, 5842, 5848, 5859, - 5865, 5874, 5880, 5744, 5750, 5759, 5765, 5776, - 5782, 5791, 5797, 5817, 5823, 5832, 5838, 5849, - 5855, 5864, 5870, 5895, 5901, 5910, 5916, 5927, - 5933, 5942, 5948, 5968, 5974, 5983, 5989, 6000, - 6006, 6015, 6021, 6044, 6050, 6059, 6065, 6076, - 6082, 6091, 6097, 6117, 6123, 6132, 6138, 6149, - 6155, 6164, 6170, 6195, 6201, 6210, 6216, 6227, - 6233, 6242, 6248, 6268, 6274, 6283, 6289, 6300, - 6306, 6315, 6321, 6116, 6122, 6131, 6137, 6148, - 6154, 6163, 6169, 6189, 6195, 6204, 6210, 6221, - 6227, 6236, 6242, 6267, 6273, 6282, 6288, 6299, - 6305, 6314, 6320, 6340, 6346, 6355, 6361, 6372, - 6378, 6387, 6393, 6416, 6422, 6431, 6437, 6448, - 6454, 6463, 6469, 6489, 6495, 6504, 6510, 6521, - 6527, 6536, 6542, 6567, 6573, 6582, 6588, 6599, - 6605, 6614, 6620, 6640, 6646, 6655, 6661, 6672, - 6678, 6687, 6693, 6557, 6563, 6572, 6578, 6589, - 6595, 6604, 6610, 6630, 6636, 6645, 6651, 6662, - 6668, 6677, 6683, 6708, 6714, 6723, 6729, 6740, - 6746, 6755, 6761, 6781, 6787, 6796, 6802, 6813, - 6819, 6828, 6834, 6857, 6863, 6872, 6878, 6889, - 6895, 6904, 6910, 6930, 6936, 6945, 6951, 6962, - 6968, 6977, 6983, 7008, 7014, 7023, 7029, 7040, - 7046, 7055, 7061, 7081, 7087, 7096, 7102, 7113, - 7119, 7128, 7134, 6392, 6398, 6407, 6413, 6424, - 6430, 6439, 6445, 6465, 6471, 6480, 6486, 6497, - 6503, 6512, 6518, 6543, 6549, 6558, 6564, 6575, - 6581, 6590, 6596, 6616, 6622, 6631, 6637, 6648, - 6654, 6663, 6669, 6692, 6698, 6707, 6713, 6724, - 6730, 6739, 6745, 6765, 6771, 6780, 6786, 6797, - 6803, 6812, 6818, 6843, 6849, 6858, 6864, 6875, - 6881, 6890, 6896, 6916, 6922, 6931, 6937, 6948, - 6954, 6963, 6969, 6833, 6839, 6848, 6854, 6865, - 6871, 6880, 6886, 6906, 6912, 6921, 6927, 6938, - 6944, 6953, 6959, 6984, 6990, 6999, 7005, 7016, - 7022, 7031, 7037, 7057, 7063, 7072, 7078, 7089, - 7095, 7104, 7110, 7133, 7139, 7148, 7154, 7165, - 7171, 7180, 7186, 7206, 7212, 7221, 7227, 7238, - 7244, 7253, 7259, 7284, 7290, 7299, 7305, 7316, - 7322, 7331, 7337, 7357, 7363, 7372, 7378, 7389, - 7395, 7404, 7410, 7205, 7211, 7220, 7226, 7237, - 7243, 7252, 7258, 7278, 7284, 7293, 7299, 7310, - 7316, 7325, 7331, 7356, 7362, 7371, 7377, 7388, - 7394, 7403, 7409, 7429, 7435, 7444, 7450, 7461, - 7467, 7476, 7482, 7505, 7511, 7520, 7526, 7537, - 7543, 7552, 7558, 7578, 7584, 7593, 7599, 7610, - 7616, 7625, 7631, 7656, 7662, 7671, 7677, 7688, - 7694, 7703, 7709, 7729, 7735, 7744, 7750, 7761 -}; - -//------------------------------------------------------------------------------ -// Tables for level coding - -const uint8_t VP8EncBands[16 + 1] = { - 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, - 0 // sentinel -}; - -//------------------------------------------------------------------------------ -// Mode costs - -static int GetResidualCost(int ctx0, const VP8Residual* const res) { - int n = res->first; - // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 - const int p0 = res->prob[n][ctx0][0]; - CostArrayPtr const costs = res->costs; - const uint16_t* t = costs[n][ctx0]; - // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0 - // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll - // be missing during the loop. - int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0; - - if (res->last < 0) { - return VP8BitCost(0, p0); - } - for (; n < res->last; ++n) { - const int v = abs(res->coeffs[n]); - const int ctx = (v >= 2) ? 2 : v; - cost += VP8LevelCost(t, v); - t = costs[n + 1][ctx]; - } - // Last coefficient is always non-zero - { - const int v = abs(res->coeffs[n]); - assert(v != 0); - cost += VP8LevelCost(t, v); - if (n < 15) { - const int b = VP8EncBands[n + 1]; - const int ctx = (v == 1) ? 1 : 2; - const int last_p0 = res->prob[b][ctx][0]; - cost += VP8BitCost(0, last_p0); - } - } - return cost; -} - -static void SetResidualCoeffs(const int16_t* const coeffs, - VP8Residual* const res) { - int n; - res->last = -1; - assert(res->first == 0 || coeffs[0] == 0); - for (n = 15; n >= 0; --n) { - if (coeffs[n]) { - res->last = n; - break; - } - } - res->coeffs = coeffs; -} - -//------------------------------------------------------------------------------ -// init function - -VP8GetResidualCostFunc VP8GetResidualCost; -VP8SetResidualCoeffsFunc VP8SetResidualCoeffs; - -extern void VP8EncDspCostInitMIPS32(void); -extern void VP8EncDspCostInitMIPSdspR2(void); -extern void VP8EncDspCostInitSSE2(void); - -static volatile VP8CPUInfo cost_last_cpuinfo_used = - (VP8CPUInfo)&cost_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInit(void) { - if (cost_last_cpuinfo_used == VP8GetCPUInfo) return; - - VP8GetResidualCost = GetResidualCost; - VP8SetResidualCoeffs = SetResidualCoeffs; - - // If defined, use CPUInfo() to overwrite some pointers with faster versions. - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_MIPS32) - if (VP8GetCPUInfo(kMIPS32)) { - VP8EncDspCostInitMIPS32(); - } -#endif -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - VP8EncDspCostInitMIPSdspR2(); - } -#endif -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - VP8EncDspCostInitSSE2(); - } -#endif - } - - cost_last_cpuinfo_used = VP8GetCPUInfo; -} - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/dsp/cost_mips32.c b/Example-Mac/Pods/libwebp/src/dsp/cost_mips32.c deleted file mode 100644 index d1e240e1..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/cost_mips32.c +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Djordje Pesut (djordje.pesut@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS32) - -#include "../enc/cost.h" - -static int GetResidualCost(int ctx0, const VP8Residual* const res) { - int temp0, temp1; - int v_reg, ctx_reg; - int n = res->first; - // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 - int p0 = res->prob[n][ctx0][0]; - CostArrayPtr const costs = res->costs; - const uint16_t* t = costs[n][ctx0]; - // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0 - // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll - // be missing during the loop. - int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0; - const int16_t* res_coeffs = res->coeffs; - const int res_last = res->last; - const int const_max_level = MAX_VARIABLE_LEVEL; - const int const_2 = 2; - const uint16_t** p_costs = &costs[n][0]; - const size_t inc_p_costs = NUM_CTX * sizeof(*p_costs); - - if (res->last < 0) { - return VP8BitCost(0, p0); - } - - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "subu %[temp1], %[res_last], %[n] \n\t" - "sll %[temp0], %[n], 1 \n\t" - "blez %[temp1], 2f \n\t" - " addu %[res_coeffs], %[res_coeffs], %[temp0] \n\t" - "1: \n\t" - "lh %[v_reg], 0(%[res_coeffs]) \n\t" - "addiu %[n], %[n], 1 \n\t" - "negu %[temp0], %[v_reg] \n\t" - "slti %[temp1], %[v_reg], 0 \n\t" - "movn %[v_reg], %[temp0], %[temp1] \n\t" - "sltiu %[temp0], %[v_reg], 2 \n\t" - "move %[ctx_reg], %[v_reg] \n\t" - "movz %[ctx_reg], %[const_2], %[temp0] \n\t" - "sll %[temp1], %[v_reg], 1 \n\t" - "addu %[temp1], %[temp1], %[VP8LevelFixedCosts] \n\t" - "lhu %[temp1], 0(%[temp1]) \n\t" - "slt %[temp0], %[v_reg], %[const_max_level] \n\t" - "movz %[v_reg], %[const_max_level], %[temp0] \n\t" - "addu %[cost], %[cost], %[temp1] \n\t" - "sll %[v_reg], %[v_reg], 1 \n\t" - "sll %[ctx_reg], %[ctx_reg], 2 \n\t" - "addu %[v_reg], %[v_reg], %[t] \n\t" - "lhu %[temp0], 0(%[v_reg]) \n\t" - "addu %[p_costs], %[p_costs], %[inc_p_costs] \n\t" - "addu %[t], %[p_costs], %[ctx_reg] \n\t" - "addu %[cost], %[cost], %[temp0] \n\t" - "addiu %[res_coeffs], %[res_coeffs], 2 \n\t" - "bne %[n], %[res_last], 1b \n\t" - " lw %[t], 0(%[t]) \n\t" - "2: \n\t" - ".set pop \n\t" - : [cost]"+&r"(cost), [t]"+&r"(t), [n]"+&r"(n), [v_reg]"=&r"(v_reg), - [ctx_reg]"=&r"(ctx_reg), [p_costs]"+&r"(p_costs), [temp0]"=&r"(temp0), - [temp1]"=&r"(temp1), [res_coeffs]"+&r"(res_coeffs) - : [const_2]"r"(const_2), [const_max_level]"r"(const_max_level), - [VP8LevelFixedCosts]"r"(VP8LevelFixedCosts), [res_last]"r"(res_last), - [inc_p_costs]"r"(inc_p_costs) - : "memory" - ); - - // Last coefficient is always non-zero - { - const int v = abs(res->coeffs[n]); - assert(v != 0); - cost += VP8LevelCost(t, v); - if (n < 15) { - const int b = VP8EncBands[n + 1]; - const int ctx = (v == 1) ? 1 : 2; - const int last_p0 = res->prob[b][ctx][0]; - cost += VP8BitCost(0, last_p0); - } - } - return cost; -} - -static void SetResidualCoeffs(const int16_t* const coeffs, - VP8Residual* const res) { - const int16_t* p_coeffs = (int16_t*)coeffs; - int temp0, temp1, temp2, n, n1; - assert(res->first == 0 || coeffs[0] == 0); - - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "addiu %[p_coeffs], %[p_coeffs], 28 \n\t" - "li %[n], 15 \n\t" - "li %[temp2], -1 \n\t" - "0: \n\t" - "ulw %[temp0], 0(%[p_coeffs]) \n\t" - "beqz %[temp0], 1f \n\t" -#if defined(WORDS_BIGENDIAN) - " sll %[temp1], %[temp0], 16 \n\t" -#else - " srl %[temp1], %[temp0], 16 \n\t" -#endif - "addiu %[n1], %[n], -1 \n\t" - "movz %[temp0], %[n1], %[temp1] \n\t" - "movn %[temp0], %[n], %[temp1] \n\t" - "j 2f \n\t" - " addiu %[temp2], %[temp0], 0 \n\t" - "1: \n\t" - "addiu %[n], %[n], -2 \n\t" - "bgtz %[n], 0b \n\t" - " addiu %[p_coeffs], %[p_coeffs], -4 \n\t" - "2: \n\t" - ".set pop \n\t" - : [p_coeffs]"+&r"(p_coeffs), [temp0]"=&r"(temp0), - [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [n]"=&r"(n), [n1]"=&r"(n1) - : - : "memory" - ); - res->last = temp2; - res->coeffs = coeffs; -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8EncDspCostInitMIPS32(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitMIPS32(void) { - VP8GetResidualCost = GetResidualCost; - VP8SetResidualCoeffs = SetResidualCoeffs; -} - -#else // !WEBP_USE_MIPS32 - -WEBP_DSP_INIT_STUB(VP8EncDspCostInitMIPS32) - -#endif // WEBP_USE_MIPS32 diff --git a/Example-Mac/Pods/libwebp/src/dsp/cost_mips_dsp_r2.c b/Example-Mac/Pods/libwebp/src/dsp/cost_mips_dsp_r2.c deleted file mode 100644 index ce640677..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/cost_mips_dsp_r2.c +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Djordje Pesut (djordje.pesut@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS_DSP_R2) - -#include "../enc/cost.h" - -static int GetResidualCost(int ctx0, const VP8Residual* const res) { - int temp0, temp1; - int v_reg, ctx_reg; - int n = res->first; - // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 - int p0 = res->prob[n][ctx0][0]; - CostArrayPtr const costs = res->costs; - const uint16_t* t = costs[n][ctx0]; - // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0 - // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll - // be missing during the loop. - int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0; - const int16_t* res_coeffs = res->coeffs; - const int res_last = res->last; - const int const_max_level = MAX_VARIABLE_LEVEL; - const int const_2 = 2; - const uint16_t** p_costs = &costs[n][0]; - const size_t inc_p_costs = NUM_CTX * sizeof(*p_costs); - - if (res->last < 0) { - return VP8BitCost(0, p0); - } - - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "subu %[temp1], %[res_last], %[n] \n\t" - "blez %[temp1], 2f \n\t" - " nop \n\t" - "1: \n\t" - "sll %[temp0], %[n], 1 \n\t" - "lhx %[v_reg], %[temp0](%[res_coeffs]) \n\t" - "addiu %[n], %[n], 1 \n\t" - "absq_s.w %[v_reg], %[v_reg] \n\t" - "sltiu %[temp0], %[v_reg], 2 \n\t" - "move %[ctx_reg], %[v_reg] \n\t" - "movz %[ctx_reg], %[const_2], %[temp0] \n\t" - "sll %[temp1], %[v_reg], 1 \n\t" - "lhx %[temp1], %[temp1](%[VP8LevelFixedCosts]) \n\t" - "slt %[temp0], %[v_reg], %[const_max_level] \n\t" - "movz %[v_reg], %[const_max_level], %[temp0] \n\t" - "addu %[cost], %[cost], %[temp1] \n\t" - "sll %[v_reg], %[v_reg], 1 \n\t" - "sll %[ctx_reg], %[ctx_reg], 2 \n\t" - "lhx %[temp0], %[v_reg](%[t]) \n\t" - "addu %[p_costs], %[p_costs], %[inc_p_costs] \n\t" - "addu %[t], %[p_costs], %[ctx_reg] \n\t" - "addu %[cost], %[cost], %[temp0] \n\t" - "bne %[n], %[res_last], 1b \n\t" - " lw %[t], 0(%[t]) \n\t" - "2: \n\t" - ".set pop \n\t" - : [cost]"+&r"(cost), [t]"+&r"(t), [n]"+&r"(n), [v_reg]"=&r"(v_reg), - [ctx_reg]"=&r"(ctx_reg), [p_costs]"+&r"(p_costs), [temp0]"=&r"(temp0), - [temp1]"=&r"(temp1) - : [const_2]"r"(const_2), [const_max_level]"r"(const_max_level), - [VP8LevelFixedCosts]"r"(VP8LevelFixedCosts), [res_last]"r"(res_last), - [res_coeffs]"r"(res_coeffs), [inc_p_costs]"r"(inc_p_costs) - : "memory" - ); - - // Last coefficient is always non-zero - { - const int v = abs(res->coeffs[n]); - assert(v != 0); - cost += VP8LevelCost(t, v); - if (n < 15) { - const int b = VP8EncBands[n + 1]; - const int ctx = (v == 1) ? 1 : 2; - const int last_p0 = res->prob[b][ctx][0]; - cost += VP8BitCost(0, last_p0); - } - } - return cost; -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8EncDspCostInitMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitMIPSdspR2(void) { - VP8GetResidualCost = GetResidualCost; -} - -#else // !WEBP_USE_MIPS_DSP_R2 - -WEBP_DSP_INIT_STUB(VP8EncDspCostInitMIPSdspR2) - -#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/Example-Mac/Pods/libwebp/src/dsp/cost_sse2.c b/Example-Mac/Pods/libwebp/src/dsp/cost_sse2.c deleted file mode 100644 index 0cb1c1fa..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/cost_sse2.c +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// SSE2 version of cost functions -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE2) -#include - -#include "../enc/cost.h" -#include "../enc/vp8enci.h" -#include "../utils/utils.h" - -//------------------------------------------------------------------------------ - -static void SetResidualCoeffsSSE2(const int16_t* const coeffs, - VP8Residual* const res) { - const __m128i c0 = _mm_loadu_si128((const __m128i*)(coeffs + 0)); - const __m128i c1 = _mm_loadu_si128((const __m128i*)(coeffs + 8)); - // Use SSE2 to compare 16 values with a single instruction. - const __m128i zero = _mm_setzero_si128(); - const __m128i m0 = _mm_packs_epi16(c0, c1); - const __m128i m1 = _mm_cmpeq_epi8(m0, zero); - // Get the comparison results as a bitmask into 16bits. Negate the mask to get - // the position of entries that are not equal to zero. We don't need to mask - // out least significant bits according to res->first, since coeffs[0] is 0 - // if res->first > 0. - const uint32_t mask = 0x0000ffffu ^ (uint32_t)_mm_movemask_epi8(m1); - // The position of the most significant non-zero bit indicates the position of - // the last non-zero value. - assert(res->first == 0 || coeffs[0] == 0); - res->last = mask ? BitsLog2Floor(mask) : -1; - res->coeffs = coeffs; -} - -static int GetResidualCostSSE2(int ctx0, const VP8Residual* const res) { - uint8_t levels[16], ctxs[16]; - uint16_t abs_levels[16]; - int n = res->first; - // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 - const int p0 = res->prob[n][ctx0][0]; - CostArrayPtr const costs = res->costs; - const uint16_t* t = costs[n][ctx0]; - // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0 - // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll - // be missing during the loop. - int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0; - - if (res->last < 0) { - return VP8BitCost(0, p0); - } - - { // precompute clamped levels and contexts, packed to 8b. - const __m128i zero = _mm_setzero_si128(); - const __m128i kCst2 = _mm_set1_epi8(2); - const __m128i kCst67 = _mm_set1_epi8(MAX_VARIABLE_LEVEL); - const __m128i c0 = _mm_loadu_si128((const __m128i*)&res->coeffs[0]); - const __m128i c1 = _mm_loadu_si128((const __m128i*)&res->coeffs[8]); - const __m128i D0 = _mm_sub_epi16(zero, c0); - const __m128i D1 = _mm_sub_epi16(zero, c1); - const __m128i E0 = _mm_max_epi16(c0, D0); // abs(v), 16b - const __m128i E1 = _mm_max_epi16(c1, D1); - const __m128i F = _mm_packs_epi16(E0, E1); - const __m128i G = _mm_min_epu8(F, kCst2); // context = 0,1,2 - const __m128i H = _mm_min_epu8(F, kCst67); // clamp_level in [0..67] - - _mm_storeu_si128((__m128i*)&ctxs[0], G); - _mm_storeu_si128((__m128i*)&levels[0], H); - - _mm_storeu_si128((__m128i*)&abs_levels[0], E0); - _mm_storeu_si128((__m128i*)&abs_levels[8], E1); - } - for (; n < res->last; ++n) { - const int ctx = ctxs[n]; - const int level = levels[n]; - const int flevel = abs_levels[n]; // full level - cost += VP8LevelFixedCosts[flevel] + t[level]; // simplified VP8LevelCost() - t = costs[n + 1][ctx]; - } - // Last coefficient is always non-zero - { - const int level = levels[n]; - const int flevel = abs_levels[n]; - assert(flevel != 0); - cost += VP8LevelFixedCosts[flevel] + t[level]; - if (n < 15) { - const int b = VP8EncBands[n + 1]; - const int ctx = ctxs[n]; - const int last_p0 = res->prob[b][ctx][0]; - cost += VP8BitCost(0, last_p0); - } - } - return cost; -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8EncDspCostInitSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitSSE2(void) { - VP8SetResidualCoeffs = SetResidualCoeffsSSE2; - VP8GetResidualCost = GetResidualCostSSE2; -} - -#else // !WEBP_USE_SSE2 - -WEBP_DSP_INIT_STUB(VP8EncDspCostInitSSE2) - -#endif // WEBP_USE_SSE2 diff --git a/Example-Mac/Pods/libwebp/src/dsp/cpu.c b/Example-Mac/Pods/libwebp/src/dsp/cpu.c deleted file mode 100644 index 8844cb40..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/cpu.c +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// CPU detection -// -// Author: Christian Duvivier (cduvivier@google.com) - -#include "./dsp.h" - -#if defined(WEBP_ANDROID_NEON) -#include -#endif - -//------------------------------------------------------------------------------ -// SSE2 detection. -// - -// apple/darwin gcc-4.0.1 defines __PIC__, but not __pic__ with -fPIC. -#if (defined(__pic__) || defined(__PIC__)) && defined(__i386__) -static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { - __asm__ volatile ( - "mov %%ebx, %%edi\n" - "cpuid\n" - "xchg %%edi, %%ebx\n" - : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) - : "a"(info_type), "c"(0)); -} -#elif defined(__x86_64__) && \ - (defined(__code_model_medium__) || defined(__code_model_large__)) && \ - defined(__PIC__) -static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { - __asm__ volatile ( - "xchg{q}\t{%%rbx}, %q1\n" - "cpuid\n" - "xchg{q}\t{%%rbx}, %q1\n" - : "=a"(cpu_info[0]), "=&r"(cpu_info[1]), "=c"(cpu_info[2]), - "=d"(cpu_info[3]) - : "a"(info_type), "c"(0)); -} -#elif defined(__i386__) || defined(__x86_64__) -static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { - __asm__ volatile ( - "cpuid\n" - : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) - : "a"(info_type), "c"(0)); -} -#elif (defined(_M_X64) || defined(_M_IX86)) && \ - defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 150030729 // >= VS2008 SP1 -#include -#define GetCPUInfo(info, type) __cpuidex(info, type, 0) // set ecx=0 -#elif defined(WEBP_MSC_SSE2) -#define GetCPUInfo __cpuid -#endif - -// NaCl has no support for xgetbv or the raw opcode. -#if !defined(__native_client__) && (defined(__i386__) || defined(__x86_64__)) -static WEBP_INLINE uint64_t xgetbv(void) { - const uint32_t ecx = 0; - uint32_t eax, edx; - // Use the raw opcode for xgetbv for compatibility with older toolchains. - __asm__ volatile ( - ".byte 0x0f, 0x01, 0xd0\n" - : "=a"(eax), "=d"(edx) : "c" (ecx)); - return ((uint64_t)edx << 32) | eax; -} -#elif (defined(_M_X64) || defined(_M_IX86)) && \ - defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219 // >= VS2010 SP1 -#include -#define xgetbv() _xgetbv(0) -#elif defined(_MSC_VER) && defined(_M_IX86) -static WEBP_INLINE uint64_t xgetbv(void) { - uint32_t eax_, edx_; - __asm { - xor ecx, ecx // ecx = 0 - // Use the raw opcode for xgetbv for compatibility with older toolchains. - __asm _emit 0x0f __asm _emit 0x01 __asm _emit 0xd0 - mov eax_, eax - mov edx_, edx - } - return ((uint64_t)edx_ << 32) | eax_; -} -#else -#define xgetbv() 0U // no AVX for older x64 or unrecognized toolchains. -#endif - -#if defined(__i386__) || defined(__x86_64__) || defined(WEBP_MSC_SSE2) -static int x86CPUInfo(CPUFeature feature) { - int max_cpuid_value; - int cpu_info[4]; - - // get the highest feature value cpuid supports - GetCPUInfo(cpu_info, 0); - max_cpuid_value = cpu_info[0]; - if (max_cpuid_value < 1) { - return 0; - } - - GetCPUInfo(cpu_info, 1); - if (feature == kSSE2) { - return 0 != (cpu_info[3] & 0x04000000); - } - if (feature == kSSE3) { - return 0 != (cpu_info[2] & 0x00000001); - } - if (feature == kSSE4_1) { - return 0 != (cpu_info[2] & 0x00080000); - } - if (feature == kAVX) { - // bits 27 (OSXSAVE) & 28 (256-bit AVX) - if ((cpu_info[2] & 0x18000000) == 0x18000000) { - // XMM state and YMM state enabled by the OS. - return (xgetbv() & 0x6) == 0x6; - } - } - if (feature == kAVX2) { - if (x86CPUInfo(kAVX) && max_cpuid_value >= 7) { - GetCPUInfo(cpu_info, 7); - return ((cpu_info[1] & 0x00000020) == 0x00000020); - } - } - return 0; -} -VP8CPUInfo VP8GetCPUInfo = x86CPUInfo; -#elif defined(WEBP_ANDROID_NEON) // NB: needs to be before generic NEON test. -static int AndroidCPUInfo(CPUFeature feature) { - const AndroidCpuFamily cpu_family = android_getCpuFamily(); - const uint64_t cpu_features = android_getCpuFeatures(); - if (feature == kNEON) { - return (cpu_family == ANDROID_CPU_FAMILY_ARM && - 0 != (cpu_features & ANDROID_CPU_ARM_FEATURE_NEON)); - } - return 0; -} -VP8CPUInfo VP8GetCPUInfo = AndroidCPUInfo; -#elif defined(WEBP_USE_NEON) -// define a dummy function to enable turning off NEON at runtime by setting -// VP8DecGetCPUInfo = NULL -static int armCPUInfo(CPUFeature feature) { - (void)feature; - return 1; -} -VP8CPUInfo VP8GetCPUInfo = armCPUInfo; -#elif defined(WEBP_USE_MIPS32) || defined(WEBP_USE_MIPS_DSP_R2) -static int mipsCPUInfo(CPUFeature feature) { - if ((feature == kMIPS32) || (feature == kMIPSdspR2)) { - return 1; - } else { - return 0; - } - -} -VP8CPUInfo VP8GetCPUInfo = mipsCPUInfo; -#else -VP8CPUInfo VP8GetCPUInfo = NULL; -#endif - diff --git a/Example-Mac/Pods/libwebp/src/dsp/dec.c b/Example-Mac/Pods/libwebp/src/dsp/dec.c deleted file mode 100644 index a7872064..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/dec.c +++ /dev/null @@ -1,766 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Speed-critical decoding functions, default plain-C implementations. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" -#include "../dec/vp8i.h" - -//------------------------------------------------------------------------------ - -static WEBP_INLINE uint8_t clip_8b(int v) { - return (!(v & ~0xff)) ? v : (v < 0) ? 0 : 255; -} - -//------------------------------------------------------------------------------ -// Transforms (Paragraph 14.4) - -#define STORE(x, y, v) \ - dst[x + y * BPS] = clip_8b(dst[x + y * BPS] + ((v) >> 3)) - -#define STORE2(y, dc, d, c) do { \ - const int DC = (dc); \ - STORE(0, y, DC + (d)); \ - STORE(1, y, DC + (c)); \ - STORE(2, y, DC - (c)); \ - STORE(3, y, DC - (d)); \ -} while (0) - -#define MUL1(a) ((((a) * 20091) >> 16) + (a)) -#define MUL2(a) (((a) * 35468) >> 16) - -static void TransformOne(const int16_t* in, uint8_t* dst) { - int C[4 * 4], *tmp; - int i; - tmp = C; - for (i = 0; i < 4; ++i) { // vertical pass - const int a = in[0] + in[8]; // [-4096, 4094] - const int b = in[0] - in[8]; // [-4095, 4095] - const int c = MUL2(in[4]) - MUL1(in[12]); // [-3783, 3783] - const int d = MUL1(in[4]) + MUL2(in[12]); // [-3785, 3781] - tmp[0] = a + d; // [-7881, 7875] - tmp[1] = b + c; // [-7878, 7878] - tmp[2] = b - c; // [-7878, 7878] - tmp[3] = a - d; // [-7877, 7879] - tmp += 4; - in++; - } - // Each pass is expanding the dynamic range by ~3.85 (upper bound). - // The exact value is (2. + (20091 + 35468) / 65536). - // After the second pass, maximum interval is [-3794, 3794], assuming - // an input in [-2048, 2047] interval. We then need to add a dst value - // in the [0, 255] range. - // In the worst case scenario, the input to clip_8b() can be as large as - // [-60713, 60968]. - tmp = C; - for (i = 0; i < 4; ++i) { // horizontal pass - const int dc = tmp[0] + 4; - const int a = dc + tmp[8]; - const int b = dc - tmp[8]; - const int c = MUL2(tmp[4]) - MUL1(tmp[12]); - const int d = MUL1(tmp[4]) + MUL2(tmp[12]); - STORE(0, 0, a + d); - STORE(1, 0, b + c); - STORE(2, 0, b - c); - STORE(3, 0, a - d); - tmp++; - dst += BPS; - } -} - -// Simplified transform when only in[0], in[1] and in[4] are non-zero -static void TransformAC3(const int16_t* in, uint8_t* dst) { - const int a = in[0] + 4; - const int c4 = MUL2(in[4]); - const int d4 = MUL1(in[4]); - const int c1 = MUL2(in[1]); - const int d1 = MUL1(in[1]); - STORE2(0, a + d4, d1, c1); - STORE2(1, a + c4, d1, c1); - STORE2(2, a - c4, d1, c1); - STORE2(3, a - d4, d1, c1); -} -#undef MUL1 -#undef MUL2 -#undef STORE2 - -static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) { - TransformOne(in, dst); - if (do_two) { - TransformOne(in + 16, dst + 4); - } -} - -static void TransformUV(const int16_t* in, uint8_t* dst) { - VP8Transform(in + 0 * 16, dst, 1); - VP8Transform(in + 2 * 16, dst + 4 * BPS, 1); -} - -static void TransformDC(const int16_t* in, uint8_t* dst) { - const int DC = in[0] + 4; - int i, j; - for (j = 0; j < 4; ++j) { - for (i = 0; i < 4; ++i) { - STORE(i, j, DC); - } - } -} - -static void TransformDCUV(const int16_t* in, uint8_t* dst) { - if (in[0 * 16]) VP8TransformDC(in + 0 * 16, dst); - if (in[1 * 16]) VP8TransformDC(in + 1 * 16, dst + 4); - if (in[2 * 16]) VP8TransformDC(in + 2 * 16, dst + 4 * BPS); - if (in[3 * 16]) VP8TransformDC(in + 3 * 16, dst + 4 * BPS + 4); -} - -#undef STORE - -//------------------------------------------------------------------------------ -// Paragraph 14.3 - -static void TransformWHT(const int16_t* in, int16_t* out) { - int tmp[16]; - int i; - for (i = 0; i < 4; ++i) { - const int a0 = in[0 + i] + in[12 + i]; - const int a1 = in[4 + i] + in[ 8 + i]; - const int a2 = in[4 + i] - in[ 8 + i]; - const int a3 = in[0 + i] - in[12 + i]; - tmp[0 + i] = a0 + a1; - tmp[8 + i] = a0 - a1; - tmp[4 + i] = a3 + a2; - tmp[12 + i] = a3 - a2; - } - for (i = 0; i < 4; ++i) { - const int dc = tmp[0 + i * 4] + 3; // w/ rounder - const int a0 = dc + tmp[3 + i * 4]; - const int a1 = tmp[1 + i * 4] + tmp[2 + i * 4]; - const int a2 = tmp[1 + i * 4] - tmp[2 + i * 4]; - const int a3 = dc - tmp[3 + i * 4]; - out[ 0] = (a0 + a1) >> 3; - out[16] = (a3 + a2) >> 3; - out[32] = (a0 - a1) >> 3; - out[48] = (a3 - a2) >> 3; - out += 64; - } -} - -void (*VP8TransformWHT)(const int16_t* in, int16_t* out); - -//------------------------------------------------------------------------------ -// Intra predictions - -#define DST(x, y) dst[(x) + (y) * BPS] - -static WEBP_INLINE void TrueMotion(uint8_t* dst, int size) { - const uint8_t* top = dst - BPS; - const uint8_t* const clip0 = VP8kclip1 - top[-1]; - int y; - for (y = 0; y < size; ++y) { - const uint8_t* const clip = clip0 + dst[-1]; - int x; - for (x = 0; x < size; ++x) { - dst[x] = clip[top[x]]; - } - dst += BPS; - } -} -static void TM4(uint8_t* dst) { TrueMotion(dst, 4); } -static void TM8uv(uint8_t* dst) { TrueMotion(dst, 8); } -static void TM16(uint8_t* dst) { TrueMotion(dst, 16); } - -//------------------------------------------------------------------------------ -// 16x16 - -static void VE16(uint8_t* dst) { // vertical - int j; - for (j = 0; j < 16; ++j) { - memcpy(dst + j * BPS, dst - BPS, 16); - } -} - -static void HE16(uint8_t* dst) { // horizontal - int j; - for (j = 16; j > 0; --j) { - memset(dst, dst[-1], 16); - dst += BPS; - } -} - -static WEBP_INLINE void Put16(int v, uint8_t* dst) { - int j; - for (j = 0; j < 16; ++j) { - memset(dst + j * BPS, v, 16); - } -} - -static void DC16(uint8_t* dst) { // DC - int DC = 16; - int j; - for (j = 0; j < 16; ++j) { - DC += dst[-1 + j * BPS] + dst[j - BPS]; - } - Put16(DC >> 5, dst); -} - -static void DC16NoTop(uint8_t* dst) { // DC with top samples not available - int DC = 8; - int j; - for (j = 0; j < 16; ++j) { - DC += dst[-1 + j * BPS]; - } - Put16(DC >> 4, dst); -} - -static void DC16NoLeft(uint8_t* dst) { // DC with left samples not available - int DC = 8; - int i; - for (i = 0; i < 16; ++i) { - DC += dst[i - BPS]; - } - Put16(DC >> 4, dst); -} - -static void DC16NoTopLeft(uint8_t* dst) { // DC with no top and left samples - Put16(0x80, dst); -} - -VP8PredFunc VP8PredLuma16[NUM_B_DC_MODES]; - -//------------------------------------------------------------------------------ -// 4x4 - -#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2) -#define AVG2(a, b) (((a) + (b) + 1) >> 1) - -static void VE4(uint8_t* dst) { // vertical - const uint8_t* top = dst - BPS; - const uint8_t vals[4] = { - AVG3(top[-1], top[0], top[1]), - AVG3(top[ 0], top[1], top[2]), - AVG3(top[ 1], top[2], top[3]), - AVG3(top[ 2], top[3], top[4]) - }; - int i; - for (i = 0; i < 4; ++i) { - memcpy(dst + i * BPS, vals, sizeof(vals)); - } -} - -static void HE4(uint8_t* dst) { // horizontal - const int A = dst[-1 - BPS]; - const int B = dst[-1]; - const int C = dst[-1 + BPS]; - const int D = dst[-1 + 2 * BPS]; - const int E = dst[-1 + 3 * BPS]; - WebPUint32ToMem(dst + 0 * BPS, 0x01010101U * AVG3(A, B, C)); - WebPUint32ToMem(dst + 1 * BPS, 0x01010101U * AVG3(B, C, D)); - WebPUint32ToMem(dst + 2 * BPS, 0x01010101U * AVG3(C, D, E)); - WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(D, E, E)); -} - -static void DC4(uint8_t* dst) { // DC - uint32_t dc = 4; - int i; - for (i = 0; i < 4; ++i) dc += dst[i - BPS] + dst[-1 + i * BPS]; - dc >>= 3; - for (i = 0; i < 4; ++i) memset(dst + i * BPS, dc, 4); -} - -static void RD4(uint8_t* dst) { // Down-right - const int I = dst[-1 + 0 * BPS]; - const int J = dst[-1 + 1 * BPS]; - const int K = dst[-1 + 2 * BPS]; - const int L = dst[-1 + 3 * BPS]; - const int X = dst[-1 - BPS]; - const int A = dst[0 - BPS]; - const int B = dst[1 - BPS]; - const int C = dst[2 - BPS]; - const int D = dst[3 - BPS]; - DST(0, 3) = AVG3(J, K, L); - DST(1, 3) = DST(0, 2) = AVG3(I, J, K); - DST(2, 3) = DST(1, 2) = DST(0, 1) = AVG3(X, I, J); - DST(3, 3) = DST(2, 2) = DST(1, 1) = DST(0, 0) = AVG3(A, X, I); - DST(3, 2) = DST(2, 1) = DST(1, 0) = AVG3(B, A, X); - DST(3, 1) = DST(2, 0) = AVG3(C, B, A); - DST(3, 0) = AVG3(D, C, B); -} - -static void LD4(uint8_t* dst) { // Down-Left - const int A = dst[0 - BPS]; - const int B = dst[1 - BPS]; - const int C = dst[2 - BPS]; - const int D = dst[3 - BPS]; - const int E = dst[4 - BPS]; - const int F = dst[5 - BPS]; - const int G = dst[6 - BPS]; - const int H = dst[7 - BPS]; - DST(0, 0) = AVG3(A, B, C); - DST(1, 0) = DST(0, 1) = AVG3(B, C, D); - DST(2, 0) = DST(1, 1) = DST(0, 2) = AVG3(C, D, E); - DST(3, 0) = DST(2, 1) = DST(1, 2) = DST(0, 3) = AVG3(D, E, F); - DST(3, 1) = DST(2, 2) = DST(1, 3) = AVG3(E, F, G); - DST(3, 2) = DST(2, 3) = AVG3(F, G, H); - DST(3, 3) = AVG3(G, H, H); -} - -static void VR4(uint8_t* dst) { // Vertical-Right - const int I = dst[-1 + 0 * BPS]; - const int J = dst[-1 + 1 * BPS]; - const int K = dst[-1 + 2 * BPS]; - const int X = dst[-1 - BPS]; - const int A = dst[0 - BPS]; - const int B = dst[1 - BPS]; - const int C = dst[2 - BPS]; - const int D = dst[3 - BPS]; - DST(0, 0) = DST(1, 2) = AVG2(X, A); - DST(1, 0) = DST(2, 2) = AVG2(A, B); - DST(2, 0) = DST(3, 2) = AVG2(B, C); - DST(3, 0) = AVG2(C, D); - - DST(0, 3) = AVG3(K, J, I); - DST(0, 2) = AVG3(J, I, X); - DST(0, 1) = DST(1, 3) = AVG3(I, X, A); - DST(1, 1) = DST(2, 3) = AVG3(X, A, B); - DST(2, 1) = DST(3, 3) = AVG3(A, B, C); - DST(3, 1) = AVG3(B, C, D); -} - -static void VL4(uint8_t* dst) { // Vertical-Left - const int A = dst[0 - BPS]; - const int B = dst[1 - BPS]; - const int C = dst[2 - BPS]; - const int D = dst[3 - BPS]; - const int E = dst[4 - BPS]; - const int F = dst[5 - BPS]; - const int G = dst[6 - BPS]; - const int H = dst[7 - BPS]; - DST(0, 0) = AVG2(A, B); - DST(1, 0) = DST(0, 2) = AVG2(B, C); - DST(2, 0) = DST(1, 2) = AVG2(C, D); - DST(3, 0) = DST(2, 2) = AVG2(D, E); - - DST(0, 1) = AVG3(A, B, C); - DST(1, 1) = DST(0, 3) = AVG3(B, C, D); - DST(2, 1) = DST(1, 3) = AVG3(C, D, E); - DST(3, 1) = DST(2, 3) = AVG3(D, E, F); - DST(3, 2) = AVG3(E, F, G); - DST(3, 3) = AVG3(F, G, H); -} - -static void HU4(uint8_t* dst) { // Horizontal-Up - const int I = dst[-1 + 0 * BPS]; - const int J = dst[-1 + 1 * BPS]; - const int K = dst[-1 + 2 * BPS]; - const int L = dst[-1 + 3 * BPS]; - DST(0, 0) = AVG2(I, J); - DST(2, 0) = DST(0, 1) = AVG2(J, K); - DST(2, 1) = DST(0, 2) = AVG2(K, L); - DST(1, 0) = AVG3(I, J, K); - DST(3, 0) = DST(1, 1) = AVG3(J, K, L); - DST(3, 1) = DST(1, 2) = AVG3(K, L, L); - DST(3, 2) = DST(2, 2) = - DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L; -} - -static void HD4(uint8_t* dst) { // Horizontal-Down - const int I = dst[-1 + 0 * BPS]; - const int J = dst[-1 + 1 * BPS]; - const int K = dst[-1 + 2 * BPS]; - const int L = dst[-1 + 3 * BPS]; - const int X = dst[-1 - BPS]; - const int A = dst[0 - BPS]; - const int B = dst[1 - BPS]; - const int C = dst[2 - BPS]; - - DST(0, 0) = DST(2, 1) = AVG2(I, X); - DST(0, 1) = DST(2, 2) = AVG2(J, I); - DST(0, 2) = DST(2, 3) = AVG2(K, J); - DST(0, 3) = AVG2(L, K); - - DST(3, 0) = AVG3(A, B, C); - DST(2, 0) = AVG3(X, A, B); - DST(1, 0) = DST(3, 1) = AVG3(I, X, A); - DST(1, 1) = DST(3, 2) = AVG3(J, I, X); - DST(1, 2) = DST(3, 3) = AVG3(K, J, I); - DST(1, 3) = AVG3(L, K, J); -} - -#undef DST -#undef AVG3 -#undef AVG2 - -VP8PredFunc VP8PredLuma4[NUM_BMODES]; - -//------------------------------------------------------------------------------ -// Chroma - -static void VE8uv(uint8_t* dst) { // vertical - int j; - for (j = 0; j < 8; ++j) { - memcpy(dst + j * BPS, dst - BPS, 8); - } -} - -static void HE8uv(uint8_t* dst) { // horizontal - int j; - for (j = 0; j < 8; ++j) { - memset(dst, dst[-1], 8); - dst += BPS; - } -} - -// helper for chroma-DC predictions -static WEBP_INLINE void Put8x8uv(uint8_t value, uint8_t* dst) { - int j; - for (j = 0; j < 8; ++j) { - memset(dst + j * BPS, value, 8); - } -} - -static void DC8uv(uint8_t* dst) { // DC - int dc0 = 8; - int i; - for (i = 0; i < 8; ++i) { - dc0 += dst[i - BPS] + dst[-1 + i * BPS]; - } - Put8x8uv(dc0 >> 4, dst); -} - -static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples - int dc0 = 4; - int i; - for (i = 0; i < 8; ++i) { - dc0 += dst[i - BPS]; - } - Put8x8uv(dc0 >> 3, dst); -} - -static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples - int dc0 = 4; - int i; - for (i = 0; i < 8; ++i) { - dc0 += dst[-1 + i * BPS]; - } - Put8x8uv(dc0 >> 3, dst); -} - -static void DC8uvNoTopLeft(uint8_t* dst) { // DC with nothing - Put8x8uv(0x80, dst); -} - -VP8PredFunc VP8PredChroma8[NUM_B_DC_MODES]; - -//------------------------------------------------------------------------------ -// Edge filtering functions - -// 4 pixels in, 2 pixels out -static WEBP_INLINE void do_filter2(uint8_t* p, int step) { - const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step]; - const int a = 3 * (q0 - p0) + VP8ksclip1[p1 - q1]; // in [-893,892] - const int a1 = VP8ksclip2[(a + 4) >> 3]; // in [-16,15] - const int a2 = VP8ksclip2[(a + 3) >> 3]; - p[-step] = VP8kclip1[p0 + a2]; - p[ 0] = VP8kclip1[q0 - a1]; -} - -// 4 pixels in, 4 pixels out -static WEBP_INLINE void do_filter4(uint8_t* p, int step) { - const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step]; - const int a = 3 * (q0 - p0); - const int a1 = VP8ksclip2[(a + 4) >> 3]; - const int a2 = VP8ksclip2[(a + 3) >> 3]; - const int a3 = (a1 + 1) >> 1; - p[-2*step] = VP8kclip1[p1 + a3]; - p[- step] = VP8kclip1[p0 + a2]; - p[ 0] = VP8kclip1[q0 - a1]; - p[ step] = VP8kclip1[q1 - a3]; -} - -// 6 pixels in, 6 pixels out -static WEBP_INLINE void do_filter6(uint8_t* p, int step) { - const int p2 = p[-3*step], p1 = p[-2*step], p0 = p[-step]; - const int q0 = p[0], q1 = p[step], q2 = p[2*step]; - const int a = VP8ksclip1[3 * (q0 - p0) + VP8ksclip1[p1 - q1]]; - // a is in [-128,127], a1 in [-27,27], a2 in [-18,18] and a3 in [-9,9] - const int a1 = (27 * a + 63) >> 7; // eq. to ((3 * a + 7) * 9) >> 7 - const int a2 = (18 * a + 63) >> 7; // eq. to ((2 * a + 7) * 9) >> 7 - const int a3 = (9 * a + 63) >> 7; // eq. to ((1 * a + 7) * 9) >> 7 - p[-3*step] = VP8kclip1[p2 + a3]; - p[-2*step] = VP8kclip1[p1 + a2]; - p[- step] = VP8kclip1[p0 + a1]; - p[ 0] = VP8kclip1[q0 - a1]; - p[ step] = VP8kclip1[q1 - a2]; - p[ 2*step] = VP8kclip1[q2 - a3]; -} - -static WEBP_INLINE int hev(const uint8_t* p, int step, int thresh) { - const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step]; - return (VP8kabs0[p1 - p0] > thresh) || (VP8kabs0[q1 - q0] > thresh); -} - -static WEBP_INLINE int needs_filter(const uint8_t* p, int step, int t) { - const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step]; - return ((4 * VP8kabs0[p0 - q0] + VP8kabs0[p1 - q1]) <= t); -} - -static WEBP_INLINE int needs_filter2(const uint8_t* p, - int step, int t, int it) { - const int p3 = p[-4 * step], p2 = p[-3 * step], p1 = p[-2 * step]; - const int p0 = p[-step], q0 = p[0]; - const int q1 = p[step], q2 = p[2 * step], q3 = p[3 * step]; - if ((4 * VP8kabs0[p0 - q0] + VP8kabs0[p1 - q1]) > t) return 0; - return VP8kabs0[p3 - p2] <= it && VP8kabs0[p2 - p1] <= it && - VP8kabs0[p1 - p0] <= it && VP8kabs0[q3 - q2] <= it && - VP8kabs0[q2 - q1] <= it && VP8kabs0[q1 - q0] <= it; -} - -//------------------------------------------------------------------------------ -// Simple In-loop filtering (Paragraph 15.2) - -static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { - int i; - const int thresh2 = 2 * thresh + 1; - for (i = 0; i < 16; ++i) { - if (needs_filter(p + i, stride, thresh2)) { - do_filter2(p + i, stride); - } - } -} - -static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { - int i; - const int thresh2 = 2 * thresh + 1; - for (i = 0; i < 16; ++i) { - if (needs_filter(p + i * stride, 1, thresh2)) { - do_filter2(p + i * stride, 1); - } - } -} - -static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4 * stride; - SimpleVFilter16(p, stride, thresh); - } -} - -static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4; - SimpleHFilter16(p, stride, thresh); - } -} - -//------------------------------------------------------------------------------ -// Complex In-loop filtering (Paragraph 15.3) - -static WEBP_INLINE void FilterLoop26(uint8_t* p, - int hstride, int vstride, int size, - int thresh, int ithresh, int hev_thresh) { - const int thresh2 = 2 * thresh + 1; - while (size-- > 0) { - if (needs_filter2(p, hstride, thresh2, ithresh)) { - if (hev(p, hstride, hev_thresh)) { - do_filter2(p, hstride); - } else { - do_filter6(p, hstride); - } - } - p += vstride; - } -} - -static WEBP_INLINE void FilterLoop24(uint8_t* p, - int hstride, int vstride, int size, - int thresh, int ithresh, int hev_thresh) { - const int thresh2 = 2 * thresh + 1; - while (size-- > 0) { - if (needs_filter2(p, hstride, thresh2, ithresh)) { - if (hev(p, hstride, hev_thresh)) { - do_filter2(p, hstride); - } else { - do_filter4(p, hstride); - } - } - p += vstride; - } -} - -// on macroblock edges -static void VFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh); -} - -static void HFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh); -} - -// on three inner edges -static void VFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4 * stride; - FilterLoop24(p, stride, 1, 16, thresh, ithresh, hev_thresh); - } -} - -static void HFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4; - FilterLoop24(p, 1, stride, 16, thresh, ithresh, hev_thresh); - } -} - -// 8-pixels wide variant, for chroma filtering -static void VFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(u, stride, 1, 8, thresh, ithresh, hev_thresh); - FilterLoop26(v, stride, 1, 8, thresh, ithresh, hev_thresh); -} - -static void HFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(u, 1, stride, 8, thresh, ithresh, hev_thresh); - FilterLoop26(v, 1, stride, 8, thresh, ithresh, hev_thresh); -} - -static void VFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop24(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); - FilterLoop24(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); -} - -static void HFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop24(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh); - FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh); -} - -//------------------------------------------------------------------------------ - -VP8DecIdct2 VP8Transform; -VP8DecIdct VP8TransformAC3; -VP8DecIdct VP8TransformUV; -VP8DecIdct VP8TransformDC; -VP8DecIdct VP8TransformDCUV; - -VP8LumaFilterFunc VP8VFilter16; -VP8LumaFilterFunc VP8HFilter16; -VP8ChromaFilterFunc VP8VFilter8; -VP8ChromaFilterFunc VP8HFilter8; -VP8LumaFilterFunc VP8VFilter16i; -VP8LumaFilterFunc VP8HFilter16i; -VP8ChromaFilterFunc VP8VFilter8i; -VP8ChromaFilterFunc VP8HFilter8i; -VP8SimpleFilterFunc VP8SimpleVFilter16; -VP8SimpleFilterFunc VP8SimpleHFilter16; -VP8SimpleFilterFunc VP8SimpleVFilter16i; -VP8SimpleFilterFunc VP8SimpleHFilter16i; - -extern void VP8DspInitSSE2(void); -extern void VP8DspInitSSE41(void); -extern void VP8DspInitNEON(void); -extern void VP8DspInitMIPS32(void); -extern void VP8DspInitMIPSdspR2(void); - -static volatile VP8CPUInfo dec_last_cpuinfo_used = - (VP8CPUInfo)&dec_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void VP8DspInit(void) { - if (dec_last_cpuinfo_used == VP8GetCPUInfo) return; - - VP8InitClipTables(); - - VP8TransformWHT = TransformWHT; - VP8Transform = TransformTwo; - VP8TransformUV = TransformUV; - VP8TransformDC = TransformDC; - VP8TransformDCUV = TransformDCUV; - VP8TransformAC3 = TransformAC3; - - VP8VFilter16 = VFilter16; - VP8HFilter16 = HFilter16; - VP8VFilter8 = VFilter8; - VP8HFilter8 = HFilter8; - VP8VFilter16i = VFilter16i; - VP8HFilter16i = HFilter16i; - VP8VFilter8i = VFilter8i; - VP8HFilter8i = HFilter8i; - VP8SimpleVFilter16 = SimpleVFilter16; - VP8SimpleHFilter16 = SimpleHFilter16; - VP8SimpleVFilter16i = SimpleVFilter16i; - VP8SimpleHFilter16i = SimpleHFilter16i; - - VP8PredLuma4[0] = DC4; - VP8PredLuma4[1] = TM4; - VP8PredLuma4[2] = VE4; - VP8PredLuma4[3] = HE4; - VP8PredLuma4[4] = RD4; - VP8PredLuma4[5] = VR4; - VP8PredLuma4[6] = LD4; - VP8PredLuma4[7] = VL4; - VP8PredLuma4[8] = HD4; - VP8PredLuma4[9] = HU4; - - VP8PredLuma16[0] = DC16; - VP8PredLuma16[1] = TM16; - VP8PredLuma16[2] = VE16; - VP8PredLuma16[3] = HE16; - VP8PredLuma16[4] = DC16NoTop; - VP8PredLuma16[5] = DC16NoLeft; - VP8PredLuma16[6] = DC16NoTopLeft; - - VP8PredChroma8[0] = DC8uv; - VP8PredChroma8[1] = TM8uv; - VP8PredChroma8[2] = VE8uv; - VP8PredChroma8[3] = HE8uv; - VP8PredChroma8[4] = DC8uvNoTop; - VP8PredChroma8[5] = DC8uvNoLeft; - VP8PredChroma8[6] = DC8uvNoTopLeft; - - // If defined, use CPUInfo() to overwrite some pointers with faster versions. - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - VP8DspInitSSE2(); -#if defined(WEBP_USE_SSE41) - if (VP8GetCPUInfo(kSSE4_1)) { - VP8DspInitSSE41(); - } -#endif - } -#endif -#if defined(WEBP_USE_NEON) - if (VP8GetCPUInfo(kNEON)) { - VP8DspInitNEON(); - } -#endif -#if defined(WEBP_USE_MIPS32) - if (VP8GetCPUInfo(kMIPS32)) { - VP8DspInitMIPS32(); - } -#endif -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - VP8DspInitMIPSdspR2(); - } -#endif - } - dec_last_cpuinfo_used = VP8GetCPUInfo; -} diff --git a/Example-Mac/Pods/libwebp/src/dsp/dec_clip_tables.c b/Example-Mac/Pods/libwebp/src/dsp/dec_clip_tables.c deleted file mode 100644 index 3b6dde86..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/dec_clip_tables.c +++ /dev/null @@ -1,366 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Clipping tables for filtering -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#define USE_STATIC_TABLES // undefine to have run-time table initialization - -#ifdef USE_STATIC_TABLES - -static const uint8_t abs0[255 + 255 + 1] = { - 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, - 0xf3, 0xf2, 0xf1, 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8, - 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde, 0xdd, 0xdc, - 0xdb, 0xda, 0xd9, 0xd8, 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0, - 0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5, 0xc4, - 0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, - 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf, 0xae, 0xad, 0xac, - 0xab, 0xaa, 0xa9, 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0, - 0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, - 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, - 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7e, 0x7d, 0x7c, - 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, - 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, - 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, - 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, 0x4c, - 0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, - 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, - 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, - 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, - 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, - 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, - 0x03, 0x02, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, - 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, - 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, - 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, - 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, - 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, - 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, - 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, - 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, - 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, - 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, - 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, - 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, - 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, - 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, - 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff -}; - -static const int8_t sclip1[1020 + 1020 + 1] = { - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, - 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, - 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, - 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, - 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, - 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, - 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, - 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, - 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, - 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, - 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f -}; - -static const int8_t sclip2[112 + 112 + 1] = { - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, - 0xfc, 0xfd, 0xfe, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f -}; - -static const uint8_t clip1[255 + 511 + 1] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, - 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, - 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, - 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, - 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, - 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, - 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, - 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, - 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, - 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, - 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, - 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, - 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, - 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, - 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, - 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff -}; - -#else - -// uninitialized tables -static uint8_t abs0[255 + 255 + 1]; -static int8_t sclip1[1020 + 1020 + 1]; -static int8_t sclip2[112 + 112 + 1]; -static uint8_t clip1[255 + 511 + 1]; - -// We declare this variable 'volatile' to prevent instruction reordering -// and make sure it's set to true _last_ (so as to be thread-safe) -static volatile int tables_ok = 0; - -#endif - -const int8_t* const VP8ksclip1 = &sclip1[1020]; -const int8_t* const VP8ksclip2 = &sclip2[112]; -const uint8_t* const VP8kclip1 = &clip1[255]; -const uint8_t* const VP8kabs0 = &abs0[255]; - -WEBP_TSAN_IGNORE_FUNCTION void VP8InitClipTables(void) { -#if !defined(USE_STATIC_TABLES) - int i; - if (!tables_ok) { - for (i = -255; i <= 255; ++i) { - abs0[255 + i] = (i < 0) ? -i : i; - } - for (i = -1020; i <= 1020; ++i) { - sclip1[1020 + i] = (i < -128) ? -128 : (i > 127) ? 127 : i; - } - for (i = -112; i <= 112; ++i) { - sclip2[112 + i] = (i < -16) ? -16 : (i > 15) ? 15 : i; - } - for (i = -255; i <= 255 + 255; ++i) { - clip1[255 + i] = (i < 0) ? 0 : (i > 255) ? 255 : i; - } - tables_ok = 1; - } -#endif // USE_STATIC_TABLES -} diff --git a/Example-Mac/Pods/libwebp/src/dsp/dec_mips32.c b/Example-Mac/Pods/libwebp/src/dsp/dec_mips32.c deleted file mode 100644 index 4e9ef426..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/dec_mips32.c +++ /dev/null @@ -1,587 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// MIPS version of dsp functions -// -// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) -// Jovan Zelincevic (jovan.zelincevic@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS32) - -#include "./mips_macro.h" - -static const int kC1 = 20091 + (1 << 16); -static const int kC2 = 35468; - -static WEBP_INLINE int abs_mips32(int x) { - const int sign = x >> 31; - return (x ^ sign) - sign; -} - -// 4 pixels in, 2 pixels out -static WEBP_INLINE void do_filter2(uint8_t* p, int step) { - const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step]; - const int a = 3 * (q0 - p0) + VP8ksclip1[p1 - q1]; - const int a1 = VP8ksclip2[(a + 4) >> 3]; - const int a2 = VP8ksclip2[(a + 3) >> 3]; - p[-step] = VP8kclip1[p0 + a2]; - p[ 0] = VP8kclip1[q0 - a1]; -} - -// 4 pixels in, 4 pixels out -static WEBP_INLINE void do_filter4(uint8_t* p, int step) { - const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step]; - const int a = 3 * (q0 - p0); - const int a1 = VP8ksclip2[(a + 4) >> 3]; - const int a2 = VP8ksclip2[(a + 3) >> 3]; - const int a3 = (a1 + 1) >> 1; - p[-2 * step] = VP8kclip1[p1 + a3]; - p[- step] = VP8kclip1[p0 + a2]; - p[ 0] = VP8kclip1[q0 - a1]; - p[ step] = VP8kclip1[q1 - a3]; -} - -// 6 pixels in, 6 pixels out -static WEBP_INLINE void do_filter6(uint8_t* p, int step) { - const int p2 = p[-3 * step], p1 = p[-2 * step], p0 = p[-step]; - const int q0 = p[0], q1 = p[step], q2 = p[2 * step]; - const int a = VP8ksclip1[3 * (q0 - p0) + VP8ksclip1[p1 - q1]]; - // a is in [-128,127], a1 in [-27,27], a2 in [-18,18] and a3 in [-9,9] - const int a1 = (27 * a + 63) >> 7; // eq. to ((3 * a + 7) * 9) >> 7 - const int a2 = (18 * a + 63) >> 7; // eq. to ((2 * a + 7) * 9) >> 7 - const int a3 = (9 * a + 63) >> 7; // eq. to ((1 * a + 7) * 9) >> 7 - p[-3 * step] = VP8kclip1[p2 + a3]; - p[-2 * step] = VP8kclip1[p1 + a2]; - p[- step] = VP8kclip1[p0 + a1]; - p[ 0] = VP8kclip1[q0 - a1]; - p[ step] = VP8kclip1[q1 - a2]; - p[ 2 * step] = VP8kclip1[q2 - a3]; -} - -static WEBP_INLINE int hev(const uint8_t* p, int step, int thresh) { - const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step]; - return (abs_mips32(p1 - p0) > thresh) || (abs_mips32(q1 - q0) > thresh); -} - -static WEBP_INLINE int needs_filter(const uint8_t* p, int step, int t) { - const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step]; - return ((4 * abs_mips32(p0 - q0) + abs_mips32(p1 - q1)) <= t); -} - -static WEBP_INLINE int needs_filter2(const uint8_t* p, - int step, int t, int it) { - const int p3 = p[-4 * step], p2 = p[-3 * step]; - const int p1 = p[-2 * step], p0 = p[-step]; - const int q0 = p[0], q1 = p[step], q2 = p[2 * step], q3 = p[3 * step]; - if ((4 * abs_mips32(p0 - q0) + abs_mips32(p1 - q1)) > t) { - return 0; - } - return abs_mips32(p3 - p2) <= it && abs_mips32(p2 - p1) <= it && - abs_mips32(p1 - p0) <= it && abs_mips32(q3 - q2) <= it && - abs_mips32(q2 - q1) <= it && abs_mips32(q1 - q0) <= it; -} - -static WEBP_INLINE void FilterLoop26(uint8_t* p, - int hstride, int vstride, int size, - int thresh, int ithresh, int hev_thresh) { - const int thresh2 = 2 * thresh + 1; - while (size-- > 0) { - if (needs_filter2(p, hstride, thresh2, ithresh)) { - if (hev(p, hstride, hev_thresh)) { - do_filter2(p, hstride); - } else { - do_filter6(p, hstride); - } - } - p += vstride; - } -} - -static WEBP_INLINE void FilterLoop24(uint8_t* p, - int hstride, int vstride, int size, - int thresh, int ithresh, int hev_thresh) { - const int thresh2 = 2 * thresh + 1; - while (size-- > 0) { - if (needs_filter2(p, hstride, thresh2, ithresh)) { - if (hev(p, hstride, hev_thresh)) { - do_filter2(p, hstride); - } else { - do_filter4(p, hstride); - } - } - p += vstride; - } -} - -// on macroblock edges -static void VFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh); -} - -static void HFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh); -} - -// 8-pixels wide variant, for chroma filtering -static void VFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(u, stride, 1, 8, thresh, ithresh, hev_thresh); - FilterLoop26(v, stride, 1, 8, thresh, ithresh, hev_thresh); -} - -static void HFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(u, 1, stride, 8, thresh, ithresh, hev_thresh); - FilterLoop26(v, 1, stride, 8, thresh, ithresh, hev_thresh); -} - -static void VFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop24(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); - FilterLoop24(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); -} - -static void HFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop24(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh); - FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh); -} - -// on three inner edges -static void VFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4 * stride; - FilterLoop24(p, stride, 1, 16, thresh, ithresh, hev_thresh); - } -} - -static void HFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4; - FilterLoop24(p, 1, stride, 16, thresh, ithresh, hev_thresh); - } -} - -//------------------------------------------------------------------------------ -// Simple In-loop filtering (Paragraph 15.2) - -static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { - int i; - const int thresh2 = 2 * thresh + 1; - for (i = 0; i < 16; ++i) { - if (needs_filter(p + i, stride, thresh2)) { - do_filter2(p + i, stride); - } - } -} - -static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { - int i; - const int thresh2 = 2 * thresh + 1; - for (i = 0; i < 16; ++i) { - if (needs_filter(p + i * stride, 1, thresh2)) { - do_filter2(p + i * stride, 1); - } - } -} - -static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4 * stride; - SimpleVFilter16(p, stride, thresh); - } -} - -static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4; - SimpleHFilter16(p, stride, thresh); - } -} - -static void TransformOne(const int16_t* in, uint8_t* dst) { - int temp0, temp1, temp2, temp3, temp4; - int temp5, temp6, temp7, temp8, temp9; - int temp10, temp11, temp12, temp13, temp14; - int temp15, temp16, temp17, temp18; - int16_t* p_in = (int16_t*)in; - - // loops unrolled and merged to avoid usage of tmp buffer - // and to reduce number of stalls. MUL macro is written - // in assembler and inlined - __asm__ volatile( - "lh %[temp0], 0(%[in]) \n\t" - "lh %[temp8], 16(%[in]) \n\t" - "lh %[temp4], 8(%[in]) \n\t" - "lh %[temp12], 24(%[in]) \n\t" - "addu %[temp16], %[temp0], %[temp8] \n\t" - "subu %[temp0], %[temp0], %[temp8] \n\t" - "mul %[temp8], %[temp4], %[kC2] \n\t" - "mul %[temp17], %[temp12], %[kC1] \n\t" - "mul %[temp4], %[temp4], %[kC1] \n\t" - "mul %[temp12], %[temp12], %[kC2] \n\t" - "lh %[temp1], 2(%[in]) \n\t" - "lh %[temp5], 10(%[in]) \n\t" - "lh %[temp9], 18(%[in]) \n\t" - "lh %[temp13], 26(%[in]) \n\t" - "sra %[temp8], %[temp8], 16 \n\t" - "sra %[temp17], %[temp17], 16 \n\t" - "sra %[temp4], %[temp4], 16 \n\t" - "sra %[temp12], %[temp12], 16 \n\t" - "lh %[temp2], 4(%[in]) \n\t" - "lh %[temp6], 12(%[in]) \n\t" - "lh %[temp10], 20(%[in]) \n\t" - "lh %[temp14], 28(%[in]) \n\t" - "subu %[temp17], %[temp8], %[temp17] \n\t" - "addu %[temp4], %[temp4], %[temp12] \n\t" - "addu %[temp8], %[temp16], %[temp4] \n\t" - "subu %[temp4], %[temp16], %[temp4] \n\t" - "addu %[temp16], %[temp1], %[temp9] \n\t" - "subu %[temp1], %[temp1], %[temp9] \n\t" - "lh %[temp3], 6(%[in]) \n\t" - "lh %[temp7], 14(%[in]) \n\t" - "lh %[temp11], 22(%[in]) \n\t" - "lh %[temp15], 30(%[in]) \n\t" - "addu %[temp12], %[temp0], %[temp17] \n\t" - "subu %[temp0], %[temp0], %[temp17] \n\t" - "mul %[temp9], %[temp5], %[kC2] \n\t" - "mul %[temp17], %[temp13], %[kC1] \n\t" - "mul %[temp5], %[temp5], %[kC1] \n\t" - "mul %[temp13], %[temp13], %[kC2] \n\t" - "sra %[temp9], %[temp9], 16 \n\t" - "sra %[temp17], %[temp17], 16 \n\t" - "subu %[temp17], %[temp9], %[temp17] \n\t" - "sra %[temp5], %[temp5], 16 \n\t" - "sra %[temp13], %[temp13], 16 \n\t" - "addu %[temp5], %[temp5], %[temp13] \n\t" - "addu %[temp13], %[temp1], %[temp17] \n\t" - "subu %[temp1], %[temp1], %[temp17] \n\t" - "mul %[temp17], %[temp14], %[kC1] \n\t" - "mul %[temp14], %[temp14], %[kC2] \n\t" - "addu %[temp9], %[temp16], %[temp5] \n\t" - "subu %[temp5], %[temp16], %[temp5] \n\t" - "addu %[temp16], %[temp2], %[temp10] \n\t" - "subu %[temp2], %[temp2], %[temp10] \n\t" - "mul %[temp10], %[temp6], %[kC2] \n\t" - "mul %[temp6], %[temp6], %[kC1] \n\t" - "sra %[temp17], %[temp17], 16 \n\t" - "sra %[temp14], %[temp14], 16 \n\t" - "sra %[temp10], %[temp10], 16 \n\t" - "sra %[temp6], %[temp6], 16 \n\t" - "subu %[temp17], %[temp10], %[temp17] \n\t" - "addu %[temp6], %[temp6], %[temp14] \n\t" - "addu %[temp10], %[temp16], %[temp6] \n\t" - "subu %[temp6], %[temp16], %[temp6] \n\t" - "addu %[temp14], %[temp2], %[temp17] \n\t" - "subu %[temp2], %[temp2], %[temp17] \n\t" - "mul %[temp17], %[temp15], %[kC1] \n\t" - "mul %[temp15], %[temp15], %[kC2] \n\t" - "addu %[temp16], %[temp3], %[temp11] \n\t" - "subu %[temp3], %[temp3], %[temp11] \n\t" - "mul %[temp11], %[temp7], %[kC2] \n\t" - "mul %[temp7], %[temp7], %[kC1] \n\t" - "addiu %[temp8], %[temp8], 4 \n\t" - "addiu %[temp12], %[temp12], 4 \n\t" - "addiu %[temp0], %[temp0], 4 \n\t" - "addiu %[temp4], %[temp4], 4 \n\t" - "sra %[temp17], %[temp17], 16 \n\t" - "sra %[temp15], %[temp15], 16 \n\t" - "sra %[temp11], %[temp11], 16 \n\t" - "sra %[temp7], %[temp7], 16 \n\t" - "subu %[temp17], %[temp11], %[temp17] \n\t" - "addu %[temp7], %[temp7], %[temp15] \n\t" - "addu %[temp15], %[temp3], %[temp17] \n\t" - "subu %[temp3], %[temp3], %[temp17] \n\t" - "addu %[temp11], %[temp16], %[temp7] \n\t" - "subu %[temp7], %[temp16], %[temp7] \n\t" - "addu %[temp16], %[temp8], %[temp10] \n\t" - "subu %[temp8], %[temp8], %[temp10] \n\t" - "mul %[temp10], %[temp9], %[kC2] \n\t" - "mul %[temp17], %[temp11], %[kC1] \n\t" - "mul %[temp9], %[temp9], %[kC1] \n\t" - "mul %[temp11], %[temp11], %[kC2] \n\t" - "sra %[temp10], %[temp10], 16 \n\t" - "sra %[temp17], %[temp17], 16 \n\t" - "sra %[temp9], %[temp9], 16 \n\t" - "sra %[temp11], %[temp11], 16 \n\t" - "subu %[temp17], %[temp10], %[temp17] \n\t" - "addu %[temp11], %[temp9], %[temp11] \n\t" - "addu %[temp10], %[temp12], %[temp14] \n\t" - "subu %[temp12], %[temp12], %[temp14] \n\t" - "mul %[temp14], %[temp13], %[kC2] \n\t" - "mul %[temp9], %[temp15], %[kC1] \n\t" - "mul %[temp13], %[temp13], %[kC1] \n\t" - "mul %[temp15], %[temp15], %[kC2] \n\t" - "sra %[temp14], %[temp14], 16 \n\t" - "sra %[temp9], %[temp9], 16 \n\t" - "sra %[temp13], %[temp13], 16 \n\t" - "sra %[temp15], %[temp15], 16 \n\t" - "subu %[temp9], %[temp14], %[temp9] \n\t" - "addu %[temp15], %[temp13], %[temp15] \n\t" - "addu %[temp14], %[temp0], %[temp2] \n\t" - "subu %[temp0], %[temp0], %[temp2] \n\t" - "mul %[temp2], %[temp1], %[kC2] \n\t" - "mul %[temp13], %[temp3], %[kC1] \n\t" - "mul %[temp1], %[temp1], %[kC1] \n\t" - "mul %[temp3], %[temp3], %[kC2] \n\t" - "sra %[temp2], %[temp2], 16 \n\t" - "sra %[temp13], %[temp13], 16 \n\t" - "sra %[temp1], %[temp1], 16 \n\t" - "sra %[temp3], %[temp3], 16 \n\t" - "subu %[temp13], %[temp2], %[temp13] \n\t" - "addu %[temp3], %[temp1], %[temp3] \n\t" - "addu %[temp2], %[temp4], %[temp6] \n\t" - "subu %[temp4], %[temp4], %[temp6] \n\t" - "mul %[temp6], %[temp5], %[kC2] \n\t" - "mul %[temp1], %[temp7], %[kC1] \n\t" - "mul %[temp5], %[temp5], %[kC1] \n\t" - "mul %[temp7], %[temp7], %[kC2] \n\t" - "sra %[temp6], %[temp6], 16 \n\t" - "sra %[temp1], %[temp1], 16 \n\t" - "sra %[temp5], %[temp5], 16 \n\t" - "sra %[temp7], %[temp7], 16 \n\t" - "subu %[temp1], %[temp6], %[temp1] \n\t" - "addu %[temp7], %[temp5], %[temp7] \n\t" - "addu %[temp5], %[temp16], %[temp11] \n\t" - "subu %[temp16], %[temp16], %[temp11] \n\t" - "addu %[temp11], %[temp8], %[temp17] \n\t" - "subu %[temp8], %[temp8], %[temp17] \n\t" - "sra %[temp5], %[temp5], 3 \n\t" - "sra %[temp16], %[temp16], 3 \n\t" - "sra %[temp11], %[temp11], 3 \n\t" - "sra %[temp8], %[temp8], 3 \n\t" - "addu %[temp17], %[temp10], %[temp15] \n\t" - "subu %[temp10], %[temp10], %[temp15] \n\t" - "addu %[temp15], %[temp12], %[temp9] \n\t" - "subu %[temp12], %[temp12], %[temp9] \n\t" - "sra %[temp17], %[temp17], 3 \n\t" - "sra %[temp10], %[temp10], 3 \n\t" - "sra %[temp15], %[temp15], 3 \n\t" - "sra %[temp12], %[temp12], 3 \n\t" - "addu %[temp9], %[temp14], %[temp3] \n\t" - "subu %[temp14], %[temp14], %[temp3] \n\t" - "addu %[temp3], %[temp0], %[temp13] \n\t" - "subu %[temp0], %[temp0], %[temp13] \n\t" - "sra %[temp9], %[temp9], 3 \n\t" - "sra %[temp14], %[temp14], 3 \n\t" - "sra %[temp3], %[temp3], 3 \n\t" - "sra %[temp0], %[temp0], 3 \n\t" - "addu %[temp13], %[temp2], %[temp7] \n\t" - "subu %[temp2], %[temp2], %[temp7] \n\t" - "addu %[temp7], %[temp4], %[temp1] \n\t" - "subu %[temp4], %[temp4], %[temp1] \n\t" - "sra %[temp13], %[temp13], 3 \n\t" - "sra %[temp2], %[temp2], 3 \n\t" - "sra %[temp7], %[temp7], 3 \n\t" - "sra %[temp4], %[temp4], 3 \n\t" - "addiu %[temp6], $zero, 255 \n\t" - "lbu %[temp1], 0+0*" XSTR(BPS) "(%[dst]) \n\t" - "addu %[temp1], %[temp1], %[temp5] \n\t" - "sra %[temp5], %[temp1], 8 \n\t" - "sra %[temp18], %[temp1], 31 \n\t" - "beqz %[temp5], 1f \n\t" - "xor %[temp1], %[temp1], %[temp1] \n\t" - "movz %[temp1], %[temp6], %[temp18] \n\t" - "1: \n\t" - "lbu %[temp18], 1+0*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp1], 0+0*" XSTR(BPS) "(%[dst]) \n\t" - "addu %[temp18], %[temp18], %[temp11] \n\t" - "sra %[temp11], %[temp18], 8 \n\t" - "sra %[temp1], %[temp18], 31 \n\t" - "beqz %[temp11], 2f \n\t" - "xor %[temp18], %[temp18], %[temp18] \n\t" - "movz %[temp18], %[temp6], %[temp1] \n\t" - "2: \n\t" - "lbu %[temp1], 2+0*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp18], 1+0*" XSTR(BPS) "(%[dst]) \n\t" - "addu %[temp1], %[temp1], %[temp8] \n\t" - "sra %[temp8], %[temp1], 8 \n\t" - "sra %[temp18], %[temp1], 31 \n\t" - "beqz %[temp8], 3f \n\t" - "xor %[temp1], %[temp1], %[temp1] \n\t" - "movz %[temp1], %[temp6], %[temp18] \n\t" - "3: \n\t" - "lbu %[temp18], 3+0*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp1], 2+0*" XSTR(BPS) "(%[dst]) \n\t" - "addu %[temp18], %[temp18], %[temp16] \n\t" - "sra %[temp16], %[temp18], 8 \n\t" - "sra %[temp1], %[temp18], 31 \n\t" - "beqz %[temp16], 4f \n\t" - "xor %[temp18], %[temp18], %[temp18] \n\t" - "movz %[temp18], %[temp6], %[temp1] \n\t" - "4: \n\t" - "sb %[temp18], 3+0*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp5], 0+1*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp8], 1+1*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp11], 2+1*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp16], 3+1*" XSTR(BPS) "(%[dst]) \n\t" - "addu %[temp5], %[temp5], %[temp17] \n\t" - "addu %[temp8], %[temp8], %[temp15] \n\t" - "addu %[temp11], %[temp11], %[temp12] \n\t" - "addu %[temp16], %[temp16], %[temp10] \n\t" - "sra %[temp18], %[temp5], 8 \n\t" - "sra %[temp1], %[temp5], 31 \n\t" - "beqz %[temp18], 5f \n\t" - "xor %[temp5], %[temp5], %[temp5] \n\t" - "movz %[temp5], %[temp6], %[temp1] \n\t" - "5: \n\t" - "sra %[temp18], %[temp8], 8 \n\t" - "sra %[temp1], %[temp8], 31 \n\t" - "beqz %[temp18], 6f \n\t" - "xor %[temp8], %[temp8], %[temp8] \n\t" - "movz %[temp8], %[temp6], %[temp1] \n\t" - "6: \n\t" - "sra %[temp18], %[temp11], 8 \n\t" - "sra %[temp1], %[temp11], 31 \n\t" - "sra %[temp17], %[temp16], 8 \n\t" - "sra %[temp15], %[temp16], 31 \n\t" - "beqz %[temp18], 7f \n\t" - "xor %[temp11], %[temp11], %[temp11] \n\t" - "movz %[temp11], %[temp6], %[temp1] \n\t" - "7: \n\t" - "beqz %[temp17], 8f \n\t" - "xor %[temp16], %[temp16], %[temp16] \n\t" - "movz %[temp16], %[temp6], %[temp15] \n\t" - "8: \n\t" - "sb %[temp5], 0+1*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp8], 1+1*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp11], 2+1*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp16], 3+1*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp5], 0+2*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp8], 1+2*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp11], 2+2*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp16], 3+2*" XSTR(BPS) "(%[dst]) \n\t" - "addu %[temp5], %[temp5], %[temp9] \n\t" - "addu %[temp8], %[temp8], %[temp3] \n\t" - "addu %[temp11], %[temp11], %[temp0] \n\t" - "addu %[temp16], %[temp16], %[temp14] \n\t" - "sra %[temp18], %[temp5], 8 \n\t" - "sra %[temp1], %[temp5], 31 \n\t" - "sra %[temp17], %[temp8], 8 \n\t" - "sra %[temp15], %[temp8], 31 \n\t" - "sra %[temp12], %[temp11], 8 \n\t" - "sra %[temp10], %[temp11], 31 \n\t" - "sra %[temp9], %[temp16], 8 \n\t" - "sra %[temp3], %[temp16], 31 \n\t" - "beqz %[temp18], 9f \n\t" - "xor %[temp5], %[temp5], %[temp5] \n\t" - "movz %[temp5], %[temp6], %[temp1] \n\t" - "9: \n\t" - "beqz %[temp17], 10f \n\t" - "xor %[temp8], %[temp8], %[temp8] \n\t" - "movz %[temp8], %[temp6], %[temp15] \n\t" - "10: \n\t" - "beqz %[temp12], 11f \n\t" - "xor %[temp11], %[temp11], %[temp11] \n\t" - "movz %[temp11], %[temp6], %[temp10] \n\t" - "11: \n\t" - "beqz %[temp9], 12f \n\t" - "xor %[temp16], %[temp16], %[temp16] \n\t" - "movz %[temp16], %[temp6], %[temp3] \n\t" - "12: \n\t" - "sb %[temp5], 0+2*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp8], 1+2*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp11], 2+2*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp16], 3+2*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp5], 0+3*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp8], 1+3*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp11], 2+3*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp16], 3+3*" XSTR(BPS) "(%[dst]) \n\t" - "addu %[temp5], %[temp5], %[temp13] \n\t" - "addu %[temp8], %[temp8], %[temp7] \n\t" - "addu %[temp11], %[temp11], %[temp4] \n\t" - "addu %[temp16], %[temp16], %[temp2] \n\t" - "sra %[temp18], %[temp5], 8 \n\t" - "sra %[temp1], %[temp5], 31 \n\t" - "sra %[temp17], %[temp8], 8 \n\t" - "sra %[temp15], %[temp8], 31 \n\t" - "sra %[temp12], %[temp11], 8 \n\t" - "sra %[temp10], %[temp11], 31 \n\t" - "sra %[temp9], %[temp16], 8 \n\t" - "sra %[temp3], %[temp16], 31 \n\t" - "beqz %[temp18], 13f \n\t" - "xor %[temp5], %[temp5], %[temp5] \n\t" - "movz %[temp5], %[temp6], %[temp1] \n\t" - "13: \n\t" - "beqz %[temp17], 14f \n\t" - "xor %[temp8], %[temp8], %[temp8] \n\t" - "movz %[temp8], %[temp6], %[temp15] \n\t" - "14: \n\t" - "beqz %[temp12], 15f \n\t" - "xor %[temp11], %[temp11], %[temp11] \n\t" - "movz %[temp11], %[temp6], %[temp10] \n\t" - "15: \n\t" - "beqz %[temp9], 16f \n\t" - "xor %[temp16], %[temp16], %[temp16] \n\t" - "movz %[temp16], %[temp6], %[temp3] \n\t" - "16: \n\t" - "sb %[temp5], 0+3*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp8], 1+3*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp11], 2+3*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp16], 3+3*" XSTR(BPS) "(%[dst]) \n\t" - - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11), - [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14), - [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17), - [temp18]"=&r"(temp18) - : [in]"r"(p_in), [kC1]"r"(kC1), [kC2]"r"(kC2), [dst]"r"(dst) - : "memory", "hi", "lo" - ); -} - -static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) { - TransformOne(in, dst); - if (do_two) { - TransformOne(in + 16, dst + 4); - } -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8DspInitMIPS32(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitMIPS32(void) { - VP8InitClipTables(); - - VP8Transform = TransformTwo; - - VP8VFilter16 = VFilter16; - VP8HFilter16 = HFilter16; - VP8VFilter8 = VFilter8; - VP8HFilter8 = HFilter8; - VP8VFilter16i = VFilter16i; - VP8HFilter16i = HFilter16i; - VP8VFilter8i = VFilter8i; - VP8HFilter8i = HFilter8i; - - VP8SimpleVFilter16 = SimpleVFilter16; - VP8SimpleHFilter16 = SimpleHFilter16; - VP8SimpleVFilter16i = SimpleVFilter16i; - VP8SimpleHFilter16i = SimpleHFilter16i; -} - -#else // !WEBP_USE_MIPS32 - -WEBP_DSP_INIT_STUB(VP8DspInitMIPS32) - -#endif // WEBP_USE_MIPS32 diff --git a/Example-Mac/Pods/libwebp/src/dsp/dec_mips_dsp_r2.c b/Example-Mac/Pods/libwebp/src/dsp/dec_mips_dsp_r2.c deleted file mode 100644 index db5c6572..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/dec_mips_dsp_r2.c +++ /dev/null @@ -1,994 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// MIPS version of dsp functions -// -// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) -// Jovan Zelincevic (jovan.zelincevic@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS_DSP_R2) - -#include "./mips_macro.h" - -static const int kC1 = 20091 + (1 << 16); -static const int kC2 = 35468; - -#define MUL(a, b) (((a) * (b)) >> 16) - -static void TransformDC(const int16_t* in, uint8_t* dst) { - int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9, temp10; - - __asm__ volatile ( - LOAD_WITH_OFFSET_X4(temp1, temp2, temp3, temp4, dst, - 0, 0, 0, 0, - 0, 1, 2, 3, - BPS) - "lh %[temp5], 0(%[in]) \n\t" - "addiu %[temp5], %[temp5], 4 \n\t" - "ins %[temp5], %[temp5], 16, 16 \n\t" - "shra.ph %[temp5], %[temp5], 3 \n\t" - CONVERT_2_BYTES_TO_HALF(temp6, temp7, temp8, temp9, temp10, temp1, temp2, - temp3, temp1, temp2, temp3, temp4) - STORE_SAT_SUM_X2(temp6, temp7, temp8, temp9, temp10, temp1, temp2, temp3, - temp5, temp5, temp5, temp5, temp5, temp5, temp5, temp5, - dst, 0, 1, 2, 3, BPS) - - OUTPUT_EARLY_CLOBBER_REGS_10() - : [in]"r"(in), [dst]"r"(dst) - : "memory" - ); -} - -static void TransformAC3(const int16_t* in, uint8_t* dst) { - const int a = in[0] + 4; - int c4 = MUL(in[4], kC2); - const int d4 = MUL(in[4], kC1); - const int c1 = MUL(in[1], kC2); - const int d1 = MUL(in[1], kC1); - int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; - int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18; - - __asm__ volatile ( - "ins %[c4], %[d4], 16, 16 \n\t" - "replv.ph %[temp1], %[a] \n\t" - "replv.ph %[temp4], %[d1] \n\t" - ADD_SUB_HALVES(temp2, temp3, temp1, c4) - "replv.ph %[temp5], %[c1] \n\t" - SHIFT_R_SUM_X2(temp1, temp6, temp7, temp8, temp2, temp9, temp10, temp4, - temp2, temp2, temp3, temp3, temp4, temp5, temp4, temp5) - LOAD_WITH_OFFSET_X4(temp3, temp5, temp11, temp12, dst, - 0, 0, 0, 0, - 0, 1, 2, 3, - BPS) - CONVERT_2_BYTES_TO_HALF(temp13, temp14, temp3, temp15, temp5, temp16, - temp11, temp17, temp3, temp5, temp11, temp12) - PACK_2_HALVES_TO_WORD(temp12, temp18, temp7, temp6, temp1, temp8, temp2, - temp4, temp7, temp6, temp10, temp9) - STORE_SAT_SUM_X2(temp13, temp14, temp3, temp15, temp5, temp16, temp11, - temp17, temp12, temp18, temp1, temp8, temp2, temp4, - temp7, temp6, dst, 0, 1, 2, 3, BPS) - - OUTPUT_EARLY_CLOBBER_REGS_18(), - [c4]"+&r"(c4) - : [dst]"r"(dst), [a]"r"(a), [d1]"r"(d1), [d4]"r"(d4), [c1]"r"(c1) - : "memory" - ); -} - -static void TransformOne(const int16_t* in, uint8_t* dst) { - int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; - int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18; - - __asm__ volatile ( - "ulw %[temp1], 0(%[in]) \n\t" - "ulw %[temp2], 16(%[in]) \n\t" - LOAD_IN_X2(temp5, temp6, 24, 26) - ADD_SUB_HALVES(temp3, temp4, temp1, temp2) - LOAD_IN_X2(temp1, temp2, 8, 10) - MUL_SHIFT_SUM(temp7, temp8, temp9, temp10, temp11, temp12, temp13, temp14, - temp10, temp8, temp9, temp7, temp1, temp2, temp5, temp6, - temp13, temp11, temp14, temp12) - INSERT_HALF_X2(temp8, temp7, temp10, temp9) - "ulw %[temp17], 4(%[in]) \n\t" - "ulw %[temp18], 20(%[in]) \n\t" - ADD_SUB_HALVES(temp1, temp2, temp3, temp8) - ADD_SUB_HALVES(temp5, temp6, temp4, temp7) - ADD_SUB_HALVES(temp7, temp8, temp17, temp18) - LOAD_IN_X2(temp17, temp18, 12, 14) - LOAD_IN_X2(temp9, temp10, 28, 30) - MUL_SHIFT_SUM(temp11, temp12, temp13, temp14, temp15, temp16, temp4, temp17, - temp12, temp14, temp11, temp13, temp17, temp18, temp9, temp10, - temp15, temp4, temp16, temp17) - INSERT_HALF_X2(temp11, temp12, temp13, temp14) - ADD_SUB_HALVES(temp17, temp8, temp8, temp11) - ADD_SUB_HALVES(temp3, temp4, temp7, temp12) - - // horizontal - SRA_16(temp9, temp10, temp11, temp12, temp1, temp2, temp5, temp6) - INSERT_HALF_X2(temp1, temp6, temp5, temp2) - SRA_16(temp13, temp14, temp15, temp16, temp3, temp4, temp17, temp8) - "repl.ph %[temp2], 0x4 \n\t" - INSERT_HALF_X2(temp3, temp8, temp17, temp4) - "addq.ph %[temp1], %[temp1], %[temp2] \n\t" - "addq.ph %[temp6], %[temp6], %[temp2] \n\t" - ADD_SUB_HALVES(temp2, temp4, temp1, temp3) - ADD_SUB_HALVES(temp5, temp7, temp6, temp8) - MUL_SHIFT_SUM(temp1, temp3, temp6, temp8, temp9, temp13, temp17, temp18, - temp3, temp13, temp1, temp9, temp9, temp13, temp11, temp15, - temp6, temp17, temp8, temp18) - MUL_SHIFT_SUM(temp6, temp8, temp18, temp17, temp11, temp15, temp12, temp16, - temp8, temp15, temp6, temp11, temp12, temp16, temp10, temp14, - temp18, temp12, temp17, temp16) - INSERT_HALF_X2(temp1, temp3, temp9, temp13) - INSERT_HALF_X2(temp6, temp8, temp11, temp15) - SHIFT_R_SUM_X2(temp9, temp10, temp11, temp12, temp13, temp14, temp15, - temp16, temp2, temp4, temp5, temp7, temp3, temp1, temp8, - temp6) - PACK_2_HALVES_TO_WORD(temp1, temp2, temp3, temp4, temp9, temp12, temp13, - temp16, temp11, temp10, temp15, temp14) - LOAD_WITH_OFFSET_X4(temp10, temp11, temp14, temp15, dst, - 0, 0, 0, 0, - 0, 1, 2, 3, - BPS) - CONVERT_2_BYTES_TO_HALF(temp5, temp6, temp7, temp8, temp17, temp18, temp10, - temp11, temp10, temp11, temp14, temp15) - STORE_SAT_SUM_X2(temp5, temp6, temp7, temp8, temp17, temp18, temp10, temp11, - temp9, temp12, temp1, temp2, temp13, temp16, temp3, temp4, - dst, 0, 1, 2, 3, BPS) - - OUTPUT_EARLY_CLOBBER_REGS_18() - : [dst]"r"(dst), [in]"r"(in), [kC1]"r"(kC1), [kC2]"r"(kC2) - : "memory", "hi", "lo" - ); -} - -static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) { - TransformOne(in, dst); - if (do_two) { - TransformOne(in + 16, dst + 4); - } -} - -static WEBP_INLINE void FilterLoop26(uint8_t* p, - int hstride, int vstride, int size, - int thresh, int ithresh, int hev_thresh) { - const int thresh2 = 2 * thresh + 1; - int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; - int temp10, temp11, temp12, temp13, temp14, temp15; - - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "1: \n\t" - "negu %[temp1], %[hstride] \n\t" - "addiu %[size], %[size], -1 \n\t" - "sll %[temp2], %[hstride], 1 \n\t" - "sll %[temp3], %[temp1], 1 \n\t" - "addu %[temp4], %[temp2], %[hstride] \n\t" - "addu %[temp5], %[temp3], %[temp1] \n\t" - "lbu %[temp7], 0(%[p]) \n\t" - "sll %[temp6], %[temp3], 1 \n\t" - "lbux %[temp8], %[temp5](%[p]) \n\t" - "lbux %[temp9], %[temp3](%[p]) \n\t" - "lbux %[temp10], %[temp1](%[p]) \n\t" - "lbux %[temp11], %[temp6](%[p]) \n\t" - "lbux %[temp12], %[hstride](%[p]) \n\t" - "lbux %[temp13], %[temp2](%[p]) \n\t" - "lbux %[temp14], %[temp4](%[p]) \n\t" - "subu %[temp1], %[temp10], %[temp7] \n\t" - "subu %[temp2], %[temp9], %[temp12] \n\t" - "absq_s.w %[temp3], %[temp1] \n\t" - "absq_s.w %[temp4], %[temp2] \n\t" - "negu %[temp1], %[temp1] \n\t" - "sll %[temp3], %[temp3], 2 \n\t" - "addu %[temp15], %[temp3], %[temp4] \n\t" - "subu %[temp3], %[temp15], %[thresh2] \n\t" - "sll %[temp6], %[temp1], 1 \n\t" - "bgtz %[temp3], 3f \n\t" - " subu %[temp4], %[temp11], %[temp8] \n\t" - "absq_s.w %[temp4], %[temp4] \n\t" - "shll_s.w %[temp2], %[temp2], 24 \n\t" - "subu %[temp4], %[temp4], %[ithresh] \n\t" - "bgtz %[temp4], 3f \n\t" - " subu %[temp3], %[temp8], %[temp9] \n\t" - "absq_s.w %[temp3], %[temp3] \n\t" - "subu %[temp3], %[temp3], %[ithresh] \n\t" - "bgtz %[temp3], 3f \n\t" - " subu %[temp5], %[temp9], %[temp10] \n\t" - "absq_s.w %[temp3], %[temp5] \n\t" - "absq_s.w %[temp5], %[temp5] \n\t" - "subu %[temp3], %[temp3], %[ithresh] \n\t" - "bgtz %[temp3], 3f \n\t" - " subu %[temp3], %[temp14], %[temp13] \n\t" - "absq_s.w %[temp3], %[temp3] \n\t" - "slt %[temp5], %[hev_thresh], %[temp5] \n\t" - "subu %[temp3], %[temp3], %[ithresh] \n\t" - "bgtz %[temp3], 3f \n\t" - " subu %[temp3], %[temp13], %[temp12] \n\t" - "absq_s.w %[temp3], %[temp3] \n\t" - "sra %[temp4], %[temp2], 24 \n\t" - "subu %[temp3], %[temp3], %[ithresh] \n\t" - "bgtz %[temp3], 3f \n\t" - " subu %[temp15], %[temp12], %[temp7] \n\t" - "absq_s.w %[temp3], %[temp15] \n\t" - "absq_s.w %[temp15], %[temp15] \n\t" - "subu %[temp3], %[temp3], %[ithresh] \n\t" - "bgtz %[temp3], 3f \n\t" - " slt %[temp15], %[hev_thresh], %[temp15] \n\t" - "addu %[temp3], %[temp6], %[temp1] \n\t" - "or %[temp2], %[temp5], %[temp15] \n\t" - "addu %[temp5], %[temp4], %[temp3] \n\t" - "beqz %[temp2], 4f \n\t" - " shra_r.w %[temp1], %[temp5], 3 \n\t" - "addiu %[temp2], %[temp5], 3 \n\t" - "sra %[temp2], %[temp2], 3 \n\t" - "shll_s.w %[temp1], %[temp1], 27 \n\t" - "shll_s.w %[temp2], %[temp2], 27 \n\t" - "subu %[temp3], %[p], %[hstride] \n\t" - "sra %[temp1], %[temp1], 27 \n\t" - "sra %[temp2], %[temp2], 27 \n\t" - "subu %[temp1], %[temp7], %[temp1] \n\t" - "addu %[temp2], %[temp10], %[temp2] \n\t" - "lbux %[temp2], %[temp2](%[VP8kclip1]) \n\t" - "lbux %[temp1], %[temp1](%[VP8kclip1]) \n\t" - "sb %[temp2], 0(%[temp3]) \n\t" - "j 3f \n\t" - " sb %[temp1], 0(%[p]) \n\t" - "4: \n\t" - "shll_s.w %[temp5], %[temp5], 24 \n\t" - "subu %[temp14], %[p], %[hstride] \n\t" - "subu %[temp11], %[temp14], %[hstride] \n\t" - "sra %[temp6], %[temp5], 24 \n\t" - "sll %[temp1], %[temp6], 3 \n\t" - "subu %[temp15], %[temp11], %[hstride] \n\t" - "addu %[temp2], %[temp6], %[temp1] \n\t" - "sll %[temp3], %[temp2], 1 \n\t" - "addu %[temp4], %[temp3], %[temp2] \n\t" - "addiu %[temp2], %[temp2], 63 \n\t" - "addiu %[temp3], %[temp3], 63 \n\t" - "addiu %[temp4], %[temp4], 63 \n\t" - "sra %[temp2], %[temp2], 7 \n\t" - "sra %[temp3], %[temp3], 7 \n\t" - "sra %[temp4], %[temp4], 7 \n\t" - "addu %[temp1], %[temp8], %[temp2] \n\t" - "addu %[temp5], %[temp9], %[temp3] \n\t" - "addu %[temp6], %[temp10], %[temp4] \n\t" - "subu %[temp8], %[temp7], %[temp4] \n\t" - "subu %[temp7], %[temp12], %[temp3] \n\t" - "addu %[temp10], %[p], %[hstride] \n\t" - "subu %[temp9], %[temp13], %[temp2] \n\t" - "addu %[temp12], %[temp10], %[hstride] \n\t" - "lbux %[temp2], %[temp1](%[VP8kclip1]) \n\t" - "lbux %[temp3], %[temp5](%[VP8kclip1]) \n\t" - "lbux %[temp4], %[temp6](%[VP8kclip1]) \n\t" - "lbux %[temp5], %[temp8](%[VP8kclip1]) \n\t" - "lbux %[temp6], %[temp7](%[VP8kclip1]) \n\t" - "lbux %[temp8], %[temp9](%[VP8kclip1]) \n\t" - "sb %[temp2], 0(%[temp15]) \n\t" - "sb %[temp3], 0(%[temp11]) \n\t" - "sb %[temp4], 0(%[temp14]) \n\t" - "sb %[temp5], 0(%[p]) \n\t" - "sb %[temp6], 0(%[temp10]) \n\t" - "sb %[temp8], 0(%[temp12]) \n\t" - "3: \n\t" - "bgtz %[size], 1b \n\t" - " addu %[p], %[p], %[vstride] \n\t" - ".set pop \n\t" - : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),[temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6), - [temp7]"=&r"(temp7),[temp8]"=&r"(temp8),[temp9]"=&r"(temp9), - [temp10]"=&r"(temp10),[temp11]"=&r"(temp11),[temp12]"=&r"(temp12), - [temp13]"=&r"(temp13),[temp14]"=&r"(temp14),[temp15]"=&r"(temp15), - [size]"+&r"(size), [p]"+&r"(p) - : [hstride]"r"(hstride), [thresh2]"r"(thresh2), - [ithresh]"r"(ithresh),[vstride]"r"(vstride), [hev_thresh]"r"(hev_thresh), - [VP8kclip1]"r"(VP8kclip1) - : "memory" - ); -} - -static WEBP_INLINE void FilterLoop24(uint8_t* p, - int hstride, int vstride, int size, - int thresh, int ithresh, int hev_thresh) { - int p0, q0, p1, q1, p2, q2, p3, q3; - int step1, step2, temp1, temp2, temp3, temp4; - uint8_t* pTemp0; - uint8_t* pTemp1; - const int thresh2 = 2 * thresh + 1; - - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "bltz %[size], 3f \n\t" - " nop \n\t" - "2: \n\t" - "negu %[step1], %[hstride] \n\t" - "lbu %[q0], 0(%[p]) \n\t" - "lbux %[p0], %[step1](%[p]) \n\t" - "subu %[step1], %[step1], %[hstride] \n\t" - "lbux %[q1], %[hstride](%[p]) \n\t" - "subu %[temp1], %[p0], %[q0] \n\t" - "lbux %[p1], %[step1](%[p]) \n\t" - "addu %[step2], %[hstride], %[hstride] \n\t" - "absq_s.w %[temp2], %[temp1] \n\t" - "subu %[temp3], %[p1], %[q1] \n\t" - "absq_s.w %[temp4], %[temp3] \n\t" - "sll %[temp2], %[temp2], 2 \n\t" - "addu %[temp2], %[temp2], %[temp4] \n\t" - "subu %[temp4], %[temp2], %[thresh2] \n\t" - "subu %[step1], %[step1], %[hstride] \n\t" - "bgtz %[temp4], 0f \n\t" - " lbux %[p2], %[step1](%[p]) \n\t" - "subu %[step1], %[step1], %[hstride] \n\t" - "lbux %[q2], %[step2](%[p]) \n\t" - "lbux %[p3], %[step1](%[p]) \n\t" - "subu %[temp4], %[p2], %[p1] \n\t" - "addu %[step2], %[step2], %[hstride] \n\t" - "subu %[temp2], %[p3], %[p2] \n\t" - "absq_s.w %[temp4], %[temp4] \n\t" - "absq_s.w %[temp2], %[temp2] \n\t" - "lbux %[q3], %[step2](%[p]) \n\t" - "subu %[temp4], %[temp4], %[ithresh] \n\t" - "negu %[temp1], %[temp1] \n\t" - "bgtz %[temp4], 0f \n\t" - " subu %[temp2], %[temp2], %[ithresh] \n\t" - "subu %[p3], %[p1], %[p0] \n\t" - "bgtz %[temp2], 0f \n\t" - " absq_s.w %[p3], %[p3] \n\t" - "subu %[temp4], %[q3], %[q2] \n\t" - "subu %[pTemp0], %[p], %[hstride] \n\t" - "absq_s.w %[temp4], %[temp4] \n\t" - "subu %[temp2], %[p3], %[ithresh] \n\t" - "sll %[step1], %[temp1], 1 \n\t" - "bgtz %[temp2], 0f \n\t" - " subu %[temp4], %[temp4], %[ithresh] \n\t" - "subu %[temp2], %[q2], %[q1] \n\t" - "bgtz %[temp4], 0f \n\t" - " absq_s.w %[temp2], %[temp2] \n\t" - "subu %[q3], %[q1], %[q0] \n\t" - "absq_s.w %[q3], %[q3] \n\t" - "subu %[temp2], %[temp2], %[ithresh] \n\t" - "addu %[temp1], %[temp1], %[step1] \n\t" - "bgtz %[temp2], 0f \n\t" - " subu %[temp4], %[q3], %[ithresh] \n\t" - "slt %[p3], %[hev_thresh], %[p3] \n\t" - "bgtz %[temp4], 0f \n\t" - " slt %[q3], %[hev_thresh], %[q3] \n\t" - "or %[q3], %[q3], %[p3] \n\t" - "bgtz %[q3], 1f \n\t" - " shra_r.w %[temp2], %[temp1], 3 \n\t" - "addiu %[temp1], %[temp1], 3 \n\t" - "sra %[temp1], %[temp1], 3 \n\t" - "shll_s.w %[temp2], %[temp2], 27 \n\t" - "shll_s.w %[temp1], %[temp1], 27 \n\t" - "addu %[pTemp1], %[p], %[hstride] \n\t" - "sra %[temp2], %[temp2], 27 \n\t" - "sra %[temp1], %[temp1], 27 \n\t" - "addiu %[step1], %[temp2], 1 \n\t" - "sra %[step1], %[step1], 1 \n\t" - "addu %[p0], %[p0], %[temp1] \n\t" - "addu %[p1], %[p1], %[step1] \n\t" - "subu %[q0], %[q0], %[temp2] \n\t" - "subu %[q1], %[q1], %[step1] \n\t" - "lbux %[temp2], %[p0](%[VP8kclip1]) \n\t" - "lbux %[temp3], %[q0](%[VP8kclip1]) \n\t" - "lbux %[temp4], %[q1](%[VP8kclip1]) \n\t" - "sb %[temp2], 0(%[pTemp0]) \n\t" - "lbux %[temp1], %[p1](%[VP8kclip1]) \n\t" - "subu %[pTemp0], %[pTemp0], %[hstride] \n\t" - "sb %[temp3], 0(%[p]) \n\t" - "sb %[temp4], 0(%[pTemp1]) \n\t" - "j 0f \n\t" - " sb %[temp1], 0(%[pTemp0]) \n\t" - "1: \n\t" - "shll_s.w %[temp3], %[temp3], 24 \n\t" - "sra %[temp3], %[temp3], 24 \n\t" - "addu %[temp1], %[temp1], %[temp3] \n\t" - "shra_r.w %[temp2], %[temp1], 3 \n\t" - "addiu %[temp1], %[temp1], 3 \n\t" - "shll_s.w %[temp2], %[temp2], 27 \n\t" - "sra %[temp1], %[temp1], 3 \n\t" - "shll_s.w %[temp1], %[temp1], 27 \n\t" - "sra %[temp2], %[temp2], 27 \n\t" - "sra %[temp1], %[temp1], 27 \n\t" - "addu %[p0], %[p0], %[temp1] \n\t" - "subu %[q0], %[q0], %[temp2] \n\t" - "lbux %[temp1], %[p0](%[VP8kclip1]) \n\t" - "lbux %[temp2], %[q0](%[VP8kclip1]) \n\t" - "sb %[temp2], 0(%[p]) \n\t" - "sb %[temp1], 0(%[pTemp0]) \n\t" - "0: \n\t" - "subu %[size], %[size], 1 \n\t" - "bgtz %[size], 2b \n\t" - " addu %[p], %[p], %[vstride] \n\t" - "3: \n\t" - ".set pop \n\t" - : [p0]"=&r"(p0), [q0]"=&r"(q0), [p1]"=&r"(p1), [q1]"=&r"(q1), - [p2]"=&r"(p2), [q2]"=&r"(q2), [p3]"=&r"(p3), [q3]"=&r"(q3), - [step2]"=&r"(step2), [step1]"=&r"(step1), [temp1]"=&r"(temp1), - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), - [pTemp0]"=&r"(pTemp0), [pTemp1]"=&r"(pTemp1), [p]"+&r"(p), - [size]"+&r"(size) - : [vstride]"r"(vstride), [ithresh]"r"(ithresh), - [hev_thresh]"r"(hev_thresh), [hstride]"r"(hstride), - [VP8kclip1]"r"(VP8kclip1), [thresh2]"r"(thresh2) - : "memory" - ); -} - -// on macroblock edges -static void VFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh); -} - -static void HFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh); -} - -// 8-pixels wide variant, for chroma filtering -static void VFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(u, stride, 1, 8, thresh, ithresh, hev_thresh); - FilterLoop26(v, stride, 1, 8, thresh, ithresh, hev_thresh); -} - -static void HFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(u, 1, stride, 8, thresh, ithresh, hev_thresh); - FilterLoop26(v, 1, stride, 8, thresh, ithresh, hev_thresh); -} - -// on three inner edges -static void VFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4 * stride; - FilterLoop24(p, stride, 1, 16, thresh, ithresh, hev_thresh); - } -} - -static void HFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4; - FilterLoop24(p, 1, stride, 16, thresh, ithresh, hev_thresh); - } -} - -static void VFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop24(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); - FilterLoop24(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); -} - -static void HFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop24(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh); - FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh); -} - -#undef MUL - -//------------------------------------------------------------------------------ -// Simple In-loop filtering (Paragraph 15.2) - -static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { - int i; - const int thresh2 = 2 * thresh + 1; - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; - uint8_t* p1 = p - stride; - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "li %[i], 16 \n\t" - "0: \n\t" - "negu %[temp4], %[stride] \n\t" - "sll %[temp5], %[temp4], 1 \n\t" - "lbu %[temp2], 0(%[p]) \n\t" - "lbux %[temp3], %[stride](%[p]) \n\t" - "lbux %[temp1], %[temp4](%[p]) \n\t" - "lbux %[temp0], %[temp5](%[p]) \n\t" - "subu %[temp7], %[temp1], %[temp2] \n\t" - "subu %[temp6], %[temp0], %[temp3] \n\t" - "absq_s.w %[temp4], %[temp7] \n\t" - "absq_s.w %[temp5], %[temp6] \n\t" - "sll %[temp4], %[temp4], 2 \n\t" - "subu %[temp5], %[temp5], %[thresh2] \n\t" - "addu %[temp5], %[temp4], %[temp5] \n\t" - "negu %[temp8], %[temp7] \n\t" - "bgtz %[temp5], 1f \n\t" - " addiu %[i], %[i], -1 \n\t" - "sll %[temp4], %[temp8], 1 \n\t" - "shll_s.w %[temp5], %[temp6], 24 \n\t" - "addu %[temp3], %[temp4], %[temp8] \n\t" - "sra %[temp5], %[temp5], 24 \n\t" - "addu %[temp3], %[temp3], %[temp5] \n\t" - "addiu %[temp7], %[temp3], 3 \n\t" - "sra %[temp7], %[temp7], 3 \n\t" - "shra_r.w %[temp8], %[temp3], 3 \n\t" - "shll_s.w %[temp0], %[temp7], 27 \n\t" - "shll_s.w %[temp4], %[temp8], 27 \n\t" - "sra %[temp0], %[temp0], 27 \n\t" - "sra %[temp4], %[temp4], 27 \n\t" - "addu %[temp7], %[temp1], %[temp0] \n\t" - "subu %[temp2], %[temp2], %[temp4] \n\t" - "lbux %[temp3], %[temp7](%[VP8kclip1]) \n\t" - "lbux %[temp4], %[temp2](%[VP8kclip1]) \n\t" - "sb %[temp3], 0(%[p1]) \n\t" - "sb %[temp4], 0(%[p]) \n\t" - "1: \n\t" - "addiu %[p1], %[p1], 1 \n\t" - "bgtz %[i], 0b \n\t" - " addiu %[p], %[p], 1 \n\t" - " .set pop \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [p]"+&r"(p), [i]"=&r"(i), [p1]"+&r"(p1) - : [stride]"r"(stride), [VP8kclip1]"r"(VP8kclip1), [thresh2]"r"(thresh2) - : "memory" - ); -} - -// TEMP0 = SRC[A + A1 * BPS] -// TEMP1 = SRC[B + B1 * BPS] -// TEMP2 = SRC[C + C1 * BPS] -// TEMP3 = SRC[D + D1 * BPS] -#define LOAD_4_BYTES(TEMP0, TEMP1, TEMP2, TEMP3, \ - A, A1, B, B1, C, C1, D, D1, SRC) \ - "lbu %[" #TEMP0 "], " #A "+" #A1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \ - "lbu %[" #TEMP1 "], " #B "+" #B1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \ - "lbu %[" #TEMP2 "], " #C "+" #C1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \ - "lbu %[" #TEMP3 "], " #D "+" #D1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \ - -static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { - int i; - const int thresh2 = 2 * thresh + 1; - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "li %[i], 16 \n\t" - "0: \n\t" - LOAD_4_BYTES(temp0, temp1, temp2, temp3, -2, 0, -1, 0, 0, 0, 1, 0, p) - "subu %[temp7], %[temp1], %[temp2] \n\t" - "subu %[temp6], %[temp0], %[temp3] \n\t" - "absq_s.w %[temp4], %[temp7] \n\t" - "absq_s.w %[temp5], %[temp6] \n\t" - "sll %[temp4], %[temp4], 2 \n\t" - "addu %[temp5], %[temp4], %[temp5] \n\t" - "subu %[temp5], %[temp5], %[thresh2] \n\t" - "negu %[temp8], %[temp7] \n\t" - "bgtz %[temp5], 1f \n\t" - " addiu %[i], %[i], -1 \n\t" - "sll %[temp4], %[temp8], 1 \n\t" - "shll_s.w %[temp5], %[temp6], 24 \n\t" - "addu %[temp3], %[temp4], %[temp8] \n\t" - "sra %[temp5], %[temp5], 24 \n\t" - "addu %[temp3], %[temp3], %[temp5] \n\t" - "addiu %[temp7], %[temp3], 3 \n\t" - "sra %[temp7], %[temp7], 3 \n\t" - "shra_r.w %[temp8], %[temp3], 3 \n\t" - "shll_s.w %[temp0], %[temp7], 27 \n\t" - "shll_s.w %[temp4], %[temp8], 27 \n\t" - "sra %[temp0], %[temp0], 27 \n\t" - "sra %[temp4], %[temp4], 27 \n\t" - "addu %[temp7], %[temp1], %[temp0] \n\t" - "subu %[temp2], %[temp2], %[temp4] \n\t" - "lbux %[temp3], %[temp7](%[VP8kclip1]) \n\t" - "lbux %[temp4], %[temp2](%[VP8kclip1]) \n\t" - "sb %[temp3], -1(%[p]) \n\t" - "sb %[temp4], 0(%[p]) \n\t" - "1: \n\t" - "bgtz %[i], 0b \n\t" - " addu %[p], %[p], %[stride] \n\t" - ".set pop \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [p]"+&r"(p), [i]"=&r"(i) - : [stride]"r"(stride), [VP8kclip1]"r"(VP8kclip1), [thresh2]"r"(thresh2) - : "memory" - ); -} - -static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4 * stride; - SimpleVFilter16(p, stride, thresh); - } -} - -static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4; - SimpleHFilter16(p, stride, thresh); - } -} - -// DST[A * BPS] = TEMP0 -// DST[B + C * BPS] = TEMP1 -#define STORE_8_BYTES(TEMP0, TEMP1, A, B, C, DST) \ - "usw %[" #TEMP0 "], " #A "*" XSTR(BPS) "(%[" #DST "]) \n\t" \ - "usw %[" #TEMP1 "], " #B "+" #C "*" XSTR(BPS) "(%[" #DST "]) \n\t" - -static void VE4(uint8_t* dst) { // vertical - const uint8_t* top = dst - BPS; - int temp0, temp1, temp2, temp3, temp4, temp5, temp6; - __asm__ volatile ( - "ulw %[temp0], -1(%[top]) \n\t" - "ulh %[temp1], 3(%[top]) \n\t" - "preceu.ph.qbr %[temp2], %[temp0] \n\t" - "preceu.ph.qbl %[temp3], %[temp0] \n\t" - "preceu.ph.qbr %[temp4], %[temp1] \n\t" - "packrl.ph %[temp5], %[temp3], %[temp2] \n\t" - "packrl.ph %[temp6], %[temp4], %[temp3] \n\t" - "shll.ph %[temp5], %[temp5], 1 \n\t" - "shll.ph %[temp6], %[temp6], 1 \n\t" - "addq.ph %[temp2], %[temp5], %[temp2] \n\t" - "addq.ph %[temp6], %[temp6], %[temp4] \n\t" - "addq.ph %[temp2], %[temp2], %[temp3] \n\t" - "addq.ph %[temp6], %[temp6], %[temp3] \n\t" - "shra_r.ph %[temp2], %[temp2], 2 \n\t" - "shra_r.ph %[temp6], %[temp6], 2 \n\t" - "precr.qb.ph %[temp4], %[temp6], %[temp2] \n\t" - STORE_8_BYTES(temp4, temp4, 0, 0, 1, dst) - STORE_8_BYTES(temp4, temp4, 2, 0, 3, dst) - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6) - : [top]"r"(top), [dst]"r"(dst) - : "memory" - ); -} - -static void DC4(uint8_t* dst) { // DC - int temp0, temp1, temp2, temp3, temp4; - __asm__ volatile ( - "ulw %[temp0], -1*" XSTR(BPS) "(%[dst]) \n\t" - LOAD_4_BYTES(temp1, temp2, temp3, temp4, -1, 0, -1, 1, -1, 2, -1, 3, dst) - "ins %[temp1], %[temp2], 8, 8 \n\t" - "ins %[temp1], %[temp3], 16, 8 \n\t" - "ins %[temp1], %[temp4], 24, 8 \n\t" - "raddu.w.qb %[temp0], %[temp0] \n\t" - "raddu.w.qb %[temp1], %[temp1] \n\t" - "addu %[temp0], %[temp0], %[temp1] \n\t" - "shra_r.w %[temp0], %[temp0], 3 \n\t" - "replv.qb %[temp0], %[temp0] \n\t" - STORE_8_BYTES(temp0, temp0, 0, 0, 1, dst) - STORE_8_BYTES(temp0, temp0, 2, 0, 3, dst) - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4) - : [dst]"r"(dst) - : "memory" - ); -} - -static void RD4(uint8_t* dst) { // Down-right - int temp0, temp1, temp2, temp3, temp4; - int temp5, temp6, temp7, temp8; - __asm__ volatile ( - LOAD_4_BYTES(temp0, temp1, temp2, temp3, -1, 0, -1, 1, -1, 2, -1, 3, dst) - "ulw %[temp7], -1-" XSTR(BPS) "(%[dst]) \n\t" - "ins %[temp1], %[temp0], 16, 16 \n\t" - "preceu.ph.qbr %[temp5], %[temp7] \n\t" - "ins %[temp2], %[temp1], 16, 16 \n\t" - "preceu.ph.qbl %[temp4], %[temp7] \n\t" - "ins %[temp3], %[temp2], 16, 16 \n\t" - "shll.ph %[temp2], %[temp2], 1 \n\t" - "addq.ph %[temp3], %[temp3], %[temp1] \n\t" - "packrl.ph %[temp6], %[temp5], %[temp1] \n\t" - "addq.ph %[temp3], %[temp3], %[temp2] \n\t" - "addq.ph %[temp1], %[temp1], %[temp5] \n\t" - "shll.ph %[temp6], %[temp6], 1 \n\t" - "addq.ph %[temp1], %[temp1], %[temp6] \n\t" - "packrl.ph %[temp0], %[temp4], %[temp5] \n\t" - "addq.ph %[temp8], %[temp5], %[temp4] \n\t" - "shra_r.ph %[temp3], %[temp3], 2 \n\t" - "shll.ph %[temp0], %[temp0], 1 \n\t" - "shra_r.ph %[temp1], %[temp1], 2 \n\t" - "addq.ph %[temp8], %[temp0], %[temp8] \n\t" - "lbu %[temp5], 3-" XSTR(BPS) "(%[dst]) \n\t" - "precrq.ph.w %[temp7], %[temp7], %[temp7] \n\t" - "shra_r.ph %[temp8], %[temp8], 2 \n\t" - "ins %[temp7], %[temp5], 0, 8 \n\t" - "precr.qb.ph %[temp2], %[temp1], %[temp3] \n\t" - "raddu.w.qb %[temp4], %[temp7] \n\t" - "precr.qb.ph %[temp6], %[temp8], %[temp1] \n\t" - "shra_r.w %[temp4], %[temp4], 2 \n\t" - STORE_8_BYTES(temp2, temp6, 3, 0, 1, dst) - "prepend %[temp2], %[temp8], 8 \n\t" - "prepend %[temp6], %[temp4], 8 \n\t" - STORE_8_BYTES(temp2, temp6, 2, 0, 0, dst) - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8) - : [dst]"r"(dst) - : "memory" - ); -} - -// TEMP0 = SRC[A * BPS] -// TEMP1 = SRC[B + C * BPS] -#define LOAD_8_BYTES(TEMP0, TEMP1, A, B, C, SRC) \ - "ulw %[" #TEMP0 "], " #A "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \ - "ulw %[" #TEMP1 "], " #B "+" #C "*" XSTR(BPS) "(%[" #SRC "]) \n\t" - -static void LD4(uint8_t* dst) { // Down-Left - int temp0, temp1, temp2, temp3, temp4; - int temp5, temp6, temp7, temp8, temp9; - __asm__ volatile ( - LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst) - "preceu.ph.qbl %[temp2], %[temp0] \n\t" - "preceu.ph.qbr %[temp3], %[temp0] \n\t" - "preceu.ph.qbr %[temp4], %[temp1] \n\t" - "preceu.ph.qbl %[temp5], %[temp1] \n\t" - "packrl.ph %[temp6], %[temp2], %[temp3] \n\t" - "packrl.ph %[temp7], %[temp4], %[temp2] \n\t" - "packrl.ph %[temp8], %[temp5], %[temp4] \n\t" - "shll.ph %[temp6], %[temp6], 1 \n\t" - "addq.ph %[temp9], %[temp2], %[temp6] \n\t" - "shll.ph %[temp7], %[temp7], 1 \n\t" - "addq.ph %[temp9], %[temp9], %[temp3] \n\t" - "shll.ph %[temp8], %[temp8], 1 \n\t" - "shra_r.ph %[temp9], %[temp9], 2 \n\t" - "addq.ph %[temp3], %[temp4], %[temp7] \n\t" - "addq.ph %[temp0], %[temp5], %[temp8] \n\t" - "addq.ph %[temp3], %[temp3], %[temp2] \n\t" - "addq.ph %[temp0], %[temp0], %[temp4] \n\t" - "shra_r.ph %[temp3], %[temp3], 2 \n\t" - "shra_r.ph %[temp0], %[temp0], 2 \n\t" - "srl %[temp1], %[temp1], 24 \n\t" - "sll %[temp1], %[temp1], 1 \n\t" - "raddu.w.qb %[temp5], %[temp5] \n\t" - "precr.qb.ph %[temp9], %[temp3], %[temp9] \n\t" - "precr.qb.ph %[temp3], %[temp0], %[temp3] \n\t" - "addu %[temp1], %[temp1], %[temp5] \n\t" - "shra_r.w %[temp1], %[temp1], 2 \n\t" - STORE_8_BYTES(temp9, temp3, 0, 0, 2, dst) - "prepend %[temp9], %[temp0], 8 \n\t" - "prepend %[temp3], %[temp1], 8 \n\t" - STORE_8_BYTES(temp9, temp3, 1, 0, 3, dst) - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [temp9]"=&r"(temp9) - : [dst]"r"(dst) - : "memory" - ); -} - -//------------------------------------------------------------------------------ -// Chroma - -static void DC8uv(uint8_t* dst) { // DC - int temp0, temp1, temp2, temp3, temp4; - int temp5, temp6, temp7, temp8, temp9; - __asm__ volatile ( - LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst) - LOAD_4_BYTES(temp2, temp3, temp4, temp5, -1, 0, -1, 1, -1, 2, -1, 3, dst) - LOAD_4_BYTES(temp6, temp7, temp8, temp9, -1, 4, -1, 5, -1, 6, -1, 7, dst) - "raddu.w.qb %[temp0], %[temp0] \n\t" - "raddu.w.qb %[temp1], %[temp1] \n\t" - "addu %[temp2], %[temp2], %[temp3] \n\t" - "addu %[temp4], %[temp4], %[temp5] \n\t" - "addu %[temp6], %[temp6], %[temp7] \n\t" - "addu %[temp8], %[temp8], %[temp9] \n\t" - "addu %[temp0], %[temp0], %[temp1] \n\t" - "addu %[temp2], %[temp2], %[temp4] \n\t" - "addu %[temp6], %[temp6], %[temp8] \n\t" - "addu %[temp0], %[temp0], %[temp2] \n\t" - "addu %[temp0], %[temp0], %[temp6] \n\t" - "shra_r.w %[temp0], %[temp0], 4 \n\t" - "replv.qb %[temp0], %[temp0] \n\t" - STORE_8_BYTES(temp0, temp0, 0, 4, 0, dst) - STORE_8_BYTES(temp0, temp0, 1, 4, 1, dst) - STORE_8_BYTES(temp0, temp0, 2, 4, 2, dst) - STORE_8_BYTES(temp0, temp0, 3, 4, 3, dst) - STORE_8_BYTES(temp0, temp0, 4, 4, 4, dst) - STORE_8_BYTES(temp0, temp0, 5, 4, 5, dst) - STORE_8_BYTES(temp0, temp0, 6, 4, 6, dst) - STORE_8_BYTES(temp0, temp0, 7, 4, 7, dst) - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [temp9]"=&r"(temp9) - : [dst]"r"(dst) - : "memory" - ); -} - -static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples - int temp0, temp1; - __asm__ volatile ( - LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst) - "raddu.w.qb %[temp0], %[temp0] \n\t" - "raddu.w.qb %[temp1], %[temp1] \n\t" - "addu %[temp0], %[temp0], %[temp1] \n\t" - "shra_r.w %[temp0], %[temp0], 3 \n\t" - "replv.qb %[temp0], %[temp0] \n\t" - STORE_8_BYTES(temp0, temp0, 0, 4, 0, dst) - STORE_8_BYTES(temp0, temp0, 1, 4, 1, dst) - STORE_8_BYTES(temp0, temp0, 2, 4, 2, dst) - STORE_8_BYTES(temp0, temp0, 3, 4, 3, dst) - STORE_8_BYTES(temp0, temp0, 4, 4, 4, dst) - STORE_8_BYTES(temp0, temp0, 5, 4, 5, dst) - STORE_8_BYTES(temp0, temp0, 6, 4, 6, dst) - STORE_8_BYTES(temp0, temp0, 7, 4, 7, dst) - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1) - : [dst]"r"(dst) - : "memory" - ); -} - -static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples - int temp0, temp1, temp2, temp3, temp4; - int temp5, temp6, temp7, temp8; - __asm__ volatile ( - LOAD_4_BYTES(temp2, temp3, temp4, temp5, -1, 0, -1, 1, -1, 2, -1, 3, dst) - LOAD_4_BYTES(temp6, temp7, temp8, temp1, -1, 4, -1, 5, -1, 6, -1, 7, dst) - "addu %[temp2], %[temp2], %[temp3] \n\t" - "addu %[temp4], %[temp4], %[temp5] \n\t" - "addu %[temp6], %[temp6], %[temp7] \n\t" - "addu %[temp8], %[temp8], %[temp1] \n\t" - "addu %[temp2], %[temp2], %[temp4] \n\t" - "addu %[temp6], %[temp6], %[temp8] \n\t" - "addu %[temp0], %[temp6], %[temp2] \n\t" - "shra_r.w %[temp0], %[temp0], 3 \n\t" - "replv.qb %[temp0], %[temp0] \n\t" - STORE_8_BYTES(temp0, temp0, 0, 4, 0, dst) - STORE_8_BYTES(temp0, temp0, 1, 4, 1, dst) - STORE_8_BYTES(temp0, temp0, 2, 4, 2, dst) - STORE_8_BYTES(temp0, temp0, 3, 4, 3, dst) - STORE_8_BYTES(temp0, temp0, 4, 4, 4, dst) - STORE_8_BYTES(temp0, temp0, 5, 4, 5, dst) - STORE_8_BYTES(temp0, temp0, 6, 4, 6, dst) - STORE_8_BYTES(temp0, temp0, 7, 4, 7, dst) - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8) - : [dst]"r"(dst) - : "memory" - ); -} - -#undef LOAD_8_BYTES -#undef STORE_8_BYTES -#undef LOAD_4_BYTES - -#define CLIPPING(SIZE) \ - "preceu.ph.qbl %[temp2], %[temp0] \n\t" \ - "preceu.ph.qbr %[temp0], %[temp0] \n\t" \ -".if " #SIZE " == 8 \n\t" \ - "preceu.ph.qbl %[temp3], %[temp1] \n\t" \ - "preceu.ph.qbr %[temp1], %[temp1] \n\t" \ -".endif \n\t" \ - "addu.ph %[temp2], %[temp2], %[dst_1] \n\t" \ - "addu.ph %[temp0], %[temp0], %[dst_1] \n\t" \ -".if " #SIZE " == 8 \n\t" \ - "addu.ph %[temp3], %[temp3], %[dst_1] \n\t" \ - "addu.ph %[temp1], %[temp1], %[dst_1] \n\t" \ -".endif \n\t" \ - "shll_s.ph %[temp2], %[temp2], 7 \n\t" \ - "shll_s.ph %[temp0], %[temp0], 7 \n\t" \ -".if " #SIZE " == 8 \n\t" \ - "shll_s.ph %[temp3], %[temp3], 7 \n\t" \ - "shll_s.ph %[temp1], %[temp1], 7 \n\t" \ -".endif \n\t" \ - "precrqu_s.qb.ph %[temp0], %[temp2], %[temp0] \n\t" \ -".if " #SIZE " == 8 \n\t" \ - "precrqu_s.qb.ph %[temp1], %[temp3], %[temp1] \n\t" \ -".endif \n\t" - - -#define CLIP_8B_TO_DST(DST, TOP, SIZE) do { \ - int dst_1 = ((int)(DST)[-1] << 16) + (DST)[-1]; \ - int temp0, temp1, temp2, temp3; \ - __asm__ volatile ( \ - ".if " #SIZE " < 8 \n\t" \ - "ulw %[temp0], 0(%[top]) \n\t" \ - "subu.ph %[dst_1], %[dst_1], %[top_1] \n\t" \ - CLIPPING(4) \ - "usw %[temp0], 0(%[dst]) \n\t" \ - ".else \n\t" \ - "ulw %[temp0], 0(%[top]) \n\t" \ - "ulw %[temp1], 4(%[top]) \n\t" \ - "subu.ph %[dst_1], %[dst_1], %[top_1] \n\t" \ - CLIPPING(8) \ - "usw %[temp0], 0(%[dst]) \n\t" \ - "usw %[temp1], 4(%[dst]) \n\t" \ - ".if " #SIZE " == 16 \n\t" \ - "ulw %[temp0], 8(%[top]) \n\t" \ - "ulw %[temp1], 12(%[top]) \n\t" \ - CLIPPING(8) \ - "usw %[temp0], 8(%[dst]) \n\t" \ - "usw %[temp1], 12(%[dst]) \n\t" \ - ".endif \n\t" \ - ".endif \n\t" \ - : [dst_1]"+&r"(dst_1), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), \ - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3) \ - : [top_1]"r"(top_1), [top]"r"((TOP)), [dst]"r"((DST)) \ - : "memory" \ - ); \ -} while (0) - -#define CLIP_TO_DST(DST, SIZE) do { \ - int y; \ - const uint8_t* top = (DST) - BPS; \ - const int top_1 = ((int)top[-1] << 16) + top[-1]; \ - for (y = 0; y < (SIZE); ++y) { \ - CLIP_8B_TO_DST((DST), top, (SIZE)); \ - (DST) += BPS; \ - } \ -} while (0) - -#define TRUE_MOTION(DST, SIZE) \ -static void TrueMotion##SIZE(uint8_t* (DST)) { \ - CLIP_TO_DST((DST), (SIZE)); \ -} - -TRUE_MOTION(dst, 4) -TRUE_MOTION(dst, 8) -TRUE_MOTION(dst, 16) - -#undef TRUE_MOTION -#undef CLIP_TO_DST -#undef CLIP_8B_TO_DST -#undef CLIPPING - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8DspInitMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitMIPSdspR2(void) { - VP8TransformDC = TransformDC; - VP8TransformAC3 = TransformAC3; - VP8Transform = TransformTwo; - - VP8VFilter16 = VFilter16; - VP8HFilter16 = HFilter16; - VP8VFilter8 = VFilter8; - VP8HFilter8 = HFilter8; - VP8VFilter16i = VFilter16i; - VP8HFilter16i = HFilter16i; - VP8VFilter8i = VFilter8i; - VP8HFilter8i = HFilter8i; - VP8SimpleVFilter16 = SimpleVFilter16; - VP8SimpleHFilter16 = SimpleHFilter16; - VP8SimpleVFilter16i = SimpleVFilter16i; - VP8SimpleHFilter16i = SimpleHFilter16i; - - VP8PredLuma4[0] = DC4; - VP8PredLuma4[1] = TrueMotion4; - VP8PredLuma4[2] = VE4; - VP8PredLuma4[4] = RD4; - VP8PredLuma4[6] = LD4; - - VP8PredChroma8[0] = DC8uv; - VP8PredChroma8[1] = TrueMotion8; - VP8PredChroma8[4] = DC8uvNoTop; - VP8PredChroma8[5] = DC8uvNoLeft; - - VP8PredLuma16[1] = TrueMotion16; -} - -#else // !WEBP_USE_MIPS_DSP_R2 - -WEBP_DSP_INIT_STUB(VP8DspInitMIPSdspR2) - -#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/Example-Mac/Pods/libwebp/src/dsp/dec_neon.c b/Example-Mac/Pods/libwebp/src/dsp/dec_neon.c deleted file mode 100644 index a63f43fe..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/dec_neon.c +++ /dev/null @@ -1,1639 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// ARM NEON version of dsp functions and loop filtering. -// -// Authors: Somnath Banerjee (somnath@google.com) -// Johann Koenig (johannkoenig@google.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_NEON) - -#include "./neon.h" -#include "../dec/vp8i.h" - -//------------------------------------------------------------------------------ -// NxM Loading functions - -// Load/Store vertical edge -#define LOAD8x4(c1, c2, c3, c4, b1, b2, stride) \ - "vld4.8 {" #c1 "[0]," #c2 "[0]," #c3 "[0]," #c4 "[0]}," #b1 "," #stride "\n" \ - "vld4.8 {" #c1 "[1]," #c2 "[1]," #c3 "[1]," #c4 "[1]}," #b2 "," #stride "\n" \ - "vld4.8 {" #c1 "[2]," #c2 "[2]," #c3 "[2]," #c4 "[2]}," #b1 "," #stride "\n" \ - "vld4.8 {" #c1 "[3]," #c2 "[3]," #c3 "[3]," #c4 "[3]}," #b2 "," #stride "\n" \ - "vld4.8 {" #c1 "[4]," #c2 "[4]," #c3 "[4]," #c4 "[4]}," #b1 "," #stride "\n" \ - "vld4.8 {" #c1 "[5]," #c2 "[5]," #c3 "[5]," #c4 "[5]}," #b2 "," #stride "\n" \ - "vld4.8 {" #c1 "[6]," #c2 "[6]," #c3 "[6]," #c4 "[6]}," #b1 "," #stride "\n" \ - "vld4.8 {" #c1 "[7]," #c2 "[7]," #c3 "[7]," #c4 "[7]}," #b2 "," #stride "\n" - -#define STORE8x2(c1, c2, p, stride) \ - "vst2.8 {" #c1 "[0], " #c2 "[0]}," #p "," #stride " \n" \ - "vst2.8 {" #c1 "[1], " #c2 "[1]}," #p "," #stride " \n" \ - "vst2.8 {" #c1 "[2], " #c2 "[2]}," #p "," #stride " \n" \ - "vst2.8 {" #c1 "[3], " #c2 "[3]}," #p "," #stride " \n" \ - "vst2.8 {" #c1 "[4], " #c2 "[4]}," #p "," #stride " \n" \ - "vst2.8 {" #c1 "[5], " #c2 "[5]}," #p "," #stride " \n" \ - "vst2.8 {" #c1 "[6], " #c2 "[6]}," #p "," #stride " \n" \ - "vst2.8 {" #c1 "[7], " #c2 "[7]}," #p "," #stride " \n" - -#if !defined(WORK_AROUND_GCC) - -// This intrinsics version makes gcc-4.6.3 crash during Load4x??() compilation -// (register alloc, probably). The variants somewhat mitigate the problem, but -// not quite. HFilter16i() remains problematic. -static WEBP_INLINE uint8x8x4_t Load4x8(const uint8_t* const src, int stride) { - const uint8x8_t zero = vdup_n_u8(0); - uint8x8x4_t out; - INIT_VECTOR4(out, zero, zero, zero, zero); - out = vld4_lane_u8(src + 0 * stride, out, 0); - out = vld4_lane_u8(src + 1 * stride, out, 1); - out = vld4_lane_u8(src + 2 * stride, out, 2); - out = vld4_lane_u8(src + 3 * stride, out, 3); - out = vld4_lane_u8(src + 4 * stride, out, 4); - out = vld4_lane_u8(src + 5 * stride, out, 5); - out = vld4_lane_u8(src + 6 * stride, out, 6); - out = vld4_lane_u8(src + 7 * stride, out, 7); - return out; -} - -static WEBP_INLINE void Load4x16(const uint8_t* const src, int stride, - uint8x16_t* const p1, uint8x16_t* const p0, - uint8x16_t* const q0, uint8x16_t* const q1) { - // row0 = p1[0..7]|p0[0..7]|q0[0..7]|q1[0..7] - // row8 = p1[8..15]|p0[8..15]|q0[8..15]|q1[8..15] - const uint8x8x4_t row0 = Load4x8(src - 2 + 0 * stride, stride); - const uint8x8x4_t row8 = Load4x8(src - 2 + 8 * stride, stride); - *p1 = vcombine_u8(row0.val[0], row8.val[0]); - *p0 = vcombine_u8(row0.val[1], row8.val[1]); - *q0 = vcombine_u8(row0.val[2], row8.val[2]); - *q1 = vcombine_u8(row0.val[3], row8.val[3]); -} - -#else // WORK_AROUND_GCC - -#define LOADQ_LANE_32b(VALUE, LANE) do { \ - (VALUE) = vld1q_lane_u32((const uint32_t*)src, (VALUE), (LANE)); \ - src += stride; \ -} while (0) - -static WEBP_INLINE void Load4x16(const uint8_t* src, int stride, - uint8x16_t* const p1, uint8x16_t* const p0, - uint8x16_t* const q0, uint8x16_t* const q1) { - const uint32x4_t zero = vdupq_n_u32(0); - uint32x4x4_t in; - INIT_VECTOR4(in, zero, zero, zero, zero); - src -= 2; - LOADQ_LANE_32b(in.val[0], 0); - LOADQ_LANE_32b(in.val[1], 0); - LOADQ_LANE_32b(in.val[2], 0); - LOADQ_LANE_32b(in.val[3], 0); - LOADQ_LANE_32b(in.val[0], 1); - LOADQ_LANE_32b(in.val[1], 1); - LOADQ_LANE_32b(in.val[2], 1); - LOADQ_LANE_32b(in.val[3], 1); - LOADQ_LANE_32b(in.val[0], 2); - LOADQ_LANE_32b(in.val[1], 2); - LOADQ_LANE_32b(in.val[2], 2); - LOADQ_LANE_32b(in.val[3], 2); - LOADQ_LANE_32b(in.val[0], 3); - LOADQ_LANE_32b(in.val[1], 3); - LOADQ_LANE_32b(in.val[2], 3); - LOADQ_LANE_32b(in.val[3], 3); - // Transpose four 4x4 parts: - { - const uint8x16x2_t row01 = vtrnq_u8(vreinterpretq_u8_u32(in.val[0]), - vreinterpretq_u8_u32(in.val[1])); - const uint8x16x2_t row23 = vtrnq_u8(vreinterpretq_u8_u32(in.val[2]), - vreinterpretq_u8_u32(in.val[3])); - const uint16x8x2_t row02 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[0]), - vreinterpretq_u16_u8(row23.val[0])); - const uint16x8x2_t row13 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[1]), - vreinterpretq_u16_u8(row23.val[1])); - *p1 = vreinterpretq_u8_u16(row02.val[0]); - *p0 = vreinterpretq_u8_u16(row13.val[0]); - *q0 = vreinterpretq_u8_u16(row02.val[1]); - *q1 = vreinterpretq_u8_u16(row13.val[1]); - } -} -#undef LOADQ_LANE_32b - -#endif // !WORK_AROUND_GCC - -static WEBP_INLINE void Load8x16(const uint8_t* const src, int stride, - uint8x16_t* const p3, uint8x16_t* const p2, - uint8x16_t* const p1, uint8x16_t* const p0, - uint8x16_t* const q0, uint8x16_t* const q1, - uint8x16_t* const q2, uint8x16_t* const q3) { - Load4x16(src - 2, stride, p3, p2, p1, p0); - Load4x16(src + 2, stride, q0, q1, q2, q3); -} - -static WEBP_INLINE void Load16x4(const uint8_t* const src, int stride, - uint8x16_t* const p1, uint8x16_t* const p0, - uint8x16_t* const q0, uint8x16_t* const q1) { - *p1 = vld1q_u8(src - 2 * stride); - *p0 = vld1q_u8(src - 1 * stride); - *q0 = vld1q_u8(src + 0 * stride); - *q1 = vld1q_u8(src + 1 * stride); -} - -static WEBP_INLINE void Load16x8(const uint8_t* const src, int stride, - uint8x16_t* const p3, uint8x16_t* const p2, - uint8x16_t* const p1, uint8x16_t* const p0, - uint8x16_t* const q0, uint8x16_t* const q1, - uint8x16_t* const q2, uint8x16_t* const q3) { - Load16x4(src - 2 * stride, stride, p3, p2, p1, p0); - Load16x4(src + 2 * stride, stride, q0, q1, q2, q3); -} - -static WEBP_INLINE void Load8x8x2(const uint8_t* const u, - const uint8_t* const v, - int stride, - uint8x16_t* const p3, uint8x16_t* const p2, - uint8x16_t* const p1, uint8x16_t* const p0, - uint8x16_t* const q0, uint8x16_t* const q1, - uint8x16_t* const q2, uint8x16_t* const q3) { - // We pack the 8x8 u-samples in the lower half of the uint8x16_t destination - // and the v-samples on the higher half. - *p3 = vcombine_u8(vld1_u8(u - 4 * stride), vld1_u8(v - 4 * stride)); - *p2 = vcombine_u8(vld1_u8(u - 3 * stride), vld1_u8(v - 3 * stride)); - *p1 = vcombine_u8(vld1_u8(u - 2 * stride), vld1_u8(v - 2 * stride)); - *p0 = vcombine_u8(vld1_u8(u - 1 * stride), vld1_u8(v - 1 * stride)); - *q0 = vcombine_u8(vld1_u8(u + 0 * stride), vld1_u8(v + 0 * stride)); - *q1 = vcombine_u8(vld1_u8(u + 1 * stride), vld1_u8(v + 1 * stride)); - *q2 = vcombine_u8(vld1_u8(u + 2 * stride), vld1_u8(v + 2 * stride)); - *q3 = vcombine_u8(vld1_u8(u + 3 * stride), vld1_u8(v + 3 * stride)); -} - -#if !defined(WORK_AROUND_GCC) - -#define LOAD_UV_8(ROW) \ - vcombine_u8(vld1_u8(u - 4 + (ROW) * stride), vld1_u8(v - 4 + (ROW) * stride)) - -static WEBP_INLINE void Load8x8x2T(const uint8_t* const u, - const uint8_t* const v, - int stride, - uint8x16_t* const p3, uint8x16_t* const p2, - uint8x16_t* const p1, uint8x16_t* const p0, - uint8x16_t* const q0, uint8x16_t* const q1, - uint8x16_t* const q2, uint8x16_t* const q3) { - // We pack the 8x8 u-samples in the lower half of the uint8x16_t destination - // and the v-samples on the higher half. - const uint8x16_t row0 = LOAD_UV_8(0); - const uint8x16_t row1 = LOAD_UV_8(1); - const uint8x16_t row2 = LOAD_UV_8(2); - const uint8x16_t row3 = LOAD_UV_8(3); - const uint8x16_t row4 = LOAD_UV_8(4); - const uint8x16_t row5 = LOAD_UV_8(5); - const uint8x16_t row6 = LOAD_UV_8(6); - const uint8x16_t row7 = LOAD_UV_8(7); - // Perform two side-by-side 8x8 transposes - // u00 u01 u02 u03 u04 u05 u06 u07 | v00 v01 v02 v03 v04 v05 v06 v07 - // u10 u11 u12 u13 u14 u15 u16 u17 | v10 v11 v12 ... - // u20 u21 u22 u23 u24 u25 u26 u27 | v20 v21 ... - // u30 u31 u32 u33 u34 u35 u36 u37 | ... - // u40 u41 u42 u43 u44 u45 u46 u47 | ... - // u50 u51 u52 u53 u54 u55 u56 u57 | ... - // u60 u61 u62 u63 u64 u65 u66 u67 | v60 ... - // u70 u71 u72 u73 u74 u75 u76 u77 | v70 v71 v72 ... - const uint8x16x2_t row01 = vtrnq_u8(row0, row1); // u00 u10 u02 u12 ... - // u01 u11 u03 u13 ... - const uint8x16x2_t row23 = vtrnq_u8(row2, row3); // u20 u30 u22 u32 ... - // u21 u31 u23 u33 ... - const uint8x16x2_t row45 = vtrnq_u8(row4, row5); // ... - const uint8x16x2_t row67 = vtrnq_u8(row6, row7); // ... - const uint16x8x2_t row02 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[0]), - vreinterpretq_u16_u8(row23.val[0])); - const uint16x8x2_t row13 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[1]), - vreinterpretq_u16_u8(row23.val[1])); - const uint16x8x2_t row46 = vtrnq_u16(vreinterpretq_u16_u8(row45.val[0]), - vreinterpretq_u16_u8(row67.val[0])); - const uint16x8x2_t row57 = vtrnq_u16(vreinterpretq_u16_u8(row45.val[1]), - vreinterpretq_u16_u8(row67.val[1])); - const uint32x4x2_t row04 = vtrnq_u32(vreinterpretq_u32_u16(row02.val[0]), - vreinterpretq_u32_u16(row46.val[0])); - const uint32x4x2_t row26 = vtrnq_u32(vreinterpretq_u32_u16(row02.val[1]), - vreinterpretq_u32_u16(row46.val[1])); - const uint32x4x2_t row15 = vtrnq_u32(vreinterpretq_u32_u16(row13.val[0]), - vreinterpretq_u32_u16(row57.val[0])); - const uint32x4x2_t row37 = vtrnq_u32(vreinterpretq_u32_u16(row13.val[1]), - vreinterpretq_u32_u16(row57.val[1])); - *p3 = vreinterpretq_u8_u32(row04.val[0]); - *p2 = vreinterpretq_u8_u32(row15.val[0]); - *p1 = vreinterpretq_u8_u32(row26.val[0]); - *p0 = vreinterpretq_u8_u32(row37.val[0]); - *q0 = vreinterpretq_u8_u32(row04.val[1]); - *q1 = vreinterpretq_u8_u32(row15.val[1]); - *q2 = vreinterpretq_u8_u32(row26.val[1]); - *q3 = vreinterpretq_u8_u32(row37.val[1]); -} -#undef LOAD_UV_8 - -#endif // !WORK_AROUND_GCC - -static WEBP_INLINE void Store2x8(const uint8x8x2_t v, - uint8_t* const dst, int stride) { - vst2_lane_u8(dst + 0 * stride, v, 0); - vst2_lane_u8(dst + 1 * stride, v, 1); - vst2_lane_u8(dst + 2 * stride, v, 2); - vst2_lane_u8(dst + 3 * stride, v, 3); - vst2_lane_u8(dst + 4 * stride, v, 4); - vst2_lane_u8(dst + 5 * stride, v, 5); - vst2_lane_u8(dst + 6 * stride, v, 6); - vst2_lane_u8(dst + 7 * stride, v, 7); -} - -static WEBP_INLINE void Store2x16(const uint8x16_t p0, const uint8x16_t q0, - uint8_t* const dst, int stride) { - uint8x8x2_t lo, hi; - lo.val[0] = vget_low_u8(p0); - lo.val[1] = vget_low_u8(q0); - hi.val[0] = vget_high_u8(p0); - hi.val[1] = vget_high_u8(q0); - Store2x8(lo, dst - 1 + 0 * stride, stride); - Store2x8(hi, dst - 1 + 8 * stride, stride); -} - -#if !defined(WORK_AROUND_GCC) -static WEBP_INLINE void Store4x8(const uint8x8x4_t v, - uint8_t* const dst, int stride) { - vst4_lane_u8(dst + 0 * stride, v, 0); - vst4_lane_u8(dst + 1 * stride, v, 1); - vst4_lane_u8(dst + 2 * stride, v, 2); - vst4_lane_u8(dst + 3 * stride, v, 3); - vst4_lane_u8(dst + 4 * stride, v, 4); - vst4_lane_u8(dst + 5 * stride, v, 5); - vst4_lane_u8(dst + 6 * stride, v, 6); - vst4_lane_u8(dst + 7 * stride, v, 7); -} - -static WEBP_INLINE void Store4x16(const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - uint8_t* const dst, int stride) { - uint8x8x4_t lo, hi; - INIT_VECTOR4(lo, - vget_low_u8(p1), vget_low_u8(p0), - vget_low_u8(q0), vget_low_u8(q1)); - INIT_VECTOR4(hi, - vget_high_u8(p1), vget_high_u8(p0), - vget_high_u8(q0), vget_high_u8(q1)); - Store4x8(lo, dst - 2 + 0 * stride, stride); - Store4x8(hi, dst - 2 + 8 * stride, stride); -} -#endif // !WORK_AROUND_GCC - -static WEBP_INLINE void Store16x2(const uint8x16_t p0, const uint8x16_t q0, - uint8_t* const dst, int stride) { - vst1q_u8(dst - stride, p0); - vst1q_u8(dst, q0); -} - -static WEBP_INLINE void Store16x4(const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - uint8_t* const dst, int stride) { - Store16x2(p1, p0, dst - stride, stride); - Store16x2(q0, q1, dst + stride, stride); -} - -static WEBP_INLINE void Store8x2x2(const uint8x16_t p0, const uint8x16_t q0, - uint8_t* const u, uint8_t* const v, - int stride) { - // p0 and q0 contain the u+v samples packed in low/high halves. - vst1_u8(u - stride, vget_low_u8(p0)); - vst1_u8(u, vget_low_u8(q0)); - vst1_u8(v - stride, vget_high_u8(p0)); - vst1_u8(v, vget_high_u8(q0)); -} - -static WEBP_INLINE void Store8x4x2(const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - uint8_t* const u, uint8_t* const v, - int stride) { - // The p1...q1 registers contain the u+v samples packed in low/high halves. - Store8x2x2(p1, p0, u - stride, v - stride, stride); - Store8x2x2(q0, q1, u + stride, v + stride, stride); -} - -#if !defined(WORK_AROUND_GCC) - -#define STORE6_LANE(DST, VAL0, VAL1, LANE) do { \ - vst3_lane_u8((DST) - 3, (VAL0), (LANE)); \ - vst3_lane_u8((DST) + 0, (VAL1), (LANE)); \ - (DST) += stride; \ -} while (0) - -static WEBP_INLINE void Store6x8x2(const uint8x16_t p2, const uint8x16_t p1, - const uint8x16_t p0, const uint8x16_t q0, - const uint8x16_t q1, const uint8x16_t q2, - uint8_t* u, uint8_t* v, - int stride) { - uint8x8x3_t u0, u1, v0, v1; - INIT_VECTOR3(u0, vget_low_u8(p2), vget_low_u8(p1), vget_low_u8(p0)); - INIT_VECTOR3(u1, vget_low_u8(q0), vget_low_u8(q1), vget_low_u8(q2)); - INIT_VECTOR3(v0, vget_high_u8(p2), vget_high_u8(p1), vget_high_u8(p0)); - INIT_VECTOR3(v1, vget_high_u8(q0), vget_high_u8(q1), vget_high_u8(q2)); - STORE6_LANE(u, u0, u1, 0); - STORE6_LANE(u, u0, u1, 1); - STORE6_LANE(u, u0, u1, 2); - STORE6_LANE(u, u0, u1, 3); - STORE6_LANE(u, u0, u1, 4); - STORE6_LANE(u, u0, u1, 5); - STORE6_LANE(u, u0, u1, 6); - STORE6_LANE(u, u0, u1, 7); - STORE6_LANE(v, v0, v1, 0); - STORE6_LANE(v, v0, v1, 1); - STORE6_LANE(v, v0, v1, 2); - STORE6_LANE(v, v0, v1, 3); - STORE6_LANE(v, v0, v1, 4); - STORE6_LANE(v, v0, v1, 5); - STORE6_LANE(v, v0, v1, 6); - STORE6_LANE(v, v0, v1, 7); -} -#undef STORE6_LANE - -static WEBP_INLINE void Store4x8x2(const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - uint8_t* const u, uint8_t* const v, - int stride) { - uint8x8x4_t u0, v0; - INIT_VECTOR4(u0, - vget_low_u8(p1), vget_low_u8(p0), - vget_low_u8(q0), vget_low_u8(q1)); - INIT_VECTOR4(v0, - vget_high_u8(p1), vget_high_u8(p0), - vget_high_u8(q0), vget_high_u8(q1)); - vst4_lane_u8(u - 2 + 0 * stride, u0, 0); - vst4_lane_u8(u - 2 + 1 * stride, u0, 1); - vst4_lane_u8(u - 2 + 2 * stride, u0, 2); - vst4_lane_u8(u - 2 + 3 * stride, u0, 3); - vst4_lane_u8(u - 2 + 4 * stride, u0, 4); - vst4_lane_u8(u - 2 + 5 * stride, u0, 5); - vst4_lane_u8(u - 2 + 6 * stride, u0, 6); - vst4_lane_u8(u - 2 + 7 * stride, u0, 7); - vst4_lane_u8(v - 2 + 0 * stride, v0, 0); - vst4_lane_u8(v - 2 + 1 * stride, v0, 1); - vst4_lane_u8(v - 2 + 2 * stride, v0, 2); - vst4_lane_u8(v - 2 + 3 * stride, v0, 3); - vst4_lane_u8(v - 2 + 4 * stride, v0, 4); - vst4_lane_u8(v - 2 + 5 * stride, v0, 5); - vst4_lane_u8(v - 2 + 6 * stride, v0, 6); - vst4_lane_u8(v - 2 + 7 * stride, v0, 7); -} - -#endif // !WORK_AROUND_GCC - -// Zero extend 'v' to an int16x8_t. -static WEBP_INLINE int16x8_t ConvertU8ToS16(uint8x8_t v) { - return vreinterpretq_s16_u16(vmovl_u8(v)); -} - -// Performs unsigned 8b saturation on 'dst01' and 'dst23' storing the result -// to the corresponding rows of 'dst'. -static WEBP_INLINE void SaturateAndStore4x4(uint8_t* const dst, - const int16x8_t dst01, - const int16x8_t dst23) { - // Unsigned saturate to 8b. - const uint8x8_t dst01_u8 = vqmovun_s16(dst01); - const uint8x8_t dst23_u8 = vqmovun_s16(dst23); - - // Store the results. - vst1_lane_u32((uint32_t*)(dst + 0 * BPS), vreinterpret_u32_u8(dst01_u8), 0); - vst1_lane_u32((uint32_t*)(dst + 1 * BPS), vreinterpret_u32_u8(dst01_u8), 1); - vst1_lane_u32((uint32_t*)(dst + 2 * BPS), vreinterpret_u32_u8(dst23_u8), 0); - vst1_lane_u32((uint32_t*)(dst + 3 * BPS), vreinterpret_u32_u8(dst23_u8), 1); -} - -static WEBP_INLINE void Add4x4(const int16x8_t row01, const int16x8_t row23, - uint8_t* const dst) { - uint32x2_t dst01 = vdup_n_u32(0); - uint32x2_t dst23 = vdup_n_u32(0); - - // Load the source pixels. - dst01 = vld1_lane_u32((uint32_t*)(dst + 0 * BPS), dst01, 0); - dst23 = vld1_lane_u32((uint32_t*)(dst + 2 * BPS), dst23, 0); - dst01 = vld1_lane_u32((uint32_t*)(dst + 1 * BPS), dst01, 1); - dst23 = vld1_lane_u32((uint32_t*)(dst + 3 * BPS), dst23, 1); - - { - // Convert to 16b. - const int16x8_t dst01_s16 = ConvertU8ToS16(vreinterpret_u8_u32(dst01)); - const int16x8_t dst23_s16 = ConvertU8ToS16(vreinterpret_u8_u32(dst23)); - - // Descale with rounding. - const int16x8_t out01 = vrsraq_n_s16(dst01_s16, row01, 3); - const int16x8_t out23 = vrsraq_n_s16(dst23_s16, row23, 3); - // Add the inverse transform. - SaturateAndStore4x4(dst, out01, out23); - } -} - -//----------------------------------------------------------------------------- -// Simple In-loop filtering (Paragraph 15.2) - -static uint8x16_t NeedsFilter(const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - int thresh) { - const uint8x16_t thresh_v = vdupq_n_u8((uint8_t)thresh); - const uint8x16_t a_p0_q0 = vabdq_u8(p0, q0); // abs(p0-q0) - const uint8x16_t a_p1_q1 = vabdq_u8(p1, q1); // abs(p1-q1) - const uint8x16_t a_p0_q0_2 = vqaddq_u8(a_p0_q0, a_p0_q0); // 2 * abs(p0-q0) - const uint8x16_t a_p1_q1_2 = vshrq_n_u8(a_p1_q1, 1); // abs(p1-q1) / 2 - const uint8x16_t sum = vqaddq_u8(a_p0_q0_2, a_p1_q1_2); - const uint8x16_t mask = vcgeq_u8(thresh_v, sum); - return mask; -} - -static int8x16_t FlipSign(const uint8x16_t v) { - const uint8x16_t sign_bit = vdupq_n_u8(0x80); - return vreinterpretq_s8_u8(veorq_u8(v, sign_bit)); -} - -static uint8x16_t FlipSignBack(const int8x16_t v) { - const int8x16_t sign_bit = vdupq_n_s8(0x80); - return vreinterpretq_u8_s8(veorq_s8(v, sign_bit)); -} - -static int8x16_t GetBaseDelta(const int8x16_t p1, const int8x16_t p0, - const int8x16_t q0, const int8x16_t q1) { - const int8x16_t q0_p0 = vqsubq_s8(q0, p0); // (q0-p0) - const int8x16_t p1_q1 = vqsubq_s8(p1, q1); // (p1-q1) - const int8x16_t s1 = vqaddq_s8(p1_q1, q0_p0); // (p1-q1) + 1 * (q0 - p0) - const int8x16_t s2 = vqaddq_s8(q0_p0, s1); // (p1-q1) + 2 * (q0 - p0) - const int8x16_t s3 = vqaddq_s8(q0_p0, s2); // (p1-q1) + 3 * (q0 - p0) - return s3; -} - -static int8x16_t GetBaseDelta0(const int8x16_t p0, const int8x16_t q0) { - const int8x16_t q0_p0 = vqsubq_s8(q0, p0); // (q0-p0) - const int8x16_t s1 = vqaddq_s8(q0_p0, q0_p0); // 2 * (q0 - p0) - const int8x16_t s2 = vqaddq_s8(q0_p0, s1); // 3 * (q0 - p0) - return s2; -} - -//------------------------------------------------------------------------------ - -static void ApplyFilter2NoFlip(const int8x16_t p0s, const int8x16_t q0s, - const int8x16_t delta, - int8x16_t* const op0, int8x16_t* const oq0) { - const int8x16_t kCst3 = vdupq_n_s8(0x03); - const int8x16_t kCst4 = vdupq_n_s8(0x04); - const int8x16_t delta_p3 = vqaddq_s8(delta, kCst3); - const int8x16_t delta_p4 = vqaddq_s8(delta, kCst4); - const int8x16_t delta3 = vshrq_n_s8(delta_p3, 3); - const int8x16_t delta4 = vshrq_n_s8(delta_p4, 3); - *op0 = vqaddq_s8(p0s, delta3); - *oq0 = vqsubq_s8(q0s, delta4); -} - -#if defined(WEBP_USE_INTRINSICS) - -static void ApplyFilter2(const int8x16_t p0s, const int8x16_t q0s, - const int8x16_t delta, - uint8x16_t* const op0, uint8x16_t* const oq0) { - const int8x16_t kCst3 = vdupq_n_s8(0x03); - const int8x16_t kCst4 = vdupq_n_s8(0x04); - const int8x16_t delta_p3 = vqaddq_s8(delta, kCst3); - const int8x16_t delta_p4 = vqaddq_s8(delta, kCst4); - const int8x16_t delta3 = vshrq_n_s8(delta_p3, 3); - const int8x16_t delta4 = vshrq_n_s8(delta_p4, 3); - const int8x16_t sp0 = vqaddq_s8(p0s, delta3); - const int8x16_t sq0 = vqsubq_s8(q0s, delta4); - *op0 = FlipSignBack(sp0); - *oq0 = FlipSignBack(sq0); -} - -static void DoFilter2(const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - const uint8x16_t mask, - uint8x16_t* const op0, uint8x16_t* const oq0) { - const int8x16_t p1s = FlipSign(p1); - const int8x16_t p0s = FlipSign(p0); - const int8x16_t q0s = FlipSign(q0); - const int8x16_t q1s = FlipSign(q1); - const int8x16_t delta0 = GetBaseDelta(p1s, p0s, q0s, q1s); - const int8x16_t delta1 = vandq_s8(delta0, vreinterpretq_s8_u8(mask)); - ApplyFilter2(p0s, q0s, delta1, op0, oq0); -} - -static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { - uint8x16_t p1, p0, q0, q1, op0, oq0; - Load16x4(p, stride, &p1, &p0, &q0, &q1); - { - const uint8x16_t mask = NeedsFilter(p1, p0, q0, q1, thresh); - DoFilter2(p1, p0, q0, q1, mask, &op0, &oq0); - } - Store16x2(op0, oq0, p, stride); -} - -static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { - uint8x16_t p1, p0, q0, q1, oq0, op0; - Load4x16(p, stride, &p1, &p0, &q0, &q1); - { - const uint8x16_t mask = NeedsFilter(p1, p0, q0, q1, thresh); - DoFilter2(p1, p0, q0, q1, mask, &op0, &oq0); - } - Store2x16(op0, oq0, p, stride); -} - -#else - -#define QRegs "q0", "q1", "q2", "q3", \ - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" - -#define FLIP_SIGN_BIT2(a, b, s) \ - "veor " #a "," #a "," #s " \n" \ - "veor " #b "," #b "," #s " \n" \ - -#define FLIP_SIGN_BIT4(a, b, c, d, s) \ - FLIP_SIGN_BIT2(a, b, s) \ - FLIP_SIGN_BIT2(c, d, s) \ - -#define NEEDS_FILTER(p1, p0, q0, q1, thresh, mask) \ - "vabd.u8 q15," #p0 "," #q0 " \n" /* abs(p0 - q0) */ \ - "vabd.u8 q14," #p1 "," #q1 " \n" /* abs(p1 - q1) */ \ - "vqadd.u8 q15, q15, q15 \n" /* abs(p0 - q0) * 2 */ \ - "vshr.u8 q14, q14, #1 \n" /* abs(p1 - q1) / 2 */ \ - "vqadd.u8 q15, q15, q14 \n" /* abs(p0 - q0) * 2 + abs(p1 - q1) / 2 */ \ - "vdup.8 q14, " #thresh " \n" \ - "vcge.u8 " #mask ", q14, q15 \n" /* mask <= thresh */ - -#define GET_BASE_DELTA(p1, p0, q0, q1, o) \ - "vqsub.s8 q15," #q0 "," #p0 " \n" /* (q0 - p0) */ \ - "vqsub.s8 " #o "," #p1 "," #q1 " \n" /* (p1 - q1) */ \ - "vqadd.s8 " #o "," #o ", q15 \n" /* (p1 - q1) + 1 * (p0 - q0) */ \ - "vqadd.s8 " #o "," #o ", q15 \n" /* (p1 - q1) + 2 * (p0 - q0) */ \ - "vqadd.s8 " #o "," #o ", q15 \n" /* (p1 - q1) + 3 * (p0 - q0) */ - -#define DO_SIMPLE_FILTER(p0, q0, fl) \ - "vmov.i8 q15, #0x03 \n" \ - "vqadd.s8 q15, q15, " #fl " \n" /* filter1 = filter + 3 */ \ - "vshr.s8 q15, q15, #3 \n" /* filter1 >> 3 */ \ - "vqadd.s8 " #p0 "," #p0 ", q15 \n" /* p0 += filter1 */ \ - \ - "vmov.i8 q15, #0x04 \n" \ - "vqadd.s8 q15, q15, " #fl " \n" /* filter1 = filter + 4 */ \ - "vshr.s8 q15, q15, #3 \n" /* filter2 >> 3 */ \ - "vqsub.s8 " #q0 "," #q0 ", q15 \n" /* q0 -= filter2 */ - -// Applies filter on 2 pixels (p0 and q0) -#define DO_FILTER2(p1, p0, q0, q1, thresh) \ - NEEDS_FILTER(p1, p0, q0, q1, thresh, q9) /* filter mask in q9 */ \ - "vmov.i8 q10, #0x80 \n" /* sign bit */ \ - FLIP_SIGN_BIT4(p1, p0, q0, q1, q10) /* convert to signed value */ \ - GET_BASE_DELTA(p1, p0, q0, q1, q11) /* get filter level */ \ - "vand q9, q9, q11 \n" /* apply filter mask */ \ - DO_SIMPLE_FILTER(p0, q0, q9) /* apply filter */ \ - FLIP_SIGN_BIT2(p0, q0, q10) - -static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { - __asm__ volatile ( - "sub %[p], %[p], %[stride], lsl #1 \n" // p -= 2 * stride - - "vld1.u8 {q1}, [%[p]], %[stride] \n" // p1 - "vld1.u8 {q2}, [%[p]], %[stride] \n" // p0 - "vld1.u8 {q3}, [%[p]], %[stride] \n" // q0 - "vld1.u8 {q12}, [%[p]] \n" // q1 - - DO_FILTER2(q1, q2, q3, q12, %[thresh]) - - "sub %[p], %[p], %[stride], lsl #1 \n" // p -= 2 * stride - - "vst1.u8 {q2}, [%[p]], %[stride] \n" // store op0 - "vst1.u8 {q3}, [%[p]] \n" // store oq0 - : [p] "+r"(p) - : [stride] "r"(stride), [thresh] "r"(thresh) - : "memory", QRegs - ); -} - -static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { - __asm__ volatile ( - "sub r4, %[p], #2 \n" // base1 = p - 2 - "lsl r6, %[stride], #1 \n" // r6 = 2 * stride - "add r5, r4, %[stride] \n" // base2 = base1 + stride - - LOAD8x4(d2, d3, d4, d5, [r4], [r5], r6) - LOAD8x4(d24, d25, d26, d27, [r4], [r5], r6) - "vswp d3, d24 \n" // p1:q1 p0:q3 - "vswp d5, d26 \n" // q0:q2 q1:q4 - "vswp q2, q12 \n" // p1:q1 p0:q2 q0:q3 q1:q4 - - DO_FILTER2(q1, q2, q12, q13, %[thresh]) - - "sub %[p], %[p], #1 \n" // p - 1 - - "vswp d5, d24 \n" - STORE8x2(d4, d5, [%[p]], %[stride]) - STORE8x2(d24, d25, [%[p]], %[stride]) - - : [p] "+r"(p) - : [stride] "r"(stride), [thresh] "r"(thresh) - : "memory", "r4", "r5", "r6", QRegs - ); -} - -#endif // WEBP_USE_INTRINSICS - -static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) { - uint32_t k; - for (k = 3; k != 0; --k) { - p += 4 * stride; - SimpleVFilter16(p, stride, thresh); - } -} - -static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) { - uint32_t k; - for (k = 3; k != 0; --k) { - p += 4; - SimpleHFilter16(p, stride, thresh); - } -} - -//------------------------------------------------------------------------------ -// Complex In-loop filtering (Paragraph 15.3) - -static uint8x16_t NeedsHev(const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - int hev_thresh) { - const uint8x16_t hev_thresh_v = vdupq_n_u8((uint8_t)hev_thresh); - const uint8x16_t a_p1_p0 = vabdq_u8(p1, p0); // abs(p1 - p0) - const uint8x16_t a_q1_q0 = vabdq_u8(q1, q0); // abs(q1 - q0) - const uint8x16_t mask1 = vcgtq_u8(a_p1_p0, hev_thresh_v); - const uint8x16_t mask2 = vcgtq_u8(a_q1_q0, hev_thresh_v); - const uint8x16_t mask = vorrq_u8(mask1, mask2); - return mask; -} - -static uint8x16_t NeedsFilter2(const uint8x16_t p3, const uint8x16_t p2, - const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - const uint8x16_t q2, const uint8x16_t q3, - int ithresh, int thresh) { - const uint8x16_t ithresh_v = vdupq_n_u8((uint8_t)ithresh); - const uint8x16_t a_p3_p2 = vabdq_u8(p3, p2); // abs(p3 - p2) - const uint8x16_t a_p2_p1 = vabdq_u8(p2, p1); // abs(p2 - p1) - const uint8x16_t a_p1_p0 = vabdq_u8(p1, p0); // abs(p1 - p0) - const uint8x16_t a_q3_q2 = vabdq_u8(q3, q2); // abs(q3 - q2) - const uint8x16_t a_q2_q1 = vabdq_u8(q2, q1); // abs(q2 - q1) - const uint8x16_t a_q1_q0 = vabdq_u8(q1, q0); // abs(q1 - q0) - const uint8x16_t max1 = vmaxq_u8(a_p3_p2, a_p2_p1); - const uint8x16_t max2 = vmaxq_u8(a_p1_p0, a_q3_q2); - const uint8x16_t max3 = vmaxq_u8(a_q2_q1, a_q1_q0); - const uint8x16_t max12 = vmaxq_u8(max1, max2); - const uint8x16_t max123 = vmaxq_u8(max12, max3); - const uint8x16_t mask2 = vcgeq_u8(ithresh_v, max123); - const uint8x16_t mask1 = NeedsFilter(p1, p0, q0, q1, thresh); - const uint8x16_t mask = vandq_u8(mask1, mask2); - return mask; -} - -// 4-points filter - -static void ApplyFilter4( - const int8x16_t p1, const int8x16_t p0, - const int8x16_t q0, const int8x16_t q1, - const int8x16_t delta0, - uint8x16_t* const op1, uint8x16_t* const op0, - uint8x16_t* const oq0, uint8x16_t* const oq1) { - const int8x16_t kCst3 = vdupq_n_s8(0x03); - const int8x16_t kCst4 = vdupq_n_s8(0x04); - const int8x16_t delta1 = vqaddq_s8(delta0, kCst4); - const int8x16_t delta2 = vqaddq_s8(delta0, kCst3); - const int8x16_t a1 = vshrq_n_s8(delta1, 3); - const int8x16_t a2 = vshrq_n_s8(delta2, 3); - const int8x16_t a3 = vrshrq_n_s8(a1, 1); // a3 = (a1 + 1) >> 1 - *op0 = FlipSignBack(vqaddq_s8(p0, a2)); // clip(p0 + a2) - *oq0 = FlipSignBack(vqsubq_s8(q0, a1)); // clip(q0 - a1) - *op1 = FlipSignBack(vqaddq_s8(p1, a3)); // clip(p1 + a3) - *oq1 = FlipSignBack(vqsubq_s8(q1, a3)); // clip(q1 - a3) -} - -static void DoFilter4( - const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - const uint8x16_t mask, const uint8x16_t hev_mask, - uint8x16_t* const op1, uint8x16_t* const op0, - uint8x16_t* const oq0, uint8x16_t* const oq1) { - // This is a fused version of DoFilter2() calling ApplyFilter2 directly - const int8x16_t p1s = FlipSign(p1); - int8x16_t p0s = FlipSign(p0); - int8x16_t q0s = FlipSign(q0); - const int8x16_t q1s = FlipSign(q1); - const uint8x16_t simple_lf_mask = vandq_u8(mask, hev_mask); - - // do_filter2 part (simple loopfilter on pixels with hev) - { - const int8x16_t delta = GetBaseDelta(p1s, p0s, q0s, q1s); - const int8x16_t simple_lf_delta = - vandq_s8(delta, vreinterpretq_s8_u8(simple_lf_mask)); - ApplyFilter2NoFlip(p0s, q0s, simple_lf_delta, &p0s, &q0s); - } - - // do_filter4 part (complex loopfilter on pixels without hev) - { - const int8x16_t delta0 = GetBaseDelta0(p0s, q0s); - // we use: (mask & hev_mask) ^ mask = mask & !hev_mask - const uint8x16_t complex_lf_mask = veorq_u8(simple_lf_mask, mask); - const int8x16_t complex_lf_delta = - vandq_s8(delta0, vreinterpretq_s8_u8(complex_lf_mask)); - ApplyFilter4(p1s, p0s, q0s, q1s, complex_lf_delta, op1, op0, oq0, oq1); - } -} - -// 6-points filter - -static void ApplyFilter6( - const int8x16_t p2, const int8x16_t p1, const int8x16_t p0, - const int8x16_t q0, const int8x16_t q1, const int8x16_t q2, - const int8x16_t delta, - uint8x16_t* const op2, uint8x16_t* const op1, uint8x16_t* const op0, - uint8x16_t* const oq0, uint8x16_t* const oq1, uint8x16_t* const oq2) { - const int16x8_t kCst63 = vdupq_n_s16(63); - const int8x8_t kCst27 = vdup_n_s8(27); - const int8x8_t kCst18 = vdup_n_s8(18); - const int8x8_t kCst9 = vdup_n_s8(9); - const int8x8_t delta_lo = vget_low_s8(delta); - const int8x8_t delta_hi = vget_high_s8(delta); - const int16x8_t s1_lo = vmlal_s8(kCst63, kCst27, delta_lo); // 63 + 27 * a - const int16x8_t s1_hi = vmlal_s8(kCst63, kCst27, delta_hi); // 63 + 27 * a - const int16x8_t s2_lo = vmlal_s8(kCst63, kCst18, delta_lo); // 63 + 18 * a - const int16x8_t s2_hi = vmlal_s8(kCst63, kCst18, delta_hi); // 63 + 18 * a - const int16x8_t s3_lo = vmlal_s8(kCst63, kCst9, delta_lo); // 63 + 9 * a - const int16x8_t s3_hi = vmlal_s8(kCst63, kCst9, delta_hi); // 63 + 9 * a - const int8x8_t a1_lo = vqshrn_n_s16(s1_lo, 7); - const int8x8_t a1_hi = vqshrn_n_s16(s1_hi, 7); - const int8x8_t a2_lo = vqshrn_n_s16(s2_lo, 7); - const int8x8_t a2_hi = vqshrn_n_s16(s2_hi, 7); - const int8x8_t a3_lo = vqshrn_n_s16(s3_lo, 7); - const int8x8_t a3_hi = vqshrn_n_s16(s3_hi, 7); - const int8x16_t a1 = vcombine_s8(a1_lo, a1_hi); - const int8x16_t a2 = vcombine_s8(a2_lo, a2_hi); - const int8x16_t a3 = vcombine_s8(a3_lo, a3_hi); - - *op0 = FlipSignBack(vqaddq_s8(p0, a1)); // clip(p0 + a1) - *oq0 = FlipSignBack(vqsubq_s8(q0, a1)); // clip(q0 - q1) - *oq1 = FlipSignBack(vqsubq_s8(q1, a2)); // clip(q1 - a2) - *op1 = FlipSignBack(vqaddq_s8(p1, a2)); // clip(p1 + a2) - *oq2 = FlipSignBack(vqsubq_s8(q2, a3)); // clip(q2 - a3) - *op2 = FlipSignBack(vqaddq_s8(p2, a3)); // clip(p2 + a3) -} - -static void DoFilter6( - const uint8x16_t p2, const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, const uint8x16_t q2, - const uint8x16_t mask, const uint8x16_t hev_mask, - uint8x16_t* const op2, uint8x16_t* const op1, uint8x16_t* const op0, - uint8x16_t* const oq0, uint8x16_t* const oq1, uint8x16_t* const oq2) { - // This is a fused version of DoFilter2() calling ApplyFilter2 directly - const int8x16_t p2s = FlipSign(p2); - const int8x16_t p1s = FlipSign(p1); - int8x16_t p0s = FlipSign(p0); - int8x16_t q0s = FlipSign(q0); - const int8x16_t q1s = FlipSign(q1); - const int8x16_t q2s = FlipSign(q2); - const uint8x16_t simple_lf_mask = vandq_u8(mask, hev_mask); - const int8x16_t delta0 = GetBaseDelta(p1s, p0s, q0s, q1s); - - // do_filter2 part (simple loopfilter on pixels with hev) - { - const int8x16_t simple_lf_delta = - vandq_s8(delta0, vreinterpretq_s8_u8(simple_lf_mask)); - ApplyFilter2NoFlip(p0s, q0s, simple_lf_delta, &p0s, &q0s); - } - - // do_filter6 part (complex loopfilter on pixels without hev) - { - // we use: (mask & hev_mask) ^ mask = mask & !hev_mask - const uint8x16_t complex_lf_mask = veorq_u8(simple_lf_mask, mask); - const int8x16_t complex_lf_delta = - vandq_s8(delta0, vreinterpretq_s8_u8(complex_lf_mask)); - ApplyFilter6(p2s, p1s, p0s, q0s, q1s, q2s, complex_lf_delta, - op2, op1, op0, oq0, oq1, oq2); - } -} - -// on macroblock edges - -static void VFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; - Load16x8(p, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); - { - const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, - ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); - uint8x16_t op2, op1, op0, oq0, oq1, oq2; - DoFilter6(p2, p1, p0, q0, q1, q2, mask, hev_mask, - &op2, &op1, &op0, &oq0, &oq1, &oq2); - Store16x2(op2, op1, p - 2 * stride, stride); - Store16x2(op0, oq0, p + 0 * stride, stride); - Store16x2(oq1, oq2, p + 2 * stride, stride); - } -} - -static void HFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; - Load8x16(p, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); - { - const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, - ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); - uint8x16_t op2, op1, op0, oq0, oq1, oq2; - DoFilter6(p2, p1, p0, q0, q1, q2, mask, hev_mask, - &op2, &op1, &op0, &oq0, &oq1, &oq2); - Store2x16(op2, op1, p - 2, stride); - Store2x16(op0, oq0, p + 0, stride); - Store2x16(oq1, oq2, p + 2, stride); - } -} - -// on three inner edges -static void VFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - uint32_t k; - uint8x16_t p3, p2, p1, p0; - Load16x4(p + 2 * stride, stride, &p3, &p2, &p1, &p0); - for (k = 3; k != 0; --k) { - uint8x16_t q0, q1, q2, q3; - p += 4 * stride; - Load16x4(p + 2 * stride, stride, &q0, &q1, &q2, &q3); - { - const uint8x16_t mask = - NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); - // p3 and p2 are not just temporary variables here: they will be - // re-used for next span. And q2/q3 will become p1/p0 accordingly. - DoFilter4(p1, p0, q0, q1, mask, hev_mask, &p1, &p0, &p3, &p2); - Store16x4(p1, p0, p3, p2, p, stride); - p1 = q2; - p0 = q3; - } - } -} - -#if !defined(WORK_AROUND_GCC) -static void HFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - uint32_t k; - uint8x16_t p3, p2, p1, p0; - Load4x16(p + 2, stride, &p3, &p2, &p1, &p0); - for (k = 3; k != 0; --k) { - uint8x16_t q0, q1, q2, q3; - p += 4; - Load4x16(p + 2, stride, &q0, &q1, &q2, &q3); - { - const uint8x16_t mask = - NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); - DoFilter4(p1, p0, q0, q1, mask, hev_mask, &p1, &p0, &p3, &p2); - Store4x16(p1, p0, p3, p2, p, stride); - p1 = q2; - p0 = q3; - } - } -} -#endif // !WORK_AROUND_GCC - -// 8-pixels wide variant, for chroma filtering -static void VFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; - Load8x8x2(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); - { - const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, - ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); - uint8x16_t op2, op1, op0, oq0, oq1, oq2; - DoFilter6(p2, p1, p0, q0, q1, q2, mask, hev_mask, - &op2, &op1, &op0, &oq0, &oq1, &oq2); - Store8x2x2(op2, op1, u - 2 * stride, v - 2 * stride, stride); - Store8x2x2(op0, oq0, u + 0 * stride, v + 0 * stride, stride); - Store8x2x2(oq1, oq2, u + 2 * stride, v + 2 * stride, stride); - } -} -static void VFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; - u += 4 * stride; - v += 4 * stride; - Load8x8x2(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); - { - const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, - ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); - uint8x16_t op1, op0, oq0, oq1; - DoFilter4(p1, p0, q0, q1, mask, hev_mask, &op1, &op0, &oq0, &oq1); - Store8x4x2(op1, op0, oq0, oq1, u, v, stride); - } -} - -#if !defined(WORK_AROUND_GCC) -static void HFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; - Load8x8x2T(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); - { - const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, - ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); - uint8x16_t op2, op1, op0, oq0, oq1, oq2; - DoFilter6(p2, p1, p0, q0, q1, q2, mask, hev_mask, - &op2, &op1, &op0, &oq0, &oq1, &oq2); - Store6x8x2(op2, op1, op0, oq0, oq1, oq2, u, v, stride); - } -} - -static void HFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; - u += 4; - v += 4; - Load8x8x2T(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); - { - const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, - ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); - uint8x16_t op1, op0, oq0, oq1; - DoFilter4(p1, p0, q0, q1, mask, hev_mask, &op1, &op0, &oq0, &oq1); - Store4x8x2(op1, op0, oq0, oq1, u, v, stride); - } -} -#endif // !WORK_AROUND_GCC - -//----------------------------------------------------------------------------- -// Inverse transforms (Paragraph 14.4) - -// Technically these are unsigned but vqdmulh is only available in signed. -// vqdmulh returns high half (effectively >> 16) but also doubles the value, -// changing the >> 16 to >> 15 and requiring an additional >> 1. -// We use this to our advantage with kC2. The canonical value is 35468. -// However, the high bit is set so treating it as signed will give incorrect -// results. We avoid this by down shifting by 1 here to clear the highest bit. -// Combined with the doubling effect of vqdmulh we get >> 16. -// This can not be applied to kC1 because the lowest bit is set. Down shifting -// the constant would reduce precision. - -// libwebp uses a trick to avoid some extra addition that libvpx does. -// Instead of: -// temp2 = ip[12] + ((ip[12] * cospi8sqrt2minus1) >> 16); -// libwebp adds 1 << 16 to cospi8sqrt2minus1 (kC1). However, this causes the -// same issue with kC1 and vqdmulh that we work around by down shifting kC2 - -static const int16_t kC1 = 20091; -static const int16_t kC2 = 17734; // half of kC2, actually. See comment above. - -#if defined(WEBP_USE_INTRINSICS) -static WEBP_INLINE void Transpose8x2(const int16x8_t in0, const int16x8_t in1, - int16x8x2_t* const out) { - // a0 a1 a2 a3 | b0 b1 b2 b3 => a0 b0 c0 d0 | a1 b1 c1 d1 - // c0 c1 c2 c3 | d0 d1 d2 d3 a2 b2 c2 d2 | a3 b3 c3 d3 - const int16x8x2_t tmp0 = vzipq_s16(in0, in1); // a0 c0 a1 c1 a2 c2 ... - // b0 d0 b1 d1 b2 d2 ... - *out = vzipq_s16(tmp0.val[0], tmp0.val[1]); -} - -static WEBP_INLINE void TransformPass(int16x8x2_t* const rows) { - // {rows} = in0 | in4 - // in8 | in12 - // B1 = in4 | in12 - const int16x8_t B1 = - vcombine_s16(vget_high_s16(rows->val[0]), vget_high_s16(rows->val[1])); - // C0 = kC1 * in4 | kC1 * in12 - // C1 = kC2 * in4 | kC2 * in12 - const int16x8_t C0 = vsraq_n_s16(B1, vqdmulhq_n_s16(B1, kC1), 1); - const int16x8_t C1 = vqdmulhq_n_s16(B1, kC2); - const int16x4_t a = vqadd_s16(vget_low_s16(rows->val[0]), - vget_low_s16(rows->val[1])); // in0 + in8 - const int16x4_t b = vqsub_s16(vget_low_s16(rows->val[0]), - vget_low_s16(rows->val[1])); // in0 - in8 - // c = kC2 * in4 - kC1 * in12 - // d = kC1 * in4 + kC2 * in12 - const int16x4_t c = vqsub_s16(vget_low_s16(C1), vget_high_s16(C0)); - const int16x4_t d = vqadd_s16(vget_low_s16(C0), vget_high_s16(C1)); - const int16x8_t D0 = vcombine_s16(a, b); // D0 = a | b - const int16x8_t D1 = vcombine_s16(d, c); // D1 = d | c - const int16x8_t E0 = vqaddq_s16(D0, D1); // a+d | b+c - const int16x8_t E_tmp = vqsubq_s16(D0, D1); // a-d | b-c - const int16x8_t E1 = vcombine_s16(vget_high_s16(E_tmp), vget_low_s16(E_tmp)); - Transpose8x2(E0, E1, rows); -} - -static void TransformOne(const int16_t* in, uint8_t* dst) { - int16x8x2_t rows; - INIT_VECTOR2(rows, vld1q_s16(in + 0), vld1q_s16(in + 8)); - TransformPass(&rows); - TransformPass(&rows); - Add4x4(rows.val[0], rows.val[1], dst); -} - -#else - -static void TransformOne(const int16_t* in, uint8_t* dst) { - const int kBPS = BPS; - // kC1, kC2. Padded because vld1.16 loads 8 bytes - const int16_t constants[4] = { kC1, kC2, 0, 0 }; - /* Adapted from libvpx: vp8/common/arm/neon/shortidct4x4llm_neon.asm */ - __asm__ volatile ( - "vld1.16 {q1, q2}, [%[in]] \n" - "vld1.16 {d0}, [%[constants]] \n" - - /* d2: in[0] - * d3: in[8] - * d4: in[4] - * d5: in[12] - */ - "vswp d3, d4 \n" - - /* q8 = {in[4], in[12]} * kC1 * 2 >> 16 - * q9 = {in[4], in[12]} * kC2 >> 16 - */ - "vqdmulh.s16 q8, q2, d0[0] \n" - "vqdmulh.s16 q9, q2, d0[1] \n" - - /* d22 = a = in[0] + in[8] - * d23 = b = in[0] - in[8] - */ - "vqadd.s16 d22, d2, d3 \n" - "vqsub.s16 d23, d2, d3 \n" - - /* The multiplication should be x * kC1 >> 16 - * However, with vqdmulh we get x * kC1 * 2 >> 16 - * (multiply, double, return high half) - * We avoided this in kC2 by pre-shifting the constant. - * q8 = in[4]/[12] * kC1 >> 16 - */ - "vshr.s16 q8, q8, #1 \n" - - /* Add {in[4], in[12]} back after the multiplication. This is handled by - * adding 1 << 16 to kC1 in the libwebp C code. - */ - "vqadd.s16 q8, q2, q8 \n" - - /* d20 = c = in[4]*kC2 - in[12]*kC1 - * d21 = d = in[4]*kC1 + in[12]*kC2 - */ - "vqsub.s16 d20, d18, d17 \n" - "vqadd.s16 d21, d19, d16 \n" - - /* d2 = tmp[0] = a + d - * d3 = tmp[1] = b + c - * d4 = tmp[2] = b - c - * d5 = tmp[3] = a - d - */ - "vqadd.s16 d2, d22, d21 \n" - "vqadd.s16 d3, d23, d20 \n" - "vqsub.s16 d4, d23, d20 \n" - "vqsub.s16 d5, d22, d21 \n" - - "vzip.16 q1, q2 \n" - "vzip.16 q1, q2 \n" - - "vswp d3, d4 \n" - - /* q8 = {tmp[4], tmp[12]} * kC1 * 2 >> 16 - * q9 = {tmp[4], tmp[12]} * kC2 >> 16 - */ - "vqdmulh.s16 q8, q2, d0[0] \n" - "vqdmulh.s16 q9, q2, d0[1] \n" - - /* d22 = a = tmp[0] + tmp[8] - * d23 = b = tmp[0] - tmp[8] - */ - "vqadd.s16 d22, d2, d3 \n" - "vqsub.s16 d23, d2, d3 \n" - - /* See long winded explanations prior */ - "vshr.s16 q8, q8, #1 \n" - "vqadd.s16 q8, q2, q8 \n" - - /* d20 = c = in[4]*kC2 - in[12]*kC1 - * d21 = d = in[4]*kC1 + in[12]*kC2 - */ - "vqsub.s16 d20, d18, d17 \n" - "vqadd.s16 d21, d19, d16 \n" - - /* d2 = tmp[0] = a + d - * d3 = tmp[1] = b + c - * d4 = tmp[2] = b - c - * d5 = tmp[3] = a - d - */ - "vqadd.s16 d2, d22, d21 \n" - "vqadd.s16 d3, d23, d20 \n" - "vqsub.s16 d4, d23, d20 \n" - "vqsub.s16 d5, d22, d21 \n" - - "vld1.32 d6[0], [%[dst]], %[kBPS] \n" - "vld1.32 d6[1], [%[dst]], %[kBPS] \n" - "vld1.32 d7[0], [%[dst]], %[kBPS] \n" - "vld1.32 d7[1], [%[dst]], %[kBPS] \n" - - "sub %[dst], %[dst], %[kBPS], lsl #2 \n" - - /* (val) + 4 >> 3 */ - "vrshr.s16 d2, d2, #3 \n" - "vrshr.s16 d3, d3, #3 \n" - "vrshr.s16 d4, d4, #3 \n" - "vrshr.s16 d5, d5, #3 \n" - - "vzip.16 q1, q2 \n" - "vzip.16 q1, q2 \n" - - /* Must accumulate before saturating */ - "vmovl.u8 q8, d6 \n" - "vmovl.u8 q9, d7 \n" - - "vqadd.s16 q1, q1, q8 \n" - "vqadd.s16 q2, q2, q9 \n" - - "vqmovun.s16 d0, q1 \n" - "vqmovun.s16 d1, q2 \n" - - "vst1.32 d0[0], [%[dst]], %[kBPS] \n" - "vst1.32 d0[1], [%[dst]], %[kBPS] \n" - "vst1.32 d1[0], [%[dst]], %[kBPS] \n" - "vst1.32 d1[1], [%[dst]] \n" - - : [in] "+r"(in), [dst] "+r"(dst) /* modified registers */ - : [kBPS] "r"(kBPS), [constants] "r"(constants) /* constants */ - : "memory", "q0", "q1", "q2", "q8", "q9", "q10", "q11" /* clobbered */ - ); -} - -#endif // WEBP_USE_INTRINSICS - -static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) { - TransformOne(in, dst); - if (do_two) { - TransformOne(in + 16, dst + 4); - } -} - -static void TransformDC(const int16_t* in, uint8_t* dst) { - const int16x8_t DC = vdupq_n_s16(in[0]); - Add4x4(DC, DC, dst); -} - -//------------------------------------------------------------------------------ - -#define STORE_WHT(dst, col, rows) do { \ - *dst = vgetq_lane_s32(rows.val[0], col); (dst) += 16; \ - *dst = vgetq_lane_s32(rows.val[1], col); (dst) += 16; \ - *dst = vgetq_lane_s32(rows.val[2], col); (dst) += 16; \ - *dst = vgetq_lane_s32(rows.val[3], col); (dst) += 16; \ -} while (0) - -static void TransformWHT(const int16_t* in, int16_t* out) { - int32x4x4_t tmp; - - { - // Load the source. - const int16x4_t in00_03 = vld1_s16(in + 0); - const int16x4_t in04_07 = vld1_s16(in + 4); - const int16x4_t in08_11 = vld1_s16(in + 8); - const int16x4_t in12_15 = vld1_s16(in + 12); - const int32x4_t a0 = vaddl_s16(in00_03, in12_15); // in[0..3] + in[12..15] - const int32x4_t a1 = vaddl_s16(in04_07, in08_11); // in[4..7] + in[8..11] - const int32x4_t a2 = vsubl_s16(in04_07, in08_11); // in[4..7] - in[8..11] - const int32x4_t a3 = vsubl_s16(in00_03, in12_15); // in[0..3] - in[12..15] - tmp.val[0] = vaddq_s32(a0, a1); - tmp.val[1] = vaddq_s32(a3, a2); - tmp.val[2] = vsubq_s32(a0, a1); - tmp.val[3] = vsubq_s32(a3, a2); - // Arrange the temporary results column-wise. - tmp = Transpose4x4(tmp); - } - - { - const int32x4_t kCst3 = vdupq_n_s32(3); - const int32x4_t dc = vaddq_s32(tmp.val[0], kCst3); // add rounder - const int32x4_t a0 = vaddq_s32(dc, tmp.val[3]); - const int32x4_t a1 = vaddq_s32(tmp.val[1], tmp.val[2]); - const int32x4_t a2 = vsubq_s32(tmp.val[1], tmp.val[2]); - const int32x4_t a3 = vsubq_s32(dc, tmp.val[3]); - - tmp.val[0] = vaddq_s32(a0, a1); - tmp.val[1] = vaddq_s32(a3, a2); - tmp.val[2] = vsubq_s32(a0, a1); - tmp.val[3] = vsubq_s32(a3, a2); - - // right shift the results by 3. - tmp.val[0] = vshrq_n_s32(tmp.val[0], 3); - tmp.val[1] = vshrq_n_s32(tmp.val[1], 3); - tmp.val[2] = vshrq_n_s32(tmp.val[2], 3); - tmp.val[3] = vshrq_n_s32(tmp.val[3], 3); - - STORE_WHT(out, 0, tmp); - STORE_WHT(out, 1, tmp); - STORE_WHT(out, 2, tmp); - STORE_WHT(out, 3, tmp); - } -} - -#undef STORE_WHT - -//------------------------------------------------------------------------------ - -#define MUL(a, b) (((a) * (b)) >> 16) -static void TransformAC3(const int16_t* in, uint8_t* dst) { - static const int kC1_full = 20091 + (1 << 16); - static const int kC2_full = 35468; - const int16x4_t A = vld1_dup_s16(in); - const int16x4_t c4 = vdup_n_s16(MUL(in[4], kC2_full)); - const int16x4_t d4 = vdup_n_s16(MUL(in[4], kC1_full)); - const int c1 = MUL(in[1], kC2_full); - const int d1 = MUL(in[1], kC1_full); - const uint64_t cd = (uint64_t)( d1 & 0xffff) << 0 | - (uint64_t)( c1 & 0xffff) << 16 | - (uint64_t)(-c1 & 0xffff) << 32 | - (uint64_t)(-d1 & 0xffff) << 48; - const int16x4_t CD = vcreate_s16(cd); - const int16x4_t B = vqadd_s16(A, CD); - const int16x8_t m0_m1 = vcombine_s16(vqadd_s16(B, d4), vqadd_s16(B, c4)); - const int16x8_t m2_m3 = vcombine_s16(vqsub_s16(B, c4), vqsub_s16(B, d4)); - Add4x4(m0_m1, m2_m3, dst); -} -#undef MUL - -//------------------------------------------------------------------------------ -// 4x4 - -static void DC4(uint8_t* dst) { // DC - const uint8x8_t A = vld1_u8(dst - BPS); // top row - const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top - const uint16x4_t p1 = vpadd_u16(p0, p0); - const uint16x8_t L0 = vmovl_u8(vld1_u8(dst + 0 * BPS - 1)); - const uint16x8_t L1 = vmovl_u8(vld1_u8(dst + 1 * BPS - 1)); - const uint16x8_t L2 = vmovl_u8(vld1_u8(dst + 2 * BPS - 1)); - const uint16x8_t L3 = vmovl_u8(vld1_u8(dst + 3 * BPS - 1)); - const uint16x8_t s0 = vaddq_u16(L0, L1); - const uint16x8_t s1 = vaddq_u16(L2, L3); - const uint16x8_t s01 = vaddq_u16(s0, s1); - const uint16x8_t sum = vaddq_u16(s01, vcombine_u16(p1, p1)); - const uint8x8_t dc0 = vrshrn_n_u16(sum, 3); // (sum + 4) >> 3 - const uint8x8_t dc = vdup_lane_u8(dc0, 0); - int i; - for (i = 0; i < 4; ++i) { - vst1_lane_u32((uint32_t*)(dst + i * BPS), vreinterpret_u32_u8(dc), 0); - } -} - -// TrueMotion (4x4 + 8x8) -static WEBP_INLINE void TrueMotion(uint8_t* dst, int size) { - const uint8x8_t TL = vld1_dup_u8(dst - BPS - 1); // top-left pixel 'A[-1]' - const uint8x8_t T = vld1_u8(dst - BPS); // top row 'A[0..3]' - const int16x8_t d = vreinterpretq_s16_u16(vsubl_u8(T, TL)); // A[c] - A[-1] - int y; - for (y = 0; y < size; y += 4) { - // left edge - const int16x8_t L0 = ConvertU8ToS16(vld1_dup_u8(dst + 0 * BPS - 1)); - const int16x8_t L1 = ConvertU8ToS16(vld1_dup_u8(dst + 1 * BPS - 1)); - const int16x8_t L2 = ConvertU8ToS16(vld1_dup_u8(dst + 2 * BPS - 1)); - const int16x8_t L3 = ConvertU8ToS16(vld1_dup_u8(dst + 3 * BPS - 1)); - const int16x8_t r0 = vaddq_s16(L0, d); // L[r] + A[c] - A[-1] - const int16x8_t r1 = vaddq_s16(L1, d); - const int16x8_t r2 = vaddq_s16(L2, d); - const int16x8_t r3 = vaddq_s16(L3, d); - // Saturate and store the result. - const uint32x2_t r0_u32 = vreinterpret_u32_u8(vqmovun_s16(r0)); - const uint32x2_t r1_u32 = vreinterpret_u32_u8(vqmovun_s16(r1)); - const uint32x2_t r2_u32 = vreinterpret_u32_u8(vqmovun_s16(r2)); - const uint32x2_t r3_u32 = vreinterpret_u32_u8(vqmovun_s16(r3)); - if (size == 4) { - vst1_lane_u32((uint32_t*)(dst + 0 * BPS), r0_u32, 0); - vst1_lane_u32((uint32_t*)(dst + 1 * BPS), r1_u32, 0); - vst1_lane_u32((uint32_t*)(dst + 2 * BPS), r2_u32, 0); - vst1_lane_u32((uint32_t*)(dst + 3 * BPS), r3_u32, 0); - } else { - vst1_u32((uint32_t*)(dst + 0 * BPS), r0_u32); - vst1_u32((uint32_t*)(dst + 1 * BPS), r1_u32); - vst1_u32((uint32_t*)(dst + 2 * BPS), r2_u32); - vst1_u32((uint32_t*)(dst + 3 * BPS), r3_u32); - } - dst += 4 * BPS; - } -} - -static void TM4(uint8_t* dst) { TrueMotion(dst, 4); } - -static void VE4(uint8_t* dst) { // vertical - // NB: avoid vld1_u64 here as an alignment hint may be added -> SIGBUS. - const uint64x1_t A0 = vreinterpret_u64_u8(vld1_u8(dst - BPS - 1)); // top row - const uint64x1_t A1 = vshr_n_u64(A0, 8); - const uint64x1_t A2 = vshr_n_u64(A0, 16); - const uint8x8_t ABCDEFGH = vreinterpret_u8_u64(A0); - const uint8x8_t BCDEFGH0 = vreinterpret_u8_u64(A1); - const uint8x8_t CDEFGH00 = vreinterpret_u8_u64(A2); - const uint8x8_t b = vhadd_u8(ABCDEFGH, CDEFGH00); - const uint8x8_t avg = vrhadd_u8(b, BCDEFGH0); - int i; - for (i = 0; i < 4; ++i) { - vst1_lane_u32((uint32_t*)(dst + i * BPS), vreinterpret_u32_u8(avg), 0); - } -} - -static void RD4(uint8_t* dst) { // Down-right - const uint8x8_t XABCD_u8 = vld1_u8(dst - BPS - 1); - const uint64x1_t XABCD = vreinterpret_u64_u8(XABCD_u8); - const uint64x1_t ____XABC = vshl_n_u64(XABCD, 32); - const uint32_t I = dst[-1 + 0 * BPS]; - const uint32_t J = dst[-1 + 1 * BPS]; - const uint32_t K = dst[-1 + 2 * BPS]; - const uint32_t L = dst[-1 + 3 * BPS]; - const uint64x1_t LKJI____ = vcreate_u64(L | (K << 8) | (J << 16) | (I << 24)); - const uint64x1_t LKJIXABC = vorr_u64(LKJI____, ____XABC); - const uint8x8_t KJIXABC_ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 8)); - const uint8x8_t JIXABC__ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 16)); - const uint8_t D = vget_lane_u8(XABCD_u8, 4); - const uint8x8_t JIXABCD_ = vset_lane_u8(D, JIXABC__, 6); - const uint8x8_t LKJIXABC_u8 = vreinterpret_u8_u64(LKJIXABC); - const uint8x8_t avg1 = vhadd_u8(JIXABCD_, LKJIXABC_u8); - const uint8x8_t avg2 = vrhadd_u8(avg1, KJIXABC_); - const uint64x1_t avg2_u64 = vreinterpret_u64_u8(avg2); - const uint32x2_t r3 = vreinterpret_u32_u8(avg2); - const uint32x2_t r2 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 8)); - const uint32x2_t r1 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 16)); - const uint32x2_t r0 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 24)); - vst1_lane_u32((uint32_t*)(dst + 0 * BPS), r0, 0); - vst1_lane_u32((uint32_t*)(dst + 1 * BPS), r1, 0); - vst1_lane_u32((uint32_t*)(dst + 2 * BPS), r2, 0); - vst1_lane_u32((uint32_t*)(dst + 3 * BPS), r3, 0); -} - -static void LD4(uint8_t* dst) { // Down-left - // Note using the same shift trick as VE4() is slower here. - const uint8x8_t ABCDEFGH = vld1_u8(dst - BPS + 0); - const uint8x8_t BCDEFGH0 = vld1_u8(dst - BPS + 1); - const uint8x8_t CDEFGH00 = vld1_u8(dst - BPS + 2); - const uint8x8_t CDEFGHH0 = vset_lane_u8(dst[-BPS + 7], CDEFGH00, 6); - const uint8x8_t avg1 = vhadd_u8(ABCDEFGH, CDEFGHH0); - const uint8x8_t avg2 = vrhadd_u8(avg1, BCDEFGH0); - const uint64x1_t avg2_u64 = vreinterpret_u64_u8(avg2); - const uint32x2_t r0 = vreinterpret_u32_u8(avg2); - const uint32x2_t r1 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 8)); - const uint32x2_t r2 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 16)); - const uint32x2_t r3 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 24)); - vst1_lane_u32((uint32_t*)(dst + 0 * BPS), r0, 0); - vst1_lane_u32((uint32_t*)(dst + 1 * BPS), r1, 0); - vst1_lane_u32((uint32_t*)(dst + 2 * BPS), r2, 0); - vst1_lane_u32((uint32_t*)(dst + 3 * BPS), r3, 0); -} - -//------------------------------------------------------------------------------ -// Chroma - -static void VE8uv(uint8_t* dst) { // vertical - const uint8x8_t top = vld1_u8(dst - BPS); - int j; - for (j = 0; j < 8; ++j) { - vst1_u8(dst + j * BPS, top); - } -} - -static void HE8uv(uint8_t* dst) { // horizontal - int j; - for (j = 0; j < 8; ++j) { - const uint8x8_t left = vld1_dup_u8(dst - 1); - vst1_u8(dst, left); - dst += BPS; - } -} - -static WEBP_INLINE void DC8(uint8_t* dst, int do_top, int do_left) { - uint16x8_t sum_top; - uint16x8_t sum_left; - uint8x8_t dc0; - - if (do_top) { - const uint8x8_t A = vld1_u8(dst - BPS); // top row - const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top - const uint16x4_t p1 = vpadd_u16(p0, p0); - const uint16x4_t p2 = vpadd_u16(p1, p1); - sum_top = vcombine_u16(p2, p2); - } - - if (do_left) { - const uint16x8_t L0 = vmovl_u8(vld1_u8(dst + 0 * BPS - 1)); - const uint16x8_t L1 = vmovl_u8(vld1_u8(dst + 1 * BPS - 1)); - const uint16x8_t L2 = vmovl_u8(vld1_u8(dst + 2 * BPS - 1)); - const uint16x8_t L3 = vmovl_u8(vld1_u8(dst + 3 * BPS - 1)); - const uint16x8_t L4 = vmovl_u8(vld1_u8(dst + 4 * BPS - 1)); - const uint16x8_t L5 = vmovl_u8(vld1_u8(dst + 5 * BPS - 1)); - const uint16x8_t L6 = vmovl_u8(vld1_u8(dst + 6 * BPS - 1)); - const uint16x8_t L7 = vmovl_u8(vld1_u8(dst + 7 * BPS - 1)); - const uint16x8_t s0 = vaddq_u16(L0, L1); - const uint16x8_t s1 = vaddq_u16(L2, L3); - const uint16x8_t s2 = vaddq_u16(L4, L5); - const uint16x8_t s3 = vaddq_u16(L6, L7); - const uint16x8_t s01 = vaddq_u16(s0, s1); - const uint16x8_t s23 = vaddq_u16(s2, s3); - sum_left = vaddq_u16(s01, s23); - } - - if (do_top && do_left) { - const uint16x8_t sum = vaddq_u16(sum_left, sum_top); - dc0 = vrshrn_n_u16(sum, 4); - } else if (do_top) { - dc0 = vrshrn_n_u16(sum_top, 3); - } else if (do_left) { - dc0 = vrshrn_n_u16(sum_left, 3); - } else { - dc0 = vdup_n_u8(0x80); - } - - { - const uint8x8_t dc = vdup_lane_u8(dc0, 0); - int i; - for (i = 0; i < 8; ++i) { - vst1_u32((uint32_t*)(dst + i * BPS), vreinterpret_u32_u8(dc)); - } - } -} - -static void DC8uv(uint8_t* dst) { DC8(dst, 1, 1); } -static void DC8uvNoTop(uint8_t* dst) { DC8(dst, 0, 1); } -static void DC8uvNoLeft(uint8_t* dst) { DC8(dst, 1, 0); } -static void DC8uvNoTopLeft(uint8_t* dst) { DC8(dst, 0, 0); } - -static void TM8uv(uint8_t* dst) { TrueMotion(dst, 8); } - -//------------------------------------------------------------------------------ -// 16x16 - -static void VE16(uint8_t* dst) { // vertical - const uint8x16_t top = vld1q_u8(dst - BPS); - int j; - for (j = 0; j < 16; ++j) { - vst1q_u8(dst + j * BPS, top); - } -} - -static void HE16(uint8_t* dst) { // horizontal - int j; - for (j = 0; j < 16; ++j) { - const uint8x16_t left = vld1q_dup_u8(dst - 1); - vst1q_u8(dst, left); - dst += BPS; - } -} - -static WEBP_INLINE void DC16(uint8_t* dst, int do_top, int do_left) { - uint16x8_t sum_top; - uint16x8_t sum_left; - uint8x8_t dc0; - - if (do_top) { - const uint8x16_t A = vld1q_u8(dst - BPS); // top row - const uint16x8_t p0 = vpaddlq_u8(A); // cascading summation of the top - const uint16x4_t p1 = vadd_u16(vget_low_u16(p0), vget_high_u16(p0)); - const uint16x4_t p2 = vpadd_u16(p1, p1); - const uint16x4_t p3 = vpadd_u16(p2, p2); - sum_top = vcombine_u16(p3, p3); - } - - if (do_left) { - int i; - sum_left = vdupq_n_u16(0); - for (i = 0; i < 16; i += 8) { - const uint16x8_t L0 = vmovl_u8(vld1_u8(dst + (i + 0) * BPS - 1)); - const uint16x8_t L1 = vmovl_u8(vld1_u8(dst + (i + 1) * BPS - 1)); - const uint16x8_t L2 = vmovl_u8(vld1_u8(dst + (i + 2) * BPS - 1)); - const uint16x8_t L3 = vmovl_u8(vld1_u8(dst + (i + 3) * BPS - 1)); - const uint16x8_t L4 = vmovl_u8(vld1_u8(dst + (i + 4) * BPS - 1)); - const uint16x8_t L5 = vmovl_u8(vld1_u8(dst + (i + 5) * BPS - 1)); - const uint16x8_t L6 = vmovl_u8(vld1_u8(dst + (i + 6) * BPS - 1)); - const uint16x8_t L7 = vmovl_u8(vld1_u8(dst + (i + 7) * BPS - 1)); - const uint16x8_t s0 = vaddq_u16(L0, L1); - const uint16x8_t s1 = vaddq_u16(L2, L3); - const uint16x8_t s2 = vaddq_u16(L4, L5); - const uint16x8_t s3 = vaddq_u16(L6, L7); - const uint16x8_t s01 = vaddq_u16(s0, s1); - const uint16x8_t s23 = vaddq_u16(s2, s3); - const uint16x8_t sum = vaddq_u16(s01, s23); - sum_left = vaddq_u16(sum_left, sum); - } - } - - if (do_top && do_left) { - const uint16x8_t sum = vaddq_u16(sum_left, sum_top); - dc0 = vrshrn_n_u16(sum, 5); - } else if (do_top) { - dc0 = vrshrn_n_u16(sum_top, 4); - } else if (do_left) { - dc0 = vrshrn_n_u16(sum_left, 4); - } else { - dc0 = vdup_n_u8(0x80); - } - - { - const uint8x16_t dc = vdupq_lane_u8(dc0, 0); - int i; - for (i = 0; i < 16; ++i) { - vst1q_u8(dst + i * BPS, dc); - } - } -} - -static void DC16TopLeft(uint8_t* dst) { DC16(dst, 1, 1); } -static void DC16NoTop(uint8_t* dst) { DC16(dst, 0, 1); } -static void DC16NoLeft(uint8_t* dst) { DC16(dst, 1, 0); } -static void DC16NoTopLeft(uint8_t* dst) { DC16(dst, 0, 0); } - -static void TM16(uint8_t* dst) { - const uint8x8_t TL = vld1_dup_u8(dst - BPS - 1); // top-left pixel 'A[-1]' - const uint8x16_t T = vld1q_u8(dst - BPS); // top row 'A[0..15]' - // A[c] - A[-1] - const int16x8_t d_lo = vreinterpretq_s16_u16(vsubl_u8(vget_low_u8(T), TL)); - const int16x8_t d_hi = vreinterpretq_s16_u16(vsubl_u8(vget_high_u8(T), TL)); - int y; - for (y = 0; y < 16; y += 4) { - // left edge - const int16x8_t L0 = ConvertU8ToS16(vld1_dup_u8(dst + 0 * BPS - 1)); - const int16x8_t L1 = ConvertU8ToS16(vld1_dup_u8(dst + 1 * BPS - 1)); - const int16x8_t L2 = ConvertU8ToS16(vld1_dup_u8(dst + 2 * BPS - 1)); - const int16x8_t L3 = ConvertU8ToS16(vld1_dup_u8(dst + 3 * BPS - 1)); - const int16x8_t r0_lo = vaddq_s16(L0, d_lo); // L[r] + A[c] - A[-1] - const int16x8_t r1_lo = vaddq_s16(L1, d_lo); - const int16x8_t r2_lo = vaddq_s16(L2, d_lo); - const int16x8_t r3_lo = vaddq_s16(L3, d_lo); - const int16x8_t r0_hi = vaddq_s16(L0, d_hi); - const int16x8_t r1_hi = vaddq_s16(L1, d_hi); - const int16x8_t r2_hi = vaddq_s16(L2, d_hi); - const int16x8_t r3_hi = vaddq_s16(L3, d_hi); - // Saturate and store the result. - const uint8x16_t row0 = vcombine_u8(vqmovun_s16(r0_lo), vqmovun_s16(r0_hi)); - const uint8x16_t row1 = vcombine_u8(vqmovun_s16(r1_lo), vqmovun_s16(r1_hi)); - const uint8x16_t row2 = vcombine_u8(vqmovun_s16(r2_lo), vqmovun_s16(r2_hi)); - const uint8x16_t row3 = vcombine_u8(vqmovun_s16(r3_lo), vqmovun_s16(r3_hi)); - vst1q_u8(dst + 0 * BPS, row0); - vst1q_u8(dst + 1 * BPS, row1); - vst1q_u8(dst + 2 * BPS, row2); - vst1q_u8(dst + 3 * BPS, row3); - dst += 4 * BPS; - } -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8DspInitNEON(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitNEON(void) { - VP8Transform = TransformTwo; - VP8TransformAC3 = TransformAC3; - VP8TransformDC = TransformDC; - VP8TransformWHT = TransformWHT; - - VP8VFilter16 = VFilter16; - VP8VFilter16i = VFilter16i; - VP8HFilter16 = HFilter16; -#if !defined(WORK_AROUND_GCC) - VP8HFilter16i = HFilter16i; -#endif - VP8VFilter8 = VFilter8; - VP8VFilter8i = VFilter8i; -#if !defined(WORK_AROUND_GCC) - VP8HFilter8 = HFilter8; - VP8HFilter8i = HFilter8i; -#endif - VP8SimpleVFilter16 = SimpleVFilter16; - VP8SimpleHFilter16 = SimpleHFilter16; - VP8SimpleVFilter16i = SimpleVFilter16i; - VP8SimpleHFilter16i = SimpleHFilter16i; - - VP8PredLuma4[0] = DC4; - VP8PredLuma4[1] = TM4; - VP8PredLuma4[2] = VE4; - VP8PredLuma4[4] = RD4; - VP8PredLuma4[6] = LD4; - - VP8PredLuma16[0] = DC16TopLeft; - VP8PredLuma16[1] = TM16; - VP8PredLuma16[2] = VE16; - VP8PredLuma16[3] = HE16; - VP8PredLuma16[4] = DC16NoTop; - VP8PredLuma16[5] = DC16NoLeft; - VP8PredLuma16[6] = DC16NoTopLeft; - - VP8PredChroma8[0] = DC8uv; - VP8PredChroma8[1] = TM8uv; - VP8PredChroma8[2] = VE8uv; - VP8PredChroma8[3] = HE8uv; - VP8PredChroma8[4] = DC8uvNoTop; - VP8PredChroma8[5] = DC8uvNoLeft; - VP8PredChroma8[6] = DC8uvNoTopLeft; -} - -#else // !WEBP_USE_NEON - -WEBP_DSP_INIT_STUB(VP8DspInitNEON) - -#endif // WEBP_USE_NEON diff --git a/Example-Mac/Pods/libwebp/src/dsp/dec_sse2.c b/Example-Mac/Pods/libwebp/src/dsp/dec_sse2.c deleted file mode 100644 index 935bf02e..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/dec_sse2.c +++ /dev/null @@ -1,1282 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// SSE2 version of some decoding functions (idct, loop filtering). -// -// Author: somnath@google.com (Somnath Banerjee) -// cduvivier@google.com (Christian Duvivier) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE2) - -// The 3-coeff sparse transform in SSE2 is not really faster than the plain-C -// one it seems => disable it by default. Uncomment the following to enable: -// #define USE_TRANSFORM_AC3 - -#include -#include "../dec/vp8i.h" - -//------------------------------------------------------------------------------ -// Transforms (Paragraph 14.4) - -static void Transform(const int16_t* in, uint8_t* dst, int do_two) { - // This implementation makes use of 16-bit fixed point versions of two - // multiply constants: - // K1 = sqrt(2) * cos (pi/8) ~= 85627 / 2^16 - // K2 = sqrt(2) * sin (pi/8) ~= 35468 / 2^16 - // - // To be able to use signed 16-bit integers, we use the following trick to - // have constants within range: - // - Associated constants are obtained by subtracting the 16-bit fixed point - // version of one: - // k = K - (1 << 16) => K = k + (1 << 16) - // K1 = 85267 => k1 = 20091 - // K2 = 35468 => k2 = -30068 - // - The multiplication of a variable by a constant become the sum of the - // variable and the multiplication of that variable by the associated - // constant: - // (x * K) >> 16 = (x * (k + (1 << 16))) >> 16 = ((x * k ) >> 16) + x - const __m128i k1 = _mm_set1_epi16(20091); - const __m128i k2 = _mm_set1_epi16(-30068); - __m128i T0, T1, T2, T3; - - // Load and concatenate the transform coefficients (we'll do two transforms - // in parallel). In the case of only one transform, the second half of the - // vectors will just contain random value we'll never use nor store. - __m128i in0, in1, in2, in3; - { - in0 = _mm_loadl_epi64((const __m128i*)&in[0]); - in1 = _mm_loadl_epi64((const __m128i*)&in[4]); - in2 = _mm_loadl_epi64((const __m128i*)&in[8]); - in3 = _mm_loadl_epi64((const __m128i*)&in[12]); - // a00 a10 a20 a30 x x x x - // a01 a11 a21 a31 x x x x - // a02 a12 a22 a32 x x x x - // a03 a13 a23 a33 x x x x - if (do_two) { - const __m128i inB0 = _mm_loadl_epi64((const __m128i*)&in[16]); - const __m128i inB1 = _mm_loadl_epi64((const __m128i*)&in[20]); - const __m128i inB2 = _mm_loadl_epi64((const __m128i*)&in[24]); - const __m128i inB3 = _mm_loadl_epi64((const __m128i*)&in[28]); - in0 = _mm_unpacklo_epi64(in0, inB0); - in1 = _mm_unpacklo_epi64(in1, inB1); - in2 = _mm_unpacklo_epi64(in2, inB2); - in3 = _mm_unpacklo_epi64(in3, inB3); - // a00 a10 a20 a30 b00 b10 b20 b30 - // a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 - // a03 a13 a23 a33 b03 b13 b23 b33 - } - } - - // Vertical pass and subsequent transpose. - { - // First pass, c and d calculations are longer because of the "trick" - // multiplications. - const __m128i a = _mm_add_epi16(in0, in2); - const __m128i b = _mm_sub_epi16(in0, in2); - // c = MUL(in1, K2) - MUL(in3, K1) = MUL(in1, k2) - MUL(in3, k1) + in1 - in3 - const __m128i c1 = _mm_mulhi_epi16(in1, k2); - const __m128i c2 = _mm_mulhi_epi16(in3, k1); - const __m128i c3 = _mm_sub_epi16(in1, in3); - const __m128i c4 = _mm_sub_epi16(c1, c2); - const __m128i c = _mm_add_epi16(c3, c4); - // d = MUL(in1, K1) + MUL(in3, K2) = MUL(in1, k1) + MUL(in3, k2) + in1 + in3 - const __m128i d1 = _mm_mulhi_epi16(in1, k1); - const __m128i d2 = _mm_mulhi_epi16(in3, k2); - const __m128i d3 = _mm_add_epi16(in1, in3); - const __m128i d4 = _mm_add_epi16(d1, d2); - const __m128i d = _mm_add_epi16(d3, d4); - - // Second pass. - const __m128i tmp0 = _mm_add_epi16(a, d); - const __m128i tmp1 = _mm_add_epi16(b, c); - const __m128i tmp2 = _mm_sub_epi16(b, c); - const __m128i tmp3 = _mm_sub_epi16(a, d); - - // Transpose the two 4x4. - // a00 a01 a02 a03 b00 b01 b02 b03 - // a10 a11 a12 a13 b10 b11 b12 b13 - // a20 a21 a22 a23 b20 b21 b22 b23 - // a30 a31 a32 a33 b30 b31 b32 b33 - const __m128i transpose0_0 = _mm_unpacklo_epi16(tmp0, tmp1); - const __m128i transpose0_1 = _mm_unpacklo_epi16(tmp2, tmp3); - const __m128i transpose0_2 = _mm_unpackhi_epi16(tmp0, tmp1); - const __m128i transpose0_3 = _mm_unpackhi_epi16(tmp2, tmp3); - // a00 a10 a01 a11 a02 a12 a03 a13 - // a20 a30 a21 a31 a22 a32 a23 a33 - // b00 b10 b01 b11 b02 b12 b03 b13 - // b20 b30 b21 b31 b22 b32 b23 b33 - const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3); - const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3); - // a00 a10 a20 a30 a01 a11 a21 a31 - // b00 b10 b20 b30 b01 b11 b21 b31 - // a02 a12 a22 a32 a03 a13 a23 a33 - // b02 b12 a22 b32 b03 b13 b23 b33 - T0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1); - T1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1); - T2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3); - T3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3); - // a00 a10 a20 a30 b00 b10 b20 b30 - // a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 - // a03 a13 a23 a33 b03 b13 b23 b33 - } - - // Horizontal pass and subsequent transpose. - { - // First pass, c and d calculations are longer because of the "trick" - // multiplications. - const __m128i four = _mm_set1_epi16(4); - const __m128i dc = _mm_add_epi16(T0, four); - const __m128i a = _mm_add_epi16(dc, T2); - const __m128i b = _mm_sub_epi16(dc, T2); - // c = MUL(T1, K2) - MUL(T3, K1) = MUL(T1, k2) - MUL(T3, k1) + T1 - T3 - const __m128i c1 = _mm_mulhi_epi16(T1, k2); - const __m128i c2 = _mm_mulhi_epi16(T3, k1); - const __m128i c3 = _mm_sub_epi16(T1, T3); - const __m128i c4 = _mm_sub_epi16(c1, c2); - const __m128i c = _mm_add_epi16(c3, c4); - // d = MUL(T1, K1) + MUL(T3, K2) = MUL(T1, k1) + MUL(T3, k2) + T1 + T3 - const __m128i d1 = _mm_mulhi_epi16(T1, k1); - const __m128i d2 = _mm_mulhi_epi16(T3, k2); - const __m128i d3 = _mm_add_epi16(T1, T3); - const __m128i d4 = _mm_add_epi16(d1, d2); - const __m128i d = _mm_add_epi16(d3, d4); - - // Second pass. - const __m128i tmp0 = _mm_add_epi16(a, d); - const __m128i tmp1 = _mm_add_epi16(b, c); - const __m128i tmp2 = _mm_sub_epi16(b, c); - const __m128i tmp3 = _mm_sub_epi16(a, d); - const __m128i shifted0 = _mm_srai_epi16(tmp0, 3); - const __m128i shifted1 = _mm_srai_epi16(tmp1, 3); - const __m128i shifted2 = _mm_srai_epi16(tmp2, 3); - const __m128i shifted3 = _mm_srai_epi16(tmp3, 3); - - // Transpose the two 4x4. - // a00 a01 a02 a03 b00 b01 b02 b03 - // a10 a11 a12 a13 b10 b11 b12 b13 - // a20 a21 a22 a23 b20 b21 b22 b23 - // a30 a31 a32 a33 b30 b31 b32 b33 - const __m128i transpose0_0 = _mm_unpacklo_epi16(shifted0, shifted1); - const __m128i transpose0_1 = _mm_unpacklo_epi16(shifted2, shifted3); - const __m128i transpose0_2 = _mm_unpackhi_epi16(shifted0, shifted1); - const __m128i transpose0_3 = _mm_unpackhi_epi16(shifted2, shifted3); - // a00 a10 a01 a11 a02 a12 a03 a13 - // a20 a30 a21 a31 a22 a32 a23 a33 - // b00 b10 b01 b11 b02 b12 b03 b13 - // b20 b30 b21 b31 b22 b32 b23 b33 - const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3); - const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3); - // a00 a10 a20 a30 a01 a11 a21 a31 - // b00 b10 b20 b30 b01 b11 b21 b31 - // a02 a12 a22 a32 a03 a13 a23 a33 - // b02 b12 a22 b32 b03 b13 b23 b33 - T0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1); - T1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1); - T2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3); - T3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3); - // a00 a10 a20 a30 b00 b10 b20 b30 - // a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 - // a03 a13 a23 a33 b03 b13 b23 b33 - } - - // Add inverse transform to 'dst' and store. - { - const __m128i zero = _mm_setzero_si128(); - // Load the reference(s). - __m128i dst0, dst1, dst2, dst3; - if (do_two) { - // Load eight bytes/pixels per line. - dst0 = _mm_loadl_epi64((__m128i*)(dst + 0 * BPS)); - dst1 = _mm_loadl_epi64((__m128i*)(dst + 1 * BPS)); - dst2 = _mm_loadl_epi64((__m128i*)(dst + 2 * BPS)); - dst3 = _mm_loadl_epi64((__m128i*)(dst + 3 * BPS)); - } else { - // Load four bytes/pixels per line. - dst0 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 0 * BPS)); - dst1 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 1 * BPS)); - dst2 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 2 * BPS)); - dst3 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 3 * BPS)); - } - // Convert to 16b. - dst0 = _mm_unpacklo_epi8(dst0, zero); - dst1 = _mm_unpacklo_epi8(dst1, zero); - dst2 = _mm_unpacklo_epi8(dst2, zero); - dst3 = _mm_unpacklo_epi8(dst3, zero); - // Add the inverse transform(s). - dst0 = _mm_add_epi16(dst0, T0); - dst1 = _mm_add_epi16(dst1, T1); - dst2 = _mm_add_epi16(dst2, T2); - dst3 = _mm_add_epi16(dst3, T3); - // Unsigned saturate to 8b. - dst0 = _mm_packus_epi16(dst0, dst0); - dst1 = _mm_packus_epi16(dst1, dst1); - dst2 = _mm_packus_epi16(dst2, dst2); - dst3 = _mm_packus_epi16(dst3, dst3); - // Store the results. - if (do_two) { - // Store eight bytes/pixels per line. - _mm_storel_epi64((__m128i*)(dst + 0 * BPS), dst0); - _mm_storel_epi64((__m128i*)(dst + 1 * BPS), dst1); - _mm_storel_epi64((__m128i*)(dst + 2 * BPS), dst2); - _mm_storel_epi64((__m128i*)(dst + 3 * BPS), dst3); - } else { - // Store four bytes/pixels per line. - WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(dst0)); - WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(dst1)); - WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(dst2)); - WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(dst3)); - } - } -} - -#if defined(USE_TRANSFORM_AC3) -#define MUL(a, b) (((a) * (b)) >> 16) -static void TransformAC3(const int16_t* in, uint8_t* dst) { - static const int kC1 = 20091 + (1 << 16); - static const int kC2 = 35468; - const __m128i A = _mm_set1_epi16(in[0] + 4); - const __m128i c4 = _mm_set1_epi16(MUL(in[4], kC2)); - const __m128i d4 = _mm_set1_epi16(MUL(in[4], kC1)); - const int c1 = MUL(in[1], kC2); - const int d1 = MUL(in[1], kC1); - const __m128i CD = _mm_set_epi16(0, 0, 0, 0, -d1, -c1, c1, d1); - const __m128i B = _mm_adds_epi16(A, CD); - const __m128i m0 = _mm_adds_epi16(B, d4); - const __m128i m1 = _mm_adds_epi16(B, c4); - const __m128i m2 = _mm_subs_epi16(B, c4); - const __m128i m3 = _mm_subs_epi16(B, d4); - const __m128i zero = _mm_setzero_si128(); - // Load the source pixels. - __m128i dst0 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 0 * BPS)); - __m128i dst1 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 1 * BPS)); - __m128i dst2 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 2 * BPS)); - __m128i dst3 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 3 * BPS)); - // Convert to 16b. - dst0 = _mm_unpacklo_epi8(dst0, zero); - dst1 = _mm_unpacklo_epi8(dst1, zero); - dst2 = _mm_unpacklo_epi8(dst2, zero); - dst3 = _mm_unpacklo_epi8(dst3, zero); - // Add the inverse transform. - dst0 = _mm_adds_epi16(dst0, _mm_srai_epi16(m0, 3)); - dst1 = _mm_adds_epi16(dst1, _mm_srai_epi16(m1, 3)); - dst2 = _mm_adds_epi16(dst2, _mm_srai_epi16(m2, 3)); - dst3 = _mm_adds_epi16(dst3, _mm_srai_epi16(m3, 3)); - // Unsigned saturate to 8b. - dst0 = _mm_packus_epi16(dst0, dst0); - dst1 = _mm_packus_epi16(dst1, dst1); - dst2 = _mm_packus_epi16(dst2, dst2); - dst3 = _mm_packus_epi16(dst3, dst3); - // Store the results. - WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(dst0)); - WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(dst1)); - WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(dst2)); - WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(dst3)); -} -#undef MUL -#endif // USE_TRANSFORM_AC3 - -//------------------------------------------------------------------------------ -// Loop Filter (Paragraph 15) - -// Compute abs(p - q) = subs(p - q) OR subs(q - p) -#define MM_ABS(p, q) _mm_or_si128( \ - _mm_subs_epu8((q), (p)), \ - _mm_subs_epu8((p), (q))) - -// Shift each byte of "x" by 3 bits while preserving by the sign bit. -static WEBP_INLINE void SignedShift8b(__m128i* const x) { - const __m128i zero = _mm_setzero_si128(); - const __m128i lo_0 = _mm_unpacklo_epi8(zero, *x); - const __m128i hi_0 = _mm_unpackhi_epi8(zero, *x); - const __m128i lo_1 = _mm_srai_epi16(lo_0, 3 + 8); - const __m128i hi_1 = _mm_srai_epi16(hi_0, 3 + 8); - *x = _mm_packs_epi16(lo_1, hi_1); -} - -#define FLIP_SIGN_BIT2(a, b) { \ - a = _mm_xor_si128(a, sign_bit); \ - b = _mm_xor_si128(b, sign_bit); \ -} - -#define FLIP_SIGN_BIT4(a, b, c, d) { \ - FLIP_SIGN_BIT2(a, b); \ - FLIP_SIGN_BIT2(c, d); \ -} - -// input/output is uint8_t -static WEBP_INLINE void GetNotHEV(const __m128i* const p1, - const __m128i* const p0, - const __m128i* const q0, - const __m128i* const q1, - int hev_thresh, __m128i* const not_hev) { - const __m128i zero = _mm_setzero_si128(); - const __m128i t_1 = MM_ABS(*p1, *p0); - const __m128i t_2 = MM_ABS(*q1, *q0); - - const __m128i h = _mm_set1_epi8(hev_thresh); - const __m128i t_max = _mm_max_epu8(t_1, t_2); - - const __m128i t_max_h = _mm_subs_epu8(t_max, h); - *not_hev = _mm_cmpeq_epi8(t_max_h, zero); // not_hev <= t1 && not_hev <= t2 -} - -// input pixels are int8_t -static WEBP_INLINE void GetBaseDelta(const __m128i* const p1, - const __m128i* const p0, - const __m128i* const q0, - const __m128i* const q1, - __m128i* const delta) { - // beware of addition order, for saturation! - const __m128i p1_q1 = _mm_subs_epi8(*p1, *q1); // p1 - q1 - const __m128i q0_p0 = _mm_subs_epi8(*q0, *p0); // q0 - p0 - const __m128i s1 = _mm_adds_epi8(p1_q1, q0_p0); // p1 - q1 + 1 * (q0 - p0) - const __m128i s2 = _mm_adds_epi8(q0_p0, s1); // p1 - q1 + 2 * (q0 - p0) - const __m128i s3 = _mm_adds_epi8(q0_p0, s2); // p1 - q1 + 3 * (q0 - p0) - *delta = s3; -} - -// input and output are int8_t -static WEBP_INLINE void DoSimpleFilter(__m128i* const p0, __m128i* const q0, - const __m128i* const fl) { - const __m128i k3 = _mm_set1_epi8(3); - const __m128i k4 = _mm_set1_epi8(4); - __m128i v3 = _mm_adds_epi8(*fl, k3); - __m128i v4 = _mm_adds_epi8(*fl, k4); - - SignedShift8b(&v4); // v4 >> 3 - SignedShift8b(&v3); // v3 >> 3 - *q0 = _mm_subs_epi8(*q0, v4); // q0 -= v4 - *p0 = _mm_adds_epi8(*p0, v3); // p0 += v3 -} - -// Updates values of 2 pixels at MB edge during complex filtering. -// Update operations: -// q = q - delta and p = p + delta; where delta = [(a_hi >> 7), (a_lo >> 7)] -// Pixels 'pi' and 'qi' are int8_t on input, uint8_t on output (sign flip). -static WEBP_INLINE void Update2Pixels(__m128i* const pi, __m128i* const qi, - const __m128i* const a0_lo, - const __m128i* const a0_hi) { - const __m128i a1_lo = _mm_srai_epi16(*a0_lo, 7); - const __m128i a1_hi = _mm_srai_epi16(*a0_hi, 7); - const __m128i delta = _mm_packs_epi16(a1_lo, a1_hi); - const __m128i sign_bit = _mm_set1_epi8(0x80); - *pi = _mm_adds_epi8(*pi, delta); - *qi = _mm_subs_epi8(*qi, delta); - FLIP_SIGN_BIT2(*pi, *qi); -} - -// input pixels are uint8_t -static WEBP_INLINE void NeedsFilter(const __m128i* const p1, - const __m128i* const p0, - const __m128i* const q0, - const __m128i* const q1, - int thresh, __m128i* const mask) { - const __m128i m_thresh = _mm_set1_epi8(thresh); - const __m128i t1 = MM_ABS(*p1, *q1); // abs(p1 - q1) - const __m128i kFE = _mm_set1_epi8(0xFE); - const __m128i t2 = _mm_and_si128(t1, kFE); // set lsb of each byte to zero - const __m128i t3 = _mm_srli_epi16(t2, 1); // abs(p1 - q1) / 2 - - const __m128i t4 = MM_ABS(*p0, *q0); // abs(p0 - q0) - const __m128i t5 = _mm_adds_epu8(t4, t4); // abs(p0 - q0) * 2 - const __m128i t6 = _mm_adds_epu8(t5, t3); // abs(p0-q0)*2 + abs(p1-q1)/2 - - const __m128i t7 = _mm_subs_epu8(t6, m_thresh); // mask <= m_thresh - *mask = _mm_cmpeq_epi8(t7, _mm_setzero_si128()); -} - -//------------------------------------------------------------------------------ -// Edge filtering functions - -// Applies filter on 2 pixels (p0 and q0) -static WEBP_INLINE void DoFilter2(__m128i* const p1, __m128i* const p0, - __m128i* const q0, __m128i* const q1, - int thresh) { - __m128i a, mask; - const __m128i sign_bit = _mm_set1_epi8(0x80); - // convert p1/q1 to int8_t (for GetBaseDelta) - const __m128i p1s = _mm_xor_si128(*p1, sign_bit); - const __m128i q1s = _mm_xor_si128(*q1, sign_bit); - - NeedsFilter(p1, p0, q0, q1, thresh, &mask); - - FLIP_SIGN_BIT2(*p0, *q0); - GetBaseDelta(&p1s, p0, q0, &q1s, &a); - a = _mm_and_si128(a, mask); // mask filter values we don't care about - DoSimpleFilter(p0, q0, &a); - FLIP_SIGN_BIT2(*p0, *q0); -} - -// Applies filter on 4 pixels (p1, p0, q0 and q1) -static WEBP_INLINE void DoFilter4(__m128i* const p1, __m128i* const p0, - __m128i* const q0, __m128i* const q1, - const __m128i* const mask, int hev_thresh) { - const __m128i zero = _mm_setzero_si128(); - const __m128i sign_bit = _mm_set1_epi8(0x80); - const __m128i k64 = _mm_set1_epi8(64); - const __m128i k3 = _mm_set1_epi8(3); - const __m128i k4 = _mm_set1_epi8(4); - __m128i not_hev; - __m128i t1, t2, t3; - - // compute hev mask - GetNotHEV(p1, p0, q0, q1, hev_thresh, ¬_hev); - - // convert to signed values - FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1); - - t1 = _mm_subs_epi8(*p1, *q1); // p1 - q1 - t1 = _mm_andnot_si128(not_hev, t1); // hev(p1 - q1) - t2 = _mm_subs_epi8(*q0, *p0); // q0 - p0 - t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 1 * (q0 - p0) - t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 2 * (q0 - p0) - t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 3 * (q0 - p0) - t1 = _mm_and_si128(t1, *mask); // mask filter values we don't care about - - t2 = _mm_adds_epi8(t1, k3); // 3 * (q0 - p0) + hev(p1 - q1) + 3 - t3 = _mm_adds_epi8(t1, k4); // 3 * (q0 - p0) + hev(p1 - q1) + 4 - SignedShift8b(&t2); // (3 * (q0 - p0) + hev(p1 - q1) + 3) >> 3 - SignedShift8b(&t3); // (3 * (q0 - p0) + hev(p1 - q1) + 4) >> 3 - *p0 = _mm_adds_epi8(*p0, t2); // p0 += t2 - *q0 = _mm_subs_epi8(*q0, t3); // q0 -= t3 - FLIP_SIGN_BIT2(*p0, *q0); - - // this is equivalent to signed (a + 1) >> 1 calculation - t2 = _mm_add_epi8(t3, sign_bit); - t3 = _mm_avg_epu8(t2, zero); - t3 = _mm_sub_epi8(t3, k64); - - t3 = _mm_and_si128(not_hev, t3); // if !hev - *q1 = _mm_subs_epi8(*q1, t3); // q1 -= t3 - *p1 = _mm_adds_epi8(*p1, t3); // p1 += t3 - FLIP_SIGN_BIT2(*p1, *q1); -} - -// Applies filter on 6 pixels (p2, p1, p0, q0, q1 and q2) -static WEBP_INLINE void DoFilter6(__m128i* const p2, __m128i* const p1, - __m128i* const p0, __m128i* const q0, - __m128i* const q1, __m128i* const q2, - const __m128i* const mask, int hev_thresh) { - const __m128i zero = _mm_setzero_si128(); - const __m128i sign_bit = _mm_set1_epi8(0x80); - __m128i a, not_hev; - - // compute hev mask - GetNotHEV(p1, p0, q0, q1, hev_thresh, ¬_hev); - - FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1); - FLIP_SIGN_BIT2(*p2, *q2); - GetBaseDelta(p1, p0, q0, q1, &a); - - { // do simple filter on pixels with hev - const __m128i m = _mm_andnot_si128(not_hev, *mask); - const __m128i f = _mm_and_si128(a, m); - DoSimpleFilter(p0, q0, &f); - } - - { // do strong filter on pixels with not hev - const __m128i k9 = _mm_set1_epi16(0x0900); - const __m128i k63 = _mm_set1_epi16(63); - - const __m128i m = _mm_and_si128(not_hev, *mask); - const __m128i f = _mm_and_si128(a, m); - - const __m128i f_lo = _mm_unpacklo_epi8(zero, f); - const __m128i f_hi = _mm_unpackhi_epi8(zero, f); - - const __m128i f9_lo = _mm_mulhi_epi16(f_lo, k9); // Filter (lo) * 9 - const __m128i f9_hi = _mm_mulhi_epi16(f_hi, k9); // Filter (hi) * 9 - - const __m128i a2_lo = _mm_add_epi16(f9_lo, k63); // Filter * 9 + 63 - const __m128i a2_hi = _mm_add_epi16(f9_hi, k63); // Filter * 9 + 63 - - const __m128i a1_lo = _mm_add_epi16(a2_lo, f9_lo); // Filter * 18 + 63 - const __m128i a1_hi = _mm_add_epi16(a2_hi, f9_hi); // Filter * 18 + 63 - - const __m128i a0_lo = _mm_add_epi16(a1_lo, f9_lo); // Filter * 27 + 63 - const __m128i a0_hi = _mm_add_epi16(a1_hi, f9_hi); // Filter * 27 + 63 - - Update2Pixels(p2, q2, &a2_lo, &a2_hi); - Update2Pixels(p1, q1, &a1_lo, &a1_hi); - Update2Pixels(p0, q0, &a0_lo, &a0_hi); - } -} - -// reads 8 rows across a vertical edge. -static WEBP_INLINE void Load8x4(const uint8_t* const b, int stride, - __m128i* const p, __m128i* const q) { - // A0 = 63 62 61 60 23 22 21 20 43 42 41 40 03 02 01 00 - // A1 = 73 72 71 70 33 32 31 30 53 52 51 50 13 12 11 10 - const __m128i A0 = _mm_set_epi32( - WebPMemToUint32(&b[6 * stride]), WebPMemToUint32(&b[2 * stride]), - WebPMemToUint32(&b[4 * stride]), WebPMemToUint32(&b[0 * stride])); - const __m128i A1 = _mm_set_epi32( - WebPMemToUint32(&b[7 * stride]), WebPMemToUint32(&b[3 * stride]), - WebPMemToUint32(&b[5 * stride]), WebPMemToUint32(&b[1 * stride])); - - // B0 = 53 43 52 42 51 41 50 40 13 03 12 02 11 01 10 00 - // B1 = 73 63 72 62 71 61 70 60 33 23 32 22 31 21 30 20 - const __m128i B0 = _mm_unpacklo_epi8(A0, A1); - const __m128i B1 = _mm_unpackhi_epi8(A0, A1); - - // C0 = 33 23 13 03 32 22 12 02 31 21 11 01 30 20 10 00 - // C1 = 73 63 53 43 72 62 52 42 71 61 51 41 70 60 50 40 - const __m128i C0 = _mm_unpacklo_epi16(B0, B1); - const __m128i C1 = _mm_unpackhi_epi16(B0, B1); - - // *p = 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00 - // *q = 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02 - *p = _mm_unpacklo_epi32(C0, C1); - *q = _mm_unpackhi_epi32(C0, C1); -} - -static WEBP_INLINE void Load16x4(const uint8_t* const r0, - const uint8_t* const r8, - int stride, - __m128i* const p1, __m128i* const p0, - __m128i* const q0, __m128i* const q1) { - // Assume the pixels around the edge (|) are numbered as follows - // 00 01 | 02 03 - // 10 11 | 12 13 - // ... | ... - // e0 e1 | e2 e3 - // f0 f1 | f2 f3 - // - // r0 is pointing to the 0th row (00) - // r8 is pointing to the 8th row (80) - - // Load - // p1 = 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00 - // q0 = 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02 - // p0 = f1 e1 d1 c1 b1 a1 91 81 f0 e0 d0 c0 b0 a0 90 80 - // q1 = f3 e3 d3 c3 b3 a3 93 83 f2 e2 d2 c2 b2 a2 92 82 - Load8x4(r0, stride, p1, q0); - Load8x4(r8, stride, p0, q1); - - { - // p1 = f0 e0 d0 c0 b0 a0 90 80 70 60 50 40 30 20 10 00 - // p0 = f1 e1 d1 c1 b1 a1 91 81 71 61 51 41 31 21 11 01 - // q0 = f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02 - // q1 = f3 e3 d3 c3 b3 a3 93 83 73 63 53 43 33 23 13 03 - const __m128i t1 = *p1; - const __m128i t2 = *q0; - *p1 = _mm_unpacklo_epi64(t1, *p0); - *p0 = _mm_unpackhi_epi64(t1, *p0); - *q0 = _mm_unpacklo_epi64(t2, *q1); - *q1 = _mm_unpackhi_epi64(t2, *q1); - } -} - -static WEBP_INLINE void Store4x4(__m128i* const x, uint8_t* dst, int stride) { - int i; - for (i = 0; i < 4; ++i, dst += stride) { - WebPUint32ToMem(dst, _mm_cvtsi128_si32(*x)); - *x = _mm_srli_si128(*x, 4); - } -} - -// Transpose back and store -static WEBP_INLINE void Store16x4(const __m128i* const p1, - const __m128i* const p0, - const __m128i* const q0, - const __m128i* const q1, - uint8_t* r0, uint8_t* r8, - int stride) { - __m128i t1, p1_s, p0_s, q0_s, q1_s; - - // p0 = 71 70 61 60 51 50 41 40 31 30 21 20 11 10 01 00 - // p1 = f1 f0 e1 e0 d1 d0 c1 c0 b1 b0 a1 a0 91 90 81 80 - t1 = *p0; - p0_s = _mm_unpacklo_epi8(*p1, t1); - p1_s = _mm_unpackhi_epi8(*p1, t1); - - // q0 = 73 72 63 62 53 52 43 42 33 32 23 22 13 12 03 02 - // q1 = f3 f2 e3 e2 d3 d2 c3 c2 b3 b2 a3 a2 93 92 83 82 - t1 = *q0; - q0_s = _mm_unpacklo_epi8(t1, *q1); - q1_s = _mm_unpackhi_epi8(t1, *q1); - - // p0 = 33 32 31 30 23 22 21 20 13 12 11 10 03 02 01 00 - // q0 = 73 72 71 70 63 62 61 60 53 52 51 50 43 42 41 40 - t1 = p0_s; - p0_s = _mm_unpacklo_epi16(t1, q0_s); - q0_s = _mm_unpackhi_epi16(t1, q0_s); - - // p1 = b3 b2 b1 b0 a3 a2 a1 a0 93 92 91 90 83 82 81 80 - // q1 = f3 f2 f1 f0 e3 e2 e1 e0 d3 d2 d1 d0 c3 c2 c1 c0 - t1 = p1_s; - p1_s = _mm_unpacklo_epi16(t1, q1_s); - q1_s = _mm_unpackhi_epi16(t1, q1_s); - - Store4x4(&p0_s, r0, stride); - r0 += 4 * stride; - Store4x4(&q0_s, r0, stride); - - Store4x4(&p1_s, r8, stride); - r8 += 4 * stride; - Store4x4(&q1_s, r8, stride); -} - -//------------------------------------------------------------------------------ -// Simple In-loop filtering (Paragraph 15.2) - -static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { - // Load - __m128i p1 = _mm_loadu_si128((__m128i*)&p[-2 * stride]); - __m128i p0 = _mm_loadu_si128((__m128i*)&p[-stride]); - __m128i q0 = _mm_loadu_si128((__m128i*)&p[0]); - __m128i q1 = _mm_loadu_si128((__m128i*)&p[stride]); - - DoFilter2(&p1, &p0, &q0, &q1, thresh); - - // Store - _mm_storeu_si128((__m128i*)&p[-stride], p0); - _mm_storeu_si128((__m128i*)&p[0], q0); -} - -static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { - __m128i p1, p0, q0, q1; - - p -= 2; // beginning of p1 - - Load16x4(p, p + 8 * stride, stride, &p1, &p0, &q0, &q1); - DoFilter2(&p1, &p0, &q0, &q1, thresh); - Store16x4(&p1, &p0, &q0, &q1, p, p + 8 * stride, stride); -} - -static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4 * stride; - SimpleVFilter16(p, stride, thresh); - } -} - -static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4; - SimpleHFilter16(p, stride, thresh); - } -} - -//------------------------------------------------------------------------------ -// Complex In-loop filtering (Paragraph 15.3) - -#define MAX_DIFF1(p3, p2, p1, p0, m) do { \ - m = MM_ABS(p1, p0); \ - m = _mm_max_epu8(m, MM_ABS(p3, p2)); \ - m = _mm_max_epu8(m, MM_ABS(p2, p1)); \ -} while (0) - -#define MAX_DIFF2(p3, p2, p1, p0, m) do { \ - m = _mm_max_epu8(m, MM_ABS(p1, p0)); \ - m = _mm_max_epu8(m, MM_ABS(p3, p2)); \ - m = _mm_max_epu8(m, MM_ABS(p2, p1)); \ -} while (0) - -#define LOAD_H_EDGES4(p, stride, e1, e2, e3, e4) { \ - e1 = _mm_loadu_si128((__m128i*)&(p)[0 * stride]); \ - e2 = _mm_loadu_si128((__m128i*)&(p)[1 * stride]); \ - e3 = _mm_loadu_si128((__m128i*)&(p)[2 * stride]); \ - e4 = _mm_loadu_si128((__m128i*)&(p)[3 * stride]); \ -} - -#define LOADUV_H_EDGE(p, u, v, stride) do { \ - const __m128i U = _mm_loadl_epi64((__m128i*)&(u)[(stride)]); \ - const __m128i V = _mm_loadl_epi64((__m128i*)&(v)[(stride)]); \ - p = _mm_unpacklo_epi64(U, V); \ -} while (0) - -#define LOADUV_H_EDGES4(u, v, stride, e1, e2, e3, e4) { \ - LOADUV_H_EDGE(e1, u, v, 0 * stride); \ - LOADUV_H_EDGE(e2, u, v, 1 * stride); \ - LOADUV_H_EDGE(e3, u, v, 2 * stride); \ - LOADUV_H_EDGE(e4, u, v, 3 * stride); \ -} - -#define STOREUV(p, u, v, stride) { \ - _mm_storel_epi64((__m128i*)&u[(stride)], p); \ - p = _mm_srli_si128(p, 8); \ - _mm_storel_epi64((__m128i*)&v[(stride)], p); \ -} - -static WEBP_INLINE void ComplexMask(const __m128i* const p1, - const __m128i* const p0, - const __m128i* const q0, - const __m128i* const q1, - int thresh, int ithresh, - __m128i* const mask) { - const __m128i it = _mm_set1_epi8(ithresh); - const __m128i diff = _mm_subs_epu8(*mask, it); - const __m128i thresh_mask = _mm_cmpeq_epi8(diff, _mm_setzero_si128()); - __m128i filter_mask; - NeedsFilter(p1, p0, q0, q1, thresh, &filter_mask); - *mask = _mm_and_si128(thresh_mask, filter_mask); -} - -// on macroblock edges -static void VFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - __m128i t1; - __m128i mask; - __m128i p2, p1, p0, q0, q1, q2; - - // Load p3, p2, p1, p0 - LOAD_H_EDGES4(p - 4 * stride, stride, t1, p2, p1, p0); - MAX_DIFF1(t1, p2, p1, p0, mask); - - // Load q0, q1, q2, q3 - LOAD_H_EDGES4(p, stride, q0, q1, q2, t1); - MAX_DIFF2(t1, q2, q1, q0, mask); - - ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); - DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); - - // Store - _mm_storeu_si128((__m128i*)&p[-3 * stride], p2); - _mm_storeu_si128((__m128i*)&p[-2 * stride], p1); - _mm_storeu_si128((__m128i*)&p[-1 * stride], p0); - _mm_storeu_si128((__m128i*)&p[+0 * stride], q0); - _mm_storeu_si128((__m128i*)&p[+1 * stride], q1); - _mm_storeu_si128((__m128i*)&p[+2 * stride], q2); -} - -static void HFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - __m128i mask; - __m128i p3, p2, p1, p0, q0, q1, q2, q3; - - uint8_t* const b = p - 4; - Load16x4(b, b + 8 * stride, stride, &p3, &p2, &p1, &p0); // p3, p2, p1, p0 - MAX_DIFF1(p3, p2, p1, p0, mask); - - Load16x4(p, p + 8 * stride, stride, &q0, &q1, &q2, &q3); // q0, q1, q2, q3 - MAX_DIFF2(q3, q2, q1, q0, mask); - - ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); - DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); - - Store16x4(&p3, &p2, &p1, &p0, b, b + 8 * stride, stride); - Store16x4(&q0, &q1, &q2, &q3, p, p + 8 * stride, stride); -} - -// on three inner edges -static void VFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - int k; - __m128i p3, p2, p1, p0; // loop invariants - - LOAD_H_EDGES4(p, stride, p3, p2, p1, p0); // prologue - - for (k = 3; k > 0; --k) { - __m128i mask, tmp1, tmp2; - uint8_t* const b = p + 2 * stride; // beginning of p1 - p += 4 * stride; - - MAX_DIFF1(p3, p2, p1, p0, mask); // compute partial mask - LOAD_H_EDGES4(p, stride, p3, p2, tmp1, tmp2); - MAX_DIFF2(p3, p2, tmp1, tmp2, mask); - - // p3 and p2 are not just temporary variables here: they will be - // re-used for next span. And q2/q3 will become p1/p0 accordingly. - ComplexMask(&p1, &p0, &p3, &p2, thresh, ithresh, &mask); - DoFilter4(&p1, &p0, &p3, &p2, &mask, hev_thresh); - - // Store - _mm_storeu_si128((__m128i*)&b[0 * stride], p1); - _mm_storeu_si128((__m128i*)&b[1 * stride], p0); - _mm_storeu_si128((__m128i*)&b[2 * stride], p3); - _mm_storeu_si128((__m128i*)&b[3 * stride], p2); - - // rotate samples - p1 = tmp1; - p0 = tmp2; - } -} - -static void HFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - int k; - __m128i p3, p2, p1, p0; // loop invariants - - Load16x4(p, p + 8 * stride, stride, &p3, &p2, &p1, &p0); // prologue - - for (k = 3; k > 0; --k) { - __m128i mask, tmp1, tmp2; - uint8_t* const b = p + 2; // beginning of p1 - - p += 4; // beginning of q0 (and next span) - - MAX_DIFF1(p3, p2, p1, p0, mask); // compute partial mask - Load16x4(p, p + 8 * stride, stride, &p3, &p2, &tmp1, &tmp2); - MAX_DIFF2(p3, p2, tmp1, tmp2, mask); - - ComplexMask(&p1, &p0, &p3, &p2, thresh, ithresh, &mask); - DoFilter4(&p1, &p0, &p3, &p2, &mask, hev_thresh); - - Store16x4(&p1, &p0, &p3, &p2, b, b + 8 * stride, stride); - - // rotate samples - p1 = tmp1; - p0 = tmp2; - } -} - -// 8-pixels wide variant, for chroma filtering -static void VFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - __m128i mask; - __m128i t1, p2, p1, p0, q0, q1, q2; - - // Load p3, p2, p1, p0 - LOADUV_H_EDGES4(u - 4 * stride, v - 4 * stride, stride, t1, p2, p1, p0); - MAX_DIFF1(t1, p2, p1, p0, mask); - - // Load q0, q1, q2, q3 - LOADUV_H_EDGES4(u, v, stride, q0, q1, q2, t1); - MAX_DIFF2(t1, q2, q1, q0, mask); - - ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); - DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); - - // Store - STOREUV(p2, u, v, -3 * stride); - STOREUV(p1, u, v, -2 * stride); - STOREUV(p0, u, v, -1 * stride); - STOREUV(q0, u, v, 0 * stride); - STOREUV(q1, u, v, 1 * stride); - STOREUV(q2, u, v, 2 * stride); -} - -static void HFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - __m128i mask; - __m128i p3, p2, p1, p0, q0, q1, q2, q3; - - uint8_t* const tu = u - 4; - uint8_t* const tv = v - 4; - Load16x4(tu, tv, stride, &p3, &p2, &p1, &p0); // p3, p2, p1, p0 - MAX_DIFF1(p3, p2, p1, p0, mask); - - Load16x4(u, v, stride, &q0, &q1, &q2, &q3); // q0, q1, q2, q3 - MAX_DIFF2(q3, q2, q1, q0, mask); - - ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); - DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); - - Store16x4(&p3, &p2, &p1, &p0, tu, tv, stride); - Store16x4(&q0, &q1, &q2, &q3, u, v, stride); -} - -static void VFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - __m128i mask; - __m128i t1, t2, p1, p0, q0, q1; - - // Load p3, p2, p1, p0 - LOADUV_H_EDGES4(u, v, stride, t2, t1, p1, p0); - MAX_DIFF1(t2, t1, p1, p0, mask); - - u += 4 * stride; - v += 4 * stride; - - // Load q0, q1, q2, q3 - LOADUV_H_EDGES4(u, v, stride, q0, q1, t1, t2); - MAX_DIFF2(t2, t1, q1, q0, mask); - - ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); - DoFilter4(&p1, &p0, &q0, &q1, &mask, hev_thresh); - - // Store - STOREUV(p1, u, v, -2 * stride); - STOREUV(p0, u, v, -1 * stride); - STOREUV(q0, u, v, 0 * stride); - STOREUV(q1, u, v, 1 * stride); -} - -static void HFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - __m128i mask; - __m128i t1, t2, p1, p0, q0, q1; - Load16x4(u, v, stride, &t2, &t1, &p1, &p0); // p3, p2, p1, p0 - MAX_DIFF1(t2, t1, p1, p0, mask); - - u += 4; // beginning of q0 - v += 4; - Load16x4(u, v, stride, &q0, &q1, &t1, &t2); // q0, q1, q2, q3 - MAX_DIFF2(t2, t1, q1, q0, mask); - - ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); - DoFilter4(&p1, &p0, &q0, &q1, &mask, hev_thresh); - - u -= 2; // beginning of p1 - v -= 2; - Store16x4(&p1, &p0, &q0, &q1, u, v, stride); -} - -//------------------------------------------------------------------------------ -// 4x4 predictions - -#define DST(x, y) dst[(x) + (y) * BPS] -#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2) - -// We use the following 8b-arithmetic tricks: -// (a + 2 * b + c + 2) >> 2 = (AC + b + 1) >> 1 -// where: AC = (a + c) >> 1 = [(a + c + 1) >> 1] - [(a^c) & 1] -// and: -// (a + 2 * b + c + 2) >> 2 = (AB + BC + 1) >> 1 - (ab|bc)&lsb -// where: AC = (a + b + 1) >> 1, BC = (b + c + 1) >> 1 -// and ab = a ^ b, bc = b ^ c, lsb = (AC^BC)&1 - -static void VE4(uint8_t* dst) { // vertical - const __m128i one = _mm_set1_epi8(1); - const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS - 1)); - const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1); - const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2); - const __m128i a = _mm_avg_epu8(ABCDEFGH, CDEFGH00); - const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGH00), one); - const __m128i b = _mm_subs_epu8(a, lsb); - const __m128i avg = _mm_avg_epu8(b, BCDEFGH0); - const uint32_t vals = _mm_cvtsi128_si32(avg); - int i; - for (i = 0; i < 4; ++i) { - WebPUint32ToMem(dst + i * BPS, vals); - } -} - -static void LD4(uint8_t* dst) { // Down-Left - const __m128i one = _mm_set1_epi8(1); - const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS)); - const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1); - const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2); - const __m128i CDEFGHH0 = _mm_insert_epi16(CDEFGH00, dst[-BPS + 7], 3); - const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, CDEFGHH0); - const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one); - const __m128i avg2 = _mm_subs_epu8(avg1, lsb); - const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0); - WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcdefg )); - WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); - WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); - WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); -} - -static void VR4(uint8_t* dst) { // Vertical-Right - const __m128i one = _mm_set1_epi8(1); - const int I = dst[-1 + 0 * BPS]; - const int J = dst[-1 + 1 * BPS]; - const int K = dst[-1 + 2 * BPS]; - const int X = dst[-1 - BPS]; - const __m128i XABCD = _mm_loadl_epi64((__m128i*)(dst - BPS - 1)); - const __m128i ABCD0 = _mm_srli_si128(XABCD, 1); - const __m128i abcd = _mm_avg_epu8(XABCD, ABCD0); - const __m128i _XABCD = _mm_slli_si128(XABCD, 1); - const __m128i IXABCD = _mm_insert_epi16(_XABCD, I | (X << 8), 0); - const __m128i avg1 = _mm_avg_epu8(IXABCD, ABCD0); - const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one); - const __m128i avg2 = _mm_subs_epu8(avg1, lsb); - const __m128i efgh = _mm_avg_epu8(avg2, XABCD); - WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcd )); - WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( efgh )); - WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1))); - WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1))); - - // these two are hard to implement in SSE2, so we keep the C-version: - DST(0, 2) = AVG3(J, I, X); - DST(0, 3) = AVG3(K, J, I); -} - -static void VL4(uint8_t* dst) { // Vertical-Left - const __m128i one = _mm_set1_epi8(1); - const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS)); - const __m128i BCDEFGH_ = _mm_srli_si128(ABCDEFGH, 1); - const __m128i CDEFGH__ = _mm_srli_si128(ABCDEFGH, 2); - const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, BCDEFGH_); - const __m128i avg2 = _mm_avg_epu8(CDEFGH__, BCDEFGH_); - const __m128i avg3 = _mm_avg_epu8(avg1, avg2); - const __m128i lsb1 = _mm_and_si128(_mm_xor_si128(avg1, avg2), one); - const __m128i ab = _mm_xor_si128(ABCDEFGH, BCDEFGH_); - const __m128i bc = _mm_xor_si128(CDEFGH__, BCDEFGH_); - const __m128i abbc = _mm_or_si128(ab, bc); - const __m128i lsb2 = _mm_and_si128(abbc, lsb1); - const __m128i avg4 = _mm_subs_epu8(avg3, lsb2); - const uint32_t extra_out = _mm_cvtsi128_si32(_mm_srli_si128(avg4, 4)); - WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( avg1 )); - WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( avg4 )); - WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1))); - WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1))); - - // these two are hard to get and irregular - DST(3, 2) = (extra_out >> 0) & 0xff; - DST(3, 3) = (extra_out >> 8) & 0xff; -} - -static void RD4(uint8_t* dst) { // Down-right - const __m128i one = _mm_set1_epi8(1); - const __m128i XABCD = _mm_loadl_epi64((__m128i*)(dst - BPS - 1)); - const __m128i ____XABCD = _mm_slli_si128(XABCD, 4); - const uint32_t I = dst[-1 + 0 * BPS]; - const uint32_t J = dst[-1 + 1 * BPS]; - const uint32_t K = dst[-1 + 2 * BPS]; - const uint32_t L = dst[-1 + 3 * BPS]; - const __m128i LKJI_____ = - _mm_cvtsi32_si128(L | (K << 8) | (J << 16) | (I << 24)); - const __m128i LKJIXABCD = _mm_or_si128(LKJI_____, ____XABCD); - const __m128i KJIXABCD_ = _mm_srli_si128(LKJIXABCD, 1); - const __m128i JIXABCD__ = _mm_srli_si128(LKJIXABCD, 2); - const __m128i avg1 = _mm_avg_epu8(JIXABCD__, LKJIXABCD); - const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one); - const __m128i avg2 = _mm_subs_epu8(avg1, lsb); - const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_); - WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32( abcdefg )); - WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); - WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); - WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); -} - -#undef DST -#undef AVG3 - -//------------------------------------------------------------------------------ -// Luma 16x16 - -static WEBP_INLINE void TrueMotion(uint8_t* dst, int size) { - const uint8_t* top = dst - BPS; - const __m128i zero = _mm_setzero_si128(); - int y; - if (size == 4) { - const __m128i top_values = _mm_cvtsi32_si128(WebPMemToUint32(top)); - const __m128i top_base = _mm_unpacklo_epi8(top_values, zero); - for (y = 0; y < 4; ++y, dst += BPS) { - const int val = dst[-1] - top[-1]; - const __m128i base = _mm_set1_epi16(val); - const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero); - WebPUint32ToMem(dst, _mm_cvtsi128_si32(out)); - } - } else if (size == 8) { - const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); - const __m128i top_base = _mm_unpacklo_epi8(top_values, zero); - for (y = 0; y < 8; ++y, dst += BPS) { - const int val = dst[-1] - top[-1]; - const __m128i base = _mm_set1_epi16(val); - const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero); - _mm_storel_epi64((__m128i*)dst, out); - } - } else { - const __m128i top_values = _mm_loadu_si128((const __m128i*)top); - const __m128i top_base_0 = _mm_unpacklo_epi8(top_values, zero); - const __m128i top_base_1 = _mm_unpackhi_epi8(top_values, zero); - for (y = 0; y < 16; ++y, dst += BPS) { - const int val = dst[-1] - top[-1]; - const __m128i base = _mm_set1_epi16(val); - const __m128i out_0 = _mm_add_epi16(base, top_base_0); - const __m128i out_1 = _mm_add_epi16(base, top_base_1); - const __m128i out = _mm_packus_epi16(out_0, out_1); - _mm_storeu_si128((__m128i*)dst, out); - } - } -} - -static void TM4(uint8_t* dst) { TrueMotion(dst, 4); } -static void TM8uv(uint8_t* dst) { TrueMotion(dst, 8); } -static void TM16(uint8_t* dst) { TrueMotion(dst, 16); } - -static void VE16(uint8_t* dst) { - const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS)); - int j; - for (j = 0; j < 16; ++j) { - _mm_storeu_si128((__m128i*)(dst + j * BPS), top); - } -} - -static void HE16(uint8_t* dst) { // horizontal - int j; - for (j = 16; j > 0; --j) { - const __m128i values = _mm_set1_epi8(dst[-1]); - _mm_storeu_si128((__m128i*)dst, values); - dst += BPS; - } -} - -static WEBP_INLINE void Put16(uint8_t v, uint8_t* dst) { - int j; - const __m128i values = _mm_set1_epi8(v); - for (j = 0; j < 16; ++j) { - _mm_storeu_si128((__m128i*)(dst + j * BPS), values); - } -} - -static void DC16(uint8_t* dst) { // DC - const __m128i zero = _mm_setzero_si128(); - const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS)); - const __m128i sad8x2 = _mm_sad_epu8(top, zero); - // sum the two sads: sad8x2[0:1] + sad8x2[8:9] - const __m128i sum = _mm_add_epi16(sad8x2, _mm_shuffle_epi32(sad8x2, 2)); - int left = 0; - int j; - for (j = 0; j < 16; ++j) { - left += dst[-1 + j * BPS]; - } - { - const int DC = _mm_cvtsi128_si32(sum) + left + 16; - Put16(DC >> 5, dst); - } -} - -static void DC16NoTop(uint8_t* dst) { // DC with top samples not available - int DC = 8; - int j; - for (j = 0; j < 16; ++j) { - DC += dst[-1 + j * BPS]; - } - Put16(DC >> 4, dst); -} - -static void DC16NoLeft(uint8_t* dst) { // DC with left samples not available - const __m128i zero = _mm_setzero_si128(); - const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS)); - const __m128i sad8x2 = _mm_sad_epu8(top, zero); - // sum the two sads: sad8x2[0:1] + sad8x2[8:9] - const __m128i sum = _mm_add_epi16(sad8x2, _mm_shuffle_epi32(sad8x2, 2)); - const int DC = _mm_cvtsi128_si32(sum) + 8; - Put16(DC >> 4, dst); -} - -static void DC16NoTopLeft(uint8_t* dst) { // DC with no top and left samples - Put16(0x80, dst); -} - -//------------------------------------------------------------------------------ -// Chroma - -static void VE8uv(uint8_t* dst) { // vertical - int j; - const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS)); - for (j = 0; j < 8; ++j) { - _mm_storel_epi64((__m128i*)(dst + j * BPS), top); - } -} - -static void HE8uv(uint8_t* dst) { // horizontal - int j; - for (j = 0; j < 8; ++j) { - const __m128i values = _mm_set1_epi8(dst[-1]); - _mm_storel_epi64((__m128i*)dst, values); - dst += BPS; - } -} - -// helper for chroma-DC predictions -static WEBP_INLINE void Put8x8uv(uint8_t v, uint8_t* dst) { - int j; - const __m128i values = _mm_set1_epi8(v); - for (j = 0; j < 8; ++j) { - _mm_storel_epi64((__m128i*)(dst + j * BPS), values); - } -} - -static void DC8uv(uint8_t* dst) { // DC - const __m128i zero = _mm_setzero_si128(); - const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS)); - const __m128i sum = _mm_sad_epu8(top, zero); - int left = 0; - int j; - for (j = 0; j < 8; ++j) { - left += dst[-1 + j * BPS]; - } - { - const int DC = _mm_cvtsi128_si32(sum) + left + 8; - Put8x8uv(DC >> 4, dst); - } -} - -static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples - const __m128i zero = _mm_setzero_si128(); - const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS)); - const __m128i sum = _mm_sad_epu8(top, zero); - const int DC = _mm_cvtsi128_si32(sum) + 4; - Put8x8uv(DC >> 3, dst); -} - -static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples - int dc0 = 4; - int i; - for (i = 0; i < 8; ++i) { - dc0 += dst[-1 + i * BPS]; - } - Put8x8uv(dc0 >> 3, dst); -} - -static void DC8uvNoTopLeft(uint8_t* dst) { // DC with nothing - Put8x8uv(0x80, dst); -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8DspInitSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitSSE2(void) { - VP8Transform = Transform; -#if defined(USE_TRANSFORM_AC3) - VP8TransformAC3 = TransformAC3; -#endif - - VP8VFilter16 = VFilter16; - VP8HFilter16 = HFilter16; - VP8VFilter8 = VFilter8; - VP8HFilter8 = HFilter8; - VP8VFilter16i = VFilter16i; - VP8HFilter16i = HFilter16i; - VP8VFilter8i = VFilter8i; - VP8HFilter8i = HFilter8i; - - VP8SimpleVFilter16 = SimpleVFilter16; - VP8SimpleHFilter16 = SimpleHFilter16; - VP8SimpleVFilter16i = SimpleVFilter16i; - VP8SimpleHFilter16i = SimpleHFilter16i; - - VP8PredLuma4[1] = TM4; - VP8PredLuma4[2] = VE4; - VP8PredLuma4[4] = RD4; - VP8PredLuma4[5] = VR4; - VP8PredLuma4[6] = LD4; - VP8PredLuma4[7] = VL4; - - VP8PredLuma16[0] = DC16; - VP8PredLuma16[1] = TM16; - VP8PredLuma16[2] = VE16; - VP8PredLuma16[3] = HE16; - VP8PredLuma16[4] = DC16NoTop; - VP8PredLuma16[5] = DC16NoLeft; - VP8PredLuma16[6] = DC16NoTopLeft; - - VP8PredChroma8[0] = DC8uv; - VP8PredChroma8[1] = TM8uv; - VP8PredChroma8[2] = VE8uv; - VP8PredChroma8[3] = HE8uv; - VP8PredChroma8[4] = DC8uvNoTop; - VP8PredChroma8[5] = DC8uvNoLeft; - VP8PredChroma8[6] = DC8uvNoTopLeft; -} - -#else // !WEBP_USE_SSE2 - -WEBP_DSP_INIT_STUB(VP8DspInitSSE2) - -#endif // WEBP_USE_SSE2 diff --git a/Example-Mac/Pods/libwebp/src/dsp/dec_sse41.c b/Example-Mac/Pods/libwebp/src/dsp/dec_sse41.c deleted file mode 100644 index 224c6f89..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/dec_sse41.c +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// SSE4 version of some decoding functions. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE41) - -#include -#include "../dec/vp8i.h" - -static void HE16(uint8_t* dst) { // horizontal - int j; - const __m128i kShuffle3 = _mm_set1_epi8(3); - for (j = 16; j > 0; --j) { - const __m128i in = _mm_cvtsi32_si128(WebPMemToUint32(dst - 4)); - const __m128i values = _mm_shuffle_epi8(in, kShuffle3); - _mm_storeu_si128((__m128i*)dst, values); - dst += BPS; - } -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8DspInitSSE41(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitSSE41(void) { - VP8PredLuma16[3] = HE16; -} - -#else // !WEBP_USE_SSE41 - -WEBP_DSP_INIT_STUB(VP8DspInitSSE41) - -#endif // WEBP_USE_SSE41 diff --git a/Example-Mac/Pods/libwebp/src/dsp/dsp.h b/Example-Mac/Pods/libwebp/src/dsp/dsp.h deleted file mode 100644 index 95f1ce0f..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/dsp.h +++ /dev/null @@ -1,497 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Speed-critical functions. -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_DSP_DSP_H_ -#define WEBP_DSP_DSP_H_ - -#include "../webp/types.h" -#include "../utils/utils.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define BPS 32 // this is the common stride for enc/dec - -//------------------------------------------------------------------------------ -// CPU detection - -#if defined(__GNUC__) -# define LOCAL_GCC_VERSION ((__GNUC__ << 8) | __GNUC_MINOR__) -# define LOCAL_GCC_PREREQ(maj, min) \ - (LOCAL_GCC_VERSION >= (((maj) << 8) | (min))) -#else -# define LOCAL_GCC_VERSION 0 -# define LOCAL_GCC_PREREQ(maj, min) 0 -#endif - -#ifndef __has_builtin -# define __has_builtin(x) 0 -#endif - -#if defined(_MSC_VER) && _MSC_VER > 1310 && \ - (defined(_M_X64) || defined(_M_IX86)) -#define WEBP_MSC_SSE2 // Visual C++ SSE2 targets -#endif - -#if defined(_MSC_VER) && _MSC_VER >= 1500 && \ - (defined(_M_X64) || defined(_M_IX86)) -#define WEBP_MSC_SSE41 // Visual C++ SSE4.1 targets -#endif - -// WEBP_HAVE_* are used to indicate the presence of the instruction set in dsp -// files without intrinsics, allowing the corresponding Init() to be called. -// Files containing intrinsics will need to be built targeting the instruction -// set so should succeed on one of the earlier tests. -#if defined(__SSE2__) || defined(WEBP_MSC_SSE2) || defined(WEBP_HAVE_SSE2) -#define WEBP_USE_SSE2 -#endif - -#if defined(__SSE4_1__) || defined(WEBP_MSC_SSE41) || defined(WEBP_HAVE_SSE41) -#define WEBP_USE_SSE41 -#endif - -#if defined(__AVX2__) || defined(WEBP_HAVE_AVX2) -#define WEBP_USE_AVX2 -#endif - -#if defined(__ANDROID__) && defined(__ARM_ARCH_7A__) -#define WEBP_ANDROID_NEON // Android targets that might support NEON -#endif - -// The intrinsics currently cause compiler errors with arm-nacl-gcc and the -// inline assembly would need to be modified for use with Native Client. -#if (defined(__ARM_NEON__) || defined(WEBP_ANDROID_NEON) || \ - defined(__aarch64__)) && !defined(__native_client__) -#define WEBP_USE_NEON -#endif - -#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM) -#define WEBP_USE_NEON -#define WEBP_USE_INTRINSICS -#endif - -#if defined(__mips__) && !defined(__mips64) && \ - defined(__mips_isa_rev) && (__mips_isa_rev >= 1) && (__mips_isa_rev < 6) -#define WEBP_USE_MIPS32 -#if (__mips_isa_rev >= 2) -#define WEBP_USE_MIPS32_R2 -#if defined(__mips_dspr2) || (__mips_dsp_rev >= 2) -#define WEBP_USE_MIPS_DSP_R2 -#endif -#endif -#endif - -// This macro prevents thread_sanitizer from reporting known concurrent writes. -#define WEBP_TSAN_IGNORE_FUNCTION -#if defined(__has_feature) -#if __has_feature(thread_sanitizer) -#undef WEBP_TSAN_IGNORE_FUNCTION -#define WEBP_TSAN_IGNORE_FUNCTION __attribute__((no_sanitize_thread)) -#endif -#endif - -typedef enum { - kSSE2, - kSSE3, - kSSE4_1, - kAVX, - kAVX2, - kNEON, - kMIPS32, - kMIPSdspR2 -} CPUFeature; -// returns true if the CPU supports the feature. -typedef int (*VP8CPUInfo)(CPUFeature feature); -WEBP_EXTERN(VP8CPUInfo) VP8GetCPUInfo; - -//------------------------------------------------------------------------------ -// Init stub generator - -// Defines an init function stub to ensure each module exposes a symbol, -// avoiding a compiler warning. -#define WEBP_DSP_INIT_STUB(func) \ - extern void func(void); \ - WEBP_TSAN_IGNORE_FUNCTION void func(void) {} - -//------------------------------------------------------------------------------ -// Encoding - -// Transforms -// VP8Idct: Does one of two inverse transforms. If do_two is set, the transforms -// will be done for (ref, in, dst) and (ref + 4, in + 16, dst + 4). -typedef void (*VP8Idct)(const uint8_t* ref, const int16_t* in, uint8_t* dst, - int do_two); -typedef void (*VP8Fdct)(const uint8_t* src, const uint8_t* ref, int16_t* out); -typedef void (*VP8WHT)(const int16_t* in, int16_t* out); -extern VP8Idct VP8ITransform; -extern VP8Fdct VP8FTransform; -extern VP8Fdct VP8FTransform2; // performs two transforms at a time -extern VP8WHT VP8FTransformWHT; -// Predictions -// *dst is the destination block. *top and *left can be NULL. -typedef void (*VP8IntraPreds)(uint8_t *dst, const uint8_t* left, - const uint8_t* top); -typedef void (*VP8Intra4Preds)(uint8_t *dst, const uint8_t* top); -extern VP8Intra4Preds VP8EncPredLuma4; -extern VP8IntraPreds VP8EncPredLuma16; -extern VP8IntraPreds VP8EncPredChroma8; - -typedef int (*VP8Metric)(const uint8_t* pix, const uint8_t* ref); -extern VP8Metric VP8SSE16x16, VP8SSE16x8, VP8SSE8x8, VP8SSE4x4; -typedef int (*VP8WMetric)(const uint8_t* pix, const uint8_t* ref, - const uint16_t* const weights); -extern VP8WMetric VP8TDisto4x4, VP8TDisto16x16; - -typedef void (*VP8BlockCopy)(const uint8_t* src, uint8_t* dst); -extern VP8BlockCopy VP8Copy4x4; -extern VP8BlockCopy VP8Copy16x8; -// Quantization -struct VP8Matrix; // forward declaration -typedef int (*VP8QuantizeBlock)(int16_t in[16], int16_t out[16], - const struct VP8Matrix* const mtx); -// Same as VP8QuantizeBlock, but quantizes two consecutive blocks. -typedef int (*VP8Quantize2Blocks)(int16_t in[32], int16_t out[32], - const struct VP8Matrix* const mtx); - -extern VP8QuantizeBlock VP8EncQuantizeBlock; -extern VP8Quantize2Blocks VP8EncQuantize2Blocks; - -// specific to 2nd transform: -typedef int (*VP8QuantizeBlockWHT)(int16_t in[16], int16_t out[16], - const struct VP8Matrix* const mtx); -extern VP8QuantizeBlockWHT VP8EncQuantizeBlockWHT; - -extern const int VP8DspScan[16 + 4 + 4]; - -// Collect histogram for susceptibility calculation. -#define MAX_COEFF_THRESH 31 // size of histogram used by CollectHistogram. -typedef struct { - // We only need to store max_value and last_non_zero, not the distribution. - int max_value; - int last_non_zero; -} VP8Histogram; -typedef void (*VP8CHisto)(const uint8_t* ref, const uint8_t* pred, - int start_block, int end_block, - VP8Histogram* const histo); -extern VP8CHisto VP8CollectHistogram; -// General-purpose util function to help VP8CollectHistogram(). -void VP8SetHistogramData(const int distribution[MAX_COEFF_THRESH + 1], - VP8Histogram* const histo); - -// must be called before using any of the above -void VP8EncDspInit(void); - -//------------------------------------------------------------------------------ -// cost functions (encoding) - -extern const uint16_t VP8EntropyCost[256]; // 8bit fixed-point log(p) -// approximate cost per level: -extern const uint16_t VP8LevelFixedCosts[2047 /*MAX_LEVEL*/ + 1]; -extern const uint8_t VP8EncBands[16 + 1]; - -struct VP8Residual; -typedef void (*VP8SetResidualCoeffsFunc)(const int16_t* const coeffs, - struct VP8Residual* const res); -extern VP8SetResidualCoeffsFunc VP8SetResidualCoeffs; - -// Cost calculation function. -typedef int (*VP8GetResidualCostFunc)(int ctx0, - const struct VP8Residual* const res); -extern VP8GetResidualCostFunc VP8GetResidualCost; - -// must be called before anything using the above -void VP8EncDspCostInit(void); - -//------------------------------------------------------------------------------ -// Decoding - -typedef void (*VP8DecIdct)(const int16_t* coeffs, uint8_t* dst); -// when doing two transforms, coeffs is actually int16_t[2][16]. -typedef void (*VP8DecIdct2)(const int16_t* coeffs, uint8_t* dst, int do_two); -extern VP8DecIdct2 VP8Transform; -extern VP8DecIdct VP8TransformAC3; -extern VP8DecIdct VP8TransformUV; -extern VP8DecIdct VP8TransformDC; -extern VP8DecIdct VP8TransformDCUV; -extern VP8WHT VP8TransformWHT; - -// *dst is the destination block, with stride BPS. Boundary samples are -// assumed accessible when needed. -typedef void (*VP8PredFunc)(uint8_t* dst); -extern VP8PredFunc VP8PredLuma16[/* NUM_B_DC_MODES */]; -extern VP8PredFunc VP8PredChroma8[/* NUM_B_DC_MODES */]; -extern VP8PredFunc VP8PredLuma4[/* NUM_BMODES */]; - -// clipping tables (for filtering) -extern const int8_t* const VP8ksclip1; // clips [-1020, 1020] to [-128, 127] -extern const int8_t* const VP8ksclip2; // clips [-112, 112] to [-16, 15] -extern const uint8_t* const VP8kclip1; // clips [-255,511] to [0,255] -extern const uint8_t* const VP8kabs0; // abs(x) for x in [-255,255] -// must be called first -void VP8InitClipTables(void); - -// simple filter (only for luma) -typedef void (*VP8SimpleFilterFunc)(uint8_t* p, int stride, int thresh); -extern VP8SimpleFilterFunc VP8SimpleVFilter16; -extern VP8SimpleFilterFunc VP8SimpleHFilter16; -extern VP8SimpleFilterFunc VP8SimpleVFilter16i; // filter 3 inner edges -extern VP8SimpleFilterFunc VP8SimpleHFilter16i; - -// regular filter (on both macroblock edges and inner edges) -typedef void (*VP8LumaFilterFunc)(uint8_t* luma, int stride, - int thresh, int ithresh, int hev_t); -typedef void (*VP8ChromaFilterFunc)(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_t); -// on outer edge -extern VP8LumaFilterFunc VP8VFilter16; -extern VP8LumaFilterFunc VP8HFilter16; -extern VP8ChromaFilterFunc VP8VFilter8; -extern VP8ChromaFilterFunc VP8HFilter8; - -// on inner edge -extern VP8LumaFilterFunc VP8VFilter16i; // filtering 3 inner edges altogether -extern VP8LumaFilterFunc VP8HFilter16i; -extern VP8ChromaFilterFunc VP8VFilter8i; // filtering u and v altogether -extern VP8ChromaFilterFunc VP8HFilter8i; - -// must be called before anything using the above -void VP8DspInit(void); - -//------------------------------------------------------------------------------ -// WebP I/O - -#define FANCY_UPSAMPLING // undefined to remove fancy upsampling support - -// Convert a pair of y/u/v lines together to the output rgb/a colorspace. -// bottom_y can be NULL if only one line of output is needed (at top/bottom). -typedef void (*WebPUpsampleLinePairFunc)( - const uint8_t* top_y, const uint8_t* bottom_y, - const uint8_t* top_u, const uint8_t* top_v, - const uint8_t* cur_u, const uint8_t* cur_v, - uint8_t* top_dst, uint8_t* bottom_dst, int len); - -#ifdef FANCY_UPSAMPLING - -// Fancy upsampling functions to convert YUV to RGB(A) modes -extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; - -#endif // FANCY_UPSAMPLING - -// Per-row point-sampling methods. -typedef void (*WebPSamplerRowFunc)(const uint8_t* y, - const uint8_t* u, const uint8_t* v, - uint8_t* dst, int len); -// Generic function to apply 'WebPSamplerRowFunc' to the whole plane: -void WebPSamplerProcessPlane(const uint8_t* y, int y_stride, - const uint8_t* u, const uint8_t* v, int uv_stride, - uint8_t* dst, int dst_stride, - int width, int height, WebPSamplerRowFunc func); - -// Sampling functions to convert rows of YUV to RGB(A) -extern WebPSamplerRowFunc WebPSamplers[/* MODE_LAST */]; - -// General function for converting two lines of ARGB or RGBA. -// 'alpha_is_last' should be true if 0xff000000 is stored in memory as -// as 0x00, 0x00, 0x00, 0xff (little endian). -WebPUpsampleLinePairFunc WebPGetLinePairConverter(int alpha_is_last); - -// YUV444->RGB converters -typedef void (*WebPYUV444Converter)(const uint8_t* y, - const uint8_t* u, const uint8_t* v, - uint8_t* dst, int len); - -extern WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */]; - -// Must be called before using the WebPUpsamplers[] (and for premultiplied -// colorspaces like rgbA, rgbA4444, etc) -void WebPInitUpsamplers(void); -// Must be called before using WebPSamplers[] -void WebPInitSamplers(void); -// Must be called before using WebPYUV444Converters[] -void WebPInitYUV444Converters(void); - -//------------------------------------------------------------------------------ -// ARGB -> YUV converters - -// Convert ARGB samples to luma Y. -extern void (*WebPConvertARGBToY)(const uint32_t* argb, uint8_t* y, int width); -// Convert ARGB samples to U/V with downsampling. do_store should be '1' for -// even lines and '0' for odd ones. 'src_width' is the original width, not -// the U/V one. -extern void (*WebPConvertARGBToUV)(const uint32_t* argb, uint8_t* u, uint8_t* v, - int src_width, int do_store); - -// Convert a row of accumulated (four-values) of rgba32 toward U/V -extern void (*WebPConvertRGBA32ToUV)(const uint16_t* rgb, - uint8_t* u, uint8_t* v, int width); - -// Convert RGB or BGR to Y -extern void (*WebPConvertRGB24ToY)(const uint8_t* rgb, uint8_t* y, int width); -extern void (*WebPConvertBGR24ToY)(const uint8_t* bgr, uint8_t* y, int width); - -// used for plain-C fallback. -extern void WebPConvertARGBToUV_C(const uint32_t* argb, uint8_t* u, uint8_t* v, - int src_width, int do_store); -extern void WebPConvertRGBA32ToUV_C(const uint16_t* rgb, - uint8_t* u, uint8_t* v, int width); - -// Must be called before using the above. -void WebPInitConvertARGBToYUV(void); - -//------------------------------------------------------------------------------ -// Rescaler - -struct WebPRescaler; - -// Import a row of data and save its contribution in the rescaler. -// 'channel' denotes the channel number to be imported. 'Expand' corresponds to -// the wrk->x_expand case. Otherwise, 'Shrink' is to be used. -typedef void (*WebPRescalerImportRowFunc)(struct WebPRescaler* const wrk, - const uint8_t* src); - -extern WebPRescalerImportRowFunc WebPRescalerImportRowExpand; -extern WebPRescalerImportRowFunc WebPRescalerImportRowShrink; - -// Export one row (starting at x_out position) from rescaler. -// 'Expand' corresponds to the wrk->y_expand case. -// Otherwise 'Shrink' is to be used -typedef void (*WebPRescalerExportRowFunc)(struct WebPRescaler* const wrk); -extern WebPRescalerExportRowFunc WebPRescalerExportRowExpand; -extern WebPRescalerExportRowFunc WebPRescalerExportRowShrink; - -// Plain-C implementation, as fall-back. -extern void WebPRescalerImportRowExpandC(struct WebPRescaler* const wrk, - const uint8_t* src); -extern void WebPRescalerImportRowShrinkC(struct WebPRescaler* const wrk, - const uint8_t* src); -extern void WebPRescalerExportRowExpandC(struct WebPRescaler* const wrk); -extern void WebPRescalerExportRowShrinkC(struct WebPRescaler* const wrk); - -// Main entry calls: -extern void WebPRescalerImportRow(struct WebPRescaler* const wrk, - const uint8_t* src); -// Export one row (starting at x_out position) from rescaler. -extern void WebPRescalerExportRow(struct WebPRescaler* const wrk); - -// Must be called first before using the above. -void WebPRescalerDspInit(void); - -//------------------------------------------------------------------------------ -// Utilities for processing transparent channel. - -// Apply alpha pre-multiply on an rgba, bgra or argb plane of size w * h. -// alpha_first should be 0 for argb, 1 for rgba or bgra (where alpha is last). -extern void (*WebPApplyAlphaMultiply)( - uint8_t* rgba, int alpha_first, int w, int h, int stride); - -// Same, buf specifically for RGBA4444 format -extern void (*WebPApplyAlphaMultiply4444)( - uint8_t* rgba4444, int w, int h, int stride); - -// Dispatch the values from alpha[] plane to the ARGB destination 'dst'. -// Returns true if alpha[] plane has non-trivial values different from 0xff. -extern int (*WebPDispatchAlpha)(const uint8_t* alpha, int alpha_stride, - int width, int height, - uint8_t* dst, int dst_stride); - -// Transfer packed 8b alpha[] values to green channel in dst[], zero'ing the -// A/R/B values. 'dst_stride' is the stride for dst[] in uint32_t units. -extern void (*WebPDispatchAlphaToGreen)(const uint8_t* alpha, int alpha_stride, - int width, int height, - uint32_t* dst, int dst_stride); - -// Extract the alpha values from 32b values in argb[] and pack them into alpha[] -// (this is the opposite of WebPDispatchAlpha). -// Returns true if there's only trivial 0xff alpha values. -extern int (*WebPExtractAlpha)(const uint8_t* argb, int argb_stride, - int width, int height, - uint8_t* alpha, int alpha_stride); - -// Pre-Multiply operation transforms x into x * A / 255 (where x=Y,R,G or B). -// Un-Multiply operation transforms x into x * 255 / A. - -// Pre-Multiply or Un-Multiply (if 'inverse' is true) argb values in a row. -extern void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse); - -// Same a WebPMultARGBRow(), but for several rows. -void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows, - int inverse); - -// Same for a row of single values, with side alpha values. -extern void (*WebPMultRow)(uint8_t* const ptr, const uint8_t* const alpha, - int width, int inverse); - -// Same a WebPMultRow(), but for several 'num_rows' rows. -void WebPMultRows(uint8_t* ptr, int stride, - const uint8_t* alpha, int alpha_stride, - int width, int num_rows, int inverse); - -// Plain-C versions, used as fallback by some implementations. -void WebPMultRowC(uint8_t* const ptr, const uint8_t* const alpha, - int width, int inverse); -void WebPMultARGBRowC(uint32_t* const ptr, int width, int inverse); - -// To be called first before using the above. -void WebPInitAlphaProcessing(void); - -// ARGB packing function: a/r/g/b input is rgba or bgra order. -extern void (*VP8PackARGB)(const uint8_t* a, const uint8_t* r, - const uint8_t* g, const uint8_t* b, int len, - uint32_t* out); - -// RGB packing function. 'step' can be 3 or 4. r/g/b input is rgb or bgr order. -extern void (*VP8PackRGB)(const uint8_t* r, const uint8_t* g, const uint8_t* b, - int len, int step, uint32_t* out); - -// To be called first before using the above. -void VP8EncDspARGBInit(void); - -//------------------------------------------------------------------------------ -// Filter functions - -typedef enum { // Filter types. - WEBP_FILTER_NONE = 0, - WEBP_FILTER_HORIZONTAL, - WEBP_FILTER_VERTICAL, - WEBP_FILTER_GRADIENT, - WEBP_FILTER_LAST = WEBP_FILTER_GRADIENT + 1, // end marker - WEBP_FILTER_BEST, // meta-types - WEBP_FILTER_FAST -} WEBP_FILTER_TYPE; - -typedef void (*WebPFilterFunc)(const uint8_t* in, int width, int height, - int stride, uint8_t* out); -typedef void (*WebPUnfilterFunc)(int width, int height, int stride, - int row, int num_rows, uint8_t* data); - -// Filter the given data using the given predictor. -// 'in' corresponds to a 2-dimensional pixel array of size (stride * height) -// in raster order. -// 'stride' is number of bytes per scan line (with possible padding). -// 'out' should be pre-allocated. -extern WebPFilterFunc WebPFilters[WEBP_FILTER_LAST]; - -// In-place reconstruct the original data from the given filtered data. -// The reconstruction will be done for 'num_rows' rows starting from 'row' -// (assuming rows upto 'row - 1' are already reconstructed). -extern WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST]; - -// To be called first before using the above. -void VP8FiltersInit(void); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_DSP_DSP_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/dsp/enc.c b/Example-Mac/Pods/libwebp/src/dsp/enc.c deleted file mode 100644 index 8899d500..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/enc.c +++ /dev/null @@ -1,800 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Speed-critical encoding functions. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include // for abs() - -#include "./dsp.h" -#include "../enc/vp8enci.h" - -static WEBP_INLINE uint8_t clip_8b(int v) { - return (!(v & ~0xff)) ? v : (v < 0) ? 0 : 255; -} - -static WEBP_INLINE int clip_max(int v, int max) { - return (v > max) ? max : v; -} - -//------------------------------------------------------------------------------ -// Compute susceptibility based on DCT-coeff histograms: -// the higher, the "easier" the macroblock is to compress. - -const int VP8DspScan[16 + 4 + 4] = { - // Luma - 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS, - 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS, - 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS, - 0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS, - - 0 + 0 * BPS, 4 + 0 * BPS, 0 + 4 * BPS, 4 + 4 * BPS, // U - 8 + 0 * BPS, 12 + 0 * BPS, 8 + 4 * BPS, 12 + 4 * BPS // V -}; - -// general-purpose util function -void VP8SetHistogramData(const int distribution[MAX_COEFF_THRESH + 1], - VP8Histogram* const histo) { - int max_value = 0, last_non_zero = 1; - int k; - for (k = 0; k <= MAX_COEFF_THRESH; ++k) { - const int value = distribution[k]; - if (value > 0) { - if (value > max_value) max_value = value; - last_non_zero = k; - } - } - histo->max_value = max_value; - histo->last_non_zero = last_non_zero; -} - -static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, - int start_block, int end_block, - VP8Histogram* const histo) { - int j; - int distribution[MAX_COEFF_THRESH + 1] = { 0 }; - for (j = start_block; j < end_block; ++j) { - int k; - int16_t out[16]; - - VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); - - // Convert coefficients to bin. - for (k = 0; k < 16; ++k) { - const int v = abs(out[k]) >> 3; // TODO(skal): add rounding? - const int clipped_value = clip_max(v, MAX_COEFF_THRESH); - ++distribution[clipped_value]; - } - } - VP8SetHistogramData(distribution, histo); -} - -//------------------------------------------------------------------------------ -// run-time tables (~4k) - -static uint8_t clip1[255 + 510 + 1]; // clips [-255,510] to [0,255] - -// We declare this variable 'volatile' to prevent instruction reordering -// and make sure it's set to true _last_ (so as to be thread-safe) -static volatile int tables_ok = 0; - -static WEBP_TSAN_IGNORE_FUNCTION void InitTables(void) { - if (!tables_ok) { - int i; - for (i = -255; i <= 255 + 255; ++i) { - clip1[255 + i] = clip_8b(i); - } - tables_ok = 1; - } -} - - -//------------------------------------------------------------------------------ -// Transforms (Paragraph 14.4) - -#define STORE(x, y, v) \ - dst[(x) + (y) * BPS] = clip_8b(ref[(x) + (y) * BPS] + ((v) >> 3)) - -static const int kC1 = 20091 + (1 << 16); -static const int kC2 = 35468; -#define MUL(a, b) (((a) * (b)) >> 16) - -static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, - uint8_t* dst) { - int C[4 * 4], *tmp; - int i; - tmp = C; - for (i = 0; i < 4; ++i) { // vertical pass - const int a = in[0] + in[8]; - const int b = in[0] - in[8]; - const int c = MUL(in[4], kC2) - MUL(in[12], kC1); - const int d = MUL(in[4], kC1) + MUL(in[12], kC2); - tmp[0] = a + d; - tmp[1] = b + c; - tmp[2] = b - c; - tmp[3] = a - d; - tmp += 4; - in++; - } - - tmp = C; - for (i = 0; i < 4; ++i) { // horizontal pass - const int dc = tmp[0] + 4; - const int a = dc + tmp[8]; - const int b = dc - tmp[8]; - const int c = MUL(tmp[4], kC2) - MUL(tmp[12], kC1); - const int d = MUL(tmp[4], kC1) + MUL(tmp[12], kC2); - STORE(0, i, a + d); - STORE(1, i, b + c); - STORE(2, i, b - c); - STORE(3, i, a - d); - tmp++; - } -} - -static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst, - int do_two) { - ITransformOne(ref, in, dst); - if (do_two) { - ITransformOne(ref + 4, in + 16, dst + 4); - } -} - -static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) { - int i; - int tmp[16]; - for (i = 0; i < 4; ++i, src += BPS, ref += BPS) { - const int d0 = src[0] - ref[0]; // 9bit dynamic range ([-255,255]) - const int d1 = src[1] - ref[1]; - const int d2 = src[2] - ref[2]; - const int d3 = src[3] - ref[3]; - const int a0 = (d0 + d3); // 10b [-510,510] - const int a1 = (d1 + d2); - const int a2 = (d1 - d2); - const int a3 = (d0 - d3); - tmp[0 + i * 4] = (a0 + a1) * 8; // 14b [-8160,8160] - tmp[1 + i * 4] = (a2 * 2217 + a3 * 5352 + 1812) >> 9; // [-7536,7542] - tmp[2 + i * 4] = (a0 - a1) * 8; - tmp[3 + i * 4] = (a3 * 2217 - a2 * 5352 + 937) >> 9; - } - for (i = 0; i < 4; ++i) { - const int a0 = (tmp[0 + i] + tmp[12 + i]); // 15b - const int a1 = (tmp[4 + i] + tmp[ 8 + i]); - const int a2 = (tmp[4 + i] - tmp[ 8 + i]); - const int a3 = (tmp[0 + i] - tmp[12 + i]); - out[0 + i] = (a0 + a1 + 7) >> 4; // 12b - out[4 + i] = ((a2 * 2217 + a3 * 5352 + 12000) >> 16) + (a3 != 0); - out[8 + i] = (a0 - a1 + 7) >> 4; - out[12+ i] = ((a3 * 2217 - a2 * 5352 + 51000) >> 16); - } -} - -static void FTransform2(const uint8_t* src, const uint8_t* ref, int16_t* out) { - VP8FTransform(src, ref, out); - VP8FTransform(src + 4, ref + 4, out + 16); -} - -static void FTransformWHT(const int16_t* in, int16_t* out) { - // input is 12b signed - int32_t tmp[16]; - int i; - for (i = 0; i < 4; ++i, in += 64) { - const int a0 = (in[0 * 16] + in[2 * 16]); // 13b - const int a1 = (in[1 * 16] + in[3 * 16]); - const int a2 = (in[1 * 16] - in[3 * 16]); - const int a3 = (in[0 * 16] - in[2 * 16]); - tmp[0 + i * 4] = a0 + a1; // 14b - tmp[1 + i * 4] = a3 + a2; - tmp[2 + i * 4] = a3 - a2; - tmp[3 + i * 4] = a0 - a1; - } - for (i = 0; i < 4; ++i) { - const int a0 = (tmp[0 + i] + tmp[8 + i]); // 15b - const int a1 = (tmp[4 + i] + tmp[12+ i]); - const int a2 = (tmp[4 + i] - tmp[12+ i]); - const int a3 = (tmp[0 + i] - tmp[8 + i]); - const int b0 = a0 + a1; // 16b - const int b1 = a3 + a2; - const int b2 = a3 - a2; - const int b3 = a0 - a1; - out[ 0 + i] = b0 >> 1; // 15b - out[ 4 + i] = b1 >> 1; - out[ 8 + i] = b2 >> 1; - out[12 + i] = b3 >> 1; - } -} - -#undef MUL -#undef STORE - -//------------------------------------------------------------------------------ -// Intra predictions - -static WEBP_INLINE void Fill(uint8_t* dst, int value, int size) { - int j; - for (j = 0; j < size; ++j) { - memset(dst + j * BPS, value, size); - } -} - -static WEBP_INLINE void VerticalPred(uint8_t* dst, - const uint8_t* top, int size) { - int j; - if (top != NULL) { - for (j = 0; j < size; ++j) memcpy(dst + j * BPS, top, size); - } else { - Fill(dst, 127, size); - } -} - -static WEBP_INLINE void HorizontalPred(uint8_t* dst, - const uint8_t* left, int size) { - if (left != NULL) { - int j; - for (j = 0; j < size; ++j) { - memset(dst + j * BPS, left[j], size); - } - } else { - Fill(dst, 129, size); - } -} - -static WEBP_INLINE void TrueMotion(uint8_t* dst, const uint8_t* left, - const uint8_t* top, int size) { - int y; - if (left != NULL) { - if (top != NULL) { - const uint8_t* const clip = clip1 + 255 - left[-1]; - for (y = 0; y < size; ++y) { - const uint8_t* const clip_table = clip + left[y]; - int x; - for (x = 0; x < size; ++x) { - dst[x] = clip_table[top[x]]; - } - dst += BPS; - } - } else { - HorizontalPred(dst, left, size); - } - } else { - // true motion without left samples (hence: with default 129 value) - // is equivalent to VE prediction where you just copy the top samples. - // Note that if top samples are not available, the default value is - // then 129, and not 127 as in the VerticalPred case. - if (top != NULL) { - VerticalPred(dst, top, size); - } else { - Fill(dst, 129, size); - } - } -} - -static WEBP_INLINE void DCMode(uint8_t* dst, const uint8_t* left, - const uint8_t* top, - int size, int round, int shift) { - int DC = 0; - int j; - if (top != NULL) { - for (j = 0; j < size; ++j) DC += top[j]; - if (left != NULL) { // top and left present - for (j = 0; j < size; ++j) DC += left[j]; - } else { // top, but no left - DC += DC; - } - DC = (DC + round) >> shift; - } else if (left != NULL) { // left but no top - for (j = 0; j < size; ++j) DC += left[j]; - DC += DC; - DC = (DC + round) >> shift; - } else { // no top, no left, nothing. - DC = 0x80; - } - Fill(dst, DC, size); -} - -//------------------------------------------------------------------------------ -// Chroma 8x8 prediction (paragraph 12.2) - -static void IntraChromaPreds(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { - // U block - DCMode(C8DC8 + dst, left, top, 8, 8, 4); - VerticalPred(C8VE8 + dst, top, 8); - HorizontalPred(C8HE8 + dst, left, 8); - TrueMotion(C8TM8 + dst, left, top, 8); - // V block - dst += 8; - if (top != NULL) top += 8; - if (left != NULL) left += 16; - DCMode(C8DC8 + dst, left, top, 8, 8, 4); - VerticalPred(C8VE8 + dst, top, 8); - HorizontalPred(C8HE8 + dst, left, 8); - TrueMotion(C8TM8 + dst, left, top, 8); -} - -//------------------------------------------------------------------------------ -// luma 16x16 prediction (paragraph 12.3) - -static void Intra16Preds(uint8_t* dst, - const uint8_t* left, const uint8_t* top) { - DCMode(I16DC16 + dst, left, top, 16, 16, 5); - VerticalPred(I16VE16 + dst, top, 16); - HorizontalPred(I16HE16 + dst, left, 16); - TrueMotion(I16TM16 + dst, left, top, 16); -} - -//------------------------------------------------------------------------------ -// luma 4x4 prediction - -#define DST(x, y) dst[(x) + (y) * BPS] -#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2) -#define AVG2(a, b) (((a) + (b) + 1) >> 1) - -static void VE4(uint8_t* dst, const uint8_t* top) { // vertical - const uint8_t vals[4] = { - AVG3(top[-1], top[0], top[1]), - AVG3(top[ 0], top[1], top[2]), - AVG3(top[ 1], top[2], top[3]), - AVG3(top[ 2], top[3], top[4]) - }; - int i; - for (i = 0; i < 4; ++i) { - memcpy(dst + i * BPS, vals, 4); - } -} - -static void HE4(uint8_t* dst, const uint8_t* top) { // horizontal - const int X = top[-1]; - const int I = top[-2]; - const int J = top[-3]; - const int K = top[-4]; - const int L = top[-5]; - WebPUint32ToMem(dst + 0 * BPS, 0x01010101U * AVG3(X, I, J)); - WebPUint32ToMem(dst + 1 * BPS, 0x01010101U * AVG3(I, J, K)); - WebPUint32ToMem(dst + 2 * BPS, 0x01010101U * AVG3(J, K, L)); - WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(K, L, L)); -} - -static void DC4(uint8_t* dst, const uint8_t* top) { - uint32_t dc = 4; - int i; - for (i = 0; i < 4; ++i) dc += top[i] + top[-5 + i]; - Fill(dst, dc >> 3, 4); -} - -static void RD4(uint8_t* dst, const uint8_t* top) { - const int X = top[-1]; - const int I = top[-2]; - const int J = top[-3]; - const int K = top[-4]; - const int L = top[-5]; - const int A = top[0]; - const int B = top[1]; - const int C = top[2]; - const int D = top[3]; - DST(0, 3) = AVG3(J, K, L); - DST(0, 2) = DST(1, 3) = AVG3(I, J, K); - DST(0, 1) = DST(1, 2) = DST(2, 3) = AVG3(X, I, J); - DST(0, 0) = DST(1, 1) = DST(2, 2) = DST(3, 3) = AVG3(A, X, I); - DST(1, 0) = DST(2, 1) = DST(3, 2) = AVG3(B, A, X); - DST(2, 0) = DST(3, 1) = AVG3(C, B, A); - DST(3, 0) = AVG3(D, C, B); -} - -static void LD4(uint8_t* dst, const uint8_t* top) { - const int A = top[0]; - const int B = top[1]; - const int C = top[2]; - const int D = top[3]; - const int E = top[4]; - const int F = top[5]; - const int G = top[6]; - const int H = top[7]; - DST(0, 0) = AVG3(A, B, C); - DST(1, 0) = DST(0, 1) = AVG3(B, C, D); - DST(2, 0) = DST(1, 1) = DST(0, 2) = AVG3(C, D, E); - DST(3, 0) = DST(2, 1) = DST(1, 2) = DST(0, 3) = AVG3(D, E, F); - DST(3, 1) = DST(2, 2) = DST(1, 3) = AVG3(E, F, G); - DST(3, 2) = DST(2, 3) = AVG3(F, G, H); - DST(3, 3) = AVG3(G, H, H); -} - -static void VR4(uint8_t* dst, const uint8_t* top) { - const int X = top[-1]; - const int I = top[-2]; - const int J = top[-3]; - const int K = top[-4]; - const int A = top[0]; - const int B = top[1]; - const int C = top[2]; - const int D = top[3]; - DST(0, 0) = DST(1, 2) = AVG2(X, A); - DST(1, 0) = DST(2, 2) = AVG2(A, B); - DST(2, 0) = DST(3, 2) = AVG2(B, C); - DST(3, 0) = AVG2(C, D); - - DST(0, 3) = AVG3(K, J, I); - DST(0, 2) = AVG3(J, I, X); - DST(0, 1) = DST(1, 3) = AVG3(I, X, A); - DST(1, 1) = DST(2, 3) = AVG3(X, A, B); - DST(2, 1) = DST(3, 3) = AVG3(A, B, C); - DST(3, 1) = AVG3(B, C, D); -} - -static void VL4(uint8_t* dst, const uint8_t* top) { - const int A = top[0]; - const int B = top[1]; - const int C = top[2]; - const int D = top[3]; - const int E = top[4]; - const int F = top[5]; - const int G = top[6]; - const int H = top[7]; - DST(0, 0) = AVG2(A, B); - DST(1, 0) = DST(0, 2) = AVG2(B, C); - DST(2, 0) = DST(1, 2) = AVG2(C, D); - DST(3, 0) = DST(2, 2) = AVG2(D, E); - - DST(0, 1) = AVG3(A, B, C); - DST(1, 1) = DST(0, 3) = AVG3(B, C, D); - DST(2, 1) = DST(1, 3) = AVG3(C, D, E); - DST(3, 1) = DST(2, 3) = AVG3(D, E, F); - DST(3, 2) = AVG3(E, F, G); - DST(3, 3) = AVG3(F, G, H); -} - -static void HU4(uint8_t* dst, const uint8_t* top) { - const int I = top[-2]; - const int J = top[-3]; - const int K = top[-4]; - const int L = top[-5]; - DST(0, 0) = AVG2(I, J); - DST(2, 0) = DST(0, 1) = AVG2(J, K); - DST(2, 1) = DST(0, 2) = AVG2(K, L); - DST(1, 0) = AVG3(I, J, K); - DST(3, 0) = DST(1, 1) = AVG3(J, K, L); - DST(3, 1) = DST(1, 2) = AVG3(K, L, L); - DST(3, 2) = DST(2, 2) = - DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L; -} - -static void HD4(uint8_t* dst, const uint8_t* top) { - const int X = top[-1]; - const int I = top[-2]; - const int J = top[-3]; - const int K = top[-4]; - const int L = top[-5]; - const int A = top[0]; - const int B = top[1]; - const int C = top[2]; - - DST(0, 0) = DST(2, 1) = AVG2(I, X); - DST(0, 1) = DST(2, 2) = AVG2(J, I); - DST(0, 2) = DST(2, 3) = AVG2(K, J); - DST(0, 3) = AVG2(L, K); - - DST(3, 0) = AVG3(A, B, C); - DST(2, 0) = AVG3(X, A, B); - DST(1, 0) = DST(3, 1) = AVG3(I, X, A); - DST(1, 1) = DST(3, 2) = AVG3(J, I, X); - DST(1, 2) = DST(3, 3) = AVG3(K, J, I); - DST(1, 3) = AVG3(L, K, J); -} - -static void TM4(uint8_t* dst, const uint8_t* top) { - int x, y; - const uint8_t* const clip = clip1 + 255 - top[-1]; - for (y = 0; y < 4; ++y) { - const uint8_t* const clip_table = clip + top[-2 - y]; - for (x = 0; x < 4; ++x) { - dst[x] = clip_table[top[x]]; - } - dst += BPS; - } -} - -#undef DST -#undef AVG3 -#undef AVG2 - -// Left samples are top[-5 .. -2], top_left is top[-1], top are -// located at top[0..3], and top right is top[4..7] -static void Intra4Preds(uint8_t* dst, const uint8_t* top) { - DC4(I4DC4 + dst, top); - TM4(I4TM4 + dst, top); - VE4(I4VE4 + dst, top); - HE4(I4HE4 + dst, top); - RD4(I4RD4 + dst, top); - VR4(I4VR4 + dst, top); - LD4(I4LD4 + dst, top); - VL4(I4VL4 + dst, top); - HD4(I4HD4 + dst, top); - HU4(I4HU4 + dst, top); -} - -//------------------------------------------------------------------------------ -// Metric - -static WEBP_INLINE int GetSSE(const uint8_t* a, const uint8_t* b, - int w, int h) { - int count = 0; - int y, x; - for (y = 0; y < h; ++y) { - for (x = 0; x < w; ++x) { - const int diff = (int)a[x] - b[x]; - count += diff * diff; - } - a += BPS; - b += BPS; - } - return count; -} - -static int SSE16x16(const uint8_t* a, const uint8_t* b) { - return GetSSE(a, b, 16, 16); -} -static int SSE16x8(const uint8_t* a, const uint8_t* b) { - return GetSSE(a, b, 16, 8); -} -static int SSE8x8(const uint8_t* a, const uint8_t* b) { - return GetSSE(a, b, 8, 8); -} -static int SSE4x4(const uint8_t* a, const uint8_t* b) { - return GetSSE(a, b, 4, 4); -} - -//------------------------------------------------------------------------------ -// Texture distortion -// -// We try to match the spectral content (weighted) between source and -// reconstructed samples. - -// Hadamard transform -// Returns the weighted sum of the absolute value of transformed coefficients. -static int TTransform(const uint8_t* in, const uint16_t* w) { - int sum = 0; - int tmp[16]; - int i; - // horizontal pass - for (i = 0; i < 4; ++i, in += BPS) { - const int a0 = in[0] + in[2]; - const int a1 = in[1] + in[3]; - const int a2 = in[1] - in[3]; - const int a3 = in[0] - in[2]; - tmp[0 + i * 4] = a0 + a1; - tmp[1 + i * 4] = a3 + a2; - tmp[2 + i * 4] = a3 - a2; - tmp[3 + i * 4] = a0 - a1; - } - // vertical pass - for (i = 0; i < 4; ++i, ++w) { - const int a0 = tmp[0 + i] + tmp[8 + i]; - const int a1 = tmp[4 + i] + tmp[12+ i]; - const int a2 = tmp[4 + i] - tmp[12+ i]; - const int a3 = tmp[0 + i] - tmp[8 + i]; - const int b0 = a0 + a1; - const int b1 = a3 + a2; - const int b2 = a3 - a2; - const int b3 = a0 - a1; - - sum += w[ 0] * abs(b0); - sum += w[ 4] * abs(b1); - sum += w[ 8] * abs(b2); - sum += w[12] * abs(b3); - } - return sum; -} - -static int Disto4x4(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - const int sum1 = TTransform(a, w); - const int sum2 = TTransform(b, w); - return abs(sum2 - sum1) >> 5; -} - -static int Disto16x16(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - int D = 0; - int x, y; - for (y = 0; y < 16 * BPS; y += 4 * BPS) { - for (x = 0; x < 16; x += 4) { - D += Disto4x4(a + x + y, b + x + y, w); - } - } - return D; -} - -//------------------------------------------------------------------------------ -// Quantization -// - -static const uint8_t kZigzag[16] = { - 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 -}; - -// Simple quantization -static int QuantizeBlock(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - int last = -1; - int n; - for (n = 0; n < 16; ++n) { - const int j = kZigzag[n]; - const int sign = (in[j] < 0); - const uint32_t coeff = (sign ? -in[j] : in[j]) + mtx->sharpen_[j]; - if (coeff > mtx->zthresh_[j]) { - const uint32_t Q = mtx->q_[j]; - const uint32_t iQ = mtx->iq_[j]; - const uint32_t B = mtx->bias_[j]; - int level = QUANTDIV(coeff, iQ, B); - if (level > MAX_LEVEL) level = MAX_LEVEL; - if (sign) level = -level; - in[j] = level * Q; - out[n] = level; - if (level) last = n; - } else { - out[n] = 0; - in[j] = 0; - } - } - return (last >= 0); -} - -static int Quantize2Blocks(int16_t in[32], int16_t out[32], - const VP8Matrix* const mtx) { - int nz; - nz = VP8EncQuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0; - nz |= VP8EncQuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1; - return nz; -} - -static int QuantizeBlockWHT(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - int n, last = -1; - for (n = 0; n < 16; ++n) { - const int j = kZigzag[n]; - const int sign = (in[j] < 0); - const uint32_t coeff = sign ? -in[j] : in[j]; - assert(mtx->sharpen_[j] == 0); - if (coeff > mtx->zthresh_[j]) { - const uint32_t Q = mtx->q_[j]; - const uint32_t iQ = mtx->iq_[j]; - const uint32_t B = mtx->bias_[j]; - int level = QUANTDIV(coeff, iQ, B); - if (level > MAX_LEVEL) level = MAX_LEVEL; - if (sign) level = -level; - in[j] = level * Q; - out[n] = level; - if (level) last = n; - } else { - out[n] = 0; - in[j] = 0; - } - } - return (last >= 0); -} - -//------------------------------------------------------------------------------ -// Block copy - -static WEBP_INLINE void Copy(const uint8_t* src, uint8_t* dst, int w, int h) { - int y; - for (y = 0; y < h; ++y) { - memcpy(dst, src, w); - src += BPS; - dst += BPS; - } -} - -static void Copy4x4(const uint8_t* src, uint8_t* dst) { - Copy(src, dst, 4, 4); -} - -static void Copy16x8(const uint8_t* src, uint8_t* dst) { - Copy(src, dst, 16, 8); -} - -//------------------------------------------------------------------------------ -// Initialization - -// Speed-critical function pointers. We have to initialize them to the default -// implementations within VP8EncDspInit(). -VP8CHisto VP8CollectHistogram; -VP8Idct VP8ITransform; -VP8Fdct VP8FTransform; -VP8Fdct VP8FTransform2; -VP8WHT VP8FTransformWHT; -VP8Intra4Preds VP8EncPredLuma4; -VP8IntraPreds VP8EncPredLuma16; -VP8IntraPreds VP8EncPredChroma8; -VP8Metric VP8SSE16x16; -VP8Metric VP8SSE8x8; -VP8Metric VP8SSE16x8; -VP8Metric VP8SSE4x4; -VP8WMetric VP8TDisto4x4; -VP8WMetric VP8TDisto16x16; -VP8QuantizeBlock VP8EncQuantizeBlock; -VP8Quantize2Blocks VP8EncQuantize2Blocks; -VP8QuantizeBlockWHT VP8EncQuantizeBlockWHT; -VP8BlockCopy VP8Copy4x4; -VP8BlockCopy VP8Copy16x8; - -extern void VP8EncDspInitSSE2(void); -extern void VP8EncDspInitSSE41(void); -extern void VP8EncDspInitAVX2(void); -extern void VP8EncDspInitNEON(void); -extern void VP8EncDspInitMIPS32(void); -extern void VP8EncDspInitMIPSdspR2(void); - -static volatile VP8CPUInfo enc_last_cpuinfo_used = - (VP8CPUInfo)&enc_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInit(void) { - if (enc_last_cpuinfo_used == VP8GetCPUInfo) return; - - VP8DspInit(); // common inverse transforms - InitTables(); - - // default C implementations - VP8CollectHistogram = CollectHistogram; - VP8ITransform = ITransform; - VP8FTransform = FTransform; - VP8FTransform2 = FTransform2; - VP8FTransformWHT = FTransformWHT; - VP8EncPredLuma4 = Intra4Preds; - VP8EncPredLuma16 = Intra16Preds; - VP8EncPredChroma8 = IntraChromaPreds; - VP8SSE16x16 = SSE16x16; - VP8SSE8x8 = SSE8x8; - VP8SSE16x8 = SSE16x8; - VP8SSE4x4 = SSE4x4; - VP8TDisto4x4 = Disto4x4; - VP8TDisto16x16 = Disto16x16; - VP8EncQuantizeBlock = QuantizeBlock; - VP8EncQuantize2Blocks = Quantize2Blocks; - VP8EncQuantizeBlockWHT = QuantizeBlockWHT; - VP8Copy4x4 = Copy4x4; - VP8Copy16x8 = Copy16x8; - - // If defined, use CPUInfo() to overwrite some pointers with faster versions. - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - VP8EncDspInitSSE2(); -#if defined(WEBP_USE_SSE41) - if (VP8GetCPUInfo(kSSE4_1)) { - VP8EncDspInitSSE41(); - } -#endif - } -#endif -#if defined(WEBP_USE_AVX2) - if (VP8GetCPUInfo(kAVX2)) { - VP8EncDspInitAVX2(); - } -#endif -#if defined(WEBP_USE_NEON) - if (VP8GetCPUInfo(kNEON)) { - VP8EncDspInitNEON(); - } -#endif -#if defined(WEBP_USE_MIPS32) - if (VP8GetCPUInfo(kMIPS32)) { - VP8EncDspInitMIPS32(); - } -#endif -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - VP8EncDspInitMIPSdspR2(); - } -#endif - } - enc_last_cpuinfo_used = VP8GetCPUInfo; -} diff --git a/Example-Mac/Pods/libwebp/src/dsp/enc_avx2.c b/Example-Mac/Pods/libwebp/src/dsp/enc_avx2.c deleted file mode 100644 index 93efb30b..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/enc_avx2.c +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// AVX2 version of speed-critical encoding functions. - -#include "./dsp.h" - -#if defined(WEBP_USE_AVX2) - -#endif // WEBP_USE_AVX2 - -//------------------------------------------------------------------------------ -// Entry point - -WEBP_DSP_INIT_STUB(VP8EncDspInitAVX2) diff --git a/Example-Mac/Pods/libwebp/src/dsp/enc_mips32.c b/Example-Mac/Pods/libwebp/src/dsp/enc_mips32.c deleted file mode 100644 index fd10143d..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/enc_mips32.c +++ /dev/null @@ -1,672 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// MIPS version of speed-critical encoding functions. -// -// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) -// Jovan Zelincevic (jovan.zelincevic@imgtec.com) -// Slobodan Prijic (slobodan.prijic@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS32) - -#include "./mips_macro.h" -#include "../enc/vp8enci.h" -#include "../enc/cost.h" - -static const int kC1 = 20091 + (1 << 16); -static const int kC2 = 35468; - -// macro for one vertical pass in ITransformOne -// MUL macro inlined -// temp0..temp15 holds tmp[0]..tmp[15] -// A..D - offsets in bytes to load from in buffer -// TEMP0..TEMP3 - registers for corresponding tmp elements -// TEMP4..TEMP5 - temporary registers -#define VERTICAL_PASS(A, B, C, D, TEMP4, TEMP0, TEMP1, TEMP2, TEMP3) \ - "lh %[temp16], " #A "(%[temp20]) \n\t" \ - "lh %[temp18], " #B "(%[temp20]) \n\t" \ - "lh %[temp17], " #C "(%[temp20]) \n\t" \ - "lh %[temp19], " #D "(%[temp20]) \n\t" \ - "addu %[" #TEMP4 "], %[temp16], %[temp18] \n\t" \ - "subu %[temp16], %[temp16], %[temp18] \n\t" \ - "mul %[" #TEMP0 "], %[temp17], %[kC2] \n\t" \ - "mul %[temp18], %[temp19], %[kC1] \n\t" \ - "mul %[temp17], %[temp17], %[kC1] \n\t" \ - "mul %[temp19], %[temp19], %[kC2] \n\t" \ - "sra %[" #TEMP0 "], %[" #TEMP0 "], 16 \n\n" \ - "sra %[temp18], %[temp18], 16 \n\n" \ - "sra %[temp17], %[temp17], 16 \n\n" \ - "sra %[temp19], %[temp19], 16 \n\n" \ - "subu %[" #TEMP2 "], %[" #TEMP0 "], %[temp18] \n\t" \ - "addu %[" #TEMP3 "], %[temp17], %[temp19] \n\t" \ - "addu %[" #TEMP0 "], %[" #TEMP4 "], %[" #TEMP3 "] \n\t" \ - "addu %[" #TEMP1 "], %[temp16], %[" #TEMP2 "] \n\t" \ - "subu %[" #TEMP2 "], %[temp16], %[" #TEMP2 "] \n\t" \ - "subu %[" #TEMP3 "], %[" #TEMP4 "], %[" #TEMP3 "] \n\t" - -// macro for one horizontal pass in ITransformOne -// MUL and STORE macros inlined -// a = clip_8b(a) is replaced with: a = max(a, 0); a = min(a, 255) -// temp0..temp15 holds tmp[0]..tmp[15] -// A - offset in bytes to load from ref and store to dst buffer -// TEMP0, TEMP4, TEMP8 and TEMP12 - registers for corresponding tmp elements -#define HORIZONTAL_PASS(A, TEMP0, TEMP4, TEMP8, TEMP12) \ - "addiu %[" #TEMP0 "], %[" #TEMP0 "], 4 \n\t" \ - "addu %[temp16], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \ - "subu %[temp17], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \ - "mul %[" #TEMP0 "], %[" #TEMP4 "], %[kC2] \n\t" \ - "mul %[" #TEMP8 "], %[" #TEMP12 "], %[kC1] \n\t" \ - "mul %[" #TEMP4 "], %[" #TEMP4 "], %[kC1] \n\t" \ - "mul %[" #TEMP12 "], %[" #TEMP12 "], %[kC2] \n\t" \ - "sra %[" #TEMP0 "], %[" #TEMP0 "], 16 \n\t" \ - "sra %[" #TEMP8 "], %[" #TEMP8 "], 16 \n\t" \ - "sra %[" #TEMP4 "], %[" #TEMP4 "], 16 \n\t" \ - "sra %[" #TEMP12 "], %[" #TEMP12 "], 16 \n\t" \ - "subu %[temp18], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \ - "addu %[temp19], %[" #TEMP4 "], %[" #TEMP12 "] \n\t" \ - "addu %[" #TEMP0 "], %[temp16], %[temp19] \n\t" \ - "addu %[" #TEMP4 "], %[temp17], %[temp18] \n\t" \ - "subu %[" #TEMP8 "], %[temp17], %[temp18] \n\t" \ - "subu %[" #TEMP12 "], %[temp16], %[temp19] \n\t" \ - "lw %[temp20], 0(%[args]) \n\t" \ - "sra %[" #TEMP0 "], %[" #TEMP0 "], 3 \n\t" \ - "sra %[" #TEMP4 "], %[" #TEMP4 "], 3 \n\t" \ - "sra %[" #TEMP8 "], %[" #TEMP8 "], 3 \n\t" \ - "sra %[" #TEMP12 "], %[" #TEMP12 "], 3 \n\t" \ - "lbu %[temp16], 0+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \ - "lbu %[temp17], 1+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \ - "lbu %[temp18], 2+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \ - "lbu %[temp19], 3+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \ - "addu %[" #TEMP0 "], %[temp16], %[" #TEMP0 "] \n\t" \ - "addu %[" #TEMP4 "], %[temp17], %[" #TEMP4 "] \n\t" \ - "addu %[" #TEMP8 "], %[temp18], %[" #TEMP8 "] \n\t" \ - "addu %[" #TEMP12 "], %[temp19], %[" #TEMP12 "] \n\t" \ - "slt %[temp16], %[" #TEMP0 "], $zero \n\t" \ - "slt %[temp17], %[" #TEMP4 "], $zero \n\t" \ - "slt %[temp18], %[" #TEMP8 "], $zero \n\t" \ - "slt %[temp19], %[" #TEMP12 "], $zero \n\t" \ - "movn %[" #TEMP0 "], $zero, %[temp16] \n\t" \ - "movn %[" #TEMP4 "], $zero, %[temp17] \n\t" \ - "movn %[" #TEMP8 "], $zero, %[temp18] \n\t" \ - "movn %[" #TEMP12 "], $zero, %[temp19] \n\t" \ - "addiu %[temp20], $zero, 255 \n\t" \ - "slt %[temp16], %[" #TEMP0 "], %[temp20] \n\t" \ - "slt %[temp17], %[" #TEMP4 "], %[temp20] \n\t" \ - "slt %[temp18], %[" #TEMP8 "], %[temp20] \n\t" \ - "slt %[temp19], %[" #TEMP12 "], %[temp20] \n\t" \ - "movz %[" #TEMP0 "], %[temp20], %[temp16] \n\t" \ - "movz %[" #TEMP4 "], %[temp20], %[temp17] \n\t" \ - "lw %[temp16], 8(%[args]) \n\t" \ - "movz %[" #TEMP8 "], %[temp20], %[temp18] \n\t" \ - "movz %[" #TEMP12 "], %[temp20], %[temp19] \n\t" \ - "sb %[" #TEMP0 "], 0+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" \ - "sb %[" #TEMP4 "], 1+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" \ - "sb %[" #TEMP8 "], 2+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" \ - "sb %[" #TEMP12 "], 3+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" - -// Does one or two inverse transforms. -static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, - uint8_t* dst) { - int temp0, temp1, temp2, temp3, temp4, temp5, temp6; - int temp7, temp8, temp9, temp10, temp11, temp12, temp13; - int temp14, temp15, temp16, temp17, temp18, temp19, temp20; - const int* args[3] = {(const int*)ref, (const int*)in, (const int*)dst}; - - __asm__ volatile( - "lw %[temp20], 4(%[args]) \n\t" - VERTICAL_PASS(0, 16, 8, 24, temp4, temp0, temp1, temp2, temp3) - VERTICAL_PASS(2, 18, 10, 26, temp8, temp4, temp5, temp6, temp7) - VERTICAL_PASS(4, 20, 12, 28, temp12, temp8, temp9, temp10, temp11) - VERTICAL_PASS(6, 22, 14, 30, temp20, temp12, temp13, temp14, temp15) - - HORIZONTAL_PASS(0, temp0, temp4, temp8, temp12) - HORIZONTAL_PASS(1, temp1, temp5, temp9, temp13) - HORIZONTAL_PASS(2, temp2, temp6, temp10, temp14) - HORIZONTAL_PASS(3, temp3, temp7, temp11, temp15) - - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11), - [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14), - [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17), - [temp18]"=&r"(temp18), [temp19]"=&r"(temp19), [temp20]"=&r"(temp20) - : [args]"r"(args), [kC1]"r"(kC1), [kC2]"r"(kC2) - : "memory", "hi", "lo" - ); -} - -static void ITransform(const uint8_t* ref, const int16_t* in, - uint8_t* dst, int do_two) { - ITransformOne(ref, in, dst); - if (do_two) { - ITransformOne(ref + 4, in + 16, dst + 4); - } -} - -#undef VERTICAL_PASS -#undef HORIZONTAL_PASS - -// macro for one pass through for loop in QuantizeBlock -// QUANTDIV macro inlined -// J - offset in bytes (kZigzag[n] * 2) -// K - offset in bytes (kZigzag[n] * 4) -// N - offset in bytes (n * 2) -#define QUANTIZE_ONE(J, K, N) \ - "lh %[temp0], " #J "(%[ppin]) \n\t" \ - "lhu %[temp1], " #J "(%[ppsharpen]) \n\t" \ - "lw %[temp2], " #K "(%[ppzthresh]) \n\t" \ - "sra %[sign], %[temp0], 15 \n\t" \ - "xor %[coeff], %[temp0], %[sign] \n\t" \ - "subu %[coeff], %[coeff], %[sign] \n\t" \ - "addu %[coeff], %[coeff], %[temp1] \n\t" \ - "slt %[temp4], %[temp2], %[coeff] \n\t" \ - "addiu %[temp5], $zero, 0 \n\t" \ - "addiu %[level], $zero, 0 \n\t" \ - "beqz %[temp4], 2f \n\t" \ - "lhu %[temp1], " #J "(%[ppiq]) \n\t" \ - "lw %[temp2], " #K "(%[ppbias]) \n\t" \ - "lhu %[temp3], " #J "(%[ppq]) \n\t" \ - "mul %[level], %[coeff], %[temp1] \n\t" \ - "addu %[level], %[level], %[temp2] \n\t" \ - "sra %[level], %[level], 17 \n\t" \ - "slt %[temp4], %[max_level], %[level] \n\t" \ - "movn %[level], %[max_level], %[temp4] \n\t" \ - "xor %[level], %[level], %[sign] \n\t" \ - "subu %[level], %[level], %[sign] \n\t" \ - "mul %[temp5], %[level], %[temp3] \n\t" \ -"2: \n\t" \ - "sh %[temp5], " #J "(%[ppin]) \n\t" \ - "sh %[level], " #N "(%[pout]) \n\t" - -static int QuantizeBlock(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - int temp0, temp1, temp2, temp3, temp4, temp5; - int sign, coeff, level, i; - int max_level = MAX_LEVEL; - - int16_t* ppin = &in[0]; - int16_t* pout = &out[0]; - const uint16_t* ppsharpen = &mtx->sharpen_[0]; - const uint32_t* ppzthresh = &mtx->zthresh_[0]; - const uint16_t* ppq = &mtx->q_[0]; - const uint16_t* ppiq = &mtx->iq_[0]; - const uint32_t* ppbias = &mtx->bias_[0]; - - __asm__ volatile( - QUANTIZE_ONE( 0, 0, 0) - QUANTIZE_ONE( 2, 4, 2) - QUANTIZE_ONE( 8, 16, 4) - QUANTIZE_ONE(16, 32, 6) - QUANTIZE_ONE(10, 20, 8) - QUANTIZE_ONE( 4, 8, 10) - QUANTIZE_ONE( 6, 12, 12) - QUANTIZE_ONE(12, 24, 14) - QUANTIZE_ONE(18, 36, 16) - QUANTIZE_ONE(24, 48, 18) - QUANTIZE_ONE(26, 52, 20) - QUANTIZE_ONE(20, 40, 22) - QUANTIZE_ONE(14, 28, 24) - QUANTIZE_ONE(22, 44, 26) - QUANTIZE_ONE(28, 56, 28) - QUANTIZE_ONE(30, 60, 30) - - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [sign]"=&r"(sign), [coeff]"=&r"(coeff), - [level]"=&r"(level) - : [pout]"r"(pout), [ppin]"r"(ppin), - [ppiq]"r"(ppiq), [max_level]"r"(max_level), - [ppbias]"r"(ppbias), [ppzthresh]"r"(ppzthresh), - [ppsharpen]"r"(ppsharpen), [ppq]"r"(ppq) - : "memory", "hi", "lo" - ); - - // moved out from macro to increase possibility for earlier breaking - for (i = 15; i >= 0; i--) { - if (out[i]) return 1; - } - return 0; -} - -static int Quantize2Blocks(int16_t in[32], int16_t out[32], - const VP8Matrix* const mtx) { - int nz; - nz = QuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0; - nz |= QuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1; - return nz; -} - -#undef QUANTIZE_ONE - -// macro for one horizontal pass in Disto4x4 (TTransform) -// two calls of function TTransform are merged into single one -// A - offset in bytes to load from a and b buffers -// E..H - offsets in bytes to store first results to tmp buffer -// E1..H1 - offsets in bytes to store second results to tmp buffer -#define HORIZONTAL_PASS(A, E, F, G, H, E1, F1, G1, H1) \ - "lbu %[temp0], 0+" XSTR(BPS) "*" #A "(%[a]) \n\t" \ - "lbu %[temp1], 1+" XSTR(BPS) "*" #A "(%[a]) \n\t" \ - "lbu %[temp2], 2+" XSTR(BPS) "*" #A "(%[a]) \n\t" \ - "lbu %[temp3], 3+" XSTR(BPS) "*" #A "(%[a]) \n\t" \ - "lbu %[temp4], 0+" XSTR(BPS) "*" #A "(%[b]) \n\t" \ - "lbu %[temp5], 1+" XSTR(BPS) "*" #A "(%[b]) \n\t" \ - "lbu %[temp6], 2+" XSTR(BPS) "*" #A "(%[b]) \n\t" \ - "lbu %[temp7], 3+" XSTR(BPS) "*" #A "(%[b]) \n\t" \ - "addu %[temp8], %[temp0], %[temp2] \n\t" \ - "subu %[temp0], %[temp0], %[temp2] \n\t" \ - "addu %[temp2], %[temp1], %[temp3] \n\t" \ - "subu %[temp1], %[temp1], %[temp3] \n\t" \ - "addu %[temp3], %[temp4], %[temp6] \n\t" \ - "subu %[temp4], %[temp4], %[temp6] \n\t" \ - "addu %[temp6], %[temp5], %[temp7] \n\t" \ - "subu %[temp5], %[temp5], %[temp7] \n\t" \ - "addu %[temp7], %[temp8], %[temp2] \n\t" \ - "subu %[temp2], %[temp8], %[temp2] \n\t" \ - "addu %[temp8], %[temp0], %[temp1] \n\t" \ - "subu %[temp0], %[temp0], %[temp1] \n\t" \ - "addu %[temp1], %[temp3], %[temp6] \n\t" \ - "subu %[temp3], %[temp3], %[temp6] \n\t" \ - "addu %[temp6], %[temp4], %[temp5] \n\t" \ - "subu %[temp4], %[temp4], %[temp5] \n\t" \ - "sw %[temp7], " #E "(%[tmp]) \n\t" \ - "sw %[temp2], " #H "(%[tmp]) \n\t" \ - "sw %[temp8], " #F "(%[tmp]) \n\t" \ - "sw %[temp0], " #G "(%[tmp]) \n\t" \ - "sw %[temp1], " #E1 "(%[tmp]) \n\t" \ - "sw %[temp3], " #H1 "(%[tmp]) \n\t" \ - "sw %[temp6], " #F1 "(%[tmp]) \n\t" \ - "sw %[temp4], " #G1 "(%[tmp]) \n\t" - -// macro for one vertical pass in Disto4x4 (TTransform) -// two calls of function TTransform are merged into single one -// since only one accu is available in mips32r1 instruction set -// first is done second call of function TTransform and after -// that first one. -// const int sum1 = TTransform(a, w); -// const int sum2 = TTransform(b, w); -// return abs(sum2 - sum1) >> 5; -// (sum2 - sum1) is calculated with madds (sub2) and msubs (sub1) -// A..D - offsets in bytes to load first results from tmp buffer -// A1..D1 - offsets in bytes to load second results from tmp buffer -// E..H - offsets in bytes to load from w buffer -#define VERTICAL_PASS(A, B, C, D, A1, B1, C1, D1, E, F, G, H) \ - "lw %[temp0], " #A1 "(%[tmp]) \n\t" \ - "lw %[temp1], " #C1 "(%[tmp]) \n\t" \ - "lw %[temp2], " #B1 "(%[tmp]) \n\t" \ - "lw %[temp3], " #D1 "(%[tmp]) \n\t" \ - "addu %[temp8], %[temp0], %[temp1] \n\t" \ - "subu %[temp0], %[temp0], %[temp1] \n\t" \ - "addu %[temp1], %[temp2], %[temp3] \n\t" \ - "subu %[temp2], %[temp2], %[temp3] \n\t" \ - "addu %[temp3], %[temp8], %[temp1] \n\t" \ - "subu %[temp8], %[temp8], %[temp1] \n\t" \ - "addu %[temp1], %[temp0], %[temp2] \n\t" \ - "subu %[temp0], %[temp0], %[temp2] \n\t" \ - "sra %[temp4], %[temp3], 31 \n\t" \ - "sra %[temp5], %[temp1], 31 \n\t" \ - "sra %[temp6], %[temp0], 31 \n\t" \ - "sra %[temp7], %[temp8], 31 \n\t" \ - "xor %[temp3], %[temp3], %[temp4] \n\t" \ - "xor %[temp1], %[temp1], %[temp5] \n\t" \ - "xor %[temp0], %[temp0], %[temp6] \n\t" \ - "xor %[temp8], %[temp8], %[temp7] \n\t" \ - "subu %[temp3], %[temp3], %[temp4] \n\t" \ - "subu %[temp1], %[temp1], %[temp5] \n\t" \ - "subu %[temp0], %[temp0], %[temp6] \n\t" \ - "subu %[temp8], %[temp8], %[temp7] \n\t" \ - "lhu %[temp4], " #E "(%[w]) \n\t" \ - "lhu %[temp5], " #F "(%[w]) \n\t" \ - "lhu %[temp6], " #G "(%[w]) \n\t" \ - "lhu %[temp7], " #H "(%[w]) \n\t" \ - "madd %[temp4], %[temp3] \n\t" \ - "madd %[temp5], %[temp1] \n\t" \ - "madd %[temp6], %[temp0] \n\t" \ - "madd %[temp7], %[temp8] \n\t" \ - "lw %[temp0], " #A "(%[tmp]) \n\t" \ - "lw %[temp1], " #C "(%[tmp]) \n\t" \ - "lw %[temp2], " #B "(%[tmp]) \n\t" \ - "lw %[temp3], " #D "(%[tmp]) \n\t" \ - "addu %[temp8], %[temp0], %[temp1] \n\t" \ - "subu %[temp0], %[temp0], %[temp1] \n\t" \ - "addu %[temp1], %[temp2], %[temp3] \n\t" \ - "subu %[temp2], %[temp2], %[temp3] \n\t" \ - "addu %[temp3], %[temp8], %[temp1] \n\t" \ - "subu %[temp1], %[temp8], %[temp1] \n\t" \ - "addu %[temp8], %[temp0], %[temp2] \n\t" \ - "subu %[temp0], %[temp0], %[temp2] \n\t" \ - "sra %[temp2], %[temp3], 31 \n\t" \ - "xor %[temp3], %[temp3], %[temp2] \n\t" \ - "subu %[temp3], %[temp3], %[temp2] \n\t" \ - "msub %[temp4], %[temp3] \n\t" \ - "sra %[temp2], %[temp8], 31 \n\t" \ - "sra %[temp3], %[temp0], 31 \n\t" \ - "sra %[temp4], %[temp1], 31 \n\t" \ - "xor %[temp8], %[temp8], %[temp2] \n\t" \ - "xor %[temp0], %[temp0], %[temp3] \n\t" \ - "xor %[temp1], %[temp1], %[temp4] \n\t" \ - "subu %[temp8], %[temp8], %[temp2] \n\t" \ - "subu %[temp0], %[temp0], %[temp3] \n\t" \ - "subu %[temp1], %[temp1], %[temp4] \n\t" \ - "msub %[temp5], %[temp8] \n\t" \ - "msub %[temp6], %[temp0] \n\t" \ - "msub %[temp7], %[temp1] \n\t" - -static int Disto4x4(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - int tmp[32]; - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; - - __asm__ volatile( - HORIZONTAL_PASS(0, 0, 4, 8, 12, 64, 68, 72, 76) - HORIZONTAL_PASS(1, 16, 20, 24, 28, 80, 84, 88, 92) - HORIZONTAL_PASS(2, 32, 36, 40, 44, 96, 100, 104, 108) - HORIZONTAL_PASS(3, 48, 52, 56, 60, 112, 116, 120, 124) - "mthi $zero \n\t" - "mtlo $zero \n\t" - VERTICAL_PASS( 0, 16, 32, 48, 64, 80, 96, 112, 0, 8, 16, 24) - VERTICAL_PASS( 4, 20, 36, 52, 68, 84, 100, 116, 2, 10, 18, 26) - VERTICAL_PASS( 8, 24, 40, 56, 72, 88, 104, 120, 4, 12, 20, 28) - VERTICAL_PASS(12, 28, 44, 60, 76, 92, 108, 124, 6, 14, 22, 30) - "mflo %[temp0] \n\t" - "sra %[temp1], %[temp0], 31 \n\t" - "xor %[temp0], %[temp0], %[temp1] \n\t" - "subu %[temp0], %[temp0], %[temp1] \n\t" - "sra %[temp0], %[temp0], 5 \n\t" - - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8) - : [a]"r"(a), [b]"r"(b), [w]"r"(w), [tmp]"r"(tmp) - : "memory", "hi", "lo" - ); - - return temp0; -} - -#undef VERTICAL_PASS -#undef HORIZONTAL_PASS - -static int Disto16x16(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - int D = 0; - int x, y; - for (y = 0; y < 16 * BPS; y += 4 * BPS) { - for (x = 0; x < 16; x += 4) { - D += Disto4x4(a + x + y, b + x + y, w); - } - } - return D; -} - -// macro for one horizontal pass in FTransform -// temp0..temp15 holds tmp[0]..tmp[15] -// A - offset in bytes to load from src and ref buffers -// TEMP0..TEMP3 - registers for corresponding tmp elements -#define HORIZONTAL_PASS(A, TEMP0, TEMP1, TEMP2, TEMP3) \ - "lw %[" #TEMP1 "], 0(%[args]) \n\t" \ - "lw %[" #TEMP2 "], 4(%[args]) \n\t" \ - "lbu %[temp16], 0+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \ - "lbu %[temp17], 0+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \ - "lbu %[temp18], 1+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \ - "lbu %[temp19], 1+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \ - "subu %[temp20], %[temp16], %[temp17] \n\t" \ - "lbu %[temp16], 2+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \ - "lbu %[temp17], 2+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \ - "subu %[" #TEMP0 "], %[temp18], %[temp19] \n\t" \ - "lbu %[temp18], 3+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \ - "lbu %[temp19], 3+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \ - "subu %[" #TEMP1 "], %[temp16], %[temp17] \n\t" \ - "subu %[" #TEMP2 "], %[temp18], %[temp19] \n\t" \ - "addu %[" #TEMP3 "], %[temp20], %[" #TEMP2 "] \n\t" \ - "subu %[" #TEMP2 "], %[temp20], %[" #TEMP2 "] \n\t" \ - "addu %[temp20], %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \ - "subu %[" #TEMP0 "], %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \ - "mul %[temp16], %[" #TEMP2 "], %[c5352] \n\t" \ - "mul %[temp17], %[" #TEMP2 "], %[c2217] \n\t" \ - "mul %[temp18], %[" #TEMP0 "], %[c5352] \n\t" \ - "mul %[temp19], %[" #TEMP0 "], %[c2217] \n\t" \ - "addu %[" #TEMP1 "], %[" #TEMP3 "], %[temp20] \n\t" \ - "subu %[temp20], %[" #TEMP3 "], %[temp20] \n\t" \ - "sll %[" #TEMP0 "], %[" #TEMP1 "], 3 \n\t" \ - "sll %[" #TEMP2 "], %[temp20], 3 \n\t" \ - "addiu %[temp16], %[temp16], 1812 \n\t" \ - "addiu %[temp17], %[temp17], 937 \n\t" \ - "addu %[temp16], %[temp16], %[temp19] \n\t" \ - "subu %[temp17], %[temp17], %[temp18] \n\t" \ - "sra %[" #TEMP1 "], %[temp16], 9 \n\t" \ - "sra %[" #TEMP3 "], %[temp17], 9 \n\t" - -// macro for one vertical pass in FTransform -// temp0..temp15 holds tmp[0]..tmp[15] -// A..D - offsets in bytes to store to out buffer -// TEMP0, TEMP4, TEMP8 and TEMP12 - registers for corresponding tmp elements -#define VERTICAL_PASS(A, B, C, D, TEMP0, TEMP4, TEMP8, TEMP12) \ - "addu %[temp16], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \ - "subu %[temp19], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \ - "addu %[temp17], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \ - "subu %[temp18], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \ - "mul %[" #TEMP8 "], %[temp19], %[c2217] \n\t" \ - "mul %[" #TEMP12 "], %[temp18], %[c2217] \n\t" \ - "mul %[" #TEMP4 "], %[temp19], %[c5352] \n\t" \ - "mul %[temp18], %[temp18], %[c5352] \n\t" \ - "addiu %[temp16], %[temp16], 7 \n\t" \ - "addu %[" #TEMP0 "], %[temp16], %[temp17] \n\t" \ - "sra %[" #TEMP0 "], %[" #TEMP0 "], 4 \n\t" \ - "addu %[" #TEMP12 "], %[" #TEMP12 "], %[" #TEMP4 "] \n\t" \ - "subu %[" #TEMP4 "], %[temp16], %[temp17] \n\t" \ - "sra %[" #TEMP4 "], %[" #TEMP4 "], 4 \n\t" \ - "addiu %[" #TEMP8 "], %[" #TEMP8 "], 30000 \n\t" \ - "addiu %[" #TEMP12 "], %[" #TEMP12 "], 12000 \n\t" \ - "addiu %[" #TEMP8 "], %[" #TEMP8 "], 21000 \n\t" \ - "subu %[" #TEMP8 "], %[" #TEMP8 "], %[temp18] \n\t" \ - "sra %[" #TEMP12 "], %[" #TEMP12 "], 16 \n\t" \ - "sra %[" #TEMP8 "], %[" #TEMP8 "], 16 \n\t" \ - "addiu %[temp16], %[" #TEMP12 "], 1 \n\t" \ - "movn %[" #TEMP12 "], %[temp16], %[temp19] \n\t" \ - "sh %[" #TEMP0 "], " #A "(%[temp20]) \n\t" \ - "sh %[" #TEMP4 "], " #C "(%[temp20]) \n\t" \ - "sh %[" #TEMP8 "], " #D "(%[temp20]) \n\t" \ - "sh %[" #TEMP12 "], " #B "(%[temp20]) \n\t" - -static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) { - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; - int temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16; - int temp17, temp18, temp19, temp20; - const int c2217 = 2217; - const int c5352 = 5352; - const int* const args[3] = - { (const int*)src, (const int*)ref, (const int*)out }; - - __asm__ volatile( - HORIZONTAL_PASS(0, temp0, temp1, temp2, temp3) - HORIZONTAL_PASS(1, temp4, temp5, temp6, temp7) - HORIZONTAL_PASS(2, temp8, temp9, temp10, temp11) - HORIZONTAL_PASS(3, temp12, temp13, temp14, temp15) - "lw %[temp20], 8(%[args]) \n\t" - VERTICAL_PASS(0, 8, 16, 24, temp0, temp4, temp8, temp12) - VERTICAL_PASS(2, 10, 18, 26, temp1, temp5, temp9, temp13) - VERTICAL_PASS(4, 12, 20, 28, temp2, temp6, temp10, temp14) - VERTICAL_PASS(6, 14, 22, 30, temp3, temp7, temp11, temp15) - - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11), - [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14), - [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17), - [temp18]"=&r"(temp18), [temp19]"=&r"(temp19), [temp20]"=&r"(temp20) - : [args]"r"(args), [c2217]"r"(c2217), [c5352]"r"(c5352) - : "memory", "hi", "lo" - ); -} - -#undef VERTICAL_PASS -#undef HORIZONTAL_PASS - -#if !defined(WORK_AROUND_GCC) - -#define GET_SSE_INNER(A, B, C, D) \ - "lbu %[temp0], " #A "(%[a]) \n\t" \ - "lbu %[temp1], " #A "(%[b]) \n\t" \ - "lbu %[temp2], " #B "(%[a]) \n\t" \ - "lbu %[temp3], " #B "(%[b]) \n\t" \ - "lbu %[temp4], " #C "(%[a]) \n\t" \ - "lbu %[temp5], " #C "(%[b]) \n\t" \ - "lbu %[temp6], " #D "(%[a]) \n\t" \ - "lbu %[temp7], " #D "(%[b]) \n\t" \ - "subu %[temp0], %[temp0], %[temp1] \n\t" \ - "subu %[temp2], %[temp2], %[temp3] \n\t" \ - "subu %[temp4], %[temp4], %[temp5] \n\t" \ - "subu %[temp6], %[temp6], %[temp7] \n\t" \ - "madd %[temp0], %[temp0] \n\t" \ - "madd %[temp2], %[temp2] \n\t" \ - "madd %[temp4], %[temp4] \n\t" \ - "madd %[temp6], %[temp6] \n\t" - -#define GET_SSE(A, B, C, D) \ - GET_SSE_INNER(A, A + 1, A + 2, A + 3) \ - GET_SSE_INNER(B, B + 1, B + 2, B + 3) \ - GET_SSE_INNER(C, C + 1, C + 2, C + 3) \ - GET_SSE_INNER(D, D + 1, D + 2, D + 3) - -static int SSE16x16(const uint8_t* a, const uint8_t* b) { - int count; - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; - - __asm__ volatile( - "mult $zero, $zero \n\t" - - GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS) - GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS) - GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS) - GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS) - GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS) - GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS) - GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS) - GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS) - GET_SSE( 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS) - GET_SSE( 9 * BPS, 4 + 9 * BPS, 8 + 9 * BPS, 12 + 9 * BPS) - GET_SSE(10 * BPS, 4 + 10 * BPS, 8 + 10 * BPS, 12 + 10 * BPS) - GET_SSE(11 * BPS, 4 + 11 * BPS, 8 + 11 * BPS, 12 + 11 * BPS) - GET_SSE(12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS) - GET_SSE(13 * BPS, 4 + 13 * BPS, 8 + 13 * BPS, 12 + 13 * BPS) - GET_SSE(14 * BPS, 4 + 14 * BPS, 8 + 14 * BPS, 12 + 14 * BPS) - GET_SSE(15 * BPS, 4 + 15 * BPS, 8 + 15 * BPS, 12 + 15 * BPS) - - "mflo %[count] \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count) - : [a]"r"(a), [b]"r"(b) - : "memory", "hi", "lo" - ); - return count; -} - -static int SSE16x8(const uint8_t* a, const uint8_t* b) { - int count; - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; - - __asm__ volatile( - "mult $zero, $zero \n\t" - - GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS) - GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS) - GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS) - GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS) - GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS) - GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS) - GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS) - GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS) - - "mflo %[count] \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count) - : [a]"r"(a), [b]"r"(b) - : "memory", "hi", "lo" - ); - return count; -} - -static int SSE8x8(const uint8_t* a, const uint8_t* b) { - int count; - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; - - __asm__ volatile( - "mult $zero, $zero \n\t" - - GET_SSE(0 * BPS, 4 + 0 * BPS, 1 * BPS, 4 + 1 * BPS) - GET_SSE(2 * BPS, 4 + 2 * BPS, 3 * BPS, 4 + 3 * BPS) - GET_SSE(4 * BPS, 4 + 4 * BPS, 5 * BPS, 4 + 5 * BPS) - GET_SSE(6 * BPS, 4 + 6 * BPS, 7 * BPS, 4 + 7 * BPS) - - "mflo %[count] \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count) - : [a]"r"(a), [b]"r"(b) - : "memory", "hi", "lo" - ); - return count; -} - -static int SSE4x4(const uint8_t* a, const uint8_t* b) { - int count; - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; - - __asm__ volatile( - "mult $zero, $zero \n\t" - - GET_SSE(0 * BPS, 1 * BPS, 2 * BPS, 3 * BPS) - - "mflo %[count] \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count) - : [a]"r"(a), [b]"r"(b) - : "memory", "hi", "lo" - ); - return count; -} - -#undef GET_SSE -#undef GET_SSE_INNER - -#endif // !WORK_AROUND_GCC - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8EncDspInitMIPS32(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitMIPS32(void) { - VP8ITransform = ITransform; - VP8FTransform = FTransform; - VP8EncQuantizeBlock = QuantizeBlock; - VP8EncQuantize2Blocks = Quantize2Blocks; - VP8TDisto4x4 = Disto4x4; - VP8TDisto16x16 = Disto16x16; -#if !defined(WORK_AROUND_GCC) - VP8SSE16x16 = SSE16x16; - VP8SSE8x8 = SSE8x8; - VP8SSE16x8 = SSE16x8; - VP8SSE4x4 = SSE4x4; -#endif -} - -#else // !WEBP_USE_MIPS32 - -WEBP_DSP_INIT_STUB(VP8EncDspInitMIPS32) - -#endif // WEBP_USE_MIPS32 diff --git a/Example-Mac/Pods/libwebp/src/dsp/enc_mips_dsp_r2.c b/Example-Mac/Pods/libwebp/src/dsp/enc_mips_dsp_r2.c deleted file mode 100644 index 7c814fa0..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/enc_mips_dsp_r2.c +++ /dev/null @@ -1,1512 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// MIPS version of speed-critical encoding functions. -// -// Author(s): Darko Laus (darko.laus@imgtec.com) -// Mirko Raus (mirko.raus@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS_DSP_R2) - -#include "./mips_macro.h" -#include "../enc/cost.h" -#include "../enc/vp8enci.h" - -static const int kC1 = 20091 + (1 << 16); -static const int kC2 = 35468; - -// O - output -// I - input (macro doesn't change it) -#define ADD_SUB_HALVES_X4(O0, O1, O2, O3, O4, O5, O6, O7, \ - I0, I1, I2, I3, I4, I5, I6, I7) \ - "addq.ph %[" #O0 "], %[" #I0 "], %[" #I1 "] \n\t" \ - "subq.ph %[" #O1 "], %[" #I0 "], %[" #I1 "] \n\t" \ - "addq.ph %[" #O2 "], %[" #I2 "], %[" #I3 "] \n\t" \ - "subq.ph %[" #O3 "], %[" #I2 "], %[" #I3 "] \n\t" \ - "addq.ph %[" #O4 "], %[" #I4 "], %[" #I5 "] \n\t" \ - "subq.ph %[" #O5 "], %[" #I4 "], %[" #I5 "] \n\t" \ - "addq.ph %[" #O6 "], %[" #I6 "], %[" #I7 "] \n\t" \ - "subq.ph %[" #O7 "], %[" #I6 "], %[" #I7 "] \n\t" - -// IO - input/output -#define ABS_X8(IO0, IO1, IO2, IO3, IO4, IO5, IO6, IO7) \ - "absq_s.ph %[" #IO0 "], %[" #IO0 "] \n\t" \ - "absq_s.ph %[" #IO1 "], %[" #IO1 "] \n\t" \ - "absq_s.ph %[" #IO2 "], %[" #IO2 "] \n\t" \ - "absq_s.ph %[" #IO3 "], %[" #IO3 "] \n\t" \ - "absq_s.ph %[" #IO4 "], %[" #IO4 "] \n\t" \ - "absq_s.ph %[" #IO5 "], %[" #IO5 "] \n\t" \ - "absq_s.ph %[" #IO6 "], %[" #IO6 "] \n\t" \ - "absq_s.ph %[" #IO7 "], %[" #IO7 "] \n\t" - -// dpa.w.ph $ac0 temp0 ,temp1 -// $ac += temp0[31..16] * temp1[31..16] + temp0[15..0] * temp1[15..0] -// dpax.w.ph $ac0 temp0 ,temp1 -// $ac += temp0[31..16] * temp1[15..0] + temp0[15..0] * temp1[31..16] -// O - output -// I - input (macro doesn't change it) -#define MUL_HALF(O0, I0, I1, I2, I3, I4, I5, I6, I7, \ - I8, I9, I10, I11, I12, I13, I14, I15) \ - "mult $ac0, $zero, $zero \n\t" \ - "dpa.w.ph $ac0, %[" #I2 "], %[" #I0 "] \n\t" \ - "dpax.w.ph $ac0, %[" #I5 "], %[" #I6 "] \n\t" \ - "dpa.w.ph $ac0, %[" #I8 "], %[" #I9 "] \n\t" \ - "dpax.w.ph $ac0, %[" #I11 "], %[" #I4 "] \n\t" \ - "dpa.w.ph $ac0, %[" #I12 "], %[" #I7 "] \n\t" \ - "dpax.w.ph $ac0, %[" #I13 "], %[" #I1 "] \n\t" \ - "dpa.w.ph $ac0, %[" #I14 "], %[" #I3 "] \n\t" \ - "dpax.w.ph $ac0, %[" #I15 "], %[" #I10 "] \n\t" \ - "mflo %[" #O0 "], $ac0 \n\t" - -#define OUTPUT_EARLY_CLOBBER_REGS_17() \ - OUTPUT_EARLY_CLOBBER_REGS_10(), \ - [temp11]"=&r"(temp11), [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), \ - [temp14]"=&r"(temp14), [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), \ - [temp17]"=&r"(temp17) - -// macro for one horizontal pass in FTransform -// temp0..temp15 holds tmp[0]..tmp[15] -// A - offset in bytes to load from src and ref buffers -// TEMP0..TEMP3 - registers for corresponding tmp elements -#define HORIZONTAL_PASS(A, TEMP0, TEMP1, TEMP2, TEMP3) \ - "lw %[" #TEMP0 "], 0(%[args]) \n\t" \ - "lw %[" #TEMP1 "], 4(%[args]) \n\t" \ - "lw %[" #TEMP2 "], " XSTR(BPS) "*" #A "(%[" #TEMP0 "]) \n\t" \ - "lw %[" #TEMP3 "], " XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \ - "preceu.ph.qbl %[" #TEMP0 "], %[" #TEMP2 "] \n\t" \ - "preceu.ph.qbl %[" #TEMP1 "], %[" #TEMP3 "] \n\t" \ - "preceu.ph.qbr %[" #TEMP2 "], %[" #TEMP2 "] \n\t" \ - "preceu.ph.qbr %[" #TEMP3 "], %[" #TEMP3 "] \n\t" \ - "subq.ph %[" #TEMP0 "], %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \ - "subq.ph %[" #TEMP2 "], %[" #TEMP2 "], %[" #TEMP3 "] \n\t" \ - "rotr %[" #TEMP0 "], %[" #TEMP0 "], 16 \n\t" \ - "addq.ph %[" #TEMP1 "], %[" #TEMP2 "], %[" #TEMP0 "] \n\t" \ - "subq.ph %[" #TEMP3 "], %[" #TEMP2 "], %[" #TEMP0 "] \n\t" \ - "seh %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \ - "sra %[temp16], %[" #TEMP1 "], 16 \n\t" \ - "seh %[temp19], %[" #TEMP3 "] \n\t" \ - "sra %[" #TEMP3 "], %[" #TEMP3 "], 16 \n\t" \ - "subu %[" #TEMP2 "], %[" #TEMP0 "], %[temp16] \n\t" \ - "addu %[" #TEMP0 "], %[" #TEMP0 "], %[temp16] \n\t" \ - "mul %[temp17], %[temp19], %[c2217] \n\t" \ - "mul %[temp18], %[" #TEMP3 "], %[c5352] \n\t" \ - "mul %[" #TEMP1 "], %[temp19], %[c5352] \n\t" \ - "mul %[temp16], %[" #TEMP3 "], %[c2217] \n\t" \ - "sll %[" #TEMP2 "], %[" #TEMP2 "], 3 \n\t" \ - "sll %[" #TEMP0 "], %[" #TEMP0 "], 3 \n\t" \ - "subu %[" #TEMP3 "], %[temp17], %[temp18] \n\t" \ - "addu %[" #TEMP1 "], %[temp16], %[" #TEMP1 "] \n\t" \ - "addiu %[" #TEMP3 "], %[" #TEMP3 "], 937 \n\t" \ - "addiu %[" #TEMP1 "], %[" #TEMP1 "], 1812 \n\t" \ - "sra %[" #TEMP3 "], %[" #TEMP3 "], 9 \n\t" \ - "sra %[" #TEMP1 "], %[" #TEMP1 "], 9 \n\t" - -// macro for one vertical pass in FTransform -// temp0..temp15 holds tmp[0]..tmp[15] -// A..D - offsets in bytes to store to out buffer -// TEMP0, TEMP4, TEMP8 and TEMP12 - registers for corresponding tmp elements -#define VERTICAL_PASS(A, B, C, D, TEMP0, TEMP4, TEMP8, TEMP12) \ - "addu %[temp16], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \ - "subu %[temp19], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \ - "addu %[temp17], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \ - "subu %[temp18], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \ - "mul %[" #TEMP8 "], %[temp19], %[c2217] \n\t" \ - "mul %[" #TEMP12 "], %[temp18], %[c2217] \n\t" \ - "mul %[" #TEMP4 "], %[temp19], %[c5352] \n\t" \ - "mul %[temp18], %[temp18], %[c5352] \n\t" \ - "addiu %[temp16], %[temp16], 7 \n\t" \ - "addu %[" #TEMP0 "], %[temp16], %[temp17] \n\t" \ - "sra %[" #TEMP0 "], %[" #TEMP0 "], 4 \n\t" \ - "addu %[" #TEMP12 "], %[" #TEMP12 "], %[" #TEMP4 "] \n\t" \ - "subu %[" #TEMP4 "], %[temp16], %[temp17] \n\t" \ - "sra %[" #TEMP4 "], %[" #TEMP4 "], 4 \n\t" \ - "addiu %[" #TEMP8 "], %[" #TEMP8 "], 30000 \n\t" \ - "addiu %[" #TEMP12 "], %[" #TEMP12 "], 12000 \n\t" \ - "addiu %[" #TEMP8 "], %[" #TEMP8 "], 21000 \n\t" \ - "subu %[" #TEMP8 "], %[" #TEMP8 "], %[temp18] \n\t" \ - "sra %[" #TEMP12 "], %[" #TEMP12 "], 16 \n\t" \ - "sra %[" #TEMP8 "], %[" #TEMP8 "], 16 \n\t" \ - "addiu %[temp16], %[" #TEMP12 "], 1 \n\t" \ - "movn %[" #TEMP12 "], %[temp16], %[temp19] \n\t" \ - "sh %[" #TEMP0 "], " #A "(%[temp20]) \n\t" \ - "sh %[" #TEMP4 "], " #C "(%[temp20]) \n\t" \ - "sh %[" #TEMP8 "], " #D "(%[temp20]) \n\t" \ - "sh %[" #TEMP12 "], " #B "(%[temp20]) \n\t" - -static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) { - const int c2217 = 2217; - const int c5352 = 5352; - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; - int temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16; - int temp17, temp18, temp19, temp20; - const int* const args[3] = - { (const int*)src, (const int*)ref, (const int*)out }; - - __asm__ volatile ( - HORIZONTAL_PASS(0, temp0, temp1, temp2, temp3) - HORIZONTAL_PASS(1, temp4, temp5, temp6, temp7) - HORIZONTAL_PASS(2, temp8, temp9, temp10, temp11) - HORIZONTAL_PASS(3, temp12, temp13, temp14, temp15) - "lw %[temp20], 8(%[args]) \n\t" - VERTICAL_PASS(0, 8, 16, 24, temp0, temp4, temp8, temp12) - VERTICAL_PASS(2, 10, 18, 26, temp1, temp5, temp9, temp13) - VERTICAL_PASS(4, 12, 20, 28, temp2, temp6, temp10, temp14) - VERTICAL_PASS(6, 14, 22, 30, temp3, temp7, temp11, temp15) - OUTPUT_EARLY_CLOBBER_REGS_18(), - [temp0]"=&r"(temp0), [temp19]"=&r"(temp19), [temp20]"=&r"(temp20) - : [args]"r"(args), [c2217]"r"(c2217), [c5352]"r"(c5352) - : "memory", "hi", "lo" - ); -} - -#undef VERTICAL_PASS -#undef HORIZONTAL_PASS - -static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, - uint8_t* dst) { - int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; - int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18; - - __asm__ volatile ( - "ulw %[temp1], 0(%[in]) \n\t" - "ulw %[temp2], 16(%[in]) \n\t" - LOAD_IN_X2(temp5, temp6, 24, 26) - ADD_SUB_HALVES(temp3, temp4, temp1, temp2) - LOAD_IN_X2(temp1, temp2, 8, 10) - MUL_SHIFT_SUM(temp7, temp8, temp9, temp10, temp11, temp12, temp13, temp14, - temp10, temp8, temp9, temp7, temp1, temp2, temp5, temp6, - temp13, temp11, temp14, temp12) - INSERT_HALF_X2(temp8, temp7, temp10, temp9) - "ulw %[temp17], 4(%[in]) \n\t" - "ulw %[temp18], 20(%[in]) \n\t" - ADD_SUB_HALVES(temp1, temp2, temp3, temp8) - ADD_SUB_HALVES(temp5, temp6, temp4, temp7) - ADD_SUB_HALVES(temp7, temp8, temp17, temp18) - LOAD_IN_X2(temp17, temp18, 12, 14) - LOAD_IN_X2(temp9, temp10, 28, 30) - MUL_SHIFT_SUM(temp11, temp12, temp13, temp14, temp15, temp16, temp4, temp17, - temp12, temp14, temp11, temp13, temp17, temp18, temp9, temp10, - temp15, temp4, temp16, temp17) - INSERT_HALF_X2(temp11, temp12, temp13, temp14) - ADD_SUB_HALVES(temp17, temp8, temp8, temp11) - ADD_SUB_HALVES(temp3, temp4, temp7, temp12) - - // horizontal - SRA_16(temp9, temp10, temp11, temp12, temp1, temp2, temp5, temp6) - INSERT_HALF_X2(temp1, temp6, temp5, temp2) - SRA_16(temp13, temp14, temp15, temp16, temp3, temp4, temp17, temp8) - "repl.ph %[temp2], 0x4 \n\t" - INSERT_HALF_X2(temp3, temp8, temp17, temp4) - "addq.ph %[temp1], %[temp1], %[temp2] \n\t" - "addq.ph %[temp6], %[temp6], %[temp2] \n\t" - ADD_SUB_HALVES(temp2, temp4, temp1, temp3) - ADD_SUB_HALVES(temp5, temp7, temp6, temp8) - MUL_SHIFT_SUM(temp1, temp3, temp6, temp8, temp9, temp13, temp17, temp18, - temp3, temp13, temp1, temp9, temp9, temp13, temp11, temp15, - temp6, temp17, temp8, temp18) - MUL_SHIFT_SUM(temp6, temp8, temp18, temp17, temp11, temp15, temp12, temp16, - temp8, temp15, temp6, temp11, temp12, temp16, temp10, temp14, - temp18, temp12, temp17, temp16) - INSERT_HALF_X2(temp1, temp3, temp9, temp13) - INSERT_HALF_X2(temp6, temp8, temp11, temp15) - SHIFT_R_SUM_X2(temp9, temp10, temp11, temp12, temp13, temp14, temp15, - temp16, temp2, temp4, temp5, temp7, temp3, temp1, temp8, - temp6) - PACK_2_HALVES_TO_WORD(temp1, temp2, temp3, temp4, temp9, temp12, temp13, - temp16, temp11, temp10, temp15, temp14) - LOAD_WITH_OFFSET_X4(temp10, temp11, temp14, temp15, ref, - 0, 0, 0, 0, - 0, 1, 2, 3, - BPS) - CONVERT_2_BYTES_TO_HALF(temp5, temp6, temp7, temp8, temp17, temp18, temp10, - temp11, temp10, temp11, temp14, temp15) - STORE_SAT_SUM_X2(temp5, temp6, temp7, temp8, temp17, temp18, temp10, temp11, - temp9, temp12, temp1, temp2, temp13, temp16, temp3, temp4, - dst, 0, 1, 2, 3, BPS) - - OUTPUT_EARLY_CLOBBER_REGS_18() - : [dst]"r"(dst), [in]"r"(in), [kC1]"r"(kC1), [kC2]"r"(kC2), [ref]"r"(ref) - : "memory", "hi", "lo" - ); -} - -static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst, - int do_two) { - ITransformOne(ref, in, dst); - if (do_two) { - ITransformOne(ref + 4, in + 16, dst + 4); - } -} - -static int Disto4x4(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; - int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17; - - __asm__ volatile ( - LOAD_WITH_OFFSET_X4(temp1, temp2, temp3, temp4, a, - 0, 0, 0, 0, - 0, 1, 2, 3, - BPS) - CONVERT_2_BYTES_TO_HALF(temp5, temp6, temp7, temp8, temp9,temp10, temp11, - temp12, temp1, temp2, temp3, temp4) - ADD_SUB_HALVES_X4(temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, - temp5, temp6, temp7, temp8, temp9, temp10, temp11, temp12) - PACK_2_HALVES_TO_WORD(temp9, temp10, temp11, temp12, temp1, temp3, temp5, - temp7, temp2, temp4, temp6, temp8) - ADD_SUB_HALVES_X4(temp2, temp4, temp6, temp8, temp9, temp1, temp3, temp10, - temp1, temp9, temp3, temp10, temp5, temp11, temp7, temp12) - ADD_SUB_HALVES_X4(temp5, temp11, temp7, temp2, temp9, temp3, temp6, temp12, - temp2, temp9, temp6, temp3, temp4, temp1, temp8, temp10) - ADD_SUB_HALVES_X4(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2, - temp5, temp7, temp11, temp2, temp9, temp6, temp3, temp12) - ABS_X8(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2) - LOAD_WITH_OFFSET_X4(temp3, temp6, temp9, temp12, w, - 0, 4, 8, 12, - 0, 0, 0, 0, - 0) - LOAD_WITH_OFFSET_X4(temp13, temp14, temp15, temp16, w, - 0, 4, 8, 12, - 1, 1, 1, 1, - 16) - MUL_HALF(temp17, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, - temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16) - LOAD_WITH_OFFSET_X4(temp1, temp2, temp3, temp4, b, - 0, 0, 0, 0, - 0, 1, 2, 3, - BPS) - CONVERT_2_BYTES_TO_HALF(temp5,temp6, temp7, temp8, temp9,temp10, temp11, - temp12, temp1, temp2, temp3, temp4) - ADD_SUB_HALVES_X4(temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, - temp5, temp6, temp7, temp8, temp9, temp10, temp11, temp12) - PACK_2_HALVES_TO_WORD(temp9, temp10, temp11, temp12, temp1, temp3, temp5, - temp7, temp2, temp4, temp6, temp8) - ADD_SUB_HALVES_X4(temp2, temp4, temp6, temp8, temp9, temp1, temp3, temp10, - temp1, temp9, temp3, temp10, temp5, temp11, temp7, temp12) - ADD_SUB_HALVES_X4(temp5, temp11, temp7, temp2, temp9, temp3, temp6, temp12, - temp2, temp9, temp6, temp3, temp4, temp1, temp8, temp10) - ADD_SUB_HALVES_X4(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2, - temp5, temp7, temp11, temp2, temp9, temp6, temp3, temp12) - ABS_X8(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2) - LOAD_WITH_OFFSET_X4(temp3, temp6, temp9, temp12, w, - 0, 4, 8, 12, - 0, 0, 0, 0, - 0) - LOAD_WITH_OFFSET_X4(temp13, temp14, temp15, temp16, w, - 0, 4, 8, 12, - 1, 1, 1, 1, - 16) - MUL_HALF(temp3, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, - temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16) - OUTPUT_EARLY_CLOBBER_REGS_17() - : [a]"r"(a), [b]"r"(b), [w]"r"(w) - : "memory", "hi", "lo" - ); - return abs(temp3 - temp17) >> 5; -} - -static int Disto16x16(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - int D = 0; - int x, y; - for (y = 0; y < 16 * BPS; y += 4 * BPS) { - for (x = 0; x < 16; x += 4) { - D += Disto4x4(a + x + y, b + x + y, w); - } - } - return D; -} - -//------------------------------------------------------------------------------ -// Intra predictions - -#define FILL_PART(J, SIZE) \ - "usw %[value], 0+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \ - "usw %[value], 4+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \ - ".if " #SIZE " == 16 \n\t" \ - "usw %[value], 8+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \ - "usw %[value], 12+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \ - ".endif \n\t" - -#define FILL_8_OR_16(DST, VALUE, SIZE) do { \ - int value = (VALUE); \ - __asm__ volatile ( \ - "replv.qb %[value], %[value] \n\t" \ - FILL_PART( 0, SIZE) \ - FILL_PART( 1, SIZE) \ - FILL_PART( 2, SIZE) \ - FILL_PART( 3, SIZE) \ - FILL_PART( 4, SIZE) \ - FILL_PART( 5, SIZE) \ - FILL_PART( 6, SIZE) \ - FILL_PART( 7, SIZE) \ - ".if " #SIZE " == 16 \n\t" \ - FILL_PART( 8, 16) \ - FILL_PART( 9, 16) \ - FILL_PART(10, 16) \ - FILL_PART(11, 16) \ - FILL_PART(12, 16) \ - FILL_PART(13, 16) \ - FILL_PART(14, 16) \ - FILL_PART(15, 16) \ - ".endif \n\t" \ - : [value]"+&r"(value) \ - : [dst]"r"((DST)) \ - : "memory" \ - ); \ -} while (0) - -#define VERTICAL_PRED(DST, TOP, SIZE) \ -static WEBP_INLINE void VerticalPred##SIZE(uint8_t* (DST), \ - const uint8_t* (TOP)) { \ - int j; \ - if ((TOP)) { \ - for (j = 0; j < (SIZE); ++j) memcpy((DST) + j * BPS, (TOP), (SIZE)); \ - } else { \ - FILL_8_OR_16((DST), 127, (SIZE)); \ - } \ -} - -VERTICAL_PRED(dst, top, 8) -VERTICAL_PRED(dst, top, 16) - -#undef VERTICAL_PRED - -#define HORIZONTAL_PRED(DST, LEFT, SIZE) \ -static WEBP_INLINE void HorizontalPred##SIZE(uint8_t* (DST), \ - const uint8_t* (LEFT)) { \ - if (LEFT) { \ - int j; \ - for (j = 0; j < (SIZE); ++j) { \ - memset((DST) + j * BPS, (LEFT)[j], (SIZE)); \ - } \ - } else { \ - FILL_8_OR_16((DST), 129, (SIZE)); \ - } \ -} - -HORIZONTAL_PRED(dst, left, 8) -HORIZONTAL_PRED(dst, left, 16) - -#undef HORIZONTAL_PRED - -#define CLIPPING() \ - "preceu.ph.qbl %[temp2], %[temp0] \n\t" \ - "preceu.ph.qbr %[temp0], %[temp0] \n\t" \ - "preceu.ph.qbl %[temp3], %[temp1] \n\t" \ - "preceu.ph.qbr %[temp1], %[temp1] \n\t" \ - "addu.ph %[temp2], %[temp2], %[leftY_1] \n\t" \ - "addu.ph %[temp0], %[temp0], %[leftY_1] \n\t" \ - "addu.ph %[temp3], %[temp3], %[leftY_1] \n\t" \ - "addu.ph %[temp1], %[temp1], %[leftY_1] \n\t" \ - "shll_s.ph %[temp2], %[temp2], 7 \n\t" \ - "shll_s.ph %[temp0], %[temp0], 7 \n\t" \ - "shll_s.ph %[temp3], %[temp3], 7 \n\t" \ - "shll_s.ph %[temp1], %[temp1], 7 \n\t" \ - "precrqu_s.qb.ph %[temp0], %[temp2], %[temp0] \n\t" \ - "precrqu_s.qb.ph %[temp1], %[temp3], %[temp1] \n\t" - -#define CLIP_8B_TO_DST(DST, LEFT, TOP, SIZE) do { \ - int leftY_1 = ((int)(LEFT)[y] << 16) + (LEFT)[y]; \ - int temp0, temp1, temp2, temp3; \ - __asm__ volatile ( \ - "replv.ph %[leftY_1], %[leftY_1] \n\t" \ - "ulw %[temp0], 0(%[top]) \n\t" \ - "ulw %[temp1], 4(%[top]) \n\t" \ - "subu.ph %[leftY_1], %[leftY_1], %[left_1] \n\t" \ - CLIPPING() \ - "usw %[temp0], 0(%[dst]) \n\t" \ - "usw %[temp1], 4(%[dst]) \n\t" \ - ".if " #SIZE " == 16 \n\t" \ - "ulw %[temp0], 8(%[top]) \n\t" \ - "ulw %[temp1], 12(%[top]) \n\t" \ - CLIPPING() \ - "usw %[temp0], 8(%[dst]) \n\t" \ - "usw %[temp1], 12(%[dst]) \n\t" \ - ".endif \n\t" \ - : [leftY_1]"+&r"(leftY_1), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), \ - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3) \ - : [left_1]"r"(left_1), [top]"r"((TOP)), [dst]"r"((DST)) \ - : "memory" \ - ); \ -} while (0) - -#define CLIP_TO_DST(DST, LEFT, TOP, SIZE) do { \ - int y; \ - const int left_1 = ((int)(LEFT)[-1] << 16) + (LEFT)[-1]; \ - for (y = 0; y < (SIZE); ++y) { \ - CLIP_8B_TO_DST((DST), (LEFT), (TOP), (SIZE)); \ - (DST) += BPS; \ - } \ -} while (0) - -#define TRUE_MOTION(DST, LEFT, TOP, SIZE) \ -static WEBP_INLINE void TrueMotion##SIZE(uint8_t* (DST), const uint8_t* (LEFT),\ - const uint8_t* (TOP)) { \ - if ((LEFT) != NULL) { \ - if ((TOP) != NULL) { \ - CLIP_TO_DST((DST), (LEFT), (TOP), (SIZE)); \ - } else { \ - HorizontalPred##SIZE((DST), (LEFT)); \ - } \ - } else { \ - /* true motion without left samples (hence: with default 129 value) */ \ - /* is equivalent to VE prediction where you just copy the top samples. */ \ - /* Note that if top samples are not available, the default value is */ \ - /* then 129, and not 127 as in the VerticalPred case. */ \ - if ((TOP) != NULL) { \ - VerticalPred##SIZE((DST), (TOP)); \ - } else { \ - FILL_8_OR_16((DST), 129, (SIZE)); \ - } \ - } \ -} - -TRUE_MOTION(dst, left, top, 8) -TRUE_MOTION(dst, left, top, 16) - -#undef TRUE_MOTION -#undef CLIP_TO_DST -#undef CLIP_8B_TO_DST -#undef CLIPPING - -static WEBP_INLINE void DCMode16(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { - int DC, DC1; - int temp0, temp1, temp2, temp3; - - __asm__ volatile( - "beqz %[top], 2f \n\t" - LOAD_WITH_OFFSET_X4(temp0, temp1, temp2, temp3, top, - 0, 4, 8, 12, - 0, 0, 0, 0, - 0) - "raddu.w.qb %[temp0], %[temp0] \n\t" - "raddu.w.qb %[temp1], %[temp1] \n\t" - "raddu.w.qb %[temp2], %[temp2] \n\t" - "raddu.w.qb %[temp3], %[temp3] \n\t" - "addu %[temp0], %[temp0], %[temp1] \n\t" - "addu %[temp2], %[temp2], %[temp3] \n\t" - "addu %[DC], %[temp0], %[temp2] \n\t" - "move %[DC1], %[DC] \n\t" - "beqz %[left], 1f \n\t" - LOAD_WITH_OFFSET_X4(temp0, temp1, temp2, temp3, left, - 0, 4, 8, 12, - 0, 0, 0, 0, - 0) - "raddu.w.qb %[temp0], %[temp0] \n\t" - "raddu.w.qb %[temp1], %[temp1] \n\t" - "raddu.w.qb %[temp2], %[temp2] \n\t" - "raddu.w.qb %[temp3], %[temp3] \n\t" - "addu %[temp0], %[temp0], %[temp1] \n\t" - "addu %[temp2], %[temp2], %[temp3] \n\t" - "addu %[DC1], %[temp0], %[temp2] \n\t" - "1: \n\t" - "addu %[DC], %[DC], %[DC1] \n\t" - "j 3f \n\t" - "2: \n\t" - "beqz %[left], 4f \n\t" - LOAD_WITH_OFFSET_X4(temp0, temp1, temp2, temp3, left, - 0, 4, 8, 12, - 0, 0, 0, 0, - 0) - "raddu.w.qb %[temp0], %[temp0] \n\t" - "raddu.w.qb %[temp1], %[temp1] \n\t" - "raddu.w.qb %[temp2], %[temp2] \n\t" - "raddu.w.qb %[temp3], %[temp3] \n\t" - "addu %[temp0], %[temp0], %[temp1] \n\t" - "addu %[temp2], %[temp2], %[temp3] \n\t" - "addu %[DC], %[temp0], %[temp2] \n\t" - "addu %[DC], %[DC], %[DC] \n\t" - "3: \n\t" - "shra_r.w %[DC], %[DC], 5 \n\t" - "j 5f \n\t" - "4: \n\t" - "li %[DC], 0x80 \n\t" - "5: \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [DC]"=&r"(DC), - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [DC1]"=&r"(DC1) - : [left]"r"(left), [top]"r"(top) - : "memory" - ); - - FILL_8_OR_16(dst, DC, 16); -} - -static WEBP_INLINE void DCMode8(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { - int DC, DC1; - int temp0, temp1, temp2, temp3; - - __asm__ volatile( - "beqz %[top], 2f \n\t" - "ulw %[temp0], 0(%[top]) \n\t" - "ulw %[temp1], 4(%[top]) \n\t" - "raddu.w.qb %[temp0], %[temp0] \n\t" - "raddu.w.qb %[temp1], %[temp1] \n\t" - "addu %[DC], %[temp0], %[temp1] \n\t" - "move %[DC1], %[DC] \n\t" - "beqz %[left], 1f \n\t" - "ulw %[temp2], 0(%[left]) \n\t" - "ulw %[temp3], 4(%[left]) \n\t" - "raddu.w.qb %[temp2], %[temp2] \n\t" - "raddu.w.qb %[temp3], %[temp3] \n\t" - "addu %[DC1], %[temp2], %[temp3] \n\t" - "1: \n\t" - "addu %[DC], %[DC], %[DC1] \n\t" - "j 3f \n\t" - "2: \n\t" - "beqz %[left], 4f \n\t" - "ulw %[temp2], 0(%[left]) \n\t" - "ulw %[temp3], 4(%[left]) \n\t" - "raddu.w.qb %[temp2], %[temp2] \n\t" - "raddu.w.qb %[temp3], %[temp3] \n\t" - "addu %[DC], %[temp2], %[temp3] \n\t" - "addu %[DC], %[DC], %[DC] \n\t" - "3: \n\t" - "shra_r.w %[DC], %[DC], 4 \n\t" - "j 5f \n\t" - "4: \n\t" - "li %[DC], 0x80 \n\t" - "5: \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [DC]"=&r"(DC), - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [DC1]"=&r"(DC1) - : [left]"r"(left), [top]"r"(top) - : "memory" - ); - - FILL_8_OR_16(dst, DC, 8); -} - -static void DC4(uint8_t* dst, const uint8_t* top) { - int temp0, temp1; - __asm__ volatile( - "ulw %[temp0], 0(%[top]) \n\t" - "ulw %[temp1], -5(%[top]) \n\t" - "raddu.w.qb %[temp0], %[temp0] \n\t" - "raddu.w.qb %[temp1], %[temp1] \n\t" - "addu %[temp0], %[temp0], %[temp1] \n\t" - "addiu %[temp0], %[temp0], 4 \n\t" - "srl %[temp0], %[temp0], 3 \n\t" - "replv.qb %[temp0], %[temp0] \n\t" - "usw %[temp0], 0*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp0], 1*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp0], 2*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp0], 3*" XSTR(BPS) "(%[dst]) \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1) - : [top]"r"(top), [dst]"r"(dst) - : "memory" - ); -} - -static void TM4(uint8_t* dst, const uint8_t* top) { - int a10, a32, temp0, temp1, temp2, temp3, temp4, temp5; - const int c35 = 0xff00ff; - __asm__ volatile ( - "lbu %[temp1], 0(%[top]) \n\t" - "lbu %[a10], 1(%[top]) \n\t" - "lbu %[temp2], 2(%[top]) \n\t" - "lbu %[a32], 3(%[top]) \n\t" - "ulw %[temp0], -5(%[top]) \n\t" - "lbu %[temp4], -1(%[top]) \n\t" - "append %[a10], %[temp1], 16 \n\t" - "append %[a32], %[temp2], 16 \n\t" - "replv.ph %[temp4], %[temp4] \n\t" - "shrl.ph %[temp1], %[temp0], 8 \n\t" - "and %[temp0], %[temp0], %[c35] \n\t" - "subu.ph %[temp1], %[temp1], %[temp4] \n\t" - "subu.ph %[temp0], %[temp0], %[temp4] \n\t" - "srl %[temp2], %[temp1], 16 \n\t" - "srl %[temp3], %[temp0], 16 \n\t" - "replv.ph %[temp2], %[temp2] \n\t" - "replv.ph %[temp3], %[temp3] \n\t" - "replv.ph %[temp4], %[temp1] \n\t" - "replv.ph %[temp5], %[temp0] \n\t" - "addu.ph %[temp0], %[temp3], %[a10] \n\t" - "addu.ph %[temp1], %[temp3], %[a32] \n\t" - "addu.ph %[temp3], %[temp2], %[a10] \n\t" - "addu.ph %[temp2], %[temp2], %[a32] \n\t" - "shll_s.ph %[temp0], %[temp0], 7 \n\t" - "shll_s.ph %[temp1], %[temp1], 7 \n\t" - "shll_s.ph %[temp3], %[temp3], 7 \n\t" - "shll_s.ph %[temp2], %[temp2], 7 \n\t" - "precrqu_s.qb.ph %[temp0], %[temp1], %[temp0] \n\t" - "precrqu_s.qb.ph %[temp1], %[temp2], %[temp3] \n\t" - "addu.ph %[temp2], %[temp5], %[a10] \n\t" - "addu.ph %[temp3], %[temp5], %[a32] \n\t" - "addu.ph %[temp5], %[temp4], %[a10] \n\t" - "addu.ph %[temp4], %[temp4], %[a32] \n\t" - "shll_s.ph %[temp2], %[temp2], 7 \n\t" - "shll_s.ph %[temp3], %[temp3], 7 \n\t" - "shll_s.ph %[temp4], %[temp4], 7 \n\t" - "shll_s.ph %[temp5], %[temp5], 7 \n\t" - "precrqu_s.qb.ph %[temp2], %[temp3], %[temp2] \n\t" - "precrqu_s.qb.ph %[temp3], %[temp4], %[temp5] \n\t" - "usw %[temp1], 0*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp0], 1*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp3], 2*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp2], 3*" XSTR(BPS) "(%[dst]) \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [a10]"=&r"(a10), [a32]"=&r"(a32) - : [c35]"r"(c35), [top]"r"(top), [dst]"r"(dst) - : "memory" - ); -} - -static void VE4(uint8_t* dst, const uint8_t* top) { - int temp0, temp1, temp2, temp3, temp4, temp5, temp6; - __asm__ volatile( - "ulw %[temp0], -1(%[top]) \n\t" - "ulh %[temp1], 3(%[top]) \n\t" - "preceu.ph.qbr %[temp2], %[temp0] \n\t" - "preceu.ph.qbl %[temp3], %[temp0] \n\t" - "preceu.ph.qbr %[temp4], %[temp1] \n\t" - "packrl.ph %[temp5], %[temp3], %[temp2] \n\t" - "packrl.ph %[temp6], %[temp4], %[temp3] \n\t" - "shll.ph %[temp5], %[temp5], 1 \n\t" - "shll.ph %[temp6], %[temp6], 1 \n\t" - "addq.ph %[temp2], %[temp5], %[temp2] \n\t" - "addq.ph %[temp6], %[temp6], %[temp4] \n\t" - "addq.ph %[temp2], %[temp2], %[temp3] \n\t" - "addq.ph %[temp6], %[temp6], %[temp3] \n\t" - "shra_r.ph %[temp2], %[temp2], 2 \n\t" - "shra_r.ph %[temp6], %[temp6], 2 \n\t" - "precr.qb.ph %[temp4], %[temp6], %[temp2] \n\t" - "usw %[temp4], 0*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp4], 1*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp4], 2*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp4], 3*" XSTR(BPS) "(%[dst]) \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6) - : [top]"r"(top), [dst]"r"(dst) - : "memory" - ); -} - -static void HE4(uint8_t* dst, const uint8_t* top) { - int temp0, temp1, temp2, temp3, temp4, temp5, temp6; - __asm__ volatile( - "ulw %[temp0], -4(%[top]) \n\t" - "lbu %[temp1], -5(%[top]) \n\t" - "preceu.ph.qbr %[temp2], %[temp0] \n\t" - "preceu.ph.qbl %[temp3], %[temp0] \n\t" - "replv.ph %[temp4], %[temp1] \n\t" - "packrl.ph %[temp5], %[temp3], %[temp2] \n\t" - "packrl.ph %[temp6], %[temp2], %[temp4] \n\t" - "shll.ph %[temp5], %[temp5], 1 \n\t" - "shll.ph %[temp6], %[temp6], 1 \n\t" - "addq.ph %[temp3], %[temp3], %[temp5] \n\t" - "addq.ph %[temp3], %[temp3], %[temp2] \n\t" - "addq.ph %[temp2], %[temp2], %[temp6] \n\t" - "addq.ph %[temp2], %[temp2], %[temp4] \n\t" - "shra_r.ph %[temp3], %[temp3], 2 \n\t" - "shra_r.ph %[temp2], %[temp2], 2 \n\t" - "replv.qb %[temp0], %[temp3] \n\t" - "replv.qb %[temp1], %[temp2] \n\t" - "srl %[temp3], %[temp3], 16 \n\t" - "srl %[temp2], %[temp2], 16 \n\t" - "replv.qb %[temp3], %[temp3] \n\t" - "replv.qb %[temp2], %[temp2] \n\t" - "usw %[temp3], 0*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp0], 1*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp2], 2*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp1], 3*" XSTR(BPS) "(%[dst]) \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6) - : [top]"r"(top), [dst]"r"(dst) - : "memory" - ); -} - -static void RD4(uint8_t* dst, const uint8_t* top) { - int temp0, temp1, temp2, temp3, temp4, temp5; - int temp6, temp7, temp8, temp9, temp10, temp11; - __asm__ volatile( - "ulw %[temp0], -5(%[top]) \n\t" - "ulw %[temp1], -1(%[top]) \n\t" - "preceu.ph.qbl %[temp2], %[temp0] \n\t" - "preceu.ph.qbr %[temp3], %[temp0] \n\t" - "preceu.ph.qbr %[temp4], %[temp1] \n\t" - "preceu.ph.qbl %[temp5], %[temp1] \n\t" - "packrl.ph %[temp6], %[temp2], %[temp3] \n\t" - "packrl.ph %[temp7], %[temp4], %[temp2] \n\t" - "packrl.ph %[temp8], %[temp5], %[temp4] \n\t" - "shll.ph %[temp6], %[temp6], 1 \n\t" - "addq.ph %[temp9], %[temp2], %[temp6] \n\t" - "shll.ph %[temp7], %[temp7], 1 \n\t" - "addq.ph %[temp9], %[temp9], %[temp3] \n\t" - "shll.ph %[temp8], %[temp8], 1 \n\t" - "shra_r.ph %[temp9], %[temp9], 2 \n\t" - "addq.ph %[temp10], %[temp4], %[temp7] \n\t" - "addq.ph %[temp11], %[temp5], %[temp8] \n\t" - "addq.ph %[temp10], %[temp10], %[temp2] \n\t" - "addq.ph %[temp11], %[temp11], %[temp4] \n\t" - "shra_r.ph %[temp10], %[temp10], 2 \n\t" - "shra_r.ph %[temp11], %[temp11], 2 \n\t" - "lbu %[temp0], 3(%[top]) \n\t" - "lbu %[temp1], 2(%[top]) \n\t" - "lbu %[temp2], 1(%[top]) \n\t" - "sll %[temp1], %[temp1], 1 \n\t" - "addu %[temp0], %[temp0], %[temp1] \n\t" - "addu %[temp0], %[temp0], %[temp2] \n\t" - "precr.qb.ph %[temp9], %[temp10], %[temp9] \n\t" - "shra_r.w %[temp0], %[temp0], 2 \n\t" - "precr.qb.ph %[temp10], %[temp11], %[temp10] \n\t" - "usw %[temp9], 3*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp10], 1*" XSTR(BPS) "(%[dst]) \n\t" - "prepend %[temp9], %[temp11], 8 \n\t" - "prepend %[temp10], %[temp0], 8 \n\t" - "usw %[temp9], 2*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp10], 0*" XSTR(BPS) "(%[dst]) \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11) - : [top]"r"(top), [dst]"r"(dst) - : "memory" - ); -} - -static void VR4(uint8_t* dst, const uint8_t* top) { - int temp0, temp1, temp2, temp3, temp4; - int temp5, temp6, temp7, temp8, temp9; - __asm__ volatile ( - "ulw %[temp0], -4(%[top]) \n\t" - "ulw %[temp1], 0(%[top]) \n\t" - "preceu.ph.qbl %[temp2], %[temp0] \n\t" - "preceu.ph.qbr %[temp0], %[temp0] \n\t" - "preceu.ph.qbla %[temp3], %[temp1] \n\t" - "preceu.ph.qbra %[temp1], %[temp1] \n\t" - "packrl.ph %[temp7], %[temp3], %[temp2] \n\t" - "addqh_r.ph %[temp4], %[temp1], %[temp3] \n\t" - "move %[temp6], %[temp1] \n\t" - "append %[temp1], %[temp2], 16 \n\t" - "shll.ph %[temp9], %[temp6], 1 \n\t" - "addqh_r.ph %[temp5], %[temp7], %[temp6] \n\t" - "shll.ph %[temp8], %[temp7], 1 \n\t" - "addu.ph %[temp3], %[temp7], %[temp3] \n\t" - "addu.ph %[temp1], %[temp1], %[temp6] \n\t" - "packrl.ph %[temp7], %[temp2], %[temp0] \n\t" - "addu.ph %[temp6], %[temp0], %[temp2] \n\t" - "addu.ph %[temp3], %[temp3], %[temp9] \n\t" - "addu.ph %[temp1], %[temp1], %[temp8] \n\t" - "shll.ph %[temp7], %[temp7], 1 \n\t" - "shra_r.ph %[temp3], %[temp3], 2 \n\t" - "shra_r.ph %[temp1], %[temp1], 2 \n\t" - "addu.ph %[temp6], %[temp6], %[temp7] \n\t" - "shra_r.ph %[temp6], %[temp6], 2 \n\t" - "precrq.ph.w %[temp8], %[temp4], %[temp5] \n\t" - "append %[temp4], %[temp5], 16 \n\t" - "precrq.ph.w %[temp2], %[temp3], %[temp1] \n\t" - "append %[temp3], %[temp1], 16 \n\t" - "precr.qb.ph %[temp8], %[temp8], %[temp4] \n\t" - "precr.qb.ph %[temp3], %[temp2], %[temp3] \n\t" - "usw %[temp8], 0*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp3], 1*" XSTR(BPS) "(%[dst]) \n\t" - "append %[temp3], %[temp6], 8 \n\t" - "srl %[temp6], %[temp6], 16 \n\t" - "append %[temp8], %[temp6], 8 \n\t" - "usw %[temp3], 3*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp8], 2*" XSTR(BPS) "(%[dst]) \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [temp9]"=&r"(temp9) - : [top]"r"(top), [dst]"r"(dst) - : "memory" - ); -} - -static void LD4(uint8_t* dst, const uint8_t* top) { - int temp0, temp1, temp2, temp3, temp4, temp5; - int temp6, temp7, temp8, temp9, temp10, temp11; - __asm__ volatile( - "ulw %[temp0], 0(%[top]) \n\t" - "ulw %[temp1], 4(%[top]) \n\t" - "preceu.ph.qbl %[temp2], %[temp0] \n\t" - "preceu.ph.qbr %[temp3], %[temp0] \n\t" - "preceu.ph.qbr %[temp4], %[temp1] \n\t" - "preceu.ph.qbl %[temp5], %[temp1] \n\t" - "packrl.ph %[temp6], %[temp2], %[temp3] \n\t" - "packrl.ph %[temp7], %[temp4], %[temp2] \n\t" - "packrl.ph %[temp8], %[temp5], %[temp4] \n\t" - "shll.ph %[temp6], %[temp6], 1 \n\t" - "addq.ph %[temp9], %[temp2], %[temp6] \n\t" - "shll.ph %[temp7], %[temp7], 1 \n\t" - "addq.ph %[temp9], %[temp9], %[temp3] \n\t" - "shll.ph %[temp8], %[temp8], 1 \n\t" - "shra_r.ph %[temp9], %[temp9], 2 \n\t" - "addq.ph %[temp10], %[temp4], %[temp7] \n\t" - "addq.ph %[temp11], %[temp5], %[temp8] \n\t" - "addq.ph %[temp10], %[temp10], %[temp2] \n\t" - "addq.ph %[temp11], %[temp11], %[temp4] \n\t" - "shra_r.ph %[temp10], %[temp10], 2 \n\t" - "shra_r.ph %[temp11], %[temp11], 2 \n\t" - "srl %[temp1], %[temp1], 24 \n\t" - "sll %[temp1], %[temp1], 1 \n\t" - "raddu.w.qb %[temp5], %[temp5] \n\t" - "precr.qb.ph %[temp9], %[temp10], %[temp9] \n\t" - "precr.qb.ph %[temp10], %[temp11], %[temp10] \n\t" - "addu %[temp1], %[temp1], %[temp5] \n\t" - "shra_r.w %[temp1], %[temp1], 2 \n\t" - "usw %[temp9], 0*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp10], 2*" XSTR(BPS) "(%[dst]) \n\t" - "prepend %[temp9], %[temp11], 8 \n\t" - "prepend %[temp10], %[temp1], 8 \n\t" - "usw %[temp9], 1*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp10], 3*" XSTR(BPS) "(%[dst]) \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11) - : [top]"r"(top), [dst]"r"(dst) - : "memory" - ); -} - -static void VL4(uint8_t* dst, const uint8_t* top) { - int temp0, temp1, temp2, temp3, temp4; - int temp5, temp6, temp7, temp8, temp9; - __asm__ volatile ( - "ulw %[temp0], 0(%[top]) \n\t" - "ulw %[temp1], 4(%[top]) \n\t" - "preceu.ph.qbla %[temp2], %[temp0] \n\t" - "preceu.ph.qbra %[temp0], %[temp0] \n\t" - "preceu.ph.qbl %[temp3], %[temp1] \n\t" - "preceu.ph.qbr %[temp1], %[temp1] \n\t" - "addqh_r.ph %[temp4], %[temp0], %[temp2] \n\t" - "packrl.ph %[temp7], %[temp1], %[temp0] \n\t" - "precrq.ph.w %[temp6], %[temp1], %[temp2] \n\t" - "shll.ph %[temp9], %[temp2], 1 \n\t" - "addqh_r.ph %[temp5], %[temp7], %[temp2] \n\t" - "shll.ph %[temp8], %[temp7], 1 \n\t" - "addu.ph %[temp2], %[temp2], %[temp6] \n\t" - "addu.ph %[temp0], %[temp0], %[temp7] \n\t" - "packrl.ph %[temp7], %[temp3], %[temp1] \n\t" - "addu.ph %[temp6], %[temp1], %[temp3] \n\t" - "addu.ph %[temp2], %[temp2], %[temp8] \n\t" - "addu.ph %[temp0], %[temp0], %[temp9] \n\t" - "shll.ph %[temp7], %[temp7], 1 \n\t" - "shra_r.ph %[temp2], %[temp2], 2 \n\t" - "shra_r.ph %[temp0], %[temp0], 2 \n\t" - "addu.ph %[temp6], %[temp6], %[temp7] \n\t" - "shra_r.ph %[temp6], %[temp6], 2 \n\t" - "precrq.ph.w %[temp8], %[temp5], %[temp4] \n\t" - "append %[temp5], %[temp4], 16 \n\t" - "precrq.ph.w %[temp3], %[temp2], %[temp0] \n\t" - "append %[temp2], %[temp0], 16 \n\t" - "precr.qb.ph %[temp8], %[temp8], %[temp5] \n\t" - "precr.qb.ph %[temp3], %[temp3], %[temp2] \n\t" - "usw %[temp8], 0*" XSTR(BPS) "(%[dst]) \n\t" - "prepend %[temp8], %[temp6], 8 \n\t" - "usw %[temp3], 1*" XSTR(BPS) "(%[dst]) \n\t" - "srl %[temp6], %[temp6], 16 \n\t" - "prepend %[temp3], %[temp6], 8 \n\t" - "usw %[temp8], 2*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp3], 3*" XSTR(BPS) "(%[dst]) \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [temp9]"=&r"(temp9) - : [top]"r"(top), [dst]"r"(dst) - : "memory" - ); -} - -static void HD4(uint8_t* dst, const uint8_t* top) { - int temp0, temp1, temp2, temp3, temp4; - int temp5, temp6, temp7, temp8, temp9; - __asm__ volatile ( - "ulw %[temp0], -5(%[top]) \n\t" - "ulw %[temp1], -1(%[top]) \n\t" - "preceu.ph.qbla %[temp2], %[temp0] \n\t" - "preceu.ph.qbra %[temp0], %[temp0] \n\t" - "preceu.ph.qbl %[temp3], %[temp1] \n\t" - "preceu.ph.qbr %[temp1], %[temp1] \n\t" - "addqh_r.ph %[temp4], %[temp0], %[temp2] \n\t" - "packrl.ph %[temp7], %[temp1], %[temp0] \n\t" - "precrq.ph.w %[temp6], %[temp1], %[temp2] \n\t" - "shll.ph %[temp9], %[temp2], 1 \n\t" - "addqh_r.ph %[temp5], %[temp7], %[temp2] \n\t" - "shll.ph %[temp8], %[temp7], 1 \n\t" - "addu.ph %[temp2], %[temp2], %[temp6] \n\t" - "addu.ph %[temp0], %[temp0], %[temp7] \n\t" - "packrl.ph %[temp7], %[temp3], %[temp1] \n\t" - "addu.ph %[temp6], %[temp1], %[temp3] \n\t" - "addu.ph %[temp2], %[temp2], %[temp8] \n\t" - "addu.ph %[temp0], %[temp0], %[temp9] \n\t" - "shll.ph %[temp7], %[temp7], 1 \n\t" - "shra_r.ph %[temp2], %[temp2], 2 \n\t" - "shra_r.ph %[temp0], %[temp0], 2 \n\t" - "addu.ph %[temp6], %[temp6], %[temp7] \n\t" - "shra_r.ph %[temp6], %[temp6], 2 \n\t" - "precrq.ph.w %[temp1], %[temp2], %[temp5] \n\t" - "precrq.ph.w %[temp3], %[temp0], %[temp4] \n\t" - "precr.qb.ph %[temp7], %[temp6], %[temp1] \n\t" - "precr.qb.ph %[temp6], %[temp1], %[temp3] \n\t" - "usw %[temp7], 0*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp6], 1*" XSTR(BPS) "(%[dst]) \n\t" - "append %[temp2], %[temp5], 16 \n\t" - "append %[temp0], %[temp4], 16 \n\t" - "precr.qb.ph %[temp5], %[temp3], %[temp2] \n\t" - "precr.qb.ph %[temp4], %[temp2], %[temp0] \n\t" - "usw %[temp5], 2*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp4], 3*" XSTR(BPS) "(%[dst]) \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [temp9]"=&r"(temp9) - : [top]"r"(top), [dst]"r"(dst) - : "memory" - ); -} - -static void HU4(uint8_t* dst, const uint8_t* top) { - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; - __asm__ volatile ( - "ulw %[temp0], -5(%[top]) \n\t" - "preceu.ph.qbl %[temp1], %[temp0] \n\t" - "preceu.ph.qbr %[temp2], %[temp0] \n\t" - "packrl.ph %[temp3], %[temp1], %[temp2] \n\t" - "replv.qb %[temp7], %[temp2] \n\t" - "addqh_r.ph %[temp4], %[temp1], %[temp3] \n\t" - "addqh_r.ph %[temp5], %[temp3], %[temp2] \n\t" - "shll.ph %[temp6], %[temp3], 1 \n\t" - "addu.ph %[temp3], %[temp2], %[temp3] \n\t" - "addu.ph %[temp6], %[temp1], %[temp6] \n\t" - "shll.ph %[temp0], %[temp2], 1 \n\t" - "addu.ph %[temp6], %[temp6], %[temp2] \n\t" - "addu.ph %[temp0], %[temp3], %[temp0] \n\t" - "shra_r.ph %[temp6], %[temp6], 2 \n\t" - "shra_r.ph %[temp0], %[temp0], 2 \n\t" - "packrl.ph %[temp3], %[temp6], %[temp5] \n\t" - "precrq.ph.w %[temp2], %[temp6], %[temp4] \n\t" - "append %[temp0], %[temp5], 16 \n\t" - "precr.qb.ph %[temp3], %[temp3], %[temp2] \n\t" - "usw %[temp3], 0*" XSTR(BPS) "(%[dst]) \n\t" - "precr.qb.ph %[temp1], %[temp7], %[temp0] \n\t" - "usw %[temp7], 3*" XSTR(BPS) "(%[dst]) \n\t" - "packrl.ph %[temp2], %[temp1], %[temp3] \n\t" - "usw %[temp1], 2*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp2], 1*" XSTR(BPS) "(%[dst]) \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7) - : [top]"r"(top), [dst]"r"(dst) - : "memory" - ); -} - -//------------------------------------------------------------------------------ -// Chroma 8x8 prediction (paragraph 12.2) - -static void IntraChromaPreds(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { - // U block - DCMode8(C8DC8 + dst, left, top); - VerticalPred8(C8VE8 + dst, top); - HorizontalPred8(C8HE8 + dst, left); - TrueMotion8(C8TM8 + dst, left, top); - // V block - dst += 8; - if (top) top += 8; - if (left) left += 16; - DCMode8(C8DC8 + dst, left, top); - VerticalPred8(C8VE8 + dst, top); - HorizontalPred8(C8HE8 + dst, left); - TrueMotion8(C8TM8 + dst, left, top); -} - -//------------------------------------------------------------------------------ -// luma 16x16 prediction (paragraph 12.3) - -static void Intra16Preds(uint8_t* dst, - const uint8_t* left, const uint8_t* top) { - DCMode16(I16DC16 + dst, left, top); - VerticalPred16(I16VE16 + dst, top); - HorizontalPred16(I16HE16 + dst, left); - TrueMotion16(I16TM16 + dst, left, top); -} - -// Left samples are top[-5 .. -2], top_left is top[-1], top are -// located at top[0..3], and top right is top[4..7] -static void Intra4Preds(uint8_t* dst, const uint8_t* top) { - DC4(I4DC4 + dst, top); - TM4(I4TM4 + dst, top); - VE4(I4VE4 + dst, top); - HE4(I4HE4 + dst, top); - RD4(I4RD4 + dst, top); - VR4(I4VR4 + dst, top); - LD4(I4LD4 + dst, top); - VL4(I4VL4 + dst, top); - HD4(I4HD4 + dst, top); - HU4(I4HU4 + dst, top); -} - -//------------------------------------------------------------------------------ -// Metric - -#if !defined(WORK_AROUND_GCC) - -#define GET_SSE_INNER(A) \ - "lw %[temp0], " #A "(%[a]) \n\t" \ - "lw %[temp1], " #A "(%[b]) \n\t" \ - "preceu.ph.qbr %[temp2], %[temp0] \n\t" \ - "preceu.ph.qbl %[temp0], %[temp0] \n\t" \ - "preceu.ph.qbr %[temp3], %[temp1] \n\t" \ - "preceu.ph.qbl %[temp1], %[temp1] \n\t" \ - "subq.ph %[temp2], %[temp2], %[temp3] \n\t" \ - "subq.ph %[temp0], %[temp0], %[temp1] \n\t" \ - "dpa.w.ph $ac0, %[temp2], %[temp2] \n\t" \ - "dpa.w.ph $ac0, %[temp0], %[temp0] \n\t" - -#define GET_SSE(A, B, C, D) \ - GET_SSE_INNER(A) \ - GET_SSE_INNER(B) \ - GET_SSE_INNER(C) \ - GET_SSE_INNER(D) - -static int SSE16x16(const uint8_t* a, const uint8_t* b) { - int count; - int temp0, temp1, temp2, temp3; - __asm__ volatile ( - "mult $zero, $zero \n\t" - GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS) - GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS) - GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS) - GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS) - GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS) - GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS) - GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS) - GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS) - GET_SSE( 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS) - GET_SSE( 9 * BPS, 4 + 9 * BPS, 8 + 9 * BPS, 12 + 9 * BPS) - GET_SSE(10 * BPS, 4 + 10 * BPS, 8 + 10 * BPS, 12 + 10 * BPS) - GET_SSE(11 * BPS, 4 + 11 * BPS, 8 + 11 * BPS, 12 + 11 * BPS) - GET_SSE(12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS) - GET_SSE(13 * BPS, 4 + 13 * BPS, 8 + 13 * BPS, 12 + 13 * BPS) - GET_SSE(14 * BPS, 4 + 14 * BPS, 8 + 14 * BPS, 12 + 14 * BPS) - GET_SSE(15 * BPS, 4 + 15 * BPS, 8 + 15 * BPS, 12 + 15 * BPS) - "mflo %[count] \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [count]"=&r"(count) - : [a]"r"(a), [b]"r"(b) - : "memory", "hi", "lo" - ); - return count; -} - -static int SSE16x8(const uint8_t* a, const uint8_t* b) { - int count; - int temp0, temp1, temp2, temp3; - __asm__ volatile ( - "mult $zero, $zero \n\t" - GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS) - GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS) - GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS) - GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS) - GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS) - GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS) - GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS) - GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS) - "mflo %[count] \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [count]"=&r"(count) - : [a]"r"(a), [b]"r"(b) - : "memory", "hi", "lo" - ); - return count; -} - -static int SSE8x8(const uint8_t* a, const uint8_t* b) { - int count; - int temp0, temp1, temp2, temp3; - __asm__ volatile ( - "mult $zero, $zero \n\t" - GET_SSE(0 * BPS, 4 + 0 * BPS, 1 * BPS, 4 + 1 * BPS) - GET_SSE(2 * BPS, 4 + 2 * BPS, 3 * BPS, 4 + 3 * BPS) - GET_SSE(4 * BPS, 4 + 4 * BPS, 5 * BPS, 4 + 5 * BPS) - GET_SSE(6 * BPS, 4 + 6 * BPS, 7 * BPS, 4 + 7 * BPS) - "mflo %[count] \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [count]"=&r"(count) - : [a]"r"(a), [b]"r"(b) - : "memory", "hi", "lo" - ); - return count; -} - -static int SSE4x4(const uint8_t* a, const uint8_t* b) { - int count; - int temp0, temp1, temp2, temp3; - __asm__ volatile ( - "mult $zero, $zero \n\t" - GET_SSE(0 * BPS, 1 * BPS, 2 * BPS, 3 * BPS) - "mflo %[count] \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [count]"=&r"(count) - : [a]"r"(a), [b]"r"(b) - : "memory", "hi", "lo" - ); - return count; -} - -#undef GET_SSE -#undef GET_SSE_INNER - -#endif // !WORK_AROUND_GCC - -#undef FILL_8_OR_16 -#undef FILL_PART -#undef OUTPUT_EARLY_CLOBBER_REGS_17 -#undef MUL_HALF -#undef ABS_X8 -#undef ADD_SUB_HALVES_X4 - -//------------------------------------------------------------------------------ -// Quantization -// - -// macro for one pass through for loop in QuantizeBlock reading 2 values at time -// QUANTDIV macro inlined -// J - offset in bytes (kZigzag[n] * 2) -// K - offset in bytes (kZigzag[n] * 4) -// N - offset in bytes (n * 2) -// N1 - offset in bytes ((n + 1) * 2) -#define QUANTIZE_ONE(J, K, N, N1) \ - "ulw %[temp1], " #J "(%[ppin]) \n\t" \ - "ulw %[temp2], " #J "(%[ppsharpen]) \n\t" \ - "lhu %[temp3], " #K "(%[ppzthresh]) \n\t" \ - "lhu %[temp6], " #K "+4(%[ppzthresh]) \n\t" \ - "absq_s.ph %[temp4], %[temp1] \n\t" \ - "ins %[temp3], %[temp6], 16, 16 \n\t" \ - "addu.ph %[coeff], %[temp4], %[temp2] \n\t" \ - "shra.ph %[sign], %[temp1], 15 \n\t" \ - "li %[level], 0x10001 \n\t" \ - "cmp.lt.ph %[temp3], %[coeff] \n\t" \ - "lhu %[temp1], " #J "(%[ppiq]) \n\t" \ - "pick.ph %[temp5], %[level], $0 \n\t" \ - "lw %[temp2], " #K "(%[ppbias]) \n\t" \ - "beqz %[temp5], 0f \n\t" \ - "lhu %[temp3], " #J "(%[ppq]) \n\t" \ - "beq %[temp5], %[level], 1f \n\t" \ - "andi %[temp5], %[temp5], 0x1 \n\t" \ - "andi %[temp4], %[coeff], 0xffff \n\t" \ - "beqz %[temp5], 2f \n\t" \ - "mul %[level], %[temp4], %[temp1] \n\t" \ - "sh $0, " #J "+2(%[ppin]) \n\t" \ - "sh $0, " #N1 "(%[pout]) \n\t" \ - "addu %[level], %[level], %[temp2] \n\t" \ - "sra %[level], %[level], 17 \n\t" \ - "slt %[temp4], %[max_level], %[level] \n\t" \ - "movn %[level], %[max_level], %[temp4] \n\t" \ - "andi %[temp6], %[sign], 0xffff \n\t" \ - "xor %[level], %[level], %[temp6] \n\t" \ - "subu %[level], %[level], %[temp6] \n\t" \ - "mul %[temp5], %[level], %[temp3] \n\t" \ - "or %[ret], %[ret], %[level] \n\t" \ - "sh %[level], " #N "(%[pout]) \n\t" \ - "sh %[temp5], " #J "(%[ppin]) \n\t" \ - "j 3f \n\t" \ -"2: \n\t" \ - "lhu %[temp1], " #J "+2(%[ppiq]) \n\t" \ - "srl %[temp5], %[coeff], 16 \n\t" \ - "mul %[level], %[temp5], %[temp1] \n\t" \ - "lw %[temp2], " #K "+4(%[ppbias]) \n\t" \ - "lhu %[temp3], " #J "+2(%[ppq]) \n\t" \ - "addu %[level], %[level], %[temp2] \n\t" \ - "sra %[level], %[level], 17 \n\t" \ - "srl %[temp6], %[sign], 16 \n\t" \ - "slt %[temp4], %[max_level], %[level] \n\t" \ - "movn %[level], %[max_level], %[temp4] \n\t" \ - "xor %[level], %[level], %[temp6] \n\t" \ - "subu %[level], %[level], %[temp6] \n\t" \ - "mul %[temp5], %[level], %[temp3] \n\t" \ - "sh $0, " #J "(%[ppin]) \n\t" \ - "sh $0, " #N "(%[pout]) \n\t" \ - "or %[ret], %[ret], %[level] \n\t" \ - "sh %[temp5], " #J "+2(%[ppin]) \n\t" \ - "sh %[level], " #N1 "(%[pout]) \n\t" \ - "j 3f \n\t" \ -"1: \n\t" \ - "lhu %[temp1], " #J "(%[ppiq]) \n\t" \ - "lw %[temp2], " #K "(%[ppbias]) \n\t" \ - "ulw %[temp3], " #J "(%[ppq]) \n\t" \ - "andi %[temp5], %[coeff], 0xffff \n\t" \ - "srl %[temp0], %[coeff], 16 \n\t" \ - "lhu %[temp6], " #J "+2(%[ppiq]) \n\t" \ - "lw %[coeff], " #K "+4(%[ppbias]) \n\t" \ - "mul %[level], %[temp5], %[temp1] \n\t" \ - "mul %[temp4], %[temp0], %[temp6] \n\t" \ - "addu %[level], %[level], %[temp2] \n\t" \ - "addu %[temp4], %[temp4], %[coeff] \n\t" \ - "precrq.ph.w %[level], %[temp4], %[level] \n\t" \ - "shra.ph %[level], %[level], 1 \n\t" \ - "cmp.lt.ph %[max_level1],%[level] \n\t" \ - "pick.ph %[level], %[max_level], %[level] \n\t" \ - "xor %[level], %[level], %[sign] \n\t" \ - "subu.ph %[level], %[level], %[sign] \n\t" \ - "mul.ph %[temp3], %[level], %[temp3] \n\t" \ - "or %[ret], %[ret], %[level] \n\t" \ - "sh %[level], " #N "(%[pout]) \n\t" \ - "srl %[level], %[level], 16 \n\t" \ - "sh %[level], " #N1 "(%[pout]) \n\t" \ - "usw %[temp3], " #J "(%[ppin]) \n\t" \ - "j 3f \n\t" \ -"0: \n\t" \ - "sh $0, " #N "(%[pout]) \n\t" \ - "sh $0, " #N1 "(%[pout]) \n\t" \ - "usw $0, " #J "(%[ppin]) \n\t" \ -"3: \n\t" - -static int QuantizeBlock(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - int temp0, temp1, temp2, temp3, temp4, temp5,temp6; - int sign, coeff, level; - int max_level = MAX_LEVEL; - int max_level1 = max_level << 16 | max_level; - int ret = 0; - - int16_t* ppin = &in[0]; - int16_t* pout = &out[0]; - const uint16_t* ppsharpen = &mtx->sharpen_[0]; - const uint32_t* ppzthresh = &mtx->zthresh_[0]; - const uint16_t* ppq = &mtx->q_[0]; - const uint16_t* ppiq = &mtx->iq_[0]; - const uint32_t* ppbias = &mtx->bias_[0]; - - __asm__ volatile ( - QUANTIZE_ONE( 0, 0, 0, 2) - QUANTIZE_ONE( 4, 8, 10, 12) - QUANTIZE_ONE( 8, 16, 4, 8) - QUANTIZE_ONE(12, 24, 14, 24) - QUANTIZE_ONE(16, 32, 6, 16) - QUANTIZE_ONE(20, 40, 22, 26) - QUANTIZE_ONE(24, 48, 18, 20) - QUANTIZE_ONE(28, 56, 28, 30) - - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [sign]"=&r"(sign), [coeff]"=&r"(coeff), - [level]"=&r"(level), [temp6]"=&r"(temp6), [ret]"+&r"(ret) - : [ppin]"r"(ppin), [pout]"r"(pout), [max_level1]"r"(max_level1), - [ppiq]"r"(ppiq), [max_level]"r"(max_level), - [ppbias]"r"(ppbias), [ppzthresh]"r"(ppzthresh), - [ppsharpen]"r"(ppsharpen), [ppq]"r"(ppq) - : "memory", "hi", "lo" - ); - - return (ret != 0); -} - -static int Quantize2Blocks(int16_t in[32], int16_t out[32], - const VP8Matrix* const mtx) { - int nz; - nz = QuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0; - nz |= QuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1; - return nz; -} - -#undef QUANTIZE_ONE - -// macro for one horizontal pass in FTransformWHT -// temp0..temp7 holds tmp[0]..tmp[15] -// A, B, C, D - offset in bytes to load from in buffer -// TEMP0, TEMP1 - registers for corresponding tmp elements -#define HORIZONTAL_PASS_WHT(A, B, C, D, TEMP0, TEMP1) \ - "lh %[" #TEMP0 "], " #A "(%[in]) \n\t" \ - "lh %[" #TEMP1 "], " #B "(%[in]) \n\t" \ - "lh %[temp8], " #C "(%[in]) \n\t" \ - "lh %[temp9], " #D "(%[in]) \n\t" \ - "ins %[" #TEMP1 "], %[" #TEMP0 "], 16, 16 \n\t" \ - "ins %[temp9], %[temp8], 16, 16 \n\t" \ - "subq.ph %[temp8], %[" #TEMP1 "], %[temp9] \n\t" \ - "addq.ph %[temp9], %[" #TEMP1 "], %[temp9] \n\t" \ - "precrq.ph.w %[" #TEMP0 "], %[temp8], %[temp9] \n\t" \ - "append %[temp8], %[temp9], 16 \n\t" \ - "subq.ph %[" #TEMP1 "], %[" #TEMP0 "], %[temp8] \n\t" \ - "addq.ph %[" #TEMP0 "], %[" #TEMP0 "], %[temp8] \n\t" \ - "rotr %[" #TEMP1 "], %[" #TEMP1 "], 16 \n\t" - -// macro for one vertical pass in FTransformWHT -// temp0..temp7 holds tmp[0]..tmp[15] -// A, B, C, D - offsets in bytes to store to out buffer -// TEMP0, TEMP2, TEMP4 and TEMP6 - registers for corresponding tmp elements -#define VERTICAL_PASS_WHT(A, B, C, D, TEMP0, TEMP2, TEMP4, TEMP6) \ - "addq.ph %[temp8], %[" #TEMP0 "], %[" #TEMP4 "] \n\t" \ - "addq.ph %[temp9], %[" #TEMP2 "], %[" #TEMP6 "] \n\t" \ - "subq.ph %[" #TEMP2 "], %[" #TEMP2 "], %[" #TEMP6 "] \n\t" \ - "subq.ph %[" #TEMP6 "], %[" #TEMP0 "], %[" #TEMP4 "] \n\t" \ - "addqh.ph %[" #TEMP0 "], %[temp8], %[temp9] \n\t" \ - "subqh.ph %[" #TEMP4 "], %[" #TEMP6 "], %[" #TEMP2 "] \n\t" \ - "addqh.ph %[" #TEMP2 "], %[" #TEMP2 "], %[" #TEMP6 "] \n\t" \ - "subqh.ph %[" #TEMP6 "], %[temp8], %[temp9] \n\t" \ - "usw %[" #TEMP0 "], " #A "(%[out]) \n\t" \ - "usw %[" #TEMP2 "], " #B "(%[out]) \n\t" \ - "usw %[" #TEMP4 "], " #C "(%[out]) \n\t" \ - "usw %[" #TEMP6 "], " #D "(%[out]) \n\t" - -static void FTransformWHT(const int16_t* in, int16_t* out) { - int temp0, temp1, temp2, temp3, temp4; - int temp5, temp6, temp7, temp8, temp9; - - __asm__ volatile ( - HORIZONTAL_PASS_WHT( 0, 32, 64, 96, temp0, temp1) - HORIZONTAL_PASS_WHT(128, 160, 192, 224, temp2, temp3) - HORIZONTAL_PASS_WHT(256, 288, 320, 352, temp4, temp5) - HORIZONTAL_PASS_WHT(384, 416, 448, 480, temp6, temp7) - VERTICAL_PASS_WHT(0, 8, 16, 24, temp0, temp2, temp4, temp6) - VERTICAL_PASS_WHT(4, 12, 20, 28, temp1, temp3, temp5, temp7) - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [temp9]"=&r"(temp9) - : [in]"r"(in), [out]"r"(out) - : "memory" - ); -} - -#undef VERTICAL_PASS_WHT -#undef HORIZONTAL_PASS_WHT - -// macro for converting coefficients to bin -// convert 8 coeffs at time -// A, B, C, D - offsets in bytes to load from out buffer -#define CONVERT_COEFFS_TO_BIN(A, B, C, D) \ - "ulw %[temp0], " #A "(%[out]) \n\t" \ - "ulw %[temp1], " #B "(%[out]) \n\t" \ - "ulw %[temp2], " #C "(%[out]) \n\t" \ - "ulw %[temp3], " #D "(%[out]) \n\t" \ - "absq_s.ph %[temp0], %[temp0] \n\t" \ - "absq_s.ph %[temp1], %[temp1] \n\t" \ - "absq_s.ph %[temp2], %[temp2] \n\t" \ - "absq_s.ph %[temp3], %[temp3] \n\t" \ - /* TODO(skal): add rounding ? shra_r.ph : shra.ph */ \ - /* for following 4 instructions */ \ - "shra.ph %[temp0], %[temp0], 3 \n\t" \ - "shra.ph %[temp1], %[temp1], 3 \n\t" \ - "shra.ph %[temp2], %[temp2], 3 \n\t" \ - "shra.ph %[temp3], %[temp3], 3 \n\t" \ - "shll_s.ph %[temp0], %[temp0], 10 \n\t" \ - "shll_s.ph %[temp1], %[temp1], 10 \n\t" \ - "shll_s.ph %[temp2], %[temp2], 10 \n\t" \ - "shll_s.ph %[temp3], %[temp3], 10 \n\t" \ - "shrl.ph %[temp0], %[temp0], 10 \n\t" \ - "shrl.ph %[temp1], %[temp1], 10 \n\t" \ - "shrl.ph %[temp2], %[temp2], 10 \n\t" \ - "shrl.ph %[temp3], %[temp3], 10 \n\t" \ - "shll.ph %[temp0], %[temp0], 2 \n\t" \ - "shll.ph %[temp1], %[temp1], 2 \n\t" \ - "shll.ph %[temp2], %[temp2], 2 \n\t" \ - "shll.ph %[temp3], %[temp3], 2 \n\t" \ - "ext %[temp4], %[temp0], 0, 16 \n\t" \ - "ext %[temp0], %[temp0], 16, 16 \n\t" \ - "addu %[temp4], %[temp4], %[dist] \n\t" \ - "addu %[temp0], %[temp0], %[dist] \n\t" \ - "ext %[temp5], %[temp1], 0, 16 \n\t" \ - "lw %[temp8], 0(%[temp4]) \n\t" \ - "ext %[temp1], %[temp1], 16, 16 \n\t" \ - "addu %[temp5], %[temp5], %[dist] \n\t" \ - "addiu %[temp8], %[temp8], 1 \n\t" \ - "sw %[temp8], 0(%[temp4]) \n\t" \ - "lw %[temp8], 0(%[temp0]) \n\t" \ - "addu %[temp1], %[temp1], %[dist] \n\t" \ - "ext %[temp6], %[temp2], 0, 16 \n\t" \ - "addiu %[temp8], %[temp8], 1 \n\t" \ - "sw %[temp8], 0(%[temp0]) \n\t" \ - "lw %[temp8], 0(%[temp5]) \n\t" \ - "ext %[temp2], %[temp2], 16, 16 \n\t" \ - "addu %[temp6], %[temp6], %[dist] \n\t" \ - "addiu %[temp8], %[temp8], 1 \n\t" \ - "sw %[temp8], 0(%[temp5]) \n\t" \ - "lw %[temp8], 0(%[temp1]) \n\t" \ - "addu %[temp2], %[temp2], %[dist] \n\t" \ - "ext %[temp7], %[temp3], 0, 16 \n\t" \ - "addiu %[temp8], %[temp8], 1 \n\t" \ - "sw %[temp8], 0(%[temp1]) \n\t" \ - "lw %[temp8], 0(%[temp6]) \n\t" \ - "ext %[temp3], %[temp3], 16, 16 \n\t" \ - "addu %[temp7], %[temp7], %[dist] \n\t" \ - "addiu %[temp8], %[temp8], 1 \n\t" \ - "sw %[temp8], 0(%[temp6]) \n\t" \ - "lw %[temp8], 0(%[temp2]) \n\t" \ - "addu %[temp3], %[temp3], %[dist] \n\t" \ - "addiu %[temp8], %[temp8], 1 \n\t" \ - "sw %[temp8], 0(%[temp2]) \n\t" \ - "lw %[temp8], 0(%[temp7]) \n\t" \ - "addiu %[temp8], %[temp8], 1 \n\t" \ - "sw %[temp8], 0(%[temp7]) \n\t" \ - "lw %[temp8], 0(%[temp3]) \n\t" \ - "addiu %[temp8], %[temp8], 1 \n\t" \ - "sw %[temp8], 0(%[temp3]) \n\t" - -static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, - int start_block, int end_block, - VP8Histogram* const histo) { - int j; - int distribution[MAX_COEFF_THRESH + 1] = { 0 }; - const int max_coeff = (MAX_COEFF_THRESH << 16) + MAX_COEFF_THRESH; - for (j = start_block; j < end_block; ++j) { - int16_t out[16]; - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; - - VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); - - // Convert coefficients to bin. - __asm__ volatile ( - CONVERT_COEFFS_TO_BIN( 0, 4, 8, 12) - CONVERT_COEFFS_TO_BIN(16, 20, 24, 28) - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8) - : [dist]"r"(distribution), [out]"r"(out), [max_coeff]"r"(max_coeff) - : "memory" - ); - } - VP8SetHistogramData(distribution, histo); -} - -#undef CONVERT_COEFFS_TO_BIN - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8EncDspInitMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitMIPSdspR2(void) { - VP8FTransform = FTransform; - VP8ITransform = ITransform; - VP8TDisto4x4 = Disto4x4; - VP8TDisto16x16 = Disto16x16; - VP8EncPredLuma16 = Intra16Preds; - VP8EncPredChroma8 = IntraChromaPreds; - VP8EncPredLuma4 = Intra4Preds; -#if !defined(WORK_AROUND_GCC) - VP8SSE16x16 = SSE16x16; - VP8SSE8x8 = SSE8x8; - VP8SSE16x8 = SSE16x8; - VP8SSE4x4 = SSE4x4; -#endif - VP8EncQuantizeBlock = QuantizeBlock; - VP8EncQuantize2Blocks = Quantize2Blocks; - VP8FTransformWHT = FTransformWHT; - VP8CollectHistogram = CollectHistogram; -} - -#else // !WEBP_USE_MIPS_DSP_R2 - -WEBP_DSP_INIT_STUB(VP8EncDspInitMIPSdspR2) - -#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/Example-Mac/Pods/libwebp/src/dsp/enc_neon.c b/Example-Mac/Pods/libwebp/src/dsp/enc_neon.c deleted file mode 100644 index c2aef58e..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/enc_neon.c +++ /dev/null @@ -1,934 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// ARM NEON version of speed-critical encoding functions. -// -// adapted from libvpx (http://www.webmproject.org/code/) - -#include "./dsp.h" - -#if defined(WEBP_USE_NEON) - -#include - -#include "./neon.h" -#include "../enc/vp8enci.h" - -//------------------------------------------------------------------------------ -// Transforms (Paragraph 14.4) - -// Inverse transform. -// This code is pretty much the same as TransformOne in the dec_neon.c, except -// for subtraction to *ref. See the comments there for algorithmic explanations. - -static const int16_t kC1 = 20091; -static const int16_t kC2 = 17734; // half of kC2, actually. See comment above. - -// This code works but is *slower* than the inlined-asm version below -// (with gcc-4.6). So we disable it for now. Later, it'll be conditional to -// WEBP_USE_INTRINSICS define. -// With gcc-4.8, it's a little faster speed than inlined-assembly. -#if defined(WEBP_USE_INTRINSICS) - -// Treats 'v' as an uint8x8_t and zero extends to an int16x8_t. -static WEBP_INLINE int16x8_t ConvertU8ToS16(uint32x2_t v) { - return vreinterpretq_s16_u16(vmovl_u8(vreinterpret_u8_u32(v))); -} - -// Performs unsigned 8b saturation on 'dst01' and 'dst23' storing the result -// to the corresponding rows of 'dst'. -static WEBP_INLINE void SaturateAndStore4x4(uint8_t* const dst, - const int16x8_t dst01, - const int16x8_t dst23) { - // Unsigned saturate to 8b. - const uint8x8_t dst01_u8 = vqmovun_s16(dst01); - const uint8x8_t dst23_u8 = vqmovun_s16(dst23); - - // Store the results. - vst1_lane_u32((uint32_t*)(dst + 0 * BPS), vreinterpret_u32_u8(dst01_u8), 0); - vst1_lane_u32((uint32_t*)(dst + 1 * BPS), vreinterpret_u32_u8(dst01_u8), 1); - vst1_lane_u32((uint32_t*)(dst + 2 * BPS), vreinterpret_u32_u8(dst23_u8), 0); - vst1_lane_u32((uint32_t*)(dst + 3 * BPS), vreinterpret_u32_u8(dst23_u8), 1); -} - -static WEBP_INLINE void Add4x4(const int16x8_t row01, const int16x8_t row23, - const uint8_t* const ref, uint8_t* const dst) { - uint32x2_t dst01 = vdup_n_u32(0); - uint32x2_t dst23 = vdup_n_u32(0); - - // Load the source pixels. - dst01 = vld1_lane_u32((uint32_t*)(ref + 0 * BPS), dst01, 0); - dst23 = vld1_lane_u32((uint32_t*)(ref + 2 * BPS), dst23, 0); - dst01 = vld1_lane_u32((uint32_t*)(ref + 1 * BPS), dst01, 1); - dst23 = vld1_lane_u32((uint32_t*)(ref + 3 * BPS), dst23, 1); - - { - // Convert to 16b. - const int16x8_t dst01_s16 = ConvertU8ToS16(dst01); - const int16x8_t dst23_s16 = ConvertU8ToS16(dst23); - - // Descale with rounding. - const int16x8_t out01 = vrsraq_n_s16(dst01_s16, row01, 3); - const int16x8_t out23 = vrsraq_n_s16(dst23_s16, row23, 3); - // Add the inverse transform. - SaturateAndStore4x4(dst, out01, out23); - } -} - -static WEBP_INLINE void Transpose8x2(const int16x8_t in0, const int16x8_t in1, - int16x8x2_t* const out) { - // a0 a1 a2 a3 | b0 b1 b2 b3 => a0 b0 c0 d0 | a1 b1 c1 d1 - // c0 c1 c2 c3 | d0 d1 d2 d3 a2 b2 c2 d2 | a3 b3 c3 d3 - const int16x8x2_t tmp0 = vzipq_s16(in0, in1); // a0 c0 a1 c1 a2 c2 ... - // b0 d0 b1 d1 b2 d2 ... - *out = vzipq_s16(tmp0.val[0], tmp0.val[1]); -} - -static WEBP_INLINE void TransformPass(int16x8x2_t* const rows) { - // {rows} = in0 | in4 - // in8 | in12 - // B1 = in4 | in12 - const int16x8_t B1 = - vcombine_s16(vget_high_s16(rows->val[0]), vget_high_s16(rows->val[1])); - // C0 = kC1 * in4 | kC1 * in12 - // C1 = kC2 * in4 | kC2 * in12 - const int16x8_t C0 = vsraq_n_s16(B1, vqdmulhq_n_s16(B1, kC1), 1); - const int16x8_t C1 = vqdmulhq_n_s16(B1, kC2); - const int16x4_t a = vqadd_s16(vget_low_s16(rows->val[0]), - vget_low_s16(rows->val[1])); // in0 + in8 - const int16x4_t b = vqsub_s16(vget_low_s16(rows->val[0]), - vget_low_s16(rows->val[1])); // in0 - in8 - // c = kC2 * in4 - kC1 * in12 - // d = kC1 * in4 + kC2 * in12 - const int16x4_t c = vqsub_s16(vget_low_s16(C1), vget_high_s16(C0)); - const int16x4_t d = vqadd_s16(vget_low_s16(C0), vget_high_s16(C1)); - const int16x8_t D0 = vcombine_s16(a, b); // D0 = a | b - const int16x8_t D1 = vcombine_s16(d, c); // D1 = d | c - const int16x8_t E0 = vqaddq_s16(D0, D1); // a+d | b+c - const int16x8_t E_tmp = vqsubq_s16(D0, D1); // a-d | b-c - const int16x8_t E1 = vcombine_s16(vget_high_s16(E_tmp), vget_low_s16(E_tmp)); - Transpose8x2(E0, E1, rows); -} - -static void ITransformOne(const uint8_t* ref, - const int16_t* in, uint8_t* dst) { - int16x8x2_t rows; - INIT_VECTOR2(rows, vld1q_s16(in + 0), vld1q_s16(in + 8)); - TransformPass(&rows); - TransformPass(&rows); - Add4x4(rows.val[0], rows.val[1], ref, dst); -} - -#else - -static void ITransformOne(const uint8_t* ref, - const int16_t* in, uint8_t* dst) { - const int kBPS = BPS; - const int16_t kC1C2[] = { kC1, kC2, 0, 0 }; - - __asm__ volatile ( - "vld1.16 {q1, q2}, [%[in]] \n" - "vld1.16 {d0}, [%[kC1C2]] \n" - - // d2: in[0] - // d3: in[8] - // d4: in[4] - // d5: in[12] - "vswp d3, d4 \n" - - // q8 = {in[4], in[12]} * kC1 * 2 >> 16 - // q9 = {in[4], in[12]} * kC2 >> 16 - "vqdmulh.s16 q8, q2, d0[0] \n" - "vqdmulh.s16 q9, q2, d0[1] \n" - - // d22 = a = in[0] + in[8] - // d23 = b = in[0] - in[8] - "vqadd.s16 d22, d2, d3 \n" - "vqsub.s16 d23, d2, d3 \n" - - // q8 = in[4]/[12] * kC1 >> 16 - "vshr.s16 q8, q8, #1 \n" - - // Add {in[4], in[12]} back after the multiplication. - "vqadd.s16 q8, q2, q8 \n" - - // d20 = c = in[4]*kC2 - in[12]*kC1 - // d21 = d = in[4]*kC1 + in[12]*kC2 - "vqsub.s16 d20, d18, d17 \n" - "vqadd.s16 d21, d19, d16 \n" - - // d2 = tmp[0] = a + d - // d3 = tmp[1] = b + c - // d4 = tmp[2] = b - c - // d5 = tmp[3] = a - d - "vqadd.s16 d2, d22, d21 \n" - "vqadd.s16 d3, d23, d20 \n" - "vqsub.s16 d4, d23, d20 \n" - "vqsub.s16 d5, d22, d21 \n" - - "vzip.16 q1, q2 \n" - "vzip.16 q1, q2 \n" - - "vswp d3, d4 \n" - - // q8 = {tmp[4], tmp[12]} * kC1 * 2 >> 16 - // q9 = {tmp[4], tmp[12]} * kC2 >> 16 - "vqdmulh.s16 q8, q2, d0[0] \n" - "vqdmulh.s16 q9, q2, d0[1] \n" - - // d22 = a = tmp[0] + tmp[8] - // d23 = b = tmp[0] - tmp[8] - "vqadd.s16 d22, d2, d3 \n" - "vqsub.s16 d23, d2, d3 \n" - - "vshr.s16 q8, q8, #1 \n" - "vqadd.s16 q8, q2, q8 \n" - - // d20 = c = in[4]*kC2 - in[12]*kC1 - // d21 = d = in[4]*kC1 + in[12]*kC2 - "vqsub.s16 d20, d18, d17 \n" - "vqadd.s16 d21, d19, d16 \n" - - // d2 = tmp[0] = a + d - // d3 = tmp[1] = b + c - // d4 = tmp[2] = b - c - // d5 = tmp[3] = a - d - "vqadd.s16 d2, d22, d21 \n" - "vqadd.s16 d3, d23, d20 \n" - "vqsub.s16 d4, d23, d20 \n" - "vqsub.s16 d5, d22, d21 \n" - - "vld1.32 d6[0], [%[ref]], %[kBPS] \n" - "vld1.32 d6[1], [%[ref]], %[kBPS] \n" - "vld1.32 d7[0], [%[ref]], %[kBPS] \n" - "vld1.32 d7[1], [%[ref]], %[kBPS] \n" - - "sub %[ref], %[ref], %[kBPS], lsl #2 \n" - - // (val) + 4 >> 3 - "vrshr.s16 d2, d2, #3 \n" - "vrshr.s16 d3, d3, #3 \n" - "vrshr.s16 d4, d4, #3 \n" - "vrshr.s16 d5, d5, #3 \n" - - "vzip.16 q1, q2 \n" - "vzip.16 q1, q2 \n" - - // Must accumulate before saturating - "vmovl.u8 q8, d6 \n" - "vmovl.u8 q9, d7 \n" - - "vqadd.s16 q1, q1, q8 \n" - "vqadd.s16 q2, q2, q9 \n" - - "vqmovun.s16 d0, q1 \n" - "vqmovun.s16 d1, q2 \n" - - "vst1.32 d0[0], [%[dst]], %[kBPS] \n" - "vst1.32 d0[1], [%[dst]], %[kBPS] \n" - "vst1.32 d1[0], [%[dst]], %[kBPS] \n" - "vst1.32 d1[1], [%[dst]] \n" - - : [in] "+r"(in), [dst] "+r"(dst) // modified registers - : [kBPS] "r"(kBPS), [kC1C2] "r"(kC1C2), [ref] "r"(ref) // constants - : "memory", "q0", "q1", "q2", "q8", "q9", "q10", "q11" // clobbered - ); -} - -#endif // WEBP_USE_INTRINSICS - -static void ITransform(const uint8_t* ref, - const int16_t* in, uint8_t* dst, int do_two) { - ITransformOne(ref, in, dst); - if (do_two) { - ITransformOne(ref + 4, in + 16, dst + 4); - } -} - -// Load all 4x4 pixels into a single uint8x16_t variable. -static uint8x16_t Load4x4(const uint8_t* src) { - uint32x4_t out = vdupq_n_u32(0); - out = vld1q_lane_u32((const uint32_t*)(src + 0 * BPS), out, 0); - out = vld1q_lane_u32((const uint32_t*)(src + 1 * BPS), out, 1); - out = vld1q_lane_u32((const uint32_t*)(src + 2 * BPS), out, 2); - out = vld1q_lane_u32((const uint32_t*)(src + 3 * BPS), out, 3); - return vreinterpretq_u8_u32(out); -} - -// Forward transform. - -#if defined(WEBP_USE_INTRINSICS) - -static WEBP_INLINE void Transpose4x4_S16(const int16x4_t A, const int16x4_t B, - const int16x4_t C, const int16x4_t D, - int16x8_t* const out01, - int16x8_t* const out32) { - const int16x4x2_t AB = vtrn_s16(A, B); - const int16x4x2_t CD = vtrn_s16(C, D); - const int32x2x2_t tmp02 = vtrn_s32(vreinterpret_s32_s16(AB.val[0]), - vreinterpret_s32_s16(CD.val[0])); - const int32x2x2_t tmp13 = vtrn_s32(vreinterpret_s32_s16(AB.val[1]), - vreinterpret_s32_s16(CD.val[1])); - *out01 = vreinterpretq_s16_s64( - vcombine_s64(vreinterpret_s64_s32(tmp02.val[0]), - vreinterpret_s64_s32(tmp13.val[0]))); - *out32 = vreinterpretq_s16_s64( - vcombine_s64(vreinterpret_s64_s32(tmp13.val[1]), - vreinterpret_s64_s32(tmp02.val[1]))); -} - -static WEBP_INLINE int16x8_t DiffU8ToS16(const uint8x8_t a, - const uint8x8_t b) { - return vreinterpretq_s16_u16(vsubl_u8(a, b)); -} - -static void FTransform(const uint8_t* src, const uint8_t* ref, - int16_t* out) { - int16x8_t d0d1, d3d2; // working 4x4 int16 variables - { - const uint8x16_t S0 = Load4x4(src); - const uint8x16_t R0 = Load4x4(ref); - const int16x8_t D0D1 = DiffU8ToS16(vget_low_u8(S0), vget_low_u8(R0)); - const int16x8_t D2D3 = DiffU8ToS16(vget_high_u8(S0), vget_high_u8(R0)); - const int16x4_t D0 = vget_low_s16(D0D1); - const int16x4_t D1 = vget_high_s16(D0D1); - const int16x4_t D2 = vget_low_s16(D2D3); - const int16x4_t D3 = vget_high_s16(D2D3); - Transpose4x4_S16(D0, D1, D2, D3, &d0d1, &d3d2); - } - { // 1rst pass - const int32x4_t kCst937 = vdupq_n_s32(937); - const int32x4_t kCst1812 = vdupq_n_s32(1812); - const int16x8_t a0a1 = vaddq_s16(d0d1, d3d2); // d0+d3 | d1+d2 (=a0|a1) - const int16x8_t a3a2 = vsubq_s16(d0d1, d3d2); // d0-d3 | d1-d2 (=a3|a2) - const int16x8_t a0a1_2 = vshlq_n_s16(a0a1, 3); - const int16x4_t tmp0 = vadd_s16(vget_low_s16(a0a1_2), - vget_high_s16(a0a1_2)); - const int16x4_t tmp2 = vsub_s16(vget_low_s16(a0a1_2), - vget_high_s16(a0a1_2)); - const int32x4_t a3_2217 = vmull_n_s16(vget_low_s16(a3a2), 2217); - const int32x4_t a2_2217 = vmull_n_s16(vget_high_s16(a3a2), 2217); - const int32x4_t a2_p_a3 = vmlal_n_s16(a2_2217, vget_low_s16(a3a2), 5352); - const int32x4_t a3_m_a2 = vmlsl_n_s16(a3_2217, vget_high_s16(a3a2), 5352); - const int16x4_t tmp1 = vshrn_n_s32(vaddq_s32(a2_p_a3, kCst1812), 9); - const int16x4_t tmp3 = vshrn_n_s32(vaddq_s32(a3_m_a2, kCst937), 9); - Transpose4x4_S16(tmp0, tmp1, tmp2, tmp3, &d0d1, &d3d2); - } - { // 2nd pass - // the (1<<16) addition is for the replacement: a3!=0 <-> 1-(a3==0) - const int32x4_t kCst12000 = vdupq_n_s32(12000 + (1 << 16)); - const int32x4_t kCst51000 = vdupq_n_s32(51000); - const int16x8_t a0a1 = vaddq_s16(d0d1, d3d2); // d0+d3 | d1+d2 (=a0|a1) - const int16x8_t a3a2 = vsubq_s16(d0d1, d3d2); // d0-d3 | d1-d2 (=a3|a2) - const int16x4_t a0_k7 = vadd_s16(vget_low_s16(a0a1), vdup_n_s16(7)); - const int16x4_t out0 = vshr_n_s16(vadd_s16(a0_k7, vget_high_s16(a0a1)), 4); - const int16x4_t out2 = vshr_n_s16(vsub_s16(a0_k7, vget_high_s16(a0a1)), 4); - const int32x4_t a3_2217 = vmull_n_s16(vget_low_s16(a3a2), 2217); - const int32x4_t a2_2217 = vmull_n_s16(vget_high_s16(a3a2), 2217); - const int32x4_t a2_p_a3 = vmlal_n_s16(a2_2217, vget_low_s16(a3a2), 5352); - const int32x4_t a3_m_a2 = vmlsl_n_s16(a3_2217, vget_high_s16(a3a2), 5352); - const int16x4_t tmp1 = vaddhn_s32(a2_p_a3, kCst12000); - const int16x4_t out3 = vaddhn_s32(a3_m_a2, kCst51000); - const int16x4_t a3_eq_0 = - vreinterpret_s16_u16(vceq_s16(vget_low_s16(a3a2), vdup_n_s16(0))); - const int16x4_t out1 = vadd_s16(tmp1, a3_eq_0); - vst1_s16(out + 0, out0); - vst1_s16(out + 4, out1); - vst1_s16(out + 8, out2); - vst1_s16(out + 12, out3); - } -} - -#else - -// adapted from vp8/encoder/arm/neon/shortfdct_neon.asm -static const int16_t kCoeff16[] = { - 5352, 5352, 5352, 5352, 2217, 2217, 2217, 2217 -}; -static const int32_t kCoeff32[] = { - 1812, 1812, 1812, 1812, - 937, 937, 937, 937, - 12000, 12000, 12000, 12000, - 51000, 51000, 51000, 51000 -}; - -static void FTransform(const uint8_t* src, const uint8_t* ref, - int16_t* out) { - const int kBPS = BPS; - const uint8_t* src_ptr = src; - const uint8_t* ref_ptr = ref; - const int16_t* coeff16 = kCoeff16; - const int32_t* coeff32 = kCoeff32; - - __asm__ volatile ( - // load src into q4, q5 in high half - "vld1.8 {d8}, [%[src_ptr]], %[kBPS] \n" - "vld1.8 {d10}, [%[src_ptr]], %[kBPS] \n" - "vld1.8 {d9}, [%[src_ptr]], %[kBPS] \n" - "vld1.8 {d11}, [%[src_ptr]] \n" - - // load ref into q6, q7 in high half - "vld1.8 {d12}, [%[ref_ptr]], %[kBPS] \n" - "vld1.8 {d14}, [%[ref_ptr]], %[kBPS] \n" - "vld1.8 {d13}, [%[ref_ptr]], %[kBPS] \n" - "vld1.8 {d15}, [%[ref_ptr]] \n" - - // Pack the high values in to q4 and q6 - "vtrn.32 q4, q5 \n" - "vtrn.32 q6, q7 \n" - - // d[0-3] = src - ref - "vsubl.u8 q0, d8, d12 \n" - "vsubl.u8 q1, d9, d13 \n" - - // load coeff16 into q8(d16=5352, d17=2217) - "vld1.16 {q8}, [%[coeff16]] \n" - - // load coeff32 high half into q9 = 1812, q10 = 937 - "vld1.32 {q9, q10}, [%[coeff32]]! \n" - - // load coeff32 low half into q11=12000, q12=51000 - "vld1.32 {q11,q12}, [%[coeff32]] \n" - - // part 1 - // Transpose. Register dN is the same as dN in C - "vtrn.32 d0, d2 \n" - "vtrn.32 d1, d3 \n" - "vtrn.16 d0, d1 \n" - "vtrn.16 d2, d3 \n" - - "vadd.s16 d4, d0, d3 \n" // a0 = d0 + d3 - "vadd.s16 d5, d1, d2 \n" // a1 = d1 + d2 - "vsub.s16 d6, d1, d2 \n" // a2 = d1 - d2 - "vsub.s16 d7, d0, d3 \n" // a3 = d0 - d3 - - "vadd.s16 d0, d4, d5 \n" // a0 + a1 - "vshl.s16 d0, d0, #3 \n" // temp[0+i*4] = (a0+a1) << 3 - "vsub.s16 d2, d4, d5 \n" // a0 - a1 - "vshl.s16 d2, d2, #3 \n" // (temp[2+i*4] = (a0-a1) << 3 - - "vmlal.s16 q9, d7, d16 \n" // a3*5352 + 1812 - "vmlal.s16 q10, d7, d17 \n" // a3*2217 + 937 - "vmlal.s16 q9, d6, d17 \n" // a2*2217 + a3*5352 + 1812 - "vmlsl.s16 q10, d6, d16 \n" // a3*2217 + 937 - a2*5352 - - // temp[1+i*4] = (d2*2217 + d3*5352 + 1812) >> 9 - // temp[3+i*4] = (d3*2217 + 937 - d2*5352) >> 9 - "vshrn.s32 d1, q9, #9 \n" - "vshrn.s32 d3, q10, #9 \n" - - // part 2 - // transpose d0=ip[0], d1=ip[4], d2=ip[8], d3=ip[12] - "vtrn.32 d0, d2 \n" - "vtrn.32 d1, d3 \n" - "vtrn.16 d0, d1 \n" - "vtrn.16 d2, d3 \n" - - "vmov.s16 d26, #7 \n" - - "vadd.s16 d4, d0, d3 \n" // a1 = ip[0] + ip[12] - "vadd.s16 d5, d1, d2 \n" // b1 = ip[4] + ip[8] - "vsub.s16 d6, d1, d2 \n" // c1 = ip[4] - ip[8] - "vadd.s16 d4, d4, d26 \n" // a1 + 7 - "vsub.s16 d7, d0, d3 \n" // d1 = ip[0] - ip[12] - - "vadd.s16 d0, d4, d5 \n" // op[0] = a1 + b1 + 7 - "vsub.s16 d2, d4, d5 \n" // op[8] = a1 - b1 + 7 - - "vmlal.s16 q11, d7, d16 \n" // d1*5352 + 12000 - "vmlal.s16 q12, d7, d17 \n" // d1*2217 + 51000 - - "vceq.s16 d4, d7, #0 \n" - - "vshr.s16 d0, d0, #4 \n" - "vshr.s16 d2, d2, #4 \n" - - "vmlal.s16 q11, d6, d17 \n" // c1*2217 + d1*5352 + 12000 - "vmlsl.s16 q12, d6, d16 \n" // d1*2217 - c1*5352 + 51000 - - "vmvn d4, d4 \n" // !(d1 == 0) - // op[4] = (c1*2217 + d1*5352 + 12000)>>16 - "vshrn.s32 d1, q11, #16 \n" - // op[4] += (d1!=0) - "vsub.s16 d1, d1, d4 \n" - // op[12]= (d1*2217 - c1*5352 + 51000)>>16 - "vshrn.s32 d3, q12, #16 \n" - - // set result to out array - "vst1.16 {q0, q1}, [%[out]] \n" - : [src_ptr] "+r"(src_ptr), [ref_ptr] "+r"(ref_ptr), - [coeff32] "+r"(coeff32) // modified registers - : [kBPS] "r"(kBPS), [coeff16] "r"(coeff16), - [out] "r"(out) // constants - : "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", - "q10", "q11", "q12", "q13" // clobbered - ); -} - -#endif - -#define LOAD_LANE_16b(VALUE, LANE) do { \ - (VALUE) = vld1_lane_s16(src, (VALUE), (LANE)); \ - src += stride; \ -} while (0) - -static void FTransformWHT(const int16_t* src, int16_t* out) { - const int stride = 16; - const int16x4_t zero = vdup_n_s16(0); - int32x4x4_t tmp0; - int16x4x4_t in; - INIT_VECTOR4(in, zero, zero, zero, zero); - LOAD_LANE_16b(in.val[0], 0); - LOAD_LANE_16b(in.val[1], 0); - LOAD_LANE_16b(in.val[2], 0); - LOAD_LANE_16b(in.val[3], 0); - LOAD_LANE_16b(in.val[0], 1); - LOAD_LANE_16b(in.val[1], 1); - LOAD_LANE_16b(in.val[2], 1); - LOAD_LANE_16b(in.val[3], 1); - LOAD_LANE_16b(in.val[0], 2); - LOAD_LANE_16b(in.val[1], 2); - LOAD_LANE_16b(in.val[2], 2); - LOAD_LANE_16b(in.val[3], 2); - LOAD_LANE_16b(in.val[0], 3); - LOAD_LANE_16b(in.val[1], 3); - LOAD_LANE_16b(in.val[2], 3); - LOAD_LANE_16b(in.val[3], 3); - - { - // a0 = in[0 * 16] + in[2 * 16] - // a1 = in[1 * 16] + in[3 * 16] - // a2 = in[1 * 16] - in[3 * 16] - // a3 = in[0 * 16] - in[2 * 16] - const int32x4_t a0 = vaddl_s16(in.val[0], in.val[2]); - const int32x4_t a1 = vaddl_s16(in.val[1], in.val[3]); - const int32x4_t a2 = vsubl_s16(in.val[1], in.val[3]); - const int32x4_t a3 = vsubl_s16(in.val[0], in.val[2]); - tmp0.val[0] = vaddq_s32(a0, a1); - tmp0.val[1] = vaddq_s32(a3, a2); - tmp0.val[2] = vsubq_s32(a3, a2); - tmp0.val[3] = vsubq_s32(a0, a1); - } - { - const int32x4x4_t tmp1 = Transpose4x4(tmp0); - // a0 = tmp[0 + i] + tmp[ 8 + i] - // a1 = tmp[4 + i] + tmp[12 + i] - // a2 = tmp[4 + i] - tmp[12 + i] - // a3 = tmp[0 + i] - tmp[ 8 + i] - const int32x4_t a0 = vaddq_s32(tmp1.val[0], tmp1.val[2]); - const int32x4_t a1 = vaddq_s32(tmp1.val[1], tmp1.val[3]); - const int32x4_t a2 = vsubq_s32(tmp1.val[1], tmp1.val[3]); - const int32x4_t a3 = vsubq_s32(tmp1.val[0], tmp1.val[2]); - const int32x4_t b0 = vhaddq_s32(a0, a1); // (a0 + a1) >> 1 - const int32x4_t b1 = vhaddq_s32(a3, a2); // (a3 + a2) >> 1 - const int32x4_t b2 = vhsubq_s32(a3, a2); // (a3 - a2) >> 1 - const int32x4_t b3 = vhsubq_s32(a0, a1); // (a0 - a1) >> 1 - const int16x4_t out0 = vmovn_s32(b0); - const int16x4_t out1 = vmovn_s32(b1); - const int16x4_t out2 = vmovn_s32(b2); - const int16x4_t out3 = vmovn_s32(b3); - - vst1_s16(out + 0, out0); - vst1_s16(out + 4, out1); - vst1_s16(out + 8, out2); - vst1_s16(out + 12, out3); - } -} -#undef LOAD_LANE_16b - -//------------------------------------------------------------------------------ -// Texture distortion -// -// We try to match the spectral content (weighted) between source and -// reconstructed samples. - -// a 0123, b 0123 -// a 4567, b 4567 -// a 89ab, b 89ab -// a cdef, b cdef -// -// transpose -// -// a 048c, b 048c -// a 159d, b 159d -// a 26ae, b 26ae -// a 37bf, b 37bf -// -static WEBP_INLINE uint8x8x4_t DistoTranspose4x4U8(uint8x8x4_t d4_in) { - const uint8x8x2_t d2_tmp0 = vtrn_u8(d4_in.val[0], d4_in.val[1]); - const uint8x8x2_t d2_tmp1 = vtrn_u8(d4_in.val[2], d4_in.val[3]); - const uint16x4x2_t d2_tmp2 = vtrn_u16(vreinterpret_u16_u8(d2_tmp0.val[0]), - vreinterpret_u16_u8(d2_tmp1.val[0])); - const uint16x4x2_t d2_tmp3 = vtrn_u16(vreinterpret_u16_u8(d2_tmp0.val[1]), - vreinterpret_u16_u8(d2_tmp1.val[1])); - - d4_in.val[0] = vreinterpret_u8_u16(d2_tmp2.val[0]); - d4_in.val[2] = vreinterpret_u8_u16(d2_tmp2.val[1]); - d4_in.val[1] = vreinterpret_u8_u16(d2_tmp3.val[0]); - d4_in.val[3] = vreinterpret_u8_u16(d2_tmp3.val[1]); - return d4_in; -} - -static WEBP_INLINE int16x8x4_t DistoTranspose4x4S16(int16x8x4_t q4_in) { - const int16x8x2_t q2_tmp0 = vtrnq_s16(q4_in.val[0], q4_in.val[1]); - const int16x8x2_t q2_tmp1 = vtrnq_s16(q4_in.val[2], q4_in.val[3]); - const int32x4x2_t q2_tmp2 = vtrnq_s32(vreinterpretq_s32_s16(q2_tmp0.val[0]), - vreinterpretq_s32_s16(q2_tmp1.val[0])); - const int32x4x2_t q2_tmp3 = vtrnq_s32(vreinterpretq_s32_s16(q2_tmp0.val[1]), - vreinterpretq_s32_s16(q2_tmp1.val[1])); - q4_in.val[0] = vreinterpretq_s16_s32(q2_tmp2.val[0]); - q4_in.val[2] = vreinterpretq_s16_s32(q2_tmp2.val[1]); - q4_in.val[1] = vreinterpretq_s16_s32(q2_tmp3.val[0]); - q4_in.val[3] = vreinterpretq_s16_s32(q2_tmp3.val[1]); - return q4_in; -} - -static WEBP_INLINE int16x8x4_t DistoHorizontalPass(const uint8x8x4_t d4_in) { - // {a0, a1} = {in[0] + in[2], in[1] + in[3]} - // {a3, a2} = {in[0] - in[2], in[1] - in[3]} - const int16x8_t q_a0 = vreinterpretq_s16_u16(vaddl_u8(d4_in.val[0], - d4_in.val[2])); - const int16x8_t q_a1 = vreinterpretq_s16_u16(vaddl_u8(d4_in.val[1], - d4_in.val[3])); - const int16x8_t q_a3 = vreinterpretq_s16_u16(vsubl_u8(d4_in.val[0], - d4_in.val[2])); - const int16x8_t q_a2 = vreinterpretq_s16_u16(vsubl_u8(d4_in.val[1], - d4_in.val[3])); - int16x8x4_t q4_out; - // tmp[0] = a0 + a1 - // tmp[1] = a3 + a2 - // tmp[2] = a3 - a2 - // tmp[3] = a0 - a1 - INIT_VECTOR4(q4_out, - vaddq_s16(q_a0, q_a1), vaddq_s16(q_a3, q_a2), - vsubq_s16(q_a3, q_a2), vsubq_s16(q_a0, q_a1)); - return q4_out; -} - -static WEBP_INLINE int16x8x4_t DistoVerticalPass(int16x8x4_t q4_in) { - const int16x8_t q_a0 = vaddq_s16(q4_in.val[0], q4_in.val[2]); - const int16x8_t q_a1 = vaddq_s16(q4_in.val[1], q4_in.val[3]); - const int16x8_t q_a2 = vsubq_s16(q4_in.val[1], q4_in.val[3]); - const int16x8_t q_a3 = vsubq_s16(q4_in.val[0], q4_in.val[2]); - - q4_in.val[0] = vaddq_s16(q_a0, q_a1); - q4_in.val[1] = vaddq_s16(q_a3, q_a2); - q4_in.val[2] = vabdq_s16(q_a3, q_a2); - q4_in.val[3] = vabdq_s16(q_a0, q_a1); - q4_in.val[0] = vabsq_s16(q4_in.val[0]); - q4_in.val[1] = vabsq_s16(q4_in.val[1]); - return q4_in; -} - -static WEBP_INLINE int16x4x4_t DistoLoadW(const uint16_t* w) { - const uint16x8_t q_w07 = vld1q_u16(&w[0]); - const uint16x8_t q_w8f = vld1q_u16(&w[8]); - int16x4x4_t d4_w; - INIT_VECTOR4(d4_w, - vget_low_s16(vreinterpretq_s16_u16(q_w07)), - vget_high_s16(vreinterpretq_s16_u16(q_w07)), - vget_low_s16(vreinterpretq_s16_u16(q_w8f)), - vget_high_s16(vreinterpretq_s16_u16(q_w8f))); - return d4_w; -} - -static WEBP_INLINE int32x2_t DistoSum(const int16x8x4_t q4_in, - const int16x4x4_t d4_w) { - int32x2_t d_sum; - // sum += w[ 0] * abs(b0); - // sum += w[ 4] * abs(b1); - // sum += w[ 8] * abs(b2); - // sum += w[12] * abs(b3); - int32x4_t q_sum0 = vmull_s16(d4_w.val[0], vget_low_s16(q4_in.val[0])); - int32x4_t q_sum1 = vmull_s16(d4_w.val[1], vget_low_s16(q4_in.val[1])); - int32x4_t q_sum2 = vmull_s16(d4_w.val[2], vget_low_s16(q4_in.val[2])); - int32x4_t q_sum3 = vmull_s16(d4_w.val[3], vget_low_s16(q4_in.val[3])); - q_sum0 = vmlsl_s16(q_sum0, d4_w.val[0], vget_high_s16(q4_in.val[0])); - q_sum1 = vmlsl_s16(q_sum1, d4_w.val[1], vget_high_s16(q4_in.val[1])); - q_sum2 = vmlsl_s16(q_sum2, d4_w.val[2], vget_high_s16(q4_in.val[2])); - q_sum3 = vmlsl_s16(q_sum3, d4_w.val[3], vget_high_s16(q4_in.val[3])); - - q_sum0 = vaddq_s32(q_sum0, q_sum1); - q_sum2 = vaddq_s32(q_sum2, q_sum3); - q_sum2 = vaddq_s32(q_sum0, q_sum2); - d_sum = vpadd_s32(vget_low_s32(q_sum2), vget_high_s32(q_sum2)); - d_sum = vpadd_s32(d_sum, d_sum); - return d_sum; -} - -#define LOAD_LANE_32b(src, VALUE, LANE) \ - (VALUE) = vld1_lane_u32((const uint32_t*)(src), (VALUE), (LANE)) - -// Hadamard transform -// Returns the weighted sum of the absolute value of transformed coefficients. -static int Disto4x4(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - uint32x2_t d_in_ab_0123 = vdup_n_u32(0); - uint32x2_t d_in_ab_4567 = vdup_n_u32(0); - uint32x2_t d_in_ab_89ab = vdup_n_u32(0); - uint32x2_t d_in_ab_cdef = vdup_n_u32(0); - uint8x8x4_t d4_in; - - // load data a, b - LOAD_LANE_32b(a + 0 * BPS, d_in_ab_0123, 0); - LOAD_LANE_32b(a + 1 * BPS, d_in_ab_4567, 0); - LOAD_LANE_32b(a + 2 * BPS, d_in_ab_89ab, 0); - LOAD_LANE_32b(a + 3 * BPS, d_in_ab_cdef, 0); - LOAD_LANE_32b(b + 0 * BPS, d_in_ab_0123, 1); - LOAD_LANE_32b(b + 1 * BPS, d_in_ab_4567, 1); - LOAD_LANE_32b(b + 2 * BPS, d_in_ab_89ab, 1); - LOAD_LANE_32b(b + 3 * BPS, d_in_ab_cdef, 1); - INIT_VECTOR4(d4_in, - vreinterpret_u8_u32(d_in_ab_0123), - vreinterpret_u8_u32(d_in_ab_4567), - vreinterpret_u8_u32(d_in_ab_89ab), - vreinterpret_u8_u32(d_in_ab_cdef)); - - { - // horizontal pass - const uint8x8x4_t d4_t = DistoTranspose4x4U8(d4_in); - const int16x8x4_t q4_h = DistoHorizontalPass(d4_t); - const int16x4x4_t d4_w = DistoLoadW(w); - // vertical pass - const int16x8x4_t q4_t = DistoTranspose4x4S16(q4_h); - const int16x8x4_t q4_v = DistoVerticalPass(q4_t); - int32x2_t d_sum = DistoSum(q4_v, d4_w); - - // abs(sum2 - sum1) >> 5 - d_sum = vabs_s32(d_sum); - d_sum = vshr_n_s32(d_sum, 5); - return vget_lane_s32(d_sum, 0); - } -} -#undef LOAD_LANE_32b - -static int Disto16x16(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - int D = 0; - int x, y; - for (y = 0; y < 16 * BPS; y += 4 * BPS) { - for (x = 0; x < 16; x += 4) { - D += Disto4x4(a + x + y, b + x + y, w); - } - } - return D; -} - -//------------------------------------------------------------------------------ - -static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, - int start_block, int end_block, - VP8Histogram* const histo) { - const uint16x8_t max_coeff_thresh = vdupq_n_u16(MAX_COEFF_THRESH); - int j; - int distribution[MAX_COEFF_THRESH + 1] = { 0 }; - for (j = start_block; j < end_block; ++j) { - int16_t out[16]; - FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); - { - int k; - const int16x8_t a0 = vld1q_s16(out + 0); - const int16x8_t b0 = vld1q_s16(out + 8); - const uint16x8_t a1 = vreinterpretq_u16_s16(vabsq_s16(a0)); - const uint16x8_t b1 = vreinterpretq_u16_s16(vabsq_s16(b0)); - const uint16x8_t a2 = vshrq_n_u16(a1, 3); - const uint16x8_t b2 = vshrq_n_u16(b1, 3); - const uint16x8_t a3 = vminq_u16(a2, max_coeff_thresh); - const uint16x8_t b3 = vminq_u16(b2, max_coeff_thresh); - vst1q_s16(out + 0, vreinterpretq_s16_u16(a3)); - vst1q_s16(out + 8, vreinterpretq_s16_u16(b3)); - // Convert coefficients to bin. - for (k = 0; k < 16; ++k) { - ++distribution[out[k]]; - } - } - } - VP8SetHistogramData(distribution, histo); -} - -//------------------------------------------------------------------------------ - -static WEBP_INLINE void AccumulateSSE16(const uint8_t* const a, - const uint8_t* const b, - uint32x4_t* const sum) { - const uint8x16_t a0 = vld1q_u8(a); - const uint8x16_t b0 = vld1q_u8(b); - const uint8x16_t abs_diff = vabdq_u8(a0, b0); - uint16x8_t prod = vmull_u8(vget_low_u8(abs_diff), vget_low_u8(abs_diff)); - prod = vmlal_u8(prod, vget_high_u8(abs_diff), vget_high_u8(abs_diff)); - *sum = vpadalq_u16(*sum, prod); // pair-wise add and accumulate -} - -// Horizontal sum of all four uint32_t values in 'sum'. -static int SumToInt(uint32x4_t sum) { - const uint64x2_t sum2 = vpaddlq_u32(sum); - const uint64_t sum3 = vgetq_lane_u64(sum2, 0) + vgetq_lane_u64(sum2, 1); - return (int)sum3; -} - -static int SSE16x16(const uint8_t* a, const uint8_t* b) { - uint32x4_t sum = vdupq_n_u32(0); - int y; - for (y = 0; y < 16; ++y) { - AccumulateSSE16(a + y * BPS, b + y * BPS, &sum); - } - return SumToInt(sum); -} - -static int SSE16x8(const uint8_t* a, const uint8_t* b) { - uint32x4_t sum = vdupq_n_u32(0); - int y; - for (y = 0; y < 8; ++y) { - AccumulateSSE16(a + y * BPS, b + y * BPS, &sum); - } - return SumToInt(sum); -} - -static int SSE8x8(const uint8_t* a, const uint8_t* b) { - uint32x4_t sum = vdupq_n_u32(0); - int y; - for (y = 0; y < 8; ++y) { - const uint8x8_t a0 = vld1_u8(a + y * BPS); - const uint8x8_t b0 = vld1_u8(b + y * BPS); - const uint8x8_t abs_diff = vabd_u8(a0, b0); - const uint16x8_t prod = vmull_u8(abs_diff, abs_diff); - sum = vpadalq_u16(sum, prod); - } - return SumToInt(sum); -} - -static int SSE4x4(const uint8_t* a, const uint8_t* b) { - const uint8x16_t a0 = Load4x4(a); - const uint8x16_t b0 = Load4x4(b); - const uint8x16_t abs_diff = vabdq_u8(a0, b0); - uint16x8_t prod = vmull_u8(vget_low_u8(abs_diff), vget_low_u8(abs_diff)); - prod = vmlal_u8(prod, vget_high_u8(abs_diff), vget_high_u8(abs_diff)); - return SumToInt(vpaddlq_u16(prod)); -} - -//------------------------------------------------------------------------------ - -// Compilation with gcc-4.6.x is problematic for now. -#if !defined(WORK_AROUND_GCC) - -static int16x8_t Quantize(int16_t* const in, - const VP8Matrix* const mtx, int offset) { - const uint16x8_t sharp = vld1q_u16(&mtx->sharpen_[offset]); - const uint16x8_t q = vld1q_u16(&mtx->q_[offset]); - const uint16x8_t iq = vld1q_u16(&mtx->iq_[offset]); - const uint32x4_t bias0 = vld1q_u32(&mtx->bias_[offset + 0]); - const uint32x4_t bias1 = vld1q_u32(&mtx->bias_[offset + 4]); - - const int16x8_t a = vld1q_s16(in + offset); // in - const uint16x8_t b = vreinterpretq_u16_s16(vabsq_s16(a)); // coeff = abs(in) - const int16x8_t sign = vshrq_n_s16(a, 15); // sign - const uint16x8_t c = vaddq_u16(b, sharp); // + sharpen - const uint32x4_t m0 = vmull_u16(vget_low_u16(c), vget_low_u16(iq)); - const uint32x4_t m1 = vmull_u16(vget_high_u16(c), vget_high_u16(iq)); - const uint32x4_t m2 = vhaddq_u32(m0, bias0); - const uint32x4_t m3 = vhaddq_u32(m1, bias1); // (coeff * iQ + bias) >> 1 - const uint16x8_t c0 = vcombine_u16(vshrn_n_u32(m2, 16), - vshrn_n_u32(m3, 16)); // QFIX=17 = 16+1 - const uint16x8_t c1 = vminq_u16(c0, vdupq_n_u16(MAX_LEVEL)); - const int16x8_t c2 = veorq_s16(vreinterpretq_s16_u16(c1), sign); - const int16x8_t c3 = vsubq_s16(c2, sign); // restore sign - const int16x8_t c4 = vmulq_s16(c3, vreinterpretq_s16_u16(q)); - vst1q_s16(in + offset, c4); - assert(QFIX == 17); // this function can't work as is if QFIX != 16+1 - return c3; -} - -static const uint8_t kShuffles[4][8] = { - { 0, 1, 2, 3, 8, 9, 16, 17 }, - { 10, 11, 4, 5, 6, 7, 12, 13 }, - { 18, 19, 24, 25, 26, 27, 20, 21 }, - { 14, 15, 22, 23, 28, 29, 30, 31 } -}; - -static int QuantizeBlock(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - const int16x8_t out0 = Quantize(in, mtx, 0); - const int16x8_t out1 = Quantize(in, mtx, 8); - uint8x8x4_t shuffles; - // vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use - // non-standard versions there. -#if defined(__APPLE__) && defined(__aarch64__) && \ - defined(__apple_build_version__) && (__apple_build_version__< 6020037) - uint8x16x2_t all_out; - INIT_VECTOR2(all_out, vreinterpretq_u8_s16(out0), vreinterpretq_u8_s16(out1)); - INIT_VECTOR4(shuffles, - vtbl2q_u8(all_out, vld1_u8(kShuffles[0])), - vtbl2q_u8(all_out, vld1_u8(kShuffles[1])), - vtbl2q_u8(all_out, vld1_u8(kShuffles[2])), - vtbl2q_u8(all_out, vld1_u8(kShuffles[3]))); -#else - uint8x8x4_t all_out; - INIT_VECTOR4(all_out, - vreinterpret_u8_s16(vget_low_s16(out0)), - vreinterpret_u8_s16(vget_high_s16(out0)), - vreinterpret_u8_s16(vget_low_s16(out1)), - vreinterpret_u8_s16(vget_high_s16(out1))); - INIT_VECTOR4(shuffles, - vtbl4_u8(all_out, vld1_u8(kShuffles[0])), - vtbl4_u8(all_out, vld1_u8(kShuffles[1])), - vtbl4_u8(all_out, vld1_u8(kShuffles[2])), - vtbl4_u8(all_out, vld1_u8(kShuffles[3]))); -#endif - // Zigzag reordering - vst1_u8((uint8_t*)(out + 0), shuffles.val[0]); - vst1_u8((uint8_t*)(out + 4), shuffles.val[1]); - vst1_u8((uint8_t*)(out + 8), shuffles.val[2]); - vst1_u8((uint8_t*)(out + 12), shuffles.val[3]); - // test zeros - if (*(uint64_t*)(out + 0) != 0) return 1; - if (*(uint64_t*)(out + 4) != 0) return 1; - if (*(uint64_t*)(out + 8) != 0) return 1; - if (*(uint64_t*)(out + 12) != 0) return 1; - return 0; -} - -static int Quantize2Blocks(int16_t in[32], int16_t out[32], - const VP8Matrix* const mtx) { - int nz; - nz = QuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0; - nz |= QuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1; - return nz; -} - -#endif // !WORK_AROUND_GCC - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8EncDspInitNEON(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitNEON(void) { - VP8ITransform = ITransform; - VP8FTransform = FTransform; - - VP8FTransformWHT = FTransformWHT; - - VP8TDisto4x4 = Disto4x4; - VP8TDisto16x16 = Disto16x16; - VP8CollectHistogram = CollectHistogram; - VP8SSE16x16 = SSE16x16; - VP8SSE16x8 = SSE16x8; - VP8SSE8x8 = SSE8x8; - VP8SSE4x4 = SSE4x4; -#if !defined(WORK_AROUND_GCC) - VP8EncQuantizeBlock = QuantizeBlock; - VP8EncQuantize2Blocks = Quantize2Blocks; -#endif -} - -#else // !WEBP_USE_NEON - -WEBP_DSP_INIT_STUB(VP8EncDspInitNEON) - -#endif // WEBP_USE_NEON diff --git a/Example-Mac/Pods/libwebp/src/dsp/enc_sse2.c b/Example-Mac/Pods/libwebp/src/dsp/enc_sse2.c deleted file mode 100644 index 2333d2b0..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/enc_sse2.c +++ /dev/null @@ -1,1468 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// SSE2 version of speed-critical encoding functions. -// -// Author: Christian Duvivier (cduvivier@google.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE2) -#include // for abs() -#include - -#include "../enc/cost.h" -#include "../enc/vp8enci.h" - -//------------------------------------------------------------------------------ -// Quite useful macro for debugging. Left here for convenience. - -#if 0 -#include -static void PrintReg(const __m128i r, const char* const name, int size) { - int n; - union { - __m128i r; - uint8_t i8[16]; - uint16_t i16[8]; - uint32_t i32[4]; - uint64_t i64[2]; - } tmp; - tmp.r = r; - fprintf(stderr, "%s\t: ", name); - if (size == 8) { - for (n = 0; n < 16; ++n) fprintf(stderr, "%.2x ", tmp.i8[n]); - } else if (size == 16) { - for (n = 0; n < 8; ++n) fprintf(stderr, "%.4x ", tmp.i16[n]); - } else if (size == 32) { - for (n = 0; n < 4; ++n) fprintf(stderr, "%.8x ", tmp.i32[n]); - } else { - for (n = 0; n < 2; ++n) fprintf(stderr, "%.16lx ", tmp.i64[n]); - } - fprintf(stderr, "\n"); -} -#endif - -//------------------------------------------------------------------------------ -// Transforms (Paragraph 14.4) - -// Does one or two inverse transforms. -static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst, - int do_two) { - // This implementation makes use of 16-bit fixed point versions of two - // multiply constants: - // K1 = sqrt(2) * cos (pi/8) ~= 85627 / 2^16 - // K2 = sqrt(2) * sin (pi/8) ~= 35468 / 2^16 - // - // To be able to use signed 16-bit integers, we use the following trick to - // have constants within range: - // - Associated constants are obtained by subtracting the 16-bit fixed point - // version of one: - // k = K - (1 << 16) => K = k + (1 << 16) - // K1 = 85267 => k1 = 20091 - // K2 = 35468 => k2 = -30068 - // - The multiplication of a variable by a constant become the sum of the - // variable and the multiplication of that variable by the associated - // constant: - // (x * K) >> 16 = (x * (k + (1 << 16))) >> 16 = ((x * k ) >> 16) + x - const __m128i k1 = _mm_set1_epi16(20091); - const __m128i k2 = _mm_set1_epi16(-30068); - __m128i T0, T1, T2, T3; - - // Load and concatenate the transform coefficients (we'll do two inverse - // transforms in parallel). In the case of only one inverse transform, the - // second half of the vectors will just contain random value we'll never - // use nor store. - __m128i in0, in1, in2, in3; - { - in0 = _mm_loadl_epi64((const __m128i*)&in[0]); - in1 = _mm_loadl_epi64((const __m128i*)&in[4]); - in2 = _mm_loadl_epi64((const __m128i*)&in[8]); - in3 = _mm_loadl_epi64((const __m128i*)&in[12]); - // a00 a10 a20 a30 x x x x - // a01 a11 a21 a31 x x x x - // a02 a12 a22 a32 x x x x - // a03 a13 a23 a33 x x x x - if (do_two) { - const __m128i inB0 = _mm_loadl_epi64((const __m128i*)&in[16]); - const __m128i inB1 = _mm_loadl_epi64((const __m128i*)&in[20]); - const __m128i inB2 = _mm_loadl_epi64((const __m128i*)&in[24]); - const __m128i inB3 = _mm_loadl_epi64((const __m128i*)&in[28]); - in0 = _mm_unpacklo_epi64(in0, inB0); - in1 = _mm_unpacklo_epi64(in1, inB1); - in2 = _mm_unpacklo_epi64(in2, inB2); - in3 = _mm_unpacklo_epi64(in3, inB3); - // a00 a10 a20 a30 b00 b10 b20 b30 - // a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 - // a03 a13 a23 a33 b03 b13 b23 b33 - } - } - - // Vertical pass and subsequent transpose. - { - // First pass, c and d calculations are longer because of the "trick" - // multiplications. - const __m128i a = _mm_add_epi16(in0, in2); - const __m128i b = _mm_sub_epi16(in0, in2); - // c = MUL(in1, K2) - MUL(in3, K1) = MUL(in1, k2) - MUL(in3, k1) + in1 - in3 - const __m128i c1 = _mm_mulhi_epi16(in1, k2); - const __m128i c2 = _mm_mulhi_epi16(in3, k1); - const __m128i c3 = _mm_sub_epi16(in1, in3); - const __m128i c4 = _mm_sub_epi16(c1, c2); - const __m128i c = _mm_add_epi16(c3, c4); - // d = MUL(in1, K1) + MUL(in3, K2) = MUL(in1, k1) + MUL(in3, k2) + in1 + in3 - const __m128i d1 = _mm_mulhi_epi16(in1, k1); - const __m128i d2 = _mm_mulhi_epi16(in3, k2); - const __m128i d3 = _mm_add_epi16(in1, in3); - const __m128i d4 = _mm_add_epi16(d1, d2); - const __m128i d = _mm_add_epi16(d3, d4); - - // Second pass. - const __m128i tmp0 = _mm_add_epi16(a, d); - const __m128i tmp1 = _mm_add_epi16(b, c); - const __m128i tmp2 = _mm_sub_epi16(b, c); - const __m128i tmp3 = _mm_sub_epi16(a, d); - - // Transpose the two 4x4. - // a00 a01 a02 a03 b00 b01 b02 b03 - // a10 a11 a12 a13 b10 b11 b12 b13 - // a20 a21 a22 a23 b20 b21 b22 b23 - // a30 a31 a32 a33 b30 b31 b32 b33 - const __m128i transpose0_0 = _mm_unpacklo_epi16(tmp0, tmp1); - const __m128i transpose0_1 = _mm_unpacklo_epi16(tmp2, tmp3); - const __m128i transpose0_2 = _mm_unpackhi_epi16(tmp0, tmp1); - const __m128i transpose0_3 = _mm_unpackhi_epi16(tmp2, tmp3); - // a00 a10 a01 a11 a02 a12 a03 a13 - // a20 a30 a21 a31 a22 a32 a23 a33 - // b00 b10 b01 b11 b02 b12 b03 b13 - // b20 b30 b21 b31 b22 b32 b23 b33 - const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3); - const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3); - // a00 a10 a20 a30 a01 a11 a21 a31 - // b00 b10 b20 b30 b01 b11 b21 b31 - // a02 a12 a22 a32 a03 a13 a23 a33 - // b02 b12 a22 b32 b03 b13 b23 b33 - T0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1); - T1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1); - T2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3); - T3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3); - // a00 a10 a20 a30 b00 b10 b20 b30 - // a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 - // a03 a13 a23 a33 b03 b13 b23 b33 - } - - // Horizontal pass and subsequent transpose. - { - // First pass, c and d calculations are longer because of the "trick" - // multiplications. - const __m128i four = _mm_set1_epi16(4); - const __m128i dc = _mm_add_epi16(T0, four); - const __m128i a = _mm_add_epi16(dc, T2); - const __m128i b = _mm_sub_epi16(dc, T2); - // c = MUL(T1, K2) - MUL(T3, K1) = MUL(T1, k2) - MUL(T3, k1) + T1 - T3 - const __m128i c1 = _mm_mulhi_epi16(T1, k2); - const __m128i c2 = _mm_mulhi_epi16(T3, k1); - const __m128i c3 = _mm_sub_epi16(T1, T3); - const __m128i c4 = _mm_sub_epi16(c1, c2); - const __m128i c = _mm_add_epi16(c3, c4); - // d = MUL(T1, K1) + MUL(T3, K2) = MUL(T1, k1) + MUL(T3, k2) + T1 + T3 - const __m128i d1 = _mm_mulhi_epi16(T1, k1); - const __m128i d2 = _mm_mulhi_epi16(T3, k2); - const __m128i d3 = _mm_add_epi16(T1, T3); - const __m128i d4 = _mm_add_epi16(d1, d2); - const __m128i d = _mm_add_epi16(d3, d4); - - // Second pass. - const __m128i tmp0 = _mm_add_epi16(a, d); - const __m128i tmp1 = _mm_add_epi16(b, c); - const __m128i tmp2 = _mm_sub_epi16(b, c); - const __m128i tmp3 = _mm_sub_epi16(a, d); - const __m128i shifted0 = _mm_srai_epi16(tmp0, 3); - const __m128i shifted1 = _mm_srai_epi16(tmp1, 3); - const __m128i shifted2 = _mm_srai_epi16(tmp2, 3); - const __m128i shifted3 = _mm_srai_epi16(tmp3, 3); - - // Transpose the two 4x4. - // a00 a01 a02 a03 b00 b01 b02 b03 - // a10 a11 a12 a13 b10 b11 b12 b13 - // a20 a21 a22 a23 b20 b21 b22 b23 - // a30 a31 a32 a33 b30 b31 b32 b33 - const __m128i transpose0_0 = _mm_unpacklo_epi16(shifted0, shifted1); - const __m128i transpose0_1 = _mm_unpacklo_epi16(shifted2, shifted3); - const __m128i transpose0_2 = _mm_unpackhi_epi16(shifted0, shifted1); - const __m128i transpose0_3 = _mm_unpackhi_epi16(shifted2, shifted3); - // a00 a10 a01 a11 a02 a12 a03 a13 - // a20 a30 a21 a31 a22 a32 a23 a33 - // b00 b10 b01 b11 b02 b12 b03 b13 - // b20 b30 b21 b31 b22 b32 b23 b33 - const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3); - const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3); - // a00 a10 a20 a30 a01 a11 a21 a31 - // b00 b10 b20 b30 b01 b11 b21 b31 - // a02 a12 a22 a32 a03 a13 a23 a33 - // b02 b12 a22 b32 b03 b13 b23 b33 - T0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1); - T1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1); - T2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3); - T3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3); - // a00 a10 a20 a30 b00 b10 b20 b30 - // a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 - // a03 a13 a23 a33 b03 b13 b23 b33 - } - - // Add inverse transform to 'ref' and store. - { - const __m128i zero = _mm_setzero_si128(); - // Load the reference(s). - __m128i ref0, ref1, ref2, ref3; - if (do_two) { - // Load eight bytes/pixels per line. - ref0 = _mm_loadl_epi64((const __m128i*)&ref[0 * BPS]); - ref1 = _mm_loadl_epi64((const __m128i*)&ref[1 * BPS]); - ref2 = _mm_loadl_epi64((const __m128i*)&ref[2 * BPS]); - ref3 = _mm_loadl_epi64((const __m128i*)&ref[3 * BPS]); - } else { - // Load four bytes/pixels per line. - ref0 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[0 * BPS])); - ref1 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[1 * BPS])); - ref2 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[2 * BPS])); - ref3 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[3 * BPS])); - } - // Convert to 16b. - ref0 = _mm_unpacklo_epi8(ref0, zero); - ref1 = _mm_unpacklo_epi8(ref1, zero); - ref2 = _mm_unpacklo_epi8(ref2, zero); - ref3 = _mm_unpacklo_epi8(ref3, zero); - // Add the inverse transform(s). - ref0 = _mm_add_epi16(ref0, T0); - ref1 = _mm_add_epi16(ref1, T1); - ref2 = _mm_add_epi16(ref2, T2); - ref3 = _mm_add_epi16(ref3, T3); - // Unsigned saturate to 8b. - ref0 = _mm_packus_epi16(ref0, ref0); - ref1 = _mm_packus_epi16(ref1, ref1); - ref2 = _mm_packus_epi16(ref2, ref2); - ref3 = _mm_packus_epi16(ref3, ref3); - // Store the results. - if (do_two) { - // Store eight bytes/pixels per line. - _mm_storel_epi64((__m128i*)&dst[0 * BPS], ref0); - _mm_storel_epi64((__m128i*)&dst[1 * BPS], ref1); - _mm_storel_epi64((__m128i*)&dst[2 * BPS], ref2); - _mm_storel_epi64((__m128i*)&dst[3 * BPS], ref3); - } else { - // Store four bytes/pixels per line. - WebPUint32ToMem(&dst[0 * BPS], _mm_cvtsi128_si32(ref0)); - WebPUint32ToMem(&dst[1 * BPS], _mm_cvtsi128_si32(ref1)); - WebPUint32ToMem(&dst[2 * BPS], _mm_cvtsi128_si32(ref2)); - WebPUint32ToMem(&dst[3 * BPS], _mm_cvtsi128_si32(ref3)); - } - } -} - -static void FTransformPass1(const __m128i* const in01, - const __m128i* const in23, - __m128i* const out01, - __m128i* const out32) { - const __m128i k937 = _mm_set1_epi32(937); - const __m128i k1812 = _mm_set1_epi32(1812); - - const __m128i k88p = _mm_set_epi16(8, 8, 8, 8, 8, 8, 8, 8); - const __m128i k88m = _mm_set_epi16(-8, 8, -8, 8, -8, 8, -8, 8); - const __m128i k5352_2217p = _mm_set_epi16(2217, 5352, 2217, 5352, - 2217, 5352, 2217, 5352); - const __m128i k5352_2217m = _mm_set_epi16(-5352, 2217, -5352, 2217, - -5352, 2217, -5352, 2217); - - // *in01 = 00 01 10 11 02 03 12 13 - // *in23 = 20 21 30 31 22 23 32 33 - const __m128i shuf01_p = _mm_shufflehi_epi16(*in01, _MM_SHUFFLE(2, 3, 0, 1)); - const __m128i shuf23_p = _mm_shufflehi_epi16(*in23, _MM_SHUFFLE(2, 3, 0, 1)); - // 00 01 10 11 03 02 13 12 - // 20 21 30 31 23 22 33 32 - const __m128i s01 = _mm_unpacklo_epi64(shuf01_p, shuf23_p); - const __m128i s32 = _mm_unpackhi_epi64(shuf01_p, shuf23_p); - // 00 01 10 11 20 21 30 31 - // 03 02 13 12 23 22 33 32 - const __m128i a01 = _mm_add_epi16(s01, s32); - const __m128i a32 = _mm_sub_epi16(s01, s32); - // [d0 + d3 | d1 + d2 | ...] = [a0 a1 | a0' a1' | ... ] - // [d0 - d3 | d1 - d2 | ...] = [a3 a2 | a3' a2' | ... ] - - const __m128i tmp0 = _mm_madd_epi16(a01, k88p); // [ (a0 + a1) << 3, ... ] - const __m128i tmp2 = _mm_madd_epi16(a01, k88m); // [ (a0 - a1) << 3, ... ] - const __m128i tmp1_1 = _mm_madd_epi16(a32, k5352_2217p); - const __m128i tmp3_1 = _mm_madd_epi16(a32, k5352_2217m); - const __m128i tmp1_2 = _mm_add_epi32(tmp1_1, k1812); - const __m128i tmp3_2 = _mm_add_epi32(tmp3_1, k937); - const __m128i tmp1 = _mm_srai_epi32(tmp1_2, 9); - const __m128i tmp3 = _mm_srai_epi32(tmp3_2, 9); - const __m128i s03 = _mm_packs_epi32(tmp0, tmp2); - const __m128i s12 = _mm_packs_epi32(tmp1, tmp3); - const __m128i s_lo = _mm_unpacklo_epi16(s03, s12); // 0 1 0 1 0 1... - const __m128i s_hi = _mm_unpackhi_epi16(s03, s12); // 2 3 2 3 2 3 - const __m128i v23 = _mm_unpackhi_epi32(s_lo, s_hi); - *out01 = _mm_unpacklo_epi32(s_lo, s_hi); - *out32 = _mm_shuffle_epi32(v23, _MM_SHUFFLE(1, 0, 3, 2)); // 3 2 3 2 3 2.. -} - -static void FTransformPass2(const __m128i* const v01, const __m128i* const v32, - int16_t* out) { - const __m128i zero = _mm_setzero_si128(); - const __m128i seven = _mm_set1_epi16(7); - const __m128i k5352_2217 = _mm_set_epi16(5352, 2217, 5352, 2217, - 5352, 2217, 5352, 2217); - const __m128i k2217_5352 = _mm_set_epi16(2217, -5352, 2217, -5352, - 2217, -5352, 2217, -5352); - const __m128i k12000_plus_one = _mm_set1_epi32(12000 + (1 << 16)); - const __m128i k51000 = _mm_set1_epi32(51000); - - // Same operations are done on the (0,3) and (1,2) pairs. - // a0 = v0 + v3 - // a1 = v1 + v2 - // a3 = v0 - v3 - // a2 = v1 - v2 - const __m128i a01 = _mm_add_epi16(*v01, *v32); - const __m128i a32 = _mm_sub_epi16(*v01, *v32); - const __m128i a11 = _mm_unpackhi_epi64(a01, a01); - const __m128i a22 = _mm_unpackhi_epi64(a32, a32); - const __m128i a01_plus_7 = _mm_add_epi16(a01, seven); - - // d0 = (a0 + a1 + 7) >> 4; - // d2 = (a0 - a1 + 7) >> 4; - const __m128i c0 = _mm_add_epi16(a01_plus_7, a11); - const __m128i c2 = _mm_sub_epi16(a01_plus_7, a11); - const __m128i d0 = _mm_srai_epi16(c0, 4); - const __m128i d2 = _mm_srai_epi16(c2, 4); - - // f1 = ((b3 * 5352 + b2 * 2217 + 12000) >> 16) - // f3 = ((b3 * 2217 - b2 * 5352 + 51000) >> 16) - const __m128i b23 = _mm_unpacklo_epi16(a22, a32); - const __m128i c1 = _mm_madd_epi16(b23, k5352_2217); - const __m128i c3 = _mm_madd_epi16(b23, k2217_5352); - const __m128i d1 = _mm_add_epi32(c1, k12000_plus_one); - const __m128i d3 = _mm_add_epi32(c3, k51000); - const __m128i e1 = _mm_srai_epi32(d1, 16); - const __m128i e3 = _mm_srai_epi32(d3, 16); - const __m128i f1 = _mm_packs_epi32(e1, e1); - const __m128i f3 = _mm_packs_epi32(e3, e3); - // f1 = f1 + (a3 != 0); - // The compare will return (0xffff, 0) for (==0, !=0). To turn that into the - // desired (0, 1), we add one earlier through k12000_plus_one. - // -> f1 = f1 + 1 - (a3 == 0) - const __m128i g1 = _mm_add_epi16(f1, _mm_cmpeq_epi16(a32, zero)); - - const __m128i d0_g1 = _mm_unpacklo_epi64(d0, g1); - const __m128i d2_f3 = _mm_unpacklo_epi64(d2, f3); - _mm_storeu_si128((__m128i*)&out[0], d0_g1); - _mm_storeu_si128((__m128i*)&out[8], d2_f3); -} - -static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) { - const __m128i zero = _mm_setzero_si128(); - - // Load src and convert to 16b. - const __m128i src0 = _mm_loadl_epi64((const __m128i*)&src[0 * BPS]); - const __m128i src1 = _mm_loadl_epi64((const __m128i*)&src[1 * BPS]); - const __m128i src2 = _mm_loadl_epi64((const __m128i*)&src[2 * BPS]); - const __m128i src3 = _mm_loadl_epi64((const __m128i*)&src[3 * BPS]); - const __m128i src_0 = _mm_unpacklo_epi8(src0, zero); - const __m128i src_1 = _mm_unpacklo_epi8(src1, zero); - const __m128i src_2 = _mm_unpacklo_epi8(src2, zero); - const __m128i src_3 = _mm_unpacklo_epi8(src3, zero); - // Load ref and convert to 16b. - const __m128i ref0 = _mm_loadl_epi64((const __m128i*)&ref[0 * BPS]); - const __m128i ref1 = _mm_loadl_epi64((const __m128i*)&ref[1 * BPS]); - const __m128i ref2 = _mm_loadl_epi64((const __m128i*)&ref[2 * BPS]); - const __m128i ref3 = _mm_loadl_epi64((const __m128i*)&ref[3 * BPS]); - const __m128i ref_0 = _mm_unpacklo_epi8(ref0, zero); - const __m128i ref_1 = _mm_unpacklo_epi8(ref1, zero); - const __m128i ref_2 = _mm_unpacklo_epi8(ref2, zero); - const __m128i ref_3 = _mm_unpacklo_epi8(ref3, zero); - // Compute difference. -> 00 01 02 03 00 00 00 00 - const __m128i diff0 = _mm_sub_epi16(src_0, ref_0); - const __m128i diff1 = _mm_sub_epi16(src_1, ref_1); - const __m128i diff2 = _mm_sub_epi16(src_2, ref_2); - const __m128i diff3 = _mm_sub_epi16(src_3, ref_3); - - // Unpack and shuffle - // 00 01 02 03 0 0 0 0 - // 10 11 12 13 0 0 0 0 - // 20 21 22 23 0 0 0 0 - // 30 31 32 33 0 0 0 0 - const __m128i shuf01 = _mm_unpacklo_epi32(diff0, diff1); - const __m128i shuf23 = _mm_unpacklo_epi32(diff2, diff3); - __m128i v01, v32; - - // First pass - FTransformPass1(&shuf01, &shuf23, &v01, &v32); - - // Second pass - FTransformPass2(&v01, &v32, out); -} - -static void FTransform2(const uint8_t* src, const uint8_t* ref, int16_t* out) { - const __m128i zero = _mm_setzero_si128(); - - // Load src and convert to 16b. - const __m128i src0 = _mm_loadl_epi64((const __m128i*)&src[0 * BPS]); - const __m128i src1 = _mm_loadl_epi64((const __m128i*)&src[1 * BPS]); - const __m128i src2 = _mm_loadl_epi64((const __m128i*)&src[2 * BPS]); - const __m128i src3 = _mm_loadl_epi64((const __m128i*)&src[3 * BPS]); - const __m128i src_0 = _mm_unpacklo_epi8(src0, zero); - const __m128i src_1 = _mm_unpacklo_epi8(src1, zero); - const __m128i src_2 = _mm_unpacklo_epi8(src2, zero); - const __m128i src_3 = _mm_unpacklo_epi8(src3, zero); - // Load ref and convert to 16b. - const __m128i ref0 = _mm_loadl_epi64((const __m128i*)&ref[0 * BPS]); - const __m128i ref1 = _mm_loadl_epi64((const __m128i*)&ref[1 * BPS]); - const __m128i ref2 = _mm_loadl_epi64((const __m128i*)&ref[2 * BPS]); - const __m128i ref3 = _mm_loadl_epi64((const __m128i*)&ref[3 * BPS]); - const __m128i ref_0 = _mm_unpacklo_epi8(ref0, zero); - const __m128i ref_1 = _mm_unpacklo_epi8(ref1, zero); - const __m128i ref_2 = _mm_unpacklo_epi8(ref2, zero); - const __m128i ref_3 = _mm_unpacklo_epi8(ref3, zero); - // Compute difference. -> 00 01 02 03 00' 01' 02' 03' - const __m128i diff0 = _mm_sub_epi16(src_0, ref_0); - const __m128i diff1 = _mm_sub_epi16(src_1, ref_1); - const __m128i diff2 = _mm_sub_epi16(src_2, ref_2); - const __m128i diff3 = _mm_sub_epi16(src_3, ref_3); - - // Unpack and shuffle - // 00 01 02 03 0 0 0 0 - // 10 11 12 13 0 0 0 0 - // 20 21 22 23 0 0 0 0 - // 30 31 32 33 0 0 0 0 - const __m128i shuf01l = _mm_unpacklo_epi32(diff0, diff1); - const __m128i shuf23l = _mm_unpacklo_epi32(diff2, diff3); - const __m128i shuf01h = _mm_unpackhi_epi32(diff0, diff1); - const __m128i shuf23h = _mm_unpackhi_epi32(diff2, diff3); - __m128i v01l, v32l; - __m128i v01h, v32h; - - // First pass - FTransformPass1(&shuf01l, &shuf23l, &v01l, &v32l); - FTransformPass1(&shuf01h, &shuf23h, &v01h, &v32h); - - // Second pass - FTransformPass2(&v01l, &v32l, out + 0); - FTransformPass2(&v01h, &v32h, out + 16); -} - -static void FTransformWHTRow(const int16_t* const in, __m128i* const out) { - const __m128i kMult1 = _mm_set_epi16(0, 0, 0, 0, 1, 1, 1, 1); - const __m128i kMult2 = _mm_set_epi16(0, 0, 0, 0, -1, 1, -1, 1); - const __m128i src0 = _mm_loadl_epi64((__m128i*)&in[0 * 16]); - const __m128i src1 = _mm_loadl_epi64((__m128i*)&in[1 * 16]); - const __m128i src2 = _mm_loadl_epi64((__m128i*)&in[2 * 16]); - const __m128i src3 = _mm_loadl_epi64((__m128i*)&in[3 * 16]); - const __m128i A01 = _mm_unpacklo_epi16(src0, src1); // A0 A1 | ... - const __m128i A23 = _mm_unpacklo_epi16(src2, src3); // A2 A3 | ... - const __m128i B0 = _mm_adds_epi16(A01, A23); // a0 | a1 | ... - const __m128i B1 = _mm_subs_epi16(A01, A23); // a3 | a2 | ... - const __m128i C0 = _mm_unpacklo_epi32(B0, B1); // a0 | a1 | a3 | a2 - const __m128i C1 = _mm_unpacklo_epi32(B1, B0); // a3 | a2 | a0 | a1 - const __m128i D0 = _mm_madd_epi16(C0, kMult1); // out0, out1 - const __m128i D1 = _mm_madd_epi16(C1, kMult2); // out2, out3 - *out = _mm_unpacklo_epi64(D0, D1); -} - -static void FTransformWHT(const int16_t* in, int16_t* out) { - __m128i row0, row1, row2, row3; - FTransformWHTRow(in + 0 * 64, &row0); - FTransformWHTRow(in + 1 * 64, &row1); - FTransformWHTRow(in + 2 * 64, &row2); - FTransformWHTRow(in + 3 * 64, &row3); - - { - const __m128i a0 = _mm_add_epi32(row0, row2); - const __m128i a1 = _mm_add_epi32(row1, row3); - const __m128i a2 = _mm_sub_epi32(row1, row3); - const __m128i a3 = _mm_sub_epi32(row0, row2); - const __m128i b0 = _mm_srai_epi32(_mm_add_epi32(a0, a1), 1); - const __m128i b1 = _mm_srai_epi32(_mm_add_epi32(a3, a2), 1); - const __m128i b2 = _mm_srai_epi32(_mm_sub_epi32(a3, a2), 1); - const __m128i b3 = _mm_srai_epi32(_mm_sub_epi32(a0, a1), 1); - const __m128i out0 = _mm_packs_epi32(b0, b1); - const __m128i out1 = _mm_packs_epi32(b2, b3); - _mm_storeu_si128((__m128i*)&out[0], out0); - _mm_storeu_si128((__m128i*)&out[8], out1); - } -} - -//------------------------------------------------------------------------------ -// Compute susceptibility based on DCT-coeff histograms: -// the higher, the "easier" the macroblock is to compress. - -static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, - int start_block, int end_block, - VP8Histogram* const histo) { - const __m128i zero = _mm_setzero_si128(); - const __m128i max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH); - int j; - int distribution[MAX_COEFF_THRESH + 1] = { 0 }; - for (j = start_block; j < end_block; ++j) { - int16_t out[16]; - int k; - - FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); - - // Convert coefficients to bin (within out[]). - { - // Load. - const __m128i out0 = _mm_loadu_si128((__m128i*)&out[0]); - const __m128i out1 = _mm_loadu_si128((__m128i*)&out[8]); - const __m128i d0 = _mm_sub_epi16(zero, out0); - const __m128i d1 = _mm_sub_epi16(zero, out1); - const __m128i abs0 = _mm_max_epi16(out0, d0); // abs(v), 16b - const __m128i abs1 = _mm_max_epi16(out1, d1); - // v = abs(out) >> 3 - const __m128i v0 = _mm_srai_epi16(abs0, 3); - const __m128i v1 = _mm_srai_epi16(abs1, 3); - // bin = min(v, MAX_COEFF_THRESH) - const __m128i bin0 = _mm_min_epi16(v0, max_coeff_thresh); - const __m128i bin1 = _mm_min_epi16(v1, max_coeff_thresh); - // Store. - _mm_storeu_si128((__m128i*)&out[0], bin0); - _mm_storeu_si128((__m128i*)&out[8], bin1); - } - - // Convert coefficients to bin. - for (k = 0; k < 16; ++k) { - ++distribution[out[k]]; - } - } - VP8SetHistogramData(distribution, histo); -} - -//------------------------------------------------------------------------------ -// Intra predictions - -// helper for chroma-DC predictions -static WEBP_INLINE void Put8x8uv(uint8_t v, uint8_t* dst) { - int j; - const __m128i values = _mm_set1_epi8(v); - for (j = 0; j < 8; ++j) { - _mm_storel_epi64((__m128i*)(dst + j * BPS), values); - } -} - -static WEBP_INLINE void Put16(uint8_t v, uint8_t* dst) { - int j; - const __m128i values = _mm_set1_epi8(v); - for (j = 0; j < 16; ++j) { - _mm_store_si128((__m128i*)(dst + j * BPS), values); - } -} - -static WEBP_INLINE void Fill(uint8_t* dst, int value, int size) { - if (size == 4) { - int j; - for (j = 0; j < 4; ++j) { - memset(dst + j * BPS, value, 4); - } - } else if (size == 8) { - Put8x8uv(value, dst); - } else { - Put16(value, dst); - } -} - -static WEBP_INLINE void VE8uv(uint8_t* dst, const uint8_t* top) { - int j; - const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); - for (j = 0; j < 8; ++j) { - _mm_storel_epi64((__m128i*)(dst + j * BPS), top_values); - } -} - -static WEBP_INLINE void VE16(uint8_t* dst, const uint8_t* top) { - const __m128i top_values = _mm_load_si128((const __m128i*)top); - int j; - for (j = 0; j < 16; ++j) { - _mm_store_si128((__m128i*)(dst + j * BPS), top_values); - } -} - -static WEBP_INLINE void VerticalPred(uint8_t* dst, - const uint8_t* top, int size) { - if (top != NULL) { - if (size == 8) { - VE8uv(dst, top); - } else { - VE16(dst, top); - } - } else { - Fill(dst, 127, size); - } -} - -static WEBP_INLINE void HE8uv(uint8_t* dst, const uint8_t* left) { - int j; - for (j = 0; j < 8; ++j) { - const __m128i values = _mm_set1_epi8(left[j]); - _mm_storel_epi64((__m128i*)dst, values); - dst += BPS; - } -} - -static WEBP_INLINE void HE16(uint8_t* dst, const uint8_t* left) { - int j; - for (j = 0; j < 16; ++j) { - const __m128i values = _mm_set1_epi8(left[j]); - _mm_store_si128((__m128i*)dst, values); - dst += BPS; - } -} - -static WEBP_INLINE void HorizontalPred(uint8_t* dst, - const uint8_t* left, int size) { - if (left != NULL) { - if (size == 8) { - HE8uv(dst, left); - } else { - HE16(dst, left); - } - } else { - Fill(dst, 129, size); - } -} - -static WEBP_INLINE void TM(uint8_t* dst, const uint8_t* left, - const uint8_t* top, int size) { - const __m128i zero = _mm_setzero_si128(); - int y; - if (size == 8) { - const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); - const __m128i top_base = _mm_unpacklo_epi8(top_values, zero); - for (y = 0; y < 8; ++y, dst += BPS) { - const int val = left[y] - left[-1]; - const __m128i base = _mm_set1_epi16(val); - const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero); - _mm_storel_epi64((__m128i*)dst, out); - } - } else { - const __m128i top_values = _mm_load_si128((const __m128i*)top); - const __m128i top_base_0 = _mm_unpacklo_epi8(top_values, zero); - const __m128i top_base_1 = _mm_unpackhi_epi8(top_values, zero); - for (y = 0; y < 16; ++y, dst += BPS) { - const int val = left[y] - left[-1]; - const __m128i base = _mm_set1_epi16(val); - const __m128i out_0 = _mm_add_epi16(base, top_base_0); - const __m128i out_1 = _mm_add_epi16(base, top_base_1); - const __m128i out = _mm_packus_epi16(out_0, out_1); - _mm_store_si128((__m128i*)dst, out); - } - } -} - -static WEBP_INLINE void TrueMotion(uint8_t* dst, const uint8_t* left, - const uint8_t* top, int size) { - if (left != NULL) { - if (top != NULL) { - TM(dst, left, top, size); - } else { - HorizontalPred(dst, left, size); - } - } else { - // true motion without left samples (hence: with default 129 value) - // is equivalent to VE prediction where you just copy the top samples. - // Note that if top samples are not available, the default value is - // then 129, and not 127 as in the VerticalPred case. - if (top != NULL) { - VerticalPred(dst, top, size); - } else { - Fill(dst, 129, size); - } - } -} - -static WEBP_INLINE void DC8uv(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { - const __m128i zero = _mm_setzero_si128(); - const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); - const __m128i left_values = _mm_loadl_epi64((const __m128i*)left); - const __m128i sum_top = _mm_sad_epu8(top_values, zero); - const __m128i sum_left = _mm_sad_epu8(left_values, zero); - const int DC = _mm_cvtsi128_si32(sum_top) + _mm_cvtsi128_si32(sum_left) + 8; - Put8x8uv(DC >> 4, dst); -} - -static WEBP_INLINE void DC8uvNoLeft(uint8_t* dst, const uint8_t* top) { - const __m128i zero = _mm_setzero_si128(); - const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); - const __m128i sum = _mm_sad_epu8(top_values, zero); - const int DC = _mm_cvtsi128_si32(sum) + 4; - Put8x8uv(DC >> 3, dst); -} - -static WEBP_INLINE void DC8uvNoTop(uint8_t* dst, const uint8_t* left) { - // 'left' is contiguous so we can reuse the top summation. - DC8uvNoLeft(dst, left); -} - -static WEBP_INLINE void DC8uvNoTopLeft(uint8_t* dst) { - Put8x8uv(0x80, dst); -} - -static WEBP_INLINE void DC8uvMode(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { - if (top != NULL) { - if (left != NULL) { // top and left present - DC8uv(dst, left, top); - } else { // top, but no left - DC8uvNoLeft(dst, top); - } - } else if (left != NULL) { // left but no top - DC8uvNoTop(dst, left); - } else { // no top, no left, nothing. - DC8uvNoTopLeft(dst); - } -} - -static WEBP_INLINE void DC16(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { - const __m128i zero = _mm_setzero_si128(); - const __m128i top_row = _mm_load_si128((const __m128i*)top); - const __m128i left_row = _mm_load_si128((const __m128i*)left); - const __m128i sad8x2 = _mm_sad_epu8(top_row, zero); - // sum the two sads: sad8x2[0:1] + sad8x2[8:9] - const __m128i sum_top = _mm_add_epi16(sad8x2, _mm_shuffle_epi32(sad8x2, 2)); - const __m128i sad8x2_left = _mm_sad_epu8(left_row, zero); - // sum the two sads: sad8x2[0:1] + sad8x2[8:9] - const __m128i sum_left = - _mm_add_epi16(sad8x2_left, _mm_shuffle_epi32(sad8x2_left, 2)); - const int DC = _mm_cvtsi128_si32(sum_top) + _mm_cvtsi128_si32(sum_left) + 16; - Put16(DC >> 5, dst); -} - -static WEBP_INLINE void DC16NoLeft(uint8_t* dst, const uint8_t* top) { - const __m128i zero = _mm_setzero_si128(); - const __m128i top_row = _mm_load_si128((const __m128i*)top); - const __m128i sad8x2 = _mm_sad_epu8(top_row, zero); - // sum the two sads: sad8x2[0:1] + sad8x2[8:9] - const __m128i sum = _mm_add_epi16(sad8x2, _mm_shuffle_epi32(sad8x2, 2)); - const int DC = _mm_cvtsi128_si32(sum) + 8; - Put16(DC >> 4, dst); -} - -static WEBP_INLINE void DC16NoTop(uint8_t* dst, const uint8_t* left) { - // 'left' is contiguous so we can reuse the top summation. - DC16NoLeft(dst, left); -} - -static WEBP_INLINE void DC16NoTopLeft(uint8_t* dst) { - Put16(0x80, dst); -} - -static WEBP_INLINE void DC16Mode(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { - if (top != NULL) { - if (left != NULL) { // top and left present - DC16(dst, left, top); - } else { // top, but no left - DC16NoLeft(dst, top); - } - } else if (left != NULL) { // left but no top - DC16NoTop(dst, left); - } else { // no top, no left, nothing. - DC16NoTopLeft(dst); - } -} - -//------------------------------------------------------------------------------ -// 4x4 predictions - -#define DST(x, y) dst[(x) + (y) * BPS] -#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2) -#define AVG2(a, b) (((a) + (b) + 1) >> 1) - -// We use the following 8b-arithmetic tricks: -// (a + 2 * b + c + 2) >> 2 = (AC + b + 1) >> 1 -// where: AC = (a + c) >> 1 = [(a + c + 1) >> 1] - [(a^c) & 1] -// and: -// (a + 2 * b + c + 2) >> 2 = (AB + BC + 1) >> 1 - (ab|bc)&lsb -// where: AC = (a + b + 1) >> 1, BC = (b + c + 1) >> 1 -// and ab = a ^ b, bc = b ^ c, lsb = (AC^BC)&1 - -static WEBP_INLINE void VE4(uint8_t* dst, const uint8_t* top) { // vertical - const __m128i one = _mm_set1_epi8(1); - const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(top - 1)); - const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1); - const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2); - const __m128i a = _mm_avg_epu8(ABCDEFGH, CDEFGH00); - const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGH00), one); - const __m128i b = _mm_subs_epu8(a, lsb); - const __m128i avg = _mm_avg_epu8(b, BCDEFGH0); - const uint32_t vals = _mm_cvtsi128_si32(avg); - int i; - for (i = 0; i < 4; ++i) { - WebPUint32ToMem(dst + i * BPS, vals); - } -} - -static WEBP_INLINE void HE4(uint8_t* dst, const uint8_t* top) { // horizontal - const int X = top[-1]; - const int I = top[-2]; - const int J = top[-3]; - const int K = top[-4]; - const int L = top[-5]; - WebPUint32ToMem(dst + 0 * BPS, 0x01010101U * AVG3(X, I, J)); - WebPUint32ToMem(dst + 1 * BPS, 0x01010101U * AVG3(I, J, K)); - WebPUint32ToMem(dst + 2 * BPS, 0x01010101U * AVG3(J, K, L)); - WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(K, L, L)); -} - -static WEBP_INLINE void DC4(uint8_t* dst, const uint8_t* top) { - uint32_t dc = 4; - int i; - for (i = 0; i < 4; ++i) dc += top[i] + top[-5 + i]; - Fill(dst, dc >> 3, 4); -} - -static WEBP_INLINE void LD4(uint8_t* dst, const uint8_t* top) { // Down-Left - const __m128i one = _mm_set1_epi8(1); - const __m128i ABCDEFGH = _mm_loadl_epi64((const __m128i*)top); - const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1); - const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2); - const __m128i CDEFGHH0 = _mm_insert_epi16(CDEFGH00, top[7], 3); - const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, CDEFGHH0); - const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one); - const __m128i avg2 = _mm_subs_epu8(avg1, lsb); - const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0); - WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcdefg )); - WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); - WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); - WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); -} - -static WEBP_INLINE void VR4(uint8_t* dst, - const uint8_t* top) { // Vertical-Right - const __m128i one = _mm_set1_epi8(1); - const int I = top[-2]; - const int J = top[-3]; - const int K = top[-4]; - const int X = top[-1]; - const __m128i XABCD = _mm_loadl_epi64((const __m128i*)(top - 1)); - const __m128i ABCD0 = _mm_srli_si128(XABCD, 1); - const __m128i abcd = _mm_avg_epu8(XABCD, ABCD0); - const __m128i _XABCD = _mm_slli_si128(XABCD, 1); - const __m128i IXABCD = _mm_insert_epi16(_XABCD, I | (X << 8), 0); - const __m128i avg1 = _mm_avg_epu8(IXABCD, ABCD0); - const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one); - const __m128i avg2 = _mm_subs_epu8(avg1, lsb); - const __m128i efgh = _mm_avg_epu8(avg2, XABCD); - WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcd )); - WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( efgh )); - WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1))); - WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1))); - - // these two are hard to implement in SSE2, so we keep the C-version: - DST(0, 2) = AVG3(J, I, X); - DST(0, 3) = AVG3(K, J, I); -} - -static WEBP_INLINE void VL4(uint8_t* dst, - const uint8_t* top) { // Vertical-Left - const __m128i one = _mm_set1_epi8(1); - const __m128i ABCDEFGH = _mm_loadl_epi64((const __m128i*)top); - const __m128i BCDEFGH_ = _mm_srli_si128(ABCDEFGH, 1); - const __m128i CDEFGH__ = _mm_srli_si128(ABCDEFGH, 2); - const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, BCDEFGH_); - const __m128i avg2 = _mm_avg_epu8(CDEFGH__, BCDEFGH_); - const __m128i avg3 = _mm_avg_epu8(avg1, avg2); - const __m128i lsb1 = _mm_and_si128(_mm_xor_si128(avg1, avg2), one); - const __m128i ab = _mm_xor_si128(ABCDEFGH, BCDEFGH_); - const __m128i bc = _mm_xor_si128(CDEFGH__, BCDEFGH_); - const __m128i abbc = _mm_or_si128(ab, bc); - const __m128i lsb2 = _mm_and_si128(abbc, lsb1); - const __m128i avg4 = _mm_subs_epu8(avg3, lsb2); - const uint32_t extra_out = _mm_cvtsi128_si32(_mm_srli_si128(avg4, 4)); - WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( avg1 )); - WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( avg4 )); - WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1))); - WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1))); - - // these two are hard to get and irregular - DST(3, 2) = (extra_out >> 0) & 0xff; - DST(3, 3) = (extra_out >> 8) & 0xff; -} - -static WEBP_INLINE void RD4(uint8_t* dst, const uint8_t* top) { // Down-right - const __m128i one = _mm_set1_epi8(1); - const __m128i LKJIXABC = _mm_loadl_epi64((const __m128i*)(top - 5)); - const __m128i LKJIXABCD = _mm_insert_epi16(LKJIXABC, top[3], 4); - const __m128i KJIXABCD_ = _mm_srli_si128(LKJIXABCD, 1); - const __m128i JIXABCD__ = _mm_srli_si128(LKJIXABCD, 2); - const __m128i avg1 = _mm_avg_epu8(JIXABCD__, LKJIXABCD); - const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one); - const __m128i avg2 = _mm_subs_epu8(avg1, lsb); - const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_); - WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32( abcdefg )); - WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); - WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); - WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); -} - -static WEBP_INLINE void HU4(uint8_t* dst, const uint8_t* top) { - const int I = top[-2]; - const int J = top[-3]; - const int K = top[-4]; - const int L = top[-5]; - DST(0, 0) = AVG2(I, J); - DST(2, 0) = DST(0, 1) = AVG2(J, K); - DST(2, 1) = DST(0, 2) = AVG2(K, L); - DST(1, 0) = AVG3(I, J, K); - DST(3, 0) = DST(1, 1) = AVG3(J, K, L); - DST(3, 1) = DST(1, 2) = AVG3(K, L, L); - DST(3, 2) = DST(2, 2) = - DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L; -} - -static WEBP_INLINE void HD4(uint8_t* dst, const uint8_t* top) { - const int X = top[-1]; - const int I = top[-2]; - const int J = top[-3]; - const int K = top[-4]; - const int L = top[-5]; - const int A = top[0]; - const int B = top[1]; - const int C = top[2]; - - DST(0, 0) = DST(2, 1) = AVG2(I, X); - DST(0, 1) = DST(2, 2) = AVG2(J, I); - DST(0, 2) = DST(2, 3) = AVG2(K, J); - DST(0, 3) = AVG2(L, K); - - DST(3, 0) = AVG3(A, B, C); - DST(2, 0) = AVG3(X, A, B); - DST(1, 0) = DST(3, 1) = AVG3(I, X, A); - DST(1, 1) = DST(3, 2) = AVG3(J, I, X); - DST(1, 2) = DST(3, 3) = AVG3(K, J, I); - DST(1, 3) = AVG3(L, K, J); -} - -static WEBP_INLINE void TM4(uint8_t* dst, const uint8_t* top) { - const __m128i zero = _mm_setzero_si128(); - const __m128i top_values = _mm_cvtsi32_si128(WebPMemToUint32(top)); - const __m128i top_base = _mm_unpacklo_epi8(top_values, zero); - int y; - for (y = 0; y < 4; ++y, dst += BPS) { - const int val = top[-2 - y] - top[-1]; - const __m128i base = _mm_set1_epi16(val); - const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero); - WebPUint32ToMem(dst, _mm_cvtsi128_si32(out)); - } -} - -#undef DST -#undef AVG3 -#undef AVG2 - -//------------------------------------------------------------------------------ -// luma 4x4 prediction - -// Left samples are top[-5 .. -2], top_left is top[-1], top are -// located at top[0..3], and top right is top[4..7] -static void Intra4Preds(uint8_t* dst, const uint8_t* top) { - DC4(I4DC4 + dst, top); - TM4(I4TM4 + dst, top); - VE4(I4VE4 + dst, top); - HE4(I4HE4 + dst, top); - RD4(I4RD4 + dst, top); - VR4(I4VR4 + dst, top); - LD4(I4LD4 + dst, top); - VL4(I4VL4 + dst, top); - HD4(I4HD4 + dst, top); - HU4(I4HU4 + dst, top); -} - -//------------------------------------------------------------------------------ -// Chroma 8x8 prediction (paragraph 12.2) - -static void IntraChromaPreds(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { - // U block - DC8uvMode(C8DC8 + dst, left, top); - VerticalPred(C8VE8 + dst, top, 8); - HorizontalPred(C8HE8 + dst, left, 8); - TrueMotion(C8TM8 + dst, left, top, 8); - // V block - dst += 8; - if (top != NULL) top += 8; - if (left != NULL) left += 16; - DC8uvMode(C8DC8 + dst, left, top); - VerticalPred(C8VE8 + dst, top, 8); - HorizontalPred(C8HE8 + dst, left, 8); - TrueMotion(C8TM8 + dst, left, top, 8); -} - -//------------------------------------------------------------------------------ -// luma 16x16 prediction (paragraph 12.3) - -static void Intra16Preds(uint8_t* dst, - const uint8_t* left, const uint8_t* top) { - DC16Mode(I16DC16 + dst, left, top); - VerticalPred(I16VE16 + dst, top, 16); - HorizontalPred(I16HE16 + dst, left, 16); - TrueMotion(I16TM16 + dst, left, top, 16); -} - -//------------------------------------------------------------------------------ -// Metric - -static WEBP_INLINE void SubtractAndAccumulate(const __m128i a, const __m128i b, - __m128i* const sum) { - // take abs(a-b) in 8b - const __m128i a_b = _mm_subs_epu8(a, b); - const __m128i b_a = _mm_subs_epu8(b, a); - const __m128i abs_a_b = _mm_or_si128(a_b, b_a); - // zero-extend to 16b - const __m128i zero = _mm_setzero_si128(); - const __m128i C0 = _mm_unpacklo_epi8(abs_a_b, zero); - const __m128i C1 = _mm_unpackhi_epi8(abs_a_b, zero); - // multiply with self - const __m128i sum1 = _mm_madd_epi16(C0, C0); - const __m128i sum2 = _mm_madd_epi16(C1, C1); - *sum = _mm_add_epi32(sum1, sum2); -} - -static WEBP_INLINE int SSE_16xN(const uint8_t* a, const uint8_t* b, - int num_pairs) { - __m128i sum = _mm_setzero_si128(); - int32_t tmp[4]; - int i; - - for (i = 0; i < num_pairs; ++i) { - const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[BPS * 0]); - const __m128i b0 = _mm_loadu_si128((const __m128i*)&b[BPS * 0]); - const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[BPS * 1]); - const __m128i b1 = _mm_loadu_si128((const __m128i*)&b[BPS * 1]); - __m128i sum1, sum2; - SubtractAndAccumulate(a0, b0, &sum1); - SubtractAndAccumulate(a1, b1, &sum2); - sum = _mm_add_epi32(sum, _mm_add_epi32(sum1, sum2)); - a += 2 * BPS; - b += 2 * BPS; - } - _mm_storeu_si128((__m128i*)tmp, sum); - return (tmp[3] + tmp[2] + tmp[1] + tmp[0]); -} - -static int SSE16x16(const uint8_t* a, const uint8_t* b) { - return SSE_16xN(a, b, 8); -} - -static int SSE16x8(const uint8_t* a, const uint8_t* b) { - return SSE_16xN(a, b, 4); -} - -#define LOAD_8x16b(ptr) \ - _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i*)(ptr)), zero) - -static int SSE8x8(const uint8_t* a, const uint8_t* b) { - const __m128i zero = _mm_setzero_si128(); - int num_pairs = 4; - __m128i sum = zero; - int32_t tmp[4]; - while (num_pairs-- > 0) { - const __m128i a0 = LOAD_8x16b(&a[BPS * 0]); - const __m128i a1 = LOAD_8x16b(&a[BPS * 1]); - const __m128i b0 = LOAD_8x16b(&b[BPS * 0]); - const __m128i b1 = LOAD_8x16b(&b[BPS * 1]); - // subtract - const __m128i c0 = _mm_subs_epi16(a0, b0); - const __m128i c1 = _mm_subs_epi16(a1, b1); - // multiply/accumulate with self - const __m128i d0 = _mm_madd_epi16(c0, c0); - const __m128i d1 = _mm_madd_epi16(c1, c1); - // collect - const __m128i sum01 = _mm_add_epi32(d0, d1); - sum = _mm_add_epi32(sum, sum01); - a += 2 * BPS; - b += 2 * BPS; - } - _mm_storeu_si128((__m128i*)tmp, sum); - return (tmp[3] + tmp[2] + tmp[1] + tmp[0]); -} -#undef LOAD_8x16b - -static int SSE4x4(const uint8_t* a, const uint8_t* b) { - const __m128i zero = _mm_setzero_si128(); - - // Load values. Note that we read 8 pixels instead of 4, - // but the a/b buffers are over-allocated to that effect. - const __m128i a0 = _mm_loadl_epi64((const __m128i*)&a[BPS * 0]); - const __m128i a1 = _mm_loadl_epi64((const __m128i*)&a[BPS * 1]); - const __m128i a2 = _mm_loadl_epi64((const __m128i*)&a[BPS * 2]); - const __m128i a3 = _mm_loadl_epi64((const __m128i*)&a[BPS * 3]); - const __m128i b0 = _mm_loadl_epi64((const __m128i*)&b[BPS * 0]); - const __m128i b1 = _mm_loadl_epi64((const __m128i*)&b[BPS * 1]); - const __m128i b2 = _mm_loadl_epi64((const __m128i*)&b[BPS * 2]); - const __m128i b3 = _mm_loadl_epi64((const __m128i*)&b[BPS * 3]); - // Combine pair of lines. - const __m128i a01 = _mm_unpacklo_epi32(a0, a1); - const __m128i a23 = _mm_unpacklo_epi32(a2, a3); - const __m128i b01 = _mm_unpacklo_epi32(b0, b1); - const __m128i b23 = _mm_unpacklo_epi32(b2, b3); - // Convert to 16b. - const __m128i a01s = _mm_unpacklo_epi8(a01, zero); - const __m128i a23s = _mm_unpacklo_epi8(a23, zero); - const __m128i b01s = _mm_unpacklo_epi8(b01, zero); - const __m128i b23s = _mm_unpacklo_epi8(b23, zero); - // subtract, square and accumulate - const __m128i d0 = _mm_subs_epi16(a01s, b01s); - const __m128i d1 = _mm_subs_epi16(a23s, b23s); - const __m128i e0 = _mm_madd_epi16(d0, d0); - const __m128i e1 = _mm_madd_epi16(d1, d1); - const __m128i sum = _mm_add_epi32(e0, e1); - - int32_t tmp[4]; - _mm_storeu_si128((__m128i*)tmp, sum); - return (tmp[3] + tmp[2] + tmp[1] + tmp[0]); -} - -//------------------------------------------------------------------------------ -// Texture distortion -// -// We try to match the spectral content (weighted) between source and -// reconstructed samples. - -// Hadamard transform -// Returns the difference between the weighted sum of the absolute value of -// transformed coefficients. -static int TTransform(const uint8_t* inA, const uint8_t* inB, - const uint16_t* const w) { - int32_t sum[4]; - __m128i tmp_0, tmp_1, tmp_2, tmp_3; - const __m128i zero = _mm_setzero_si128(); - - // Load, combine and transpose inputs. - { - const __m128i inA_0 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 0]); - const __m128i inA_1 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 1]); - const __m128i inA_2 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 2]); - const __m128i inA_3 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 3]); - const __m128i inB_0 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 0]); - const __m128i inB_1 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 1]); - const __m128i inB_2 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 2]); - const __m128i inB_3 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 3]); - - // Combine inA and inB (we'll do two transforms in parallel). - const __m128i inAB_0 = _mm_unpacklo_epi8(inA_0, inB_0); - const __m128i inAB_1 = _mm_unpacklo_epi8(inA_1, inB_1); - const __m128i inAB_2 = _mm_unpacklo_epi8(inA_2, inB_2); - const __m128i inAB_3 = _mm_unpacklo_epi8(inA_3, inB_3); - // a00 b00 a01 b01 a02 b03 a03 b03 0 0 0 0 0 0 0 0 - // a10 b10 a11 b11 a12 b12 a13 b13 0 0 0 0 0 0 0 0 - // a20 b20 a21 b21 a22 b22 a23 b23 0 0 0 0 0 0 0 0 - // a30 b30 a31 b31 a32 b32 a33 b33 0 0 0 0 0 0 0 0 - - // Transpose the two 4x4, discarding the filling zeroes. - const __m128i transpose0_0 = _mm_unpacklo_epi8(inAB_0, inAB_2); - const __m128i transpose0_1 = _mm_unpacklo_epi8(inAB_1, inAB_3); - // a00 a20 b00 b20 a01 a21 b01 b21 a02 a22 b02 b22 a03 a23 b03 b23 - // a10 a30 b10 b30 a11 a31 b11 b31 a12 a32 b12 b32 a13 a33 b13 b33 - const __m128i transpose1_0 = _mm_unpacklo_epi8(transpose0_0, transpose0_1); - const __m128i transpose1_1 = _mm_unpackhi_epi8(transpose0_0, transpose0_1); - // a00 a10 a20 a30 b00 b10 b20 b30 a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 a03 a13 a23 a33 b03 b13 b23 b33 - - // Convert to 16b. - tmp_0 = _mm_unpacklo_epi8(transpose1_0, zero); - tmp_1 = _mm_unpackhi_epi8(transpose1_0, zero); - tmp_2 = _mm_unpacklo_epi8(transpose1_1, zero); - tmp_3 = _mm_unpackhi_epi8(transpose1_1, zero); - // a00 a10 a20 a30 b00 b10 b20 b30 - // a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 - // a03 a13 a23 a33 b03 b13 b23 b33 - } - - // Horizontal pass and subsequent transpose. - { - // Calculate a and b (two 4x4 at once). - const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2); - const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3); - const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3); - const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2); - const __m128i b0 = _mm_add_epi16(a0, a1); - const __m128i b1 = _mm_add_epi16(a3, a2); - const __m128i b2 = _mm_sub_epi16(a3, a2); - const __m128i b3 = _mm_sub_epi16(a0, a1); - // a00 a01 a02 a03 b00 b01 b02 b03 - // a10 a11 a12 a13 b10 b11 b12 b13 - // a20 a21 a22 a23 b20 b21 b22 b23 - // a30 a31 a32 a33 b30 b31 b32 b33 - - // Transpose the two 4x4. - const __m128i transpose0_0 = _mm_unpacklo_epi16(b0, b1); - const __m128i transpose0_1 = _mm_unpacklo_epi16(b2, b3); - const __m128i transpose0_2 = _mm_unpackhi_epi16(b0, b1); - const __m128i transpose0_3 = _mm_unpackhi_epi16(b2, b3); - // a00 a10 a01 a11 a02 a12 a03 a13 - // a20 a30 a21 a31 a22 a32 a23 a33 - // b00 b10 b01 b11 b02 b12 b03 b13 - // b20 b30 b21 b31 b22 b32 b23 b33 - const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3); - const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3); - // a00 a10 a20 a30 a01 a11 a21 a31 - // b00 b10 b20 b30 b01 b11 b21 b31 - // a02 a12 a22 a32 a03 a13 a23 a33 - // b02 b12 a22 b32 b03 b13 b23 b33 - tmp_0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1); - tmp_1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1); - tmp_2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3); - tmp_3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3); - // a00 a10 a20 a30 b00 b10 b20 b30 - // a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 - // a03 a13 a23 a33 b03 b13 b23 b33 - } - - // Vertical pass and difference of weighted sums. - { - // Load all inputs. - const __m128i w_0 = _mm_loadu_si128((const __m128i*)&w[0]); - const __m128i w_8 = _mm_loadu_si128((const __m128i*)&w[8]); - - // Calculate a and b (two 4x4 at once). - const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2); - const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3); - const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3); - const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2); - const __m128i b0 = _mm_add_epi16(a0, a1); - const __m128i b1 = _mm_add_epi16(a3, a2); - const __m128i b2 = _mm_sub_epi16(a3, a2); - const __m128i b3 = _mm_sub_epi16(a0, a1); - - // Separate the transforms of inA and inB. - __m128i A_b0 = _mm_unpacklo_epi64(b0, b1); - __m128i A_b2 = _mm_unpacklo_epi64(b2, b3); - __m128i B_b0 = _mm_unpackhi_epi64(b0, b1); - __m128i B_b2 = _mm_unpackhi_epi64(b2, b3); - - { - const __m128i d0 = _mm_sub_epi16(zero, A_b0); - const __m128i d1 = _mm_sub_epi16(zero, A_b2); - const __m128i d2 = _mm_sub_epi16(zero, B_b0); - const __m128i d3 = _mm_sub_epi16(zero, B_b2); - A_b0 = _mm_max_epi16(A_b0, d0); // abs(v), 16b - A_b2 = _mm_max_epi16(A_b2, d1); - B_b0 = _mm_max_epi16(B_b0, d2); - B_b2 = _mm_max_epi16(B_b2, d3); - } - - // weighted sums - A_b0 = _mm_madd_epi16(A_b0, w_0); - A_b2 = _mm_madd_epi16(A_b2, w_8); - B_b0 = _mm_madd_epi16(B_b0, w_0); - B_b2 = _mm_madd_epi16(B_b2, w_8); - A_b0 = _mm_add_epi32(A_b0, A_b2); - B_b0 = _mm_add_epi32(B_b0, B_b2); - - // difference of weighted sums - A_b0 = _mm_sub_epi32(A_b0, B_b0); - _mm_storeu_si128((__m128i*)&sum[0], A_b0); - } - return sum[0] + sum[1] + sum[2] + sum[3]; -} - -static int Disto4x4(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - const int diff_sum = TTransform(a, b, w); - return abs(diff_sum) >> 5; -} - -static int Disto16x16(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - int D = 0; - int x, y; - for (y = 0; y < 16 * BPS; y += 4 * BPS) { - for (x = 0; x < 16; x += 4) { - D += Disto4x4(a + x + y, b + x + y, w); - } - } - return D; -} - -//------------------------------------------------------------------------------ -// Quantization -// - -static WEBP_INLINE int DoQuantizeBlock(int16_t in[16], int16_t out[16], - const uint16_t* const sharpen, - const VP8Matrix* const mtx) { - const __m128i max_coeff_2047 = _mm_set1_epi16(MAX_LEVEL); - const __m128i zero = _mm_setzero_si128(); - __m128i coeff0, coeff8; - __m128i out0, out8; - __m128i packed_out; - - // Load all inputs. - __m128i in0 = _mm_loadu_si128((__m128i*)&in[0]); - __m128i in8 = _mm_loadu_si128((__m128i*)&in[8]); - const __m128i iq0 = _mm_loadu_si128((const __m128i*)&mtx->iq_[0]); - const __m128i iq8 = _mm_loadu_si128((const __m128i*)&mtx->iq_[8]); - const __m128i q0 = _mm_loadu_si128((const __m128i*)&mtx->q_[0]); - const __m128i q8 = _mm_loadu_si128((const __m128i*)&mtx->q_[8]); - - // extract sign(in) (0x0000 if positive, 0xffff if negative) - const __m128i sign0 = _mm_cmpgt_epi16(zero, in0); - const __m128i sign8 = _mm_cmpgt_epi16(zero, in8); - - // coeff = abs(in) = (in ^ sign) - sign - coeff0 = _mm_xor_si128(in0, sign0); - coeff8 = _mm_xor_si128(in8, sign8); - coeff0 = _mm_sub_epi16(coeff0, sign0); - coeff8 = _mm_sub_epi16(coeff8, sign8); - - // coeff = abs(in) + sharpen - if (sharpen != NULL) { - const __m128i sharpen0 = _mm_loadu_si128((const __m128i*)&sharpen[0]); - const __m128i sharpen8 = _mm_loadu_si128((const __m128i*)&sharpen[8]); - coeff0 = _mm_add_epi16(coeff0, sharpen0); - coeff8 = _mm_add_epi16(coeff8, sharpen8); - } - - // out = (coeff * iQ + B) >> QFIX - { - // doing calculations with 32b precision (QFIX=17) - // out = (coeff * iQ) - const __m128i coeff_iQ0H = _mm_mulhi_epu16(coeff0, iq0); - const __m128i coeff_iQ0L = _mm_mullo_epi16(coeff0, iq0); - const __m128i coeff_iQ8H = _mm_mulhi_epu16(coeff8, iq8); - const __m128i coeff_iQ8L = _mm_mullo_epi16(coeff8, iq8); - __m128i out_00 = _mm_unpacklo_epi16(coeff_iQ0L, coeff_iQ0H); - __m128i out_04 = _mm_unpackhi_epi16(coeff_iQ0L, coeff_iQ0H); - __m128i out_08 = _mm_unpacklo_epi16(coeff_iQ8L, coeff_iQ8H); - __m128i out_12 = _mm_unpackhi_epi16(coeff_iQ8L, coeff_iQ8H); - // out = (coeff * iQ + B) - const __m128i bias_00 = _mm_loadu_si128((const __m128i*)&mtx->bias_[0]); - const __m128i bias_04 = _mm_loadu_si128((const __m128i*)&mtx->bias_[4]); - const __m128i bias_08 = _mm_loadu_si128((const __m128i*)&mtx->bias_[8]); - const __m128i bias_12 = _mm_loadu_si128((const __m128i*)&mtx->bias_[12]); - out_00 = _mm_add_epi32(out_00, bias_00); - out_04 = _mm_add_epi32(out_04, bias_04); - out_08 = _mm_add_epi32(out_08, bias_08); - out_12 = _mm_add_epi32(out_12, bias_12); - // out = QUANTDIV(coeff, iQ, B, QFIX) - out_00 = _mm_srai_epi32(out_00, QFIX); - out_04 = _mm_srai_epi32(out_04, QFIX); - out_08 = _mm_srai_epi32(out_08, QFIX); - out_12 = _mm_srai_epi32(out_12, QFIX); - - // pack result as 16b - out0 = _mm_packs_epi32(out_00, out_04); - out8 = _mm_packs_epi32(out_08, out_12); - - // if (coeff > 2047) coeff = 2047 - out0 = _mm_min_epi16(out0, max_coeff_2047); - out8 = _mm_min_epi16(out8, max_coeff_2047); - } - - // get sign back (if (sign[j]) out_n = -out_n) - out0 = _mm_xor_si128(out0, sign0); - out8 = _mm_xor_si128(out8, sign8); - out0 = _mm_sub_epi16(out0, sign0); - out8 = _mm_sub_epi16(out8, sign8); - - // in = out * Q - in0 = _mm_mullo_epi16(out0, q0); - in8 = _mm_mullo_epi16(out8, q8); - - _mm_storeu_si128((__m128i*)&in[0], in0); - _mm_storeu_si128((__m128i*)&in[8], in8); - - // zigzag the output before storing it. - // - // The zigzag pattern can almost be reproduced with a small sequence of - // shuffles. After it, we only need to swap the 7th (ending up in third - // position instead of twelfth) and 8th values. - { - __m128i outZ0, outZ8; - outZ0 = _mm_shufflehi_epi16(out0, _MM_SHUFFLE(2, 1, 3, 0)); - outZ0 = _mm_shuffle_epi32 (outZ0, _MM_SHUFFLE(3, 1, 2, 0)); - outZ0 = _mm_shufflehi_epi16(outZ0, _MM_SHUFFLE(3, 1, 0, 2)); - outZ8 = _mm_shufflelo_epi16(out8, _MM_SHUFFLE(3, 0, 2, 1)); - outZ8 = _mm_shuffle_epi32 (outZ8, _MM_SHUFFLE(3, 1, 2, 0)); - outZ8 = _mm_shufflelo_epi16(outZ8, _MM_SHUFFLE(1, 3, 2, 0)); - _mm_storeu_si128((__m128i*)&out[0], outZ0); - _mm_storeu_si128((__m128i*)&out[8], outZ8); - packed_out = _mm_packs_epi16(outZ0, outZ8); - } - { - const int16_t outZ_12 = out[12]; - const int16_t outZ_3 = out[3]; - out[3] = outZ_12; - out[12] = outZ_3; - } - - // detect if all 'out' values are zeroes or not - return (_mm_movemask_epi8(_mm_cmpeq_epi8(packed_out, zero)) != 0xffff); -} - -static int QuantizeBlock(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - return DoQuantizeBlock(in, out, &mtx->sharpen_[0], mtx); -} - -static int QuantizeBlockWHT(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - return DoQuantizeBlock(in, out, NULL, mtx); -} - -static int Quantize2Blocks(int16_t in[32], int16_t out[32], - const VP8Matrix* const mtx) { - int nz; - const uint16_t* const sharpen = &mtx->sharpen_[0]; - nz = DoQuantizeBlock(in + 0 * 16, out + 0 * 16, sharpen, mtx) << 0; - nz |= DoQuantizeBlock(in + 1 * 16, out + 1 * 16, sharpen, mtx) << 1; - return nz; -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8EncDspInitSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitSSE2(void) { - VP8CollectHistogram = CollectHistogram; - VP8EncPredLuma16 = Intra16Preds; - VP8EncPredChroma8 = IntraChromaPreds; - VP8EncPredLuma4 = Intra4Preds; - VP8EncQuantizeBlock = QuantizeBlock; - VP8EncQuantize2Blocks = Quantize2Blocks; - VP8EncQuantizeBlockWHT = QuantizeBlockWHT; - VP8ITransform = ITransform; - VP8FTransform = FTransform; - VP8FTransform2 = FTransform2; - VP8FTransformWHT = FTransformWHT; - VP8SSE16x16 = SSE16x16; - VP8SSE16x8 = SSE16x8; - VP8SSE8x8 = SSE8x8; - VP8SSE4x4 = SSE4x4; - VP8TDisto4x4 = Disto4x4; - VP8TDisto16x16 = Disto16x16; -} - -#else // !WEBP_USE_SSE2 - -WEBP_DSP_INIT_STUB(VP8EncDspInitSSE2) - -#endif // WEBP_USE_SSE2 diff --git a/Example-Mac/Pods/libwebp/src/dsp/enc_sse41.c b/Example-Mac/Pods/libwebp/src/dsp/enc_sse41.c deleted file mode 100644 index 65c01aef..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/enc_sse41.c +++ /dev/null @@ -1,373 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// SSE4 version of some encoding functions. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE41) -#include -#include // for abs() - -#include "../enc/vp8enci.h" - -//------------------------------------------------------------------------------ -// Compute susceptibility based on DCT-coeff histograms. - -static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, - int start_block, int end_block, - VP8Histogram* const histo) { - const __m128i max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH); - int j; - int distribution[MAX_COEFF_THRESH + 1] = { 0 }; - for (j = start_block; j < end_block; ++j) { - int16_t out[16]; - int k; - - VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); - - // Convert coefficients to bin (within out[]). - { - // Load. - const __m128i out0 = _mm_loadu_si128((__m128i*)&out[0]); - const __m128i out1 = _mm_loadu_si128((__m128i*)&out[8]); - // v = abs(out) >> 3 - const __m128i abs0 = _mm_abs_epi16(out0); - const __m128i abs1 = _mm_abs_epi16(out1); - const __m128i v0 = _mm_srai_epi16(abs0, 3); - const __m128i v1 = _mm_srai_epi16(abs1, 3); - // bin = min(v, MAX_COEFF_THRESH) - const __m128i bin0 = _mm_min_epi16(v0, max_coeff_thresh); - const __m128i bin1 = _mm_min_epi16(v1, max_coeff_thresh); - // Store. - _mm_storeu_si128((__m128i*)&out[0], bin0); - _mm_storeu_si128((__m128i*)&out[8], bin1); - } - - // Convert coefficients to bin. - for (k = 0; k < 16; ++k) { - ++distribution[out[k]]; - } - } - VP8SetHistogramData(distribution, histo); -} - -//------------------------------------------------------------------------------ -// Texture distortion -// -// We try to match the spectral content (weighted) between source and -// reconstructed samples. - -// Hadamard transform -// Returns the difference between the weighted sum of the absolute value of -// transformed coefficients. -static int TTransform(const uint8_t* inA, const uint8_t* inB, - const uint16_t* const w) { - __m128i tmp_0, tmp_1, tmp_2, tmp_3; - - // Load, combine and transpose inputs. - { - const __m128i inA_0 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 0]); - const __m128i inA_1 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 1]); - const __m128i inA_2 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 2]); - const __m128i inA_3 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 3]); - const __m128i inB_0 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 0]); - const __m128i inB_1 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 1]); - const __m128i inB_2 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 2]); - const __m128i inB_3 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 3]); - - // Combine inA and inB (we'll do two transforms in parallel). - const __m128i inAB_0 = _mm_unpacklo_epi8(inA_0, inB_0); - const __m128i inAB_1 = _mm_unpacklo_epi8(inA_1, inB_1); - const __m128i inAB_2 = _mm_unpacklo_epi8(inA_2, inB_2); - const __m128i inAB_3 = _mm_unpacklo_epi8(inA_3, inB_3); - // a00 b00 a01 b01 a02 b03 a03 b03 0 0 0 0 0 0 0 0 - // a10 b10 a11 b11 a12 b12 a13 b13 0 0 0 0 0 0 0 0 - // a20 b20 a21 b21 a22 b22 a23 b23 0 0 0 0 0 0 0 0 - // a30 b30 a31 b31 a32 b32 a33 b33 0 0 0 0 0 0 0 0 - - // Transpose the two 4x4, discarding the filling zeroes. - const __m128i transpose0_0 = _mm_unpacklo_epi8(inAB_0, inAB_2); - const __m128i transpose0_1 = _mm_unpacklo_epi8(inAB_1, inAB_3); - // a00 a20 b00 b20 a01 a21 b01 b21 a02 a22 b02 b22 a03 a23 b03 b23 - // a10 a30 b10 b30 a11 a31 b11 b31 a12 a32 b12 b32 a13 a33 b13 b33 - const __m128i transpose1_0 = _mm_unpacklo_epi8(transpose0_0, transpose0_1); - const __m128i transpose1_1 = _mm_unpackhi_epi8(transpose0_0, transpose0_1); - // a00 a10 a20 a30 b00 b10 b20 b30 a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 a03 a13 a23 a33 b03 b13 b23 b33 - - // Convert to 16b. - tmp_0 = _mm_cvtepu8_epi16(transpose1_0); - tmp_1 = _mm_cvtepu8_epi16(_mm_srli_si128(transpose1_0, 8)); - tmp_2 = _mm_cvtepu8_epi16(transpose1_1); - tmp_3 = _mm_cvtepu8_epi16(_mm_srli_si128(transpose1_1, 8)); - // a00 a10 a20 a30 b00 b10 b20 b30 - // a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 - // a03 a13 a23 a33 b03 b13 b23 b33 - } - - // Horizontal pass and subsequent transpose. - { - // Calculate a and b (two 4x4 at once). - const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2); - const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3); - const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3); - const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2); - const __m128i b0 = _mm_add_epi16(a0, a1); - const __m128i b1 = _mm_add_epi16(a3, a2); - const __m128i b2 = _mm_sub_epi16(a3, a2); - const __m128i b3 = _mm_sub_epi16(a0, a1); - // a00 a01 a02 a03 b00 b01 b02 b03 - // a10 a11 a12 a13 b10 b11 b12 b13 - // a20 a21 a22 a23 b20 b21 b22 b23 - // a30 a31 a32 a33 b30 b31 b32 b33 - - // Transpose the two 4x4. - const __m128i transpose0_0 = _mm_unpacklo_epi16(b0, b1); - const __m128i transpose0_1 = _mm_unpacklo_epi16(b2, b3); - const __m128i transpose0_2 = _mm_unpackhi_epi16(b0, b1); - const __m128i transpose0_3 = _mm_unpackhi_epi16(b2, b3); - // a00 a10 a01 a11 a02 a12 a03 a13 - // a20 a30 a21 a31 a22 a32 a23 a33 - // b00 b10 b01 b11 b02 b12 b03 b13 - // b20 b30 b21 b31 b22 b32 b23 b33 - const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3); - const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3); - // a00 a10 a20 a30 a01 a11 a21 a31 - // b00 b10 b20 b30 b01 b11 b21 b31 - // a02 a12 a22 a32 a03 a13 a23 a33 - // b02 b12 a22 b32 b03 b13 b23 b33 - tmp_0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1); - tmp_1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1); - tmp_2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3); - tmp_3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3); - // a00 a10 a20 a30 b00 b10 b20 b30 - // a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 - // a03 a13 a23 a33 b03 b13 b23 b33 - } - - // Vertical pass and difference of weighted sums. - { - // Load all inputs. - const __m128i w_0 = _mm_loadu_si128((const __m128i*)&w[0]); - const __m128i w_8 = _mm_loadu_si128((const __m128i*)&w[8]); - - // Calculate a and b (two 4x4 at once). - const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2); - const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3); - const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3); - const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2); - const __m128i b0 = _mm_add_epi16(a0, a1); - const __m128i b1 = _mm_add_epi16(a3, a2); - const __m128i b2 = _mm_sub_epi16(a3, a2); - const __m128i b3 = _mm_sub_epi16(a0, a1); - - // Separate the transforms of inA and inB. - __m128i A_b0 = _mm_unpacklo_epi64(b0, b1); - __m128i A_b2 = _mm_unpacklo_epi64(b2, b3); - __m128i B_b0 = _mm_unpackhi_epi64(b0, b1); - __m128i B_b2 = _mm_unpackhi_epi64(b2, b3); - - A_b0 = _mm_abs_epi16(A_b0); - A_b2 = _mm_abs_epi16(A_b2); - B_b0 = _mm_abs_epi16(B_b0); - B_b2 = _mm_abs_epi16(B_b2); - - // weighted sums - A_b0 = _mm_madd_epi16(A_b0, w_0); - A_b2 = _mm_madd_epi16(A_b2, w_8); - B_b0 = _mm_madd_epi16(B_b0, w_0); - B_b2 = _mm_madd_epi16(B_b2, w_8); - A_b0 = _mm_add_epi32(A_b0, A_b2); - B_b0 = _mm_add_epi32(B_b0, B_b2); - - // difference of weighted sums - A_b2 = _mm_sub_epi32(A_b0, B_b0); - // cascading summation of the differences - B_b0 = _mm_hadd_epi32(A_b2, A_b2); - B_b2 = _mm_hadd_epi32(B_b0, B_b0); - return _mm_cvtsi128_si32(B_b2); - } -} - -static int Disto4x4(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - const int diff_sum = TTransform(a, b, w); - return abs(diff_sum) >> 5; -} - -static int Disto16x16(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - int D = 0; - int x, y; - for (y = 0; y < 16 * BPS; y += 4 * BPS) { - for (x = 0; x < 16; x += 4) { - D += Disto4x4(a + x + y, b + x + y, w); - } - } - return D; -} - -//------------------------------------------------------------------------------ -// Quantization -// - -// Generates a pshufb constant for shuffling 16b words. -#define PSHUFB_CST(A,B,C,D,E,F,G,H) \ - _mm_set_epi8(2 * (H) + 1, 2 * (H) + 0, 2 * (G) + 1, 2 * (G) + 0, \ - 2 * (F) + 1, 2 * (F) + 0, 2 * (E) + 1, 2 * (E) + 0, \ - 2 * (D) + 1, 2 * (D) + 0, 2 * (C) + 1, 2 * (C) + 0, \ - 2 * (B) + 1, 2 * (B) + 0, 2 * (A) + 1, 2 * (A) + 0) - -static WEBP_INLINE int DoQuantizeBlock(int16_t in[16], int16_t out[16], - const uint16_t* const sharpen, - const VP8Matrix* const mtx) { - const __m128i max_coeff_2047 = _mm_set1_epi16(MAX_LEVEL); - const __m128i zero = _mm_setzero_si128(); - __m128i out0, out8; - __m128i packed_out; - - // Load all inputs. - __m128i in0 = _mm_loadu_si128((__m128i*)&in[0]); - __m128i in8 = _mm_loadu_si128((__m128i*)&in[8]); - const __m128i iq0 = _mm_loadu_si128((const __m128i*)&mtx->iq_[0]); - const __m128i iq8 = _mm_loadu_si128((const __m128i*)&mtx->iq_[8]); - const __m128i q0 = _mm_loadu_si128((const __m128i*)&mtx->q_[0]); - const __m128i q8 = _mm_loadu_si128((const __m128i*)&mtx->q_[8]); - - // coeff = abs(in) - __m128i coeff0 = _mm_abs_epi16(in0); - __m128i coeff8 = _mm_abs_epi16(in8); - - // coeff = abs(in) + sharpen - if (sharpen != NULL) { - const __m128i sharpen0 = _mm_loadu_si128((const __m128i*)&sharpen[0]); - const __m128i sharpen8 = _mm_loadu_si128((const __m128i*)&sharpen[8]); - coeff0 = _mm_add_epi16(coeff0, sharpen0); - coeff8 = _mm_add_epi16(coeff8, sharpen8); - } - - // out = (coeff * iQ + B) >> QFIX - { - // doing calculations with 32b precision (QFIX=17) - // out = (coeff * iQ) - const __m128i coeff_iQ0H = _mm_mulhi_epu16(coeff0, iq0); - const __m128i coeff_iQ0L = _mm_mullo_epi16(coeff0, iq0); - const __m128i coeff_iQ8H = _mm_mulhi_epu16(coeff8, iq8); - const __m128i coeff_iQ8L = _mm_mullo_epi16(coeff8, iq8); - __m128i out_00 = _mm_unpacklo_epi16(coeff_iQ0L, coeff_iQ0H); - __m128i out_04 = _mm_unpackhi_epi16(coeff_iQ0L, coeff_iQ0H); - __m128i out_08 = _mm_unpacklo_epi16(coeff_iQ8L, coeff_iQ8H); - __m128i out_12 = _mm_unpackhi_epi16(coeff_iQ8L, coeff_iQ8H); - // out = (coeff * iQ + B) - const __m128i bias_00 = _mm_loadu_si128((const __m128i*)&mtx->bias_[0]); - const __m128i bias_04 = _mm_loadu_si128((const __m128i*)&mtx->bias_[4]); - const __m128i bias_08 = _mm_loadu_si128((const __m128i*)&mtx->bias_[8]); - const __m128i bias_12 = _mm_loadu_si128((const __m128i*)&mtx->bias_[12]); - out_00 = _mm_add_epi32(out_00, bias_00); - out_04 = _mm_add_epi32(out_04, bias_04); - out_08 = _mm_add_epi32(out_08, bias_08); - out_12 = _mm_add_epi32(out_12, bias_12); - // out = QUANTDIV(coeff, iQ, B, QFIX) - out_00 = _mm_srai_epi32(out_00, QFIX); - out_04 = _mm_srai_epi32(out_04, QFIX); - out_08 = _mm_srai_epi32(out_08, QFIX); - out_12 = _mm_srai_epi32(out_12, QFIX); - - // pack result as 16b - out0 = _mm_packs_epi32(out_00, out_04); - out8 = _mm_packs_epi32(out_08, out_12); - - // if (coeff > 2047) coeff = 2047 - out0 = _mm_min_epi16(out0, max_coeff_2047); - out8 = _mm_min_epi16(out8, max_coeff_2047); - } - - // put sign back - out0 = _mm_sign_epi16(out0, in0); - out8 = _mm_sign_epi16(out8, in8); - - // in = out * Q - in0 = _mm_mullo_epi16(out0, q0); - in8 = _mm_mullo_epi16(out8, q8); - - _mm_storeu_si128((__m128i*)&in[0], in0); - _mm_storeu_si128((__m128i*)&in[8], in8); - - // zigzag the output before storing it. The re-ordering is: - // 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15 - // -> 0 1 4[8]5 2 3 6 | 9 12 13 10 [7]11 14 15 - // There's only two misplaced entries ([8] and [7]) that are crossing the - // reg's boundaries. - // We use pshufb instead of pshuflo/pshufhi. - { - const __m128i kCst_lo = PSHUFB_CST(0, 1, 4, -1, 5, 2, 3, 6); - const __m128i kCst_7 = PSHUFB_CST(-1, -1, -1, -1, 7, -1, -1, -1); - const __m128i tmp_lo = _mm_shuffle_epi8(out0, kCst_lo); - const __m128i tmp_7 = _mm_shuffle_epi8(out0, kCst_7); // extract #7 - const __m128i kCst_hi = PSHUFB_CST(1, 4, 5, 2, -1, 3, 6, 7); - const __m128i kCst_8 = PSHUFB_CST(-1, -1, -1, 0, -1, -1, -1, -1); - const __m128i tmp_hi = _mm_shuffle_epi8(out8, kCst_hi); - const __m128i tmp_8 = _mm_shuffle_epi8(out8, kCst_8); // extract #8 - const __m128i out_z0 = _mm_or_si128(tmp_lo, tmp_8); - const __m128i out_z8 = _mm_or_si128(tmp_hi, tmp_7); - _mm_storeu_si128((__m128i*)&out[0], out_z0); - _mm_storeu_si128((__m128i*)&out[8], out_z8); - packed_out = _mm_packs_epi16(out_z0, out_z8); - } - - // detect if all 'out' values are zeroes or not - return (_mm_movemask_epi8(_mm_cmpeq_epi8(packed_out, zero)) != 0xffff); -} - -#undef PSHUFB_CST - -static int QuantizeBlock(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - return DoQuantizeBlock(in, out, &mtx->sharpen_[0], mtx); -} - -static int QuantizeBlockWHT(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - return DoQuantizeBlock(in, out, NULL, mtx); -} - -static int Quantize2Blocks(int16_t in[32], int16_t out[32], - const VP8Matrix* const mtx) { - int nz; - const uint16_t* const sharpen = &mtx->sharpen_[0]; - nz = DoQuantizeBlock(in + 0 * 16, out + 0 * 16, sharpen, mtx) << 0; - nz |= DoQuantizeBlock(in + 1 * 16, out + 1 * 16, sharpen, mtx) << 1; - return nz; -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8EncDspInitSSE41(void); -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitSSE41(void) { - VP8CollectHistogram = CollectHistogram; - VP8EncQuantizeBlock = QuantizeBlock; - VP8EncQuantize2Blocks = Quantize2Blocks; - VP8EncQuantizeBlockWHT = QuantizeBlockWHT; - VP8TDisto4x4 = Disto4x4; - VP8TDisto16x16 = Disto16x16; -} - -#else // !WEBP_USE_SSE41 - -WEBP_DSP_INIT_STUB(VP8EncDspInitSSE41) - -#endif // WEBP_USE_SSE41 diff --git a/Example-Mac/Pods/libwebp/src/dsp/filters.c b/Example-Mac/Pods/libwebp/src/dsp/filters.c deleted file mode 100644 index 5c30f2e4..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/filters.c +++ /dev/null @@ -1,240 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Spatial prediction using various filters -// -// Author: Urvang (urvang@google.com) - -#include "./dsp.h" -#include -#include -#include - -//------------------------------------------------------------------------------ -// Helpful macro. - -# define SANITY_CHECK(in, out) \ - assert(in != NULL); \ - assert(out != NULL); \ - assert(width > 0); \ - assert(height > 0); \ - assert(stride >= width); \ - assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ - (void)height; // Silence unused warning. - -static WEBP_INLINE void PredictLine(const uint8_t* src, const uint8_t* pred, - uint8_t* dst, int length, int inverse) { - int i; - if (inverse) { - for (i = 0; i < length; ++i) dst[i] = src[i] + pred[i]; - } else { - for (i = 0; i < length; ++i) dst[i] = src[i] - pred[i]; - } -} - -//------------------------------------------------------------------------------ -// Horizontal filter. - -static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { - const uint8_t* preds; - const size_t start_offset = row * stride; - const int last_row = row + num_rows; - SANITY_CHECK(in, out); - in += start_offset; - out += start_offset; - preds = inverse ? out : in; - - if (row == 0) { - // Leftmost pixel is the same as input for topmost scanline. - out[0] = in[0]; - PredictLine(in + 1, preds, out + 1, width - 1, inverse); - row = 1; - preds += stride; - in += stride; - out += stride; - } - - // Filter line-by-line. - while (row < last_row) { - // Leftmost pixel is predicted from above. - PredictLine(in, preds - stride, out, 1, inverse); - PredictLine(in + 1, preds, out + 1, width - 1, inverse); - ++row; - preds += stride; - in += stride; - out += stride; - } -} - -//------------------------------------------------------------------------------ -// Vertical filter. - -static WEBP_INLINE void DoVerticalFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { - const uint8_t* preds; - const size_t start_offset = row * stride; - const int last_row = row + num_rows; - SANITY_CHECK(in, out); - in += start_offset; - out += start_offset; - preds = inverse ? out : in; - - if (row == 0) { - // Very first top-left pixel is copied. - out[0] = in[0]; - // Rest of top scan-line is left-predicted. - PredictLine(in + 1, preds, out + 1, width - 1, inverse); - row = 1; - in += stride; - out += stride; - } else { - // We are starting from in-between. Make sure 'preds' points to prev row. - preds -= stride; - } - - // Filter line-by-line. - while (row < last_row) { - PredictLine(in, preds, out, width, inverse); - ++row; - preds += stride; - in += stride; - out += stride; - } -} - -//------------------------------------------------------------------------------ -// Gradient filter. - -static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) { - const int g = a + b - c; - return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit -} - -static WEBP_INLINE void DoGradientFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { - const uint8_t* preds; - const size_t start_offset = row * stride; - const int last_row = row + num_rows; - SANITY_CHECK(in, out); - in += start_offset; - out += start_offset; - preds = inverse ? out : in; - - // left prediction for top scan-line - if (row == 0) { - out[0] = in[0]; - PredictLine(in + 1, preds, out + 1, width - 1, inverse); - row = 1; - preds += stride; - in += stride; - out += stride; - } - - // Filter line-by-line. - while (row < last_row) { - int w; - // leftmost pixel: predict from above. - PredictLine(in, preds - stride, out, 1, inverse); - for (w = 1; w < width; ++w) { - const int pred = GradientPredictor(preds[w - 1], - preds[w - stride], - preds[w - stride - 1]); - out[w] = in[w] + (inverse ? pred : -pred); - } - ++row; - preds += stride; - in += stride; - out += stride; - } -} - -#undef SANITY_CHECK - -//------------------------------------------------------------------------------ - -static void HorizontalFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoHorizontalFilter(data, width, height, stride, 0, height, 0, filtered_data); -} - -static void VerticalFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoVerticalFilter(data, width, height, stride, 0, height, 0, filtered_data); -} - - -static void GradientFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoGradientFilter(data, width, height, stride, 0, height, 0, filtered_data); -} - - -//------------------------------------------------------------------------------ - -static void VerticalUnfilter(int width, int height, int stride, int row, - int num_rows, uint8_t* data) { - DoVerticalFilter(data, width, height, stride, row, num_rows, 1, data); -} - -static void HorizontalUnfilter(int width, int height, int stride, int row, - int num_rows, uint8_t* data) { - DoHorizontalFilter(data, width, height, stride, row, num_rows, 1, data); -} - -static void GradientUnfilter(int width, int height, int stride, int row, - int num_rows, uint8_t* data) { - DoGradientFilter(data, width, height, stride, row, num_rows, 1, data); -} - -//------------------------------------------------------------------------------ -// Init function - -WebPFilterFunc WebPFilters[WEBP_FILTER_LAST]; -WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST]; - -extern void VP8FiltersInitMIPSdspR2(void); -extern void VP8FiltersInitSSE2(void); - -static volatile VP8CPUInfo filters_last_cpuinfo_used = - (VP8CPUInfo)&filters_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInit(void) { - if (filters_last_cpuinfo_used == VP8GetCPUInfo) return; - - WebPUnfilters[WEBP_FILTER_NONE] = NULL; - WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter; - WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter; - WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter; - - WebPFilters[WEBP_FILTER_NONE] = NULL; - WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter; - WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter; - WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter; - - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - VP8FiltersInitSSE2(); - } -#endif -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - VP8FiltersInitMIPSdspR2(); - } -#endif - } - filters_last_cpuinfo_used = VP8GetCPUInfo; -} diff --git a/Example-Mac/Pods/libwebp/src/dsp/filters_mips_dsp_r2.c b/Example-Mac/Pods/libwebp/src/dsp/filters_mips_dsp_r2.c deleted file mode 100644 index 8134af51..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/filters_mips_dsp_r2.c +++ /dev/null @@ -1,405 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Spatial prediction using various filters -// -// Author(s): Branimir Vasic (branimir.vasic@imgtec.com) -// Djordje Pesut (djordje.pesut@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS_DSP_R2) - -#include "../dsp/dsp.h" -#include -#include -#include - -//------------------------------------------------------------------------------ -// Helpful macro. - -# define SANITY_CHECK(in, out) \ - assert(in != NULL); \ - assert(out != NULL); \ - assert(width > 0); \ - assert(height > 0); \ - assert(stride >= width); \ - assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ - (void)height; // Silence unused warning. - -// if INVERSE -// preds == &dst[-1] == &src[-1] -// else -// preds == &src[-1] != &dst[-1] -#define DO_PREDICT_LINE(SRC, DST, LENGTH, INVERSE) do { \ - const uint8_t* psrc = (uint8_t*)(SRC); \ - uint8_t* pdst = (uint8_t*)(DST); \ - const int ilength = (int)(LENGTH); \ - int temp0, temp1, temp2, temp3, temp4, temp5, temp6; \ - __asm__ volatile ( \ - ".set push \n\t" \ - ".set noreorder \n\t" \ - "srl %[temp0], %[length], 0x2 \n\t" \ - "beqz %[temp0], 4f \n\t" \ - " andi %[temp6], %[length], 0x3 \n\t" \ - ".if " #INVERSE " \n\t" \ - "lbu %[temp1], -1(%[src]) \n\t" \ - "1: \n\t" \ - "lbu %[temp2], 0(%[src]) \n\t" \ - "lbu %[temp3], 1(%[src]) \n\t" \ - "lbu %[temp4], 2(%[src]) \n\t" \ - "lbu %[temp5], 3(%[src]) \n\t" \ - "addiu %[src], %[src], 4 \n\t" \ - "addiu %[temp0], %[temp0], -1 \n\t" \ - "addu %[temp2], %[temp2], %[temp1] \n\t" \ - "addu %[temp3], %[temp3], %[temp2] \n\t" \ - "addu %[temp4], %[temp4], %[temp3] \n\t" \ - "addu %[temp1], %[temp5], %[temp4] \n\t" \ - "sb %[temp2], -4(%[src]) \n\t" \ - "sb %[temp3], -3(%[src]) \n\t" \ - "sb %[temp4], -2(%[src]) \n\t" \ - "bnez %[temp0], 1b \n\t" \ - " sb %[temp1], -1(%[src]) \n\t" \ - ".else \n\t" \ - "1: \n\t" \ - "ulw %[temp1], -1(%[src]) \n\t" \ - "ulw %[temp2], 0(%[src]) \n\t" \ - "addiu %[src], %[src], 4 \n\t" \ - "addiu %[temp0], %[temp0], -1 \n\t" \ - "subu.qb %[temp3], %[temp2], %[temp1] \n\t" \ - "usw %[temp3], 0(%[dst]) \n\t" \ - "bnez %[temp0], 1b \n\t" \ - " addiu %[dst], %[dst], 4 \n\t" \ - ".endif \n\t" \ - "4: \n\t" \ - "beqz %[temp6], 3f \n\t" \ - " nop \n\t" \ - "2: \n\t" \ - "lbu %[temp1], -1(%[src]) \n\t" \ - "lbu %[temp2], 0(%[src]) \n\t" \ - "addiu %[src], %[src], 1 \n\t" \ - ".if " #INVERSE " \n\t" \ - "addu %[temp3], %[temp1], %[temp2] \n\t" \ - "sb %[temp3], -1(%[src]) \n\t" \ - ".else \n\t" \ - "subu %[temp3], %[temp1], %[temp2] \n\t" \ - "sb %[temp3], 0(%[dst]) \n\t" \ - ".endif \n\t" \ - "addiu %[temp6], %[temp6], -1 \n\t" \ - "bnez %[temp6], 2b \n\t" \ - " addiu %[dst], %[dst], 1 \n\t" \ - "3: \n\t" \ - ".set pop \n\t" \ - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \ - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \ - [temp6]"=&r"(temp6), [dst]"+&r"(pdst), [src]"+&r"(psrc) \ - : [length]"r"(ilength) \ - : "memory" \ - ); \ - } while (0) - -static WEBP_INLINE void PredictLine(const uint8_t* src, uint8_t* dst, - int length, int inverse) { - if (inverse) { - DO_PREDICT_LINE(src, dst, length, 1); - } else { - DO_PREDICT_LINE(src, dst, length, 0); - } -} - -#define DO_PREDICT_LINE_VERTICAL(SRC, PRED, DST, LENGTH, INVERSE) do { \ - const uint8_t* psrc = (uint8_t*)(SRC); \ - const uint8_t* ppred = (uint8_t*)(PRED); \ - uint8_t* pdst = (uint8_t*)(DST); \ - const int ilength = (int)(LENGTH); \ - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; \ - __asm__ volatile ( \ - ".set push \n\t" \ - ".set noreorder \n\t" \ - "srl %[temp0], %[length], 0x3 \n\t" \ - "beqz %[temp0], 4f \n\t" \ - " andi %[temp7], %[length], 0x7 \n\t" \ - "1: \n\t" \ - "ulw %[temp1], 0(%[src]) \n\t" \ - "ulw %[temp2], 0(%[pred]) \n\t" \ - "ulw %[temp3], 4(%[src]) \n\t" \ - "ulw %[temp4], 4(%[pred]) \n\t" \ - "addiu %[src], %[src], 8 \n\t" \ - ".if " #INVERSE " \n\t" \ - "addu.qb %[temp5], %[temp1], %[temp2] \n\t" \ - "addu.qb %[temp6], %[temp3], %[temp4] \n\t" \ - ".else \n\t" \ - "subu.qb %[temp5], %[temp1], %[temp2] \n\t" \ - "subu.qb %[temp6], %[temp3], %[temp4] \n\t" \ - ".endif \n\t" \ - "addiu %[pred], %[pred], 8 \n\t" \ - "usw %[temp5], 0(%[dst]) \n\t" \ - "usw %[temp6], 4(%[dst]) \n\t" \ - "addiu %[temp0], %[temp0], -1 \n\t" \ - "bnez %[temp0], 1b \n\t" \ - " addiu %[dst], %[dst], 8 \n\t" \ - "4: \n\t" \ - "beqz %[temp7], 3f \n\t" \ - " nop \n\t" \ - "2: \n\t" \ - "lbu %[temp1], 0(%[src]) \n\t" \ - "lbu %[temp2], 0(%[pred]) \n\t" \ - "addiu %[src], %[src], 1 \n\t" \ - "addiu %[pred], %[pred], 1 \n\t" \ - ".if " #INVERSE " \n\t" \ - "addu %[temp3], %[temp1], %[temp2] \n\t" \ - ".else \n\t" \ - "subu %[temp3], %[temp1], %[temp2] \n\t" \ - ".endif \n\t" \ - "sb %[temp3], 0(%[dst]) \n\t" \ - "addiu %[temp7], %[temp7], -1 \n\t" \ - "bnez %[temp7], 2b \n\t" \ - " addiu %[dst], %[dst], 1 \n\t" \ - "3: \n\t" \ - ".set pop \n\t" \ - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \ - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \ - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [pred]"+&r"(ppred), \ - [dst]"+&r"(pdst), [src]"+&r"(psrc) \ - : [length]"r"(ilength) \ - : "memory" \ - ); \ - } while (0) - -#define PREDICT_LINE_ONE_PASS(SRC, PRED, DST, INVERSE) do { \ - int temp1, temp2, temp3; \ - __asm__ volatile ( \ - "lbu %[temp1], 0(%[src]) \n\t" \ - "lbu %[temp2], 0(%[pred]) \n\t" \ - ".if " #INVERSE " \n\t" \ - "addu %[temp3], %[temp1], %[temp2] \n\t" \ - ".else \n\t" \ - "subu %[temp3], %[temp1], %[temp2] \n\t" \ - ".endif \n\t" \ - "sb %[temp3], 0(%[dst]) \n\t" \ - : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3) \ - : [pred]"r"((PRED)), [dst]"r"((DST)), [src]"r"((SRC)) \ - : "memory" \ - ); \ - } while (0) - -//------------------------------------------------------------------------------ -// Horizontal filter. - -#define FILTER_LINE_BY_LINE(INVERSE) do { \ - while (row < last_row) { \ - PREDICT_LINE_ONE_PASS(in, preds - stride, out, INVERSE); \ - DO_PREDICT_LINE(in + 1, out + 1, width - 1, INVERSE); \ - ++row; \ - preds += stride; \ - in += stride; \ - out += stride; \ - } \ - } while (0) - -static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { - const uint8_t* preds; - const size_t start_offset = row * stride; - const int last_row = row + num_rows; - SANITY_CHECK(in, out); - in += start_offset; - out += start_offset; - preds = inverse ? out : in; - - if (row == 0) { - // Leftmost pixel is the same as input for topmost scanline. - out[0] = in[0]; - PredictLine(in + 1, out + 1, width - 1, inverse); - row = 1; - preds += stride; - in += stride; - out += stride; - } - - // Filter line-by-line. - if (inverse) { - FILTER_LINE_BY_LINE(1); - } else { - FILTER_LINE_BY_LINE(0); - } -} - -#undef FILTER_LINE_BY_LINE - -static void HorizontalFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoHorizontalFilter(data, width, height, stride, 0, height, 0, filtered_data); -} - -static void HorizontalUnfilter(int width, int height, int stride, int row, - int num_rows, uint8_t* data) { - DoHorizontalFilter(data, width, height, stride, row, num_rows, 1, data); -} - -//------------------------------------------------------------------------------ -// Vertical filter. - -#define FILTER_LINE_BY_LINE(INVERSE) do { \ - while (row < last_row) { \ - DO_PREDICT_LINE_VERTICAL(in, preds, out, width, INVERSE); \ - ++row; \ - preds += stride; \ - in += stride; \ - out += stride; \ - } \ - } while (0) - -static WEBP_INLINE void DoVerticalFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { - const uint8_t* preds; - const size_t start_offset = row * stride; - const int last_row = row + num_rows; - SANITY_CHECK(in, out); - in += start_offset; - out += start_offset; - preds = inverse ? out : in; - - if (row == 0) { - // Very first top-left pixel is copied. - out[0] = in[0]; - // Rest of top scan-line is left-predicted. - PredictLine(in + 1, out + 1, width - 1, inverse); - row = 1; - in += stride; - out += stride; - } else { - // We are starting from in-between. Make sure 'preds' points to prev row. - preds -= stride; - } - - // Filter line-by-line. - if (inverse) { - FILTER_LINE_BY_LINE(1); - } else { - FILTER_LINE_BY_LINE(0); - } -} - -#undef FILTER_LINE_BY_LINE -#undef DO_PREDICT_LINE_VERTICAL - -static void VerticalFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoVerticalFilter(data, width, height, stride, 0, height, 0, filtered_data); -} - -static void VerticalUnfilter(int width, int height, int stride, int row, - int num_rows, uint8_t* data) { - DoVerticalFilter(data, width, height, stride, row, num_rows, 1, data); -} - -//------------------------------------------------------------------------------ -// Gradient filter. - -static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) { - int temp0; - __asm__ volatile ( - "addu %[temp0], %[a], %[b] \n\t" - "subu %[temp0], %[temp0], %[c] \n\t" - "shll_s.w %[temp0], %[temp0], 23 \n\t" - "precrqu_s.qb.ph %[temp0], %[temp0], $zero \n\t" - "srl %[temp0], %[temp0], 24 \n\t" - : [temp0]"=&r"(temp0) - : [a]"r"(a),[b]"r"(b),[c]"r"(c) - ); - return temp0; -} - -#define FILTER_LINE_BY_LINE(INVERSE, PREDS, OPERATION) do { \ - while (row < last_row) { \ - int w; \ - PREDICT_LINE_ONE_PASS(in, PREDS - stride, out, INVERSE); \ - for (w = 1; w < width; ++w) { \ - const int pred = GradientPredictor(PREDS[w - 1], \ - PREDS[w - stride], \ - PREDS[w - stride - 1]); \ - out[w] = in[w] OPERATION pred; \ - } \ - ++row; \ - in += stride; \ - out += stride; \ - } \ - } while (0) - -static WEBP_INLINE void DoGradientFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { - const uint8_t* preds; - const size_t start_offset = row * stride; - const int last_row = row + num_rows; - SANITY_CHECK(in, out); - in += start_offset; - out += start_offset; - preds = inverse ? out : in; - - // left prediction for top scan-line - if (row == 0) { - out[0] = in[0]; - PredictLine(in + 1, out + 1, width - 1, inverse); - row = 1; - preds += stride; - in += stride; - out += stride; - } - - // Filter line-by-line. - if (inverse) { - FILTER_LINE_BY_LINE(1, out, +); - } else { - FILTER_LINE_BY_LINE(0, in, -); - } -} - -#undef FILTER_LINE_BY_LINE - -static void GradientFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoGradientFilter(data, width, height, stride, 0, height, 0, filtered_data); -} - -static void GradientUnfilter(int width, int height, int stride, int row, - int num_rows, uint8_t* data) { - DoGradientFilter(data, width, height, stride, row, num_rows, 1, data); -} - -#undef PREDICT_LINE_ONE_PASS -#undef DO_PREDICT_LINE -#undef SANITY_CHECK - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8FiltersInitMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitMIPSdspR2(void) { - WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter; - WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter; - WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter; - - WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter; - WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter; - WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter; -} - -#else // !WEBP_USE_MIPS_DSP_R2 - -WEBP_DSP_INIT_STUB(VP8FiltersInitMIPSdspR2) - -#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/Example-Mac/Pods/libwebp/src/dsp/filters_sse2.c b/Example-Mac/Pods/libwebp/src/dsp/filters_sse2.c deleted file mode 100644 index bf93342e..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/filters_sse2.c +++ /dev/null @@ -1,352 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// SSE2 variant of alpha filters -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE2) - -#include -#include -#include -#include - -//------------------------------------------------------------------------------ -// Helpful macro. - -# define SANITY_CHECK(in, out) \ - assert(in != NULL); \ - assert(out != NULL); \ - assert(width > 0); \ - assert(height > 0); \ - assert(stride >= width); \ - assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ - (void)height; // Silence unused warning. - -static void PredictLineTop(const uint8_t* src, const uint8_t* pred, - uint8_t* dst, int length, int inverse) { - int i; - const int max_pos = length & ~31; - assert(length >= 0); - if (inverse) { - for (i = 0; i < max_pos; i += 32) { - const __m128i A0 = _mm_loadu_si128((const __m128i*)&src[i + 0]); - const __m128i A1 = _mm_loadu_si128((const __m128i*)&src[i + 16]); - const __m128i B0 = _mm_loadu_si128((const __m128i*)&pred[i + 0]); - const __m128i B1 = _mm_loadu_si128((const __m128i*)&pred[i + 16]); - const __m128i C0 = _mm_add_epi8(A0, B0); - const __m128i C1 = _mm_add_epi8(A1, B1); - _mm_storeu_si128((__m128i*)&dst[i + 0], C0); - _mm_storeu_si128((__m128i*)&dst[i + 16], C1); - } - for (; i < length; ++i) dst[i] = src[i] + pred[i]; - } else { - for (i = 0; i < max_pos; i += 32) { - const __m128i A0 = _mm_loadu_si128((const __m128i*)&src[i + 0]); - const __m128i A1 = _mm_loadu_si128((const __m128i*)&src[i + 16]); - const __m128i B0 = _mm_loadu_si128((const __m128i*)&pred[i + 0]); - const __m128i B1 = _mm_loadu_si128((const __m128i*)&pred[i + 16]); - const __m128i C0 = _mm_sub_epi8(A0, B0); - const __m128i C1 = _mm_sub_epi8(A1, B1); - _mm_storeu_si128((__m128i*)&dst[i + 0], C0); - _mm_storeu_si128((__m128i*)&dst[i + 16], C1); - } - for (; i < length; ++i) dst[i] = src[i] - pred[i]; - } -} - -// Special case for left-based prediction (when preds==dst-1 or preds==src-1). -static void PredictLineLeft(const uint8_t* src, uint8_t* dst, int length, - int inverse) { - int i; - if (length <= 0) return; - if (inverse) { - const int max_pos = length & ~7; - __m128i last = _mm_set_epi32(0, 0, 0, dst[-1]); - for (i = 0; i < max_pos; i += 8) { - const __m128i A0 = _mm_loadl_epi64((const __m128i*)(src + i)); - const __m128i A1 = _mm_add_epi8(A0, last); - const __m128i A2 = _mm_slli_si128(A1, 1); - const __m128i A3 = _mm_add_epi8(A1, A2); - const __m128i A4 = _mm_slli_si128(A3, 2); - const __m128i A5 = _mm_add_epi8(A3, A4); - const __m128i A6 = _mm_slli_si128(A5, 4); - const __m128i A7 = _mm_add_epi8(A5, A6); - _mm_storel_epi64((__m128i*)(dst + i), A7); - last = _mm_srli_epi64(A7, 56); - } - for (; i < length; ++i) dst[i] = src[i] + dst[i - 1]; - } else { - const int max_pos = length & ~31; - for (i = 0; i < max_pos; i += 32) { - const __m128i A0 = _mm_loadu_si128((const __m128i*)(src + i + 0 )); - const __m128i B0 = _mm_loadu_si128((const __m128i*)(src + i + 0 - 1)); - const __m128i A1 = _mm_loadu_si128((const __m128i*)(src + i + 16 )); - const __m128i B1 = _mm_loadu_si128((const __m128i*)(src + i + 16 - 1)); - const __m128i C0 = _mm_sub_epi8(A0, B0); - const __m128i C1 = _mm_sub_epi8(A1, B1); - _mm_storeu_si128((__m128i*)(dst + i + 0), C0); - _mm_storeu_si128((__m128i*)(dst + i + 16), C1); - } - for (; i < length; ++i) dst[i] = src[i] - src[i - 1]; - } -} - -static void PredictLineC(const uint8_t* src, const uint8_t* pred, - uint8_t* dst, int length, int inverse) { - int i; - if (inverse) { - for (i = 0; i < length; ++i) dst[i] = src[i] + pred[i]; - } else { - for (i = 0; i < length; ++i) dst[i] = src[i] - pred[i]; - } -} - -//------------------------------------------------------------------------------ -// Horizontal filter. - -static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { - const uint8_t* preds; - const size_t start_offset = row * stride; - const int last_row = row + num_rows; - SANITY_CHECK(in, out); - in += start_offset; - out += start_offset; - preds = inverse ? out : in; - - if (row == 0) { - // Leftmost pixel is the same as input for topmost scanline. - out[0] = in[0]; - PredictLineLeft(in + 1, out + 1, width - 1, inverse); - row = 1; - preds += stride; - in += stride; - out += stride; - } - - // Filter line-by-line. - while (row < last_row) { - // Leftmost pixel is predicted from above. - PredictLineC(in, preds - stride, out, 1, inverse); - PredictLineLeft(in + 1, out + 1, width - 1, inverse); - ++row; - preds += stride; - in += stride; - out += stride; - } -} - -//------------------------------------------------------------------------------ -// Vertical filter. - -static WEBP_INLINE void DoVerticalFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { - const uint8_t* preds; - const size_t start_offset = row * stride; - const int last_row = row + num_rows; - SANITY_CHECK(in, out); - in += start_offset; - out += start_offset; - preds = inverse ? out : in; - - if (row == 0) { - // Very first top-left pixel is copied. - out[0] = in[0]; - // Rest of top scan-line is left-predicted. - PredictLineLeft(in + 1, out + 1, width - 1, inverse); - row = 1; - in += stride; - out += stride; - } else { - // We are starting from in-between. Make sure 'preds' points to prev row. - preds -= stride; - } - - // Filter line-by-line. - while (row < last_row) { - PredictLineTop(in, preds, out, width, inverse); - ++row; - preds += stride; - in += stride; - out += stride; - } -} - -//------------------------------------------------------------------------------ -// Gradient filter. - -static WEBP_INLINE int GradientPredictorC(uint8_t a, uint8_t b, uint8_t c) { - const int g = a + b - c; - return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit -} - -static void GradientPredictDirect(const uint8_t* const row, - const uint8_t* const top, - uint8_t* const out, int length) { - const int max_pos = length & ~7; - int i; - const __m128i zero = _mm_setzero_si128(); - for (i = 0; i < max_pos; i += 8) { - const __m128i A0 = _mm_loadl_epi64((const __m128i*)&row[i - 1]); - const __m128i B0 = _mm_loadl_epi64((const __m128i*)&top[i]); - const __m128i C0 = _mm_loadl_epi64((const __m128i*)&top[i - 1]); - const __m128i D = _mm_loadl_epi64((const __m128i*)&row[i]); - const __m128i A1 = _mm_unpacklo_epi8(A0, zero); - const __m128i B1 = _mm_unpacklo_epi8(B0, zero); - const __m128i C1 = _mm_unpacklo_epi8(C0, zero); - const __m128i E = _mm_add_epi16(A1, B1); - const __m128i F = _mm_sub_epi16(E, C1); - const __m128i G = _mm_packus_epi16(F, zero); - const __m128i H = _mm_sub_epi8(D, G); - _mm_storel_epi64((__m128i*)(out + i), H); - } - for (; i < length; ++i) { - out[i] = row[i] - GradientPredictorC(row[i - 1], top[i], top[i - 1]); - } -} - -static void GradientPredictInverse(const uint8_t* const in, - const uint8_t* const top, - uint8_t* const row, int length) { - if (length > 0) { - int i; - const int max_pos = length & ~7; - const __m128i zero = _mm_setzero_si128(); - __m128i A = _mm_set_epi32(0, 0, 0, row[-1]); // left sample - for (i = 0; i < max_pos; i += 8) { - const __m128i tmp0 = _mm_loadl_epi64((const __m128i*)&top[i]); - const __m128i tmp1 = _mm_loadl_epi64((const __m128i*)&top[i - 1]); - const __m128i B = _mm_unpacklo_epi8(tmp0, zero); - const __m128i C = _mm_unpacklo_epi8(tmp1, zero); - const __m128i tmp2 = _mm_loadl_epi64((const __m128i*)&in[i]); - const __m128i D = _mm_unpacklo_epi8(tmp2, zero); // base input - const __m128i E = _mm_sub_epi16(B, C); // unclipped gradient basis B - C - __m128i out = zero; // accumulator for output - __m128i mask_hi = _mm_set_epi32(0, 0, 0, 0xff); - int k = 8; - while (1) { - const __m128i tmp3 = _mm_add_epi16(A, E); // delta = A + B - C - const __m128i tmp4 = _mm_min_epi16(tmp3, mask_hi); - const __m128i tmp5 = _mm_max_epi16(tmp4, zero); // clipped delta - const __m128i tmp6 = _mm_add_epi16(tmp5, D); // add to in[] values - A = _mm_and_si128(tmp6, mask_hi); // 1-complement clip - out = _mm_or_si128(out, A); // accumulate output - if (--k == 0) break; - A = _mm_slli_si128(A, 2); // rotate left sample - mask_hi = _mm_slli_si128(mask_hi, 2); // rotate mask - } - A = _mm_srli_si128(A, 14); // prepare left sample for next iteration - _mm_storel_epi64((__m128i*)&row[i], _mm_packus_epi16(out, zero)); - } - for (; i < length; ++i) { - row[i] = in[i] + GradientPredictorC(row[i - 1], top[i], top[i - 1]); - } - } -} - -static WEBP_INLINE void DoGradientFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { - const size_t start_offset = row * stride; - const int last_row = row + num_rows; - SANITY_CHECK(in, out); - in += start_offset; - out += start_offset; - - // left prediction for top scan-line - if (row == 0) { - out[0] = in[0]; - PredictLineLeft(in + 1, out + 1, width - 1, inverse); - row = 1; - in += stride; - out += stride; - } - - // Filter line-by-line. - while (row < last_row) { - if (inverse) { - PredictLineC(in, out - stride, out, 1, inverse); // predict from above - GradientPredictInverse(in + 1, out + 1 - stride, out + 1, width - 1); - } else { - PredictLineC(in, in - stride, out, 1, inverse); - GradientPredictDirect(in + 1, in + 1 - stride, out + 1, width - 1); - } - ++row; - in += stride; - out += stride; - } -} - -#undef SANITY_CHECK - -//------------------------------------------------------------------------------ - -static void HorizontalFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoHorizontalFilter(data, width, height, stride, 0, height, 0, filtered_data); -} - -static void VerticalFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoVerticalFilter(data, width, height, stride, 0, height, 0, filtered_data); -} - - -static void GradientFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoGradientFilter(data, width, height, stride, 0, height, 0, filtered_data); -} - - -//------------------------------------------------------------------------------ - -static void VerticalUnfilter(int width, int height, int stride, int row, - int num_rows, uint8_t* data) { - DoVerticalFilter(data, width, height, stride, row, num_rows, 1, data); -} - -static void HorizontalUnfilter(int width, int height, int stride, int row, - int num_rows, uint8_t* data) { - DoHorizontalFilter(data, width, height, stride, row, num_rows, 1, data); -} - -static void GradientUnfilter(int width, int height, int stride, int row, - int num_rows, uint8_t* data) { - DoGradientFilter(data, width, height, stride, row, num_rows, 1, data); -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8FiltersInitSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitSSE2(void) { - WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter; - WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter; - WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter; - - WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter; - WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter; - WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter; -} - -#else // !WEBP_USE_SSE2 - -WEBP_DSP_INIT_STUB(VP8FiltersInitSSE2) - -#endif // WEBP_USE_SSE2 diff --git a/Example-Mac/Pods/libwebp/src/dsp/lossless.c b/Example-Mac/Pods/libwebp/src/dsp/lossless.c deleted file mode 100644 index 71ae9d4a..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/lossless.c +++ /dev/null @@ -1,635 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Image transforms and color space conversion methods for lossless decoder. -// -// Authors: Vikas Arora (vikaas.arora@gmail.com) -// Jyrki Alakuijala (jyrki@google.com) -// Urvang Joshi (urvang@google.com) - -#include "./dsp.h" - -#include -#include -#include "../dec/vp8li.h" -#include "../utils/endian_inl.h" -#include "./lossless.h" - -#define MAX_DIFF_COST (1e30f) - -//------------------------------------------------------------------------------ -// Image transforms. - -// In-place sum of each component with mod 256. -static WEBP_INLINE void AddPixelsEq(uint32_t* a, uint32_t b) { - const uint32_t alpha_and_green = (*a & 0xff00ff00u) + (b & 0xff00ff00u); - const uint32_t red_and_blue = (*a & 0x00ff00ffu) + (b & 0x00ff00ffu); - *a = (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu); -} - -static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) { - return (((a0 ^ a1) & 0xfefefefeu) >> 1) + (a0 & a1); -} - -static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) { - return Average2(Average2(a0, a2), a1); -} - -static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1, - uint32_t a2, uint32_t a3) { - return Average2(Average2(a0, a1), Average2(a2, a3)); -} - -static WEBP_INLINE uint32_t Clip255(uint32_t a) { - if (a < 256) { - return a; - } - // return 0, when a is a negative integer. - // return 255, when a is positive. - return ~a >> 24; -} - -static WEBP_INLINE int AddSubtractComponentFull(int a, int b, int c) { - return Clip255(a + b - c); -} - -static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1, - uint32_t c2) { - const int a = AddSubtractComponentFull(c0 >> 24, c1 >> 24, c2 >> 24); - const int r = AddSubtractComponentFull((c0 >> 16) & 0xff, - (c1 >> 16) & 0xff, - (c2 >> 16) & 0xff); - const int g = AddSubtractComponentFull((c0 >> 8) & 0xff, - (c1 >> 8) & 0xff, - (c2 >> 8) & 0xff); - const int b = AddSubtractComponentFull(c0 & 0xff, c1 & 0xff, c2 & 0xff); - return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b; -} - -static WEBP_INLINE int AddSubtractComponentHalf(int a, int b) { - return Clip255(a + (a - b) / 2); -} - -static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1, - uint32_t c2) { - const uint32_t ave = Average2(c0, c1); - const int a = AddSubtractComponentHalf(ave >> 24, c2 >> 24); - const int r = AddSubtractComponentHalf((ave >> 16) & 0xff, (c2 >> 16) & 0xff); - const int g = AddSubtractComponentHalf((ave >> 8) & 0xff, (c2 >> 8) & 0xff); - const int b = AddSubtractComponentHalf((ave >> 0) & 0xff, (c2 >> 0) & 0xff); - return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b; -} - -// gcc-4.9 on ARM generates incorrect code in Select() when Sub3() is inlined. -#if defined(__arm__) && LOCAL_GCC_VERSION == 0x409 -# define LOCAL_INLINE __attribute__ ((noinline)) -#else -# define LOCAL_INLINE WEBP_INLINE -#endif - -static LOCAL_INLINE int Sub3(int a, int b, int c) { - const int pb = b - c; - const int pa = a - c; - return abs(pb) - abs(pa); -} - -#undef LOCAL_INLINE - -static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) { - const int pa_minus_pb = - Sub3((a >> 24) , (b >> 24) , (c >> 24) ) + - Sub3((a >> 16) & 0xff, (b >> 16) & 0xff, (c >> 16) & 0xff) + - Sub3((a >> 8) & 0xff, (b >> 8) & 0xff, (c >> 8) & 0xff) + - Sub3((a ) & 0xff, (b ) & 0xff, (c ) & 0xff); - return (pa_minus_pb <= 0) ? a : b; -} - -//------------------------------------------------------------------------------ -// Predictors - -static uint32_t Predictor0(uint32_t left, const uint32_t* const top) { - (void)top; - (void)left; - return ARGB_BLACK; -} -static uint32_t Predictor1(uint32_t left, const uint32_t* const top) { - (void)top; - return left; -} -static uint32_t Predictor2(uint32_t left, const uint32_t* const top) { - (void)left; - return top[0]; -} -static uint32_t Predictor3(uint32_t left, const uint32_t* const top) { - (void)left; - return top[1]; -} -static uint32_t Predictor4(uint32_t left, const uint32_t* const top) { - (void)left; - return top[-1]; -} -static uint32_t Predictor5(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average3(left, top[0], top[1]); - return pred; -} -static uint32_t Predictor6(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2(left, top[-1]); - return pred; -} -static uint32_t Predictor7(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2(left, top[0]); - return pred; -} -static uint32_t Predictor8(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2(top[-1], top[0]); - (void)left; - return pred; -} -static uint32_t Predictor9(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2(top[0], top[1]); - (void)left; - return pred; -} -static uint32_t Predictor10(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average4(left, top[-1], top[0], top[1]); - return pred; -} -static uint32_t Predictor11(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Select(top[0], left, top[-1]); - return pred; -} -static uint32_t Predictor12(uint32_t left, const uint32_t* const top) { - const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]); - return pred; -} -static uint32_t Predictor13(uint32_t left, const uint32_t* const top) { - const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]); - return pred; -} - -//------------------------------------------------------------------------------ - -// Inverse prediction. -static void PredictorInverseTransform(const VP8LTransform* const transform, - int y_start, int y_end, uint32_t* data) { - const int width = transform->xsize_; - if (y_start == 0) { // First Row follows the L (mode=1) mode. - int x; - const uint32_t pred0 = Predictor0(data[-1], NULL); - AddPixelsEq(data, pred0); - for (x = 1; x < width; ++x) { - const uint32_t pred1 = Predictor1(data[x - 1], NULL); - AddPixelsEq(data + x, pred1); - } - data += width; - ++y_start; - } - - { - int y = y_start; - const int tile_width = 1 << transform->bits_; - const int mask = tile_width - 1; - const int safe_width = width & ~mask; - const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_); - const uint32_t* pred_mode_base = - transform->data_ + (y >> transform->bits_) * tiles_per_row; - - while (y < y_end) { - const uint32_t pred2 = Predictor2(data[-1], data - width); - const uint32_t* pred_mode_src = pred_mode_base; - VP8LPredictorFunc pred_func; - int x = 1; - int t = 1; - // First pixel follows the T (mode=2) mode. - AddPixelsEq(data, pred2); - // .. the rest: - while (x < safe_width) { - pred_func = VP8LPredictors[((*pred_mode_src++) >> 8) & 0xf]; - for (; t < tile_width; ++t, ++x) { - const uint32_t pred = pred_func(data[x - 1], data + x - width); - AddPixelsEq(data + x, pred); - } - t = 0; - } - if (x < width) { - pred_func = VP8LPredictors[((*pred_mode_src++) >> 8) & 0xf]; - for (; x < width; ++x) { - const uint32_t pred = pred_func(data[x - 1], data + x - width); - AddPixelsEq(data + x, pred); - } - } - data += width; - ++y; - if ((y & mask) == 0) { // Use the same mask, since tiles are squares. - pred_mode_base += tiles_per_row; - } - } - } -} - -// Add green to blue and red channels (i.e. perform the inverse transform of -// 'subtract green'). -void VP8LAddGreenToBlueAndRed_C(uint32_t* data, int num_pixels) { - int i; - for (i = 0; i < num_pixels; ++i) { - const uint32_t argb = data[i]; - const uint32_t green = ((argb >> 8) & 0xff); - uint32_t red_blue = (argb & 0x00ff00ffu); - red_blue += (green << 16) | green; - red_blue &= 0x00ff00ffu; - data[i] = (argb & 0xff00ff00u) | red_blue; - } -} - -static WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred, - int8_t color) { - return (uint32_t)((int)(color_pred) * color) >> 5; -} - -static WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code, - VP8LMultipliers* const m) { - m->green_to_red_ = (color_code >> 0) & 0xff; - m->green_to_blue_ = (color_code >> 8) & 0xff; - m->red_to_blue_ = (color_code >> 16) & 0xff; -} - -void VP8LTransformColorInverse_C(const VP8LMultipliers* const m, uint32_t* data, - int num_pixels) { - int i; - for (i = 0; i < num_pixels; ++i) { - const uint32_t argb = data[i]; - const uint32_t green = argb >> 8; - const uint32_t red = argb >> 16; - uint32_t new_red = red; - uint32_t new_blue = argb; - new_red += ColorTransformDelta(m->green_to_red_, green); - new_red &= 0xff; - new_blue += ColorTransformDelta(m->green_to_blue_, green); - new_blue += ColorTransformDelta(m->red_to_blue_, new_red); - new_blue &= 0xff; - data[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue); - } -} - -// Color space inverse transform. -static void ColorSpaceInverseTransform(const VP8LTransform* const transform, - int y_start, int y_end, uint32_t* data) { - const int width = transform->xsize_; - const int tile_width = 1 << transform->bits_; - const int mask = tile_width - 1; - const int safe_width = width & ~mask; - const int remaining_width = width - safe_width; - const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_); - int y = y_start; - const uint32_t* pred_row = - transform->data_ + (y >> transform->bits_) * tiles_per_row; - - while (y < y_end) { - const uint32_t* pred = pred_row; - VP8LMultipliers m = { 0, 0, 0 }; - const uint32_t* const data_safe_end = data + safe_width; - const uint32_t* const data_end = data + width; - while (data < data_safe_end) { - ColorCodeToMultipliers(*pred++, &m); - VP8LTransformColorInverse(&m, data, tile_width); - data += tile_width; - } - if (data < data_end) { // Left-overs using C-version. - ColorCodeToMultipliers(*pred++, &m); - VP8LTransformColorInverse(&m, data, remaining_width); - data += remaining_width; - } - ++y; - if ((y & mask) == 0) pred_row += tiles_per_row; - } -} - -// Separate out pixels packed together using pixel-bundling. -// We define two methods for ARGB data (uint32_t) and alpha-only data (uint8_t). -#define COLOR_INDEX_INVERSE(FUNC_NAME, F_NAME, STATIC_DECL, TYPE, BIT_SUFFIX, \ - GET_INDEX, GET_VALUE) \ -static void F_NAME(const TYPE* src, const uint32_t* const color_map, \ - TYPE* dst, int y_start, int y_end, int width) { \ - int y; \ - for (y = y_start; y < y_end; ++y) { \ - int x; \ - for (x = 0; x < width; ++x) { \ - *dst++ = GET_VALUE(color_map[GET_INDEX(*src++)]); \ - } \ - } \ -} \ -STATIC_DECL void FUNC_NAME(const VP8LTransform* const transform, \ - int y_start, int y_end, const TYPE* src, \ - TYPE* dst) { \ - int y; \ - const int bits_per_pixel = 8 >> transform->bits_; \ - const int width = transform->xsize_; \ - const uint32_t* const color_map = transform->data_; \ - if (bits_per_pixel < 8) { \ - const int pixels_per_byte = 1 << transform->bits_; \ - const int count_mask = pixels_per_byte - 1; \ - const uint32_t bit_mask = (1 << bits_per_pixel) - 1; \ - for (y = y_start; y < y_end; ++y) { \ - uint32_t packed_pixels = 0; \ - int x; \ - for (x = 0; x < width; ++x) { \ - /* We need to load fresh 'packed_pixels' once every */ \ - /* 'pixels_per_byte' increments of x. Fortunately, pixels_per_byte */ \ - /* is a power of 2, so can just use a mask for that, instead of */ \ - /* decrementing a counter. */ \ - if ((x & count_mask) == 0) packed_pixels = GET_INDEX(*src++); \ - *dst++ = GET_VALUE(color_map[packed_pixels & bit_mask]); \ - packed_pixels >>= bits_per_pixel; \ - } \ - } \ - } else { \ - VP8LMapColor##BIT_SUFFIX(src, color_map, dst, y_start, y_end, width); \ - } \ -} - -COLOR_INDEX_INVERSE(ColorIndexInverseTransform, MapARGB, static, uint32_t, 32b, - VP8GetARGBIndex, VP8GetARGBValue) -COLOR_INDEX_INVERSE(VP8LColorIndexInverseTransformAlpha, MapAlpha, , uint8_t, - 8b, VP8GetAlphaIndex, VP8GetAlphaValue) - -#undef COLOR_INDEX_INVERSE - -void VP8LInverseTransform(const VP8LTransform* const transform, - int row_start, int row_end, - const uint32_t* const in, uint32_t* const out) { - const int width = transform->xsize_; - assert(row_start < row_end); - assert(row_end <= transform->ysize_); - switch (transform->type_) { - case SUBTRACT_GREEN: - VP8LAddGreenToBlueAndRed(out, (row_end - row_start) * width); - break; - case PREDICTOR_TRANSFORM: - PredictorInverseTransform(transform, row_start, row_end, out); - if (row_end != transform->ysize_) { - // The last predicted row in this iteration will be the top-pred row - // for the first row in next iteration. - memcpy(out - width, out + (row_end - row_start - 1) * width, - width * sizeof(*out)); - } - break; - case CROSS_COLOR_TRANSFORM: - ColorSpaceInverseTransform(transform, row_start, row_end, out); - break; - case COLOR_INDEXING_TRANSFORM: - if (in == out && transform->bits_ > 0) { - // Move packed pixels to the end of unpacked region, so that unpacking - // can occur seamlessly. - // Also, note that this is the only transform that applies on - // the effective width of VP8LSubSampleSize(xsize_, bits_). All other - // transforms work on effective width of xsize_. - const int out_stride = (row_end - row_start) * width; - const int in_stride = (row_end - row_start) * - VP8LSubSampleSize(transform->xsize_, transform->bits_); - uint32_t* const src = out + out_stride - in_stride; - memmove(src, out, in_stride * sizeof(*src)); - ColorIndexInverseTransform(transform, row_start, row_end, src, out); - } else { - ColorIndexInverseTransform(transform, row_start, row_end, in, out); - } - break; - } -} - -//------------------------------------------------------------------------------ -// Color space conversion. - -static int is_big_endian(void) { - static const union { - uint16_t w; - uint8_t b[2]; - } tmp = { 1 }; - return (tmp.b[0] != 1); -} - -void VP8LConvertBGRAToRGB_C(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const uint32_t* const src_end = src + num_pixels; - while (src < src_end) { - const uint32_t argb = *src++; - *dst++ = (argb >> 16) & 0xff; - *dst++ = (argb >> 8) & 0xff; - *dst++ = (argb >> 0) & 0xff; - } -} - -void VP8LConvertBGRAToRGBA_C(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const uint32_t* const src_end = src + num_pixels; - while (src < src_end) { - const uint32_t argb = *src++; - *dst++ = (argb >> 16) & 0xff; - *dst++ = (argb >> 8) & 0xff; - *dst++ = (argb >> 0) & 0xff; - *dst++ = (argb >> 24) & 0xff; - } -} - -void VP8LConvertBGRAToRGBA4444_C(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const uint32_t* const src_end = src + num_pixels; - while (src < src_end) { - const uint32_t argb = *src++; - const uint8_t rg = ((argb >> 16) & 0xf0) | ((argb >> 12) & 0xf); - const uint8_t ba = ((argb >> 0) & 0xf0) | ((argb >> 28) & 0xf); -#ifdef WEBP_SWAP_16BIT_CSP - *dst++ = ba; - *dst++ = rg; -#else - *dst++ = rg; - *dst++ = ba; -#endif - } -} - -void VP8LConvertBGRAToRGB565_C(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const uint32_t* const src_end = src + num_pixels; - while (src < src_end) { - const uint32_t argb = *src++; - const uint8_t rg = ((argb >> 16) & 0xf8) | ((argb >> 13) & 0x7); - const uint8_t gb = ((argb >> 5) & 0xe0) | ((argb >> 3) & 0x1f); -#ifdef WEBP_SWAP_16BIT_CSP - *dst++ = gb; - *dst++ = rg; -#else - *dst++ = rg; - *dst++ = gb; -#endif - } -} - -void VP8LConvertBGRAToBGR_C(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const uint32_t* const src_end = src + num_pixels; - while (src < src_end) { - const uint32_t argb = *src++; - *dst++ = (argb >> 0) & 0xff; - *dst++ = (argb >> 8) & 0xff; - *dst++ = (argb >> 16) & 0xff; - } -} - -static void CopyOrSwap(const uint32_t* src, int num_pixels, uint8_t* dst, - int swap_on_big_endian) { - if (is_big_endian() == swap_on_big_endian) { - const uint32_t* const src_end = src + num_pixels; - while (src < src_end) { - const uint32_t argb = *src++; - -#if !defined(WORDS_BIGENDIAN) -#if !defined(WEBP_REFERENCE_IMPLEMENTATION) - WebPUint32ToMem(dst, BSwap32(argb)); -#else // WEBP_REFERENCE_IMPLEMENTATION - dst[0] = (argb >> 24) & 0xff; - dst[1] = (argb >> 16) & 0xff; - dst[2] = (argb >> 8) & 0xff; - dst[3] = (argb >> 0) & 0xff; -#endif -#else // WORDS_BIGENDIAN - dst[0] = (argb >> 0) & 0xff; - dst[1] = (argb >> 8) & 0xff; - dst[2] = (argb >> 16) & 0xff; - dst[3] = (argb >> 24) & 0xff; -#endif - dst += sizeof(argb); - } - } else { - memcpy(dst, src, num_pixels * sizeof(*src)); - } -} - -void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels, - WEBP_CSP_MODE out_colorspace, uint8_t* const rgba) { - switch (out_colorspace) { - case MODE_RGB: - VP8LConvertBGRAToRGB(in_data, num_pixels, rgba); - break; - case MODE_RGBA: - VP8LConvertBGRAToRGBA(in_data, num_pixels, rgba); - break; - case MODE_rgbA: - VP8LConvertBGRAToRGBA(in_data, num_pixels, rgba); - WebPApplyAlphaMultiply(rgba, 0, num_pixels, 1, 0); - break; - case MODE_BGR: - VP8LConvertBGRAToBGR(in_data, num_pixels, rgba); - break; - case MODE_BGRA: - CopyOrSwap(in_data, num_pixels, rgba, 1); - break; - case MODE_bgrA: - CopyOrSwap(in_data, num_pixels, rgba, 1); - WebPApplyAlphaMultiply(rgba, 0, num_pixels, 1, 0); - break; - case MODE_ARGB: - CopyOrSwap(in_data, num_pixels, rgba, 0); - break; - case MODE_Argb: - CopyOrSwap(in_data, num_pixels, rgba, 0); - WebPApplyAlphaMultiply(rgba, 1, num_pixels, 1, 0); - break; - case MODE_RGBA_4444: - VP8LConvertBGRAToRGBA4444(in_data, num_pixels, rgba); - break; - case MODE_rgbA_4444: - VP8LConvertBGRAToRGBA4444(in_data, num_pixels, rgba); - WebPApplyAlphaMultiply4444(rgba, num_pixels, 1, 0); - break; - case MODE_RGB_565: - VP8LConvertBGRAToRGB565(in_data, num_pixels, rgba); - break; - default: - assert(0); // Code flow should not reach here. - } -} - -//------------------------------------------------------------------------------ - -VP8LProcessBlueAndRedFunc VP8LAddGreenToBlueAndRed; -VP8LPredictorFunc VP8LPredictors[16]; - -VP8LTransformColorFunc VP8LTransformColorInverse; - -VP8LConvertFunc VP8LConvertBGRAToRGB; -VP8LConvertFunc VP8LConvertBGRAToRGBA; -VP8LConvertFunc VP8LConvertBGRAToRGBA4444; -VP8LConvertFunc VP8LConvertBGRAToRGB565; -VP8LConvertFunc VP8LConvertBGRAToBGR; - -VP8LMapARGBFunc VP8LMapColor32b; -VP8LMapAlphaFunc VP8LMapColor8b; - -extern void VP8LDspInitSSE2(void); -extern void VP8LDspInitNEON(void); -extern void VP8LDspInitMIPSdspR2(void); - -static volatile VP8CPUInfo lossless_last_cpuinfo_used = - (VP8CPUInfo)&lossless_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInit(void) { - if (lossless_last_cpuinfo_used == VP8GetCPUInfo) return; - - VP8LPredictors[0] = Predictor0; - VP8LPredictors[1] = Predictor1; - VP8LPredictors[2] = Predictor2; - VP8LPredictors[3] = Predictor3; - VP8LPredictors[4] = Predictor4; - VP8LPredictors[5] = Predictor5; - VP8LPredictors[6] = Predictor6; - VP8LPredictors[7] = Predictor7; - VP8LPredictors[8] = Predictor8; - VP8LPredictors[9] = Predictor9; - VP8LPredictors[10] = Predictor10; - VP8LPredictors[11] = Predictor11; - VP8LPredictors[12] = Predictor12; - VP8LPredictors[13] = Predictor13; - VP8LPredictors[14] = Predictor0; // <- padding security sentinels - VP8LPredictors[15] = Predictor0; - - VP8LAddGreenToBlueAndRed = VP8LAddGreenToBlueAndRed_C; - - VP8LTransformColorInverse = VP8LTransformColorInverse_C; - - VP8LConvertBGRAToRGB = VP8LConvertBGRAToRGB_C; - VP8LConvertBGRAToRGBA = VP8LConvertBGRAToRGBA_C; - VP8LConvertBGRAToRGBA4444 = VP8LConvertBGRAToRGBA4444_C; - VP8LConvertBGRAToRGB565 = VP8LConvertBGRAToRGB565_C; - VP8LConvertBGRAToBGR = VP8LConvertBGRAToBGR_C; - - VP8LMapColor32b = MapARGB; - VP8LMapColor8b = MapAlpha; - - // If defined, use CPUInfo() to overwrite some pointers with faster versions. - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - VP8LDspInitSSE2(); - } -#endif -#if defined(WEBP_USE_NEON) - if (VP8GetCPUInfo(kNEON)) { - VP8LDspInitNEON(); - } -#endif -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - VP8LDspInitMIPSdspR2(); - } -#endif - } - lossless_last_cpuinfo_used = VP8GetCPUInfo; -} - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/dsp/lossless.h b/Example-Mac/Pods/libwebp/src/dsp/lossless.h deleted file mode 100644 index e063bdd1..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/lossless.h +++ /dev/null @@ -1,348 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Image transforms and color space conversion methods for lossless decoder. -// -// Authors: Vikas Arora (vikaas.arora@gmail.com) -// Jyrki Alakuijala (jyrki@google.com) - -#ifndef WEBP_DSP_LOSSLESS_H_ -#define WEBP_DSP_LOSSLESS_H_ - -#include "../webp/types.h" -#include "../webp/decode.h" - -#include "../enc/histogram.h" -#include "../utils/utils.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef WEBP_EXPERIMENTAL_FEATURES -#include "../enc/delta_palettization.h" -#endif // WEBP_EXPERIMENTAL_FEATURES - -//------------------------------------------------------------------------------ -// Decoding - -typedef uint32_t (*VP8LPredictorFunc)(uint32_t left, const uint32_t* const top); -extern VP8LPredictorFunc VP8LPredictors[16]; - -typedef void (*VP8LProcessBlueAndRedFunc)(uint32_t* argb_data, int num_pixels); -extern VP8LProcessBlueAndRedFunc VP8LAddGreenToBlueAndRed; - -typedef struct { - // Note: the members are uint8_t, so that any negative values are - // automatically converted to "mod 256" values. - uint8_t green_to_red_; - uint8_t green_to_blue_; - uint8_t red_to_blue_; -} VP8LMultipliers; -typedef void (*VP8LTransformColorFunc)(const VP8LMultipliers* const m, - uint32_t* argb_data, int num_pixels); -extern VP8LTransformColorFunc VP8LTransformColorInverse; - -struct VP8LTransform; // Defined in dec/vp8li.h. - -// Performs inverse transform of data given transform information, start and end -// rows. Transform will be applied to rows [row_start, row_end[. -// The *in and *out pointers refer to source and destination data respectively -// corresponding to the intermediate row (row_start). -void VP8LInverseTransform(const struct VP8LTransform* const transform, - int row_start, int row_end, - const uint32_t* const in, uint32_t* const out); - -// Color space conversion. -typedef void (*VP8LConvertFunc)(const uint32_t* src, int num_pixels, - uint8_t* dst); -extern VP8LConvertFunc VP8LConvertBGRAToRGB; -extern VP8LConvertFunc VP8LConvertBGRAToRGBA; -extern VP8LConvertFunc VP8LConvertBGRAToRGBA4444; -extern VP8LConvertFunc VP8LConvertBGRAToRGB565; -extern VP8LConvertFunc VP8LConvertBGRAToBGR; - -// Converts from BGRA to other color spaces. -void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels, - WEBP_CSP_MODE out_colorspace, uint8_t* const rgba); - -// color mapping related functions. -static WEBP_INLINE uint32_t VP8GetARGBIndex(uint32_t idx) { - return (idx >> 8) & 0xff; -} - -static WEBP_INLINE uint8_t VP8GetAlphaIndex(uint8_t idx) { - return idx; -} - -static WEBP_INLINE uint32_t VP8GetARGBValue(uint32_t val) { - return val; -} - -static WEBP_INLINE uint8_t VP8GetAlphaValue(uint32_t val) { - return (val >> 8) & 0xff; -} - -typedef void (*VP8LMapARGBFunc)(const uint32_t* src, - const uint32_t* const color_map, - uint32_t* dst, int y_start, - int y_end, int width); -typedef void (*VP8LMapAlphaFunc)(const uint8_t* src, - const uint32_t* const color_map, - uint8_t* dst, int y_start, - int y_end, int width); - -extern VP8LMapARGBFunc VP8LMapColor32b; -extern VP8LMapAlphaFunc VP8LMapColor8b; - -// Similar to the static method ColorIndexInverseTransform() that is part of -// lossless.c, but used only for alpha decoding. It takes uint8_t (rather than -// uint32_t) arguments for 'src' and 'dst'. -void VP8LColorIndexInverseTransformAlpha( - const struct VP8LTransform* const transform, int y_start, int y_end, - const uint8_t* src, uint8_t* dst); - -// Expose some C-only fallback functions -void VP8LTransformColorInverse_C(const VP8LMultipliers* const m, - uint32_t* data, int num_pixels); - -void VP8LConvertBGRAToRGB_C(const uint32_t* src, int num_pixels, uint8_t* dst); -void VP8LConvertBGRAToRGBA_C(const uint32_t* src, int num_pixels, uint8_t* dst); -void VP8LConvertBGRAToRGBA4444_C(const uint32_t* src, - int num_pixels, uint8_t* dst); -void VP8LConvertBGRAToRGB565_C(const uint32_t* src, - int num_pixels, uint8_t* dst); -void VP8LConvertBGRAToBGR_C(const uint32_t* src, int num_pixels, uint8_t* dst); -void VP8LAddGreenToBlueAndRed_C(uint32_t* data, int num_pixels); - -// Must be called before calling any of the above methods. -void VP8LDspInit(void); - -//------------------------------------------------------------------------------ -// Encoding - -extern VP8LProcessBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed; -extern VP8LTransformColorFunc VP8LTransformColor; -typedef void (*VP8LCollectColorBlueTransformsFunc)( - const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_blue, int red_to_blue, int histo[]); -extern VP8LCollectColorBlueTransformsFunc VP8LCollectColorBlueTransforms; - -typedef void (*VP8LCollectColorRedTransformsFunc)( - const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_red, int histo[]); -extern VP8LCollectColorRedTransformsFunc VP8LCollectColorRedTransforms; - -// Expose some C-only fallback functions -void VP8LTransformColor_C(const VP8LMultipliers* const m, - uint32_t* data, int num_pixels); -void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels); -void VP8LCollectColorRedTransforms_C(const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_red, int histo[]); -void VP8LCollectColorBlueTransforms_C(const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_blue, int red_to_blue, - int histo[]); - -//------------------------------------------------------------------------------ -// Image transforms. - -void VP8LResidualImage(int width, int height, int bits, int low_effort, - uint32_t* const argb, uint32_t* const argb_scratch, - uint32_t* const image, int exact); - -void VP8LColorSpaceTransform(int width, int height, int bits, int quality, - uint32_t* const argb, uint32_t* image); - -//------------------------------------------------------------------------------ -// Misc methods. - -// Computes sampled size of 'size' when sampling using 'sampling bits'. -static WEBP_INLINE uint32_t VP8LSubSampleSize(uint32_t size, - uint32_t sampling_bits) { - return (size + (1 << sampling_bits) - 1) >> sampling_bits; -} - -// ----------------------------------------------------------------------------- -// Faster logarithm for integers. Small values use a look-up table. - -// The threshold till approximate version of log_2 can be used. -// Practically, we can get rid of the call to log() as the two values match to -// very high degree (the ratio of these two is 0.99999x). -// Keeping a high threshold for now. -#define APPROX_LOG_WITH_CORRECTION_MAX 65536 -#define APPROX_LOG_MAX 4096 -#define LOG_2_RECIPROCAL 1.44269504088896338700465094007086 -#define LOG_LOOKUP_IDX_MAX 256 -extern const float kLog2Table[LOG_LOOKUP_IDX_MAX]; -extern const float kSLog2Table[LOG_LOOKUP_IDX_MAX]; -typedef float (*VP8LFastLog2SlowFunc)(uint32_t v); - -extern VP8LFastLog2SlowFunc VP8LFastLog2Slow; -extern VP8LFastLog2SlowFunc VP8LFastSLog2Slow; - -static WEBP_INLINE float VP8LFastLog2(uint32_t v) { - return (v < LOG_LOOKUP_IDX_MAX) ? kLog2Table[v] : VP8LFastLog2Slow(v); -} -// Fast calculation of v * log2(v) for integer input. -static WEBP_INLINE float VP8LFastSLog2(uint32_t v) { - return (v < LOG_LOOKUP_IDX_MAX) ? kSLog2Table[v] : VP8LFastSLog2Slow(v); -} - -// ----------------------------------------------------------------------------- -// Huffman-cost related functions. - -typedef double (*VP8LCostFunc)(const uint32_t* population, int length); -typedef double (*VP8LCostCombinedFunc)(const uint32_t* X, const uint32_t* Y, - int length); -typedef float (*VP8LCombinedShannonEntropyFunc)(const int X[256], - const int Y[256]); - -extern VP8LCostFunc VP8LExtraCost; -extern VP8LCostCombinedFunc VP8LExtraCostCombined; -extern VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy; - -typedef struct { // small struct to hold counters - int counts[2]; // index: 0=zero steak, 1=non-zero streak - int streaks[2][2]; // [zero/non-zero][streak<3 / streak>=3] -} VP8LStreaks; - -typedef VP8LStreaks (*VP8LCostCombinedCountFunc)(const uint32_t* X, - const uint32_t* Y, int length); - -extern VP8LCostCombinedCountFunc VP8LHuffmanCostCombinedCount; - -typedef struct { // small struct to hold bit entropy results - double entropy; // entropy - uint32_t sum; // sum of the population - int nonzeros; // number of non-zero elements in the population - uint32_t max_val; // maximum value in the population - uint32_t nonzero_code; // index of the last non-zero in the population -} VP8LBitEntropy; - -void VP8LBitEntropyInit(VP8LBitEntropy* const entropy); - -// Get the combined symbol bit entropy and Huffman cost stats for the -// distributions 'X' and 'Y'. Those results can then be refined according to -// codec specific heuristics. -void VP8LGetCombinedEntropyUnrefined(const uint32_t* const X, - const uint32_t* const Y, int length, - VP8LBitEntropy* const bit_entropy, - VP8LStreaks* const stats); -// Get the entropy for the distribution 'X'. -void VP8LGetEntropyUnrefined(const uint32_t* const X, int length, - VP8LBitEntropy* const bit_entropy, - VP8LStreaks* const stats); - -void VP8LBitsEntropyUnrefined(const uint32_t* const array, int n, - VP8LBitEntropy* const entropy); - -typedef void (*GetEntropyUnrefinedHelperFunc)(uint32_t val, int i, - uint32_t* const val_prev, - int* const i_prev, - VP8LBitEntropy* const bit_entropy, - VP8LStreaks* const stats); -// Internal function used by VP8LGet*EntropyUnrefined. -extern GetEntropyUnrefinedHelperFunc VP8LGetEntropyUnrefinedHelper; - -typedef void (*VP8LHistogramAddFunc)(const VP8LHistogram* const a, - const VP8LHistogram* const b, - VP8LHistogram* const out); -extern VP8LHistogramAddFunc VP8LHistogramAdd; - -// ----------------------------------------------------------------------------- -// PrefixEncode() - -static WEBP_INLINE int VP8LBitsLog2Ceiling(uint32_t n) { - const int log_floor = BitsLog2Floor(n); - if (n == (n & ~(n - 1))) // zero or a power of two. - return log_floor; - else - return log_floor + 1; -} - -// Splitting of distance and length codes into prefixes and -// extra bits. The prefixes are encoded with an entropy code -// while the extra bits are stored just as normal bits. -static WEBP_INLINE void VP8LPrefixEncodeBitsNoLUT(int distance, int* const code, - int* const extra_bits) { - const int highest_bit = BitsLog2Floor(--distance); - const int second_highest_bit = (distance >> (highest_bit - 1)) & 1; - *extra_bits = highest_bit - 1; - *code = 2 * highest_bit + second_highest_bit; -} - -static WEBP_INLINE void VP8LPrefixEncodeNoLUT(int distance, int* const code, - int* const extra_bits, - int* const extra_bits_value) { - const int highest_bit = BitsLog2Floor(--distance); - const int second_highest_bit = (distance >> (highest_bit - 1)) & 1; - *extra_bits = highest_bit - 1; - *extra_bits_value = distance & ((1 << *extra_bits) - 1); - *code = 2 * highest_bit + second_highest_bit; -} - -#define PREFIX_LOOKUP_IDX_MAX 512 -typedef struct { - int8_t code_; - int8_t extra_bits_; -} VP8LPrefixCode; - -// These tables are derived using VP8LPrefixEncodeNoLUT. -extern const VP8LPrefixCode kPrefixEncodeCode[PREFIX_LOOKUP_IDX_MAX]; -extern const uint8_t kPrefixEncodeExtraBitsValue[PREFIX_LOOKUP_IDX_MAX]; -static WEBP_INLINE void VP8LPrefixEncodeBits(int distance, int* const code, - int* const extra_bits) { - if (distance < PREFIX_LOOKUP_IDX_MAX) { - const VP8LPrefixCode prefix_code = kPrefixEncodeCode[distance]; - *code = prefix_code.code_; - *extra_bits = prefix_code.extra_bits_; - } else { - VP8LPrefixEncodeBitsNoLUT(distance, code, extra_bits); - } -} - -static WEBP_INLINE void VP8LPrefixEncode(int distance, int* const code, - int* const extra_bits, - int* const extra_bits_value) { - if (distance < PREFIX_LOOKUP_IDX_MAX) { - const VP8LPrefixCode prefix_code = kPrefixEncodeCode[distance]; - *code = prefix_code.code_; - *extra_bits = prefix_code.extra_bits_; - *extra_bits_value = kPrefixEncodeExtraBitsValue[distance]; - } else { - VP8LPrefixEncodeNoLUT(distance, code, extra_bits, extra_bits_value); - } -} - -// In-place difference of each component with mod 256. -static WEBP_INLINE uint32_t VP8LSubPixels(uint32_t a, uint32_t b) { - const uint32_t alpha_and_green = - 0x00ff00ffu + (a & 0xff00ff00u) - (b & 0xff00ff00u); - const uint32_t red_and_blue = - 0xff00ff00u + (a & 0x00ff00ffu) - (b & 0x00ff00ffu); - return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu); -} - -void VP8LBundleColorMap(const uint8_t* const row, int width, - int xbits, uint32_t* const dst); - -// Must be called before calling any of the above methods. -void VP8LEncDspInit(void); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // WEBP_DSP_LOSSLESS_H_ diff --git a/Example-Mac/Pods/libwebp/src/dsp/lossless_enc.c b/Example-Mac/Pods/libwebp/src/dsp/lossless_enc.c deleted file mode 100644 index 2eafa3da..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/lossless_enc.c +++ /dev/null @@ -1,1215 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Image transform methods for lossless encoder. -// -// Authors: Vikas Arora (vikaas.arora@gmail.com) -// Jyrki Alakuijala (jyrki@google.com) -// Urvang Joshi (urvang@google.com) - -#include "./dsp.h" - -#include -#include -#include "../dec/vp8li.h" -#include "../utils/endian_inl.h" -#include "./lossless.h" -#include "./yuv.h" - -#define MAX_DIFF_COST (1e30f) - -static const int kPredLowEffort = 11; -static const uint32_t kMaskAlpha = 0xff000000; - -// lookup table for small values of log2(int) -const float kLog2Table[LOG_LOOKUP_IDX_MAX] = { - 0.0000000000000000f, 0.0000000000000000f, - 1.0000000000000000f, 1.5849625007211560f, - 2.0000000000000000f, 2.3219280948873621f, - 2.5849625007211560f, 2.8073549220576041f, - 3.0000000000000000f, 3.1699250014423121f, - 3.3219280948873621f, 3.4594316186372973f, - 3.5849625007211560f, 3.7004397181410921f, - 3.8073549220576041f, 3.9068905956085187f, - 4.0000000000000000f, 4.0874628412503390f, - 4.1699250014423121f, 4.2479275134435852f, - 4.3219280948873626f, 4.3923174227787606f, - 4.4594316186372973f, 4.5235619560570130f, - 4.5849625007211560f, 4.6438561897747243f, - 4.7004397181410917f, 4.7548875021634682f, - 4.8073549220576037f, 4.8579809951275718f, - 4.9068905956085187f, 4.9541963103868749f, - 5.0000000000000000f, 5.0443941193584533f, - 5.0874628412503390f, 5.1292830169449663f, - 5.1699250014423121f, 5.2094533656289501f, - 5.2479275134435852f, 5.2854022188622487f, - 5.3219280948873626f, 5.3575520046180837f, - 5.3923174227787606f, 5.4262647547020979f, - 5.4594316186372973f, 5.4918530963296747f, - 5.5235619560570130f, 5.5545888516776376f, - 5.5849625007211560f, 5.6147098441152083f, - 5.6438561897747243f, 5.6724253419714951f, - 5.7004397181410917f, 5.7279204545631987f, - 5.7548875021634682f, 5.7813597135246599f, - 5.8073549220576037f, 5.8328900141647412f, - 5.8579809951275718f, 5.8826430493618415f, - 5.9068905956085187f, 5.9307373375628866f, - 5.9541963103868749f, 5.9772799234999167f, - 6.0000000000000000f, 6.0223678130284543f, - 6.0443941193584533f, 6.0660891904577720f, - 6.0874628412503390f, 6.1085244567781691f, - 6.1292830169449663f, 6.1497471195046822f, - 6.1699250014423121f, 6.1898245588800175f, - 6.2094533656289501f, 6.2288186904958804f, - 6.2479275134435852f, 6.2667865406949010f, - 6.2854022188622487f, 6.3037807481771030f, - 6.3219280948873626f, 6.3398500028846243f, - 6.3575520046180837f, 6.3750394313469245f, - 6.3923174227787606f, 6.4093909361377017f, - 6.4262647547020979f, 6.4429434958487279f, - 6.4594316186372973f, 6.4757334309663976f, - 6.4918530963296747f, 6.5077946401986963f, - 6.5235619560570130f, 6.5391588111080309f, - 6.5545888516776376f, 6.5698556083309478f, - 6.5849625007211560f, 6.5999128421871278f, - 6.6147098441152083f, 6.6293566200796094f, - 6.6438561897747243f, 6.6582114827517946f, - 6.6724253419714951f, 6.6865005271832185f, - 6.7004397181410917f, 6.7142455176661224f, - 6.7279204545631987f, 6.7414669864011464f, - 6.7548875021634682f, 6.7681843247769259f, - 6.7813597135246599f, 6.7944158663501061f, - 6.8073549220576037f, 6.8201789624151878f, - 6.8328900141647412f, 6.8454900509443747f, - 6.8579809951275718f, 6.8703647195834047f, - 6.8826430493618415f, 6.8948177633079437f, - 6.9068905956085187f, 6.9188632372745946f, - 6.9307373375628866f, 6.9425145053392398f, - 6.9541963103868749f, 6.9657842846620869f, - 6.9772799234999167f, 6.9886846867721654f, - 7.0000000000000000f, 7.0112272554232539f, - 7.0223678130284543f, 7.0334230015374501f, - 7.0443941193584533f, 7.0552824355011898f, - 7.0660891904577720f, 7.0768155970508308f, - 7.0874628412503390f, 7.0980320829605263f, - 7.1085244567781691f, 7.1189410727235076f, - 7.1292830169449663f, 7.1395513523987936f, - 7.1497471195046822f, 7.1598713367783890f, - 7.1699250014423121f, 7.1799090900149344f, - 7.1898245588800175f, 7.1996723448363644f, - 7.2094533656289501f, 7.2191685204621611f, - 7.2288186904958804f, 7.2384047393250785f, - 7.2479275134435852f, 7.2573878426926521f, - 7.2667865406949010f, 7.2761244052742375f, - 7.2854022188622487f, 7.2946207488916270f, - 7.3037807481771030f, 7.3128829552843557f, - 7.3219280948873626f, 7.3309168781146167f, - 7.3398500028846243f, 7.3487281542310771f, - 7.3575520046180837f, 7.3663222142458160f, - 7.3750394313469245f, 7.3837042924740519f, - 7.3923174227787606f, 7.4008794362821843f, - 7.4093909361377017f, 7.4178525148858982f, - 7.4262647547020979f, 7.4346282276367245f, - 7.4429434958487279f, 7.4512111118323289f, - 7.4594316186372973f, 7.4676055500829976f, - 7.4757334309663976f, 7.4838157772642563f, - 7.4918530963296747f, 7.4998458870832056f, - 7.5077946401986963f, 7.5156998382840427f, - 7.5235619560570130f, 7.5313814605163118f, - 7.5391588111080309f, 7.5468944598876364f, - 7.5545888516776376f, 7.5622424242210728f, - 7.5698556083309478f, 7.5774288280357486f, - 7.5849625007211560f, 7.5924570372680806f, - 7.5999128421871278f, 7.6073303137496104f, - 7.6147098441152083f, 7.6220518194563764f, - 7.6293566200796094f, 7.6366246205436487f, - 7.6438561897747243f, 7.6510516911789281f, - 7.6582114827517946f, 7.6653359171851764f, - 7.6724253419714951f, 7.6794800995054464f, - 7.6865005271832185f, 7.6934869574993252f, - 7.7004397181410917f, 7.7073591320808825f, - 7.7142455176661224f, 7.7210991887071855f, - 7.7279204545631987f, 7.7347096202258383f, - 7.7414669864011464f, 7.7481928495894605f, - 7.7548875021634682f, 7.7615512324444795f, - 7.7681843247769259f, 7.7747870596011736f, - 7.7813597135246599f, 7.7879025593914317f, - 7.7944158663501061f, 7.8008998999203047f, - 7.8073549220576037f, 7.8137811912170374f, - 7.8201789624151878f, 7.8265484872909150f, - 7.8328900141647412f, 7.8392037880969436f, - 7.8454900509443747f, 7.8517490414160571f, - 7.8579809951275718f, 7.8641861446542797f, - 7.8703647195834047f, 7.8765169465649993f, - 7.8826430493618415f, 7.8887432488982591f, - 7.8948177633079437f, 7.9008668079807486f, - 7.9068905956085187f, 7.9128893362299619f, - 7.9188632372745946f, 7.9248125036057812f, - 7.9307373375628866f, 7.9366379390025709f, - 7.9425145053392398f, 7.9483672315846778f, - 7.9541963103868749f, 7.9600019320680805f, - 7.9657842846620869f, 7.9715435539507719f, - 7.9772799234999167f, 7.9829935746943103f, - 7.9886846867721654f, 7.9943534368588577f -}; - -const float kSLog2Table[LOG_LOOKUP_IDX_MAX] = { - 0.00000000f, 0.00000000f, 2.00000000f, 4.75488750f, - 8.00000000f, 11.60964047f, 15.50977500f, 19.65148445f, - 24.00000000f, 28.52932501f, 33.21928095f, 38.05374781f, - 43.01955001f, 48.10571634f, 53.30296891f, 58.60335893f, - 64.00000000f, 69.48686830f, 75.05865003f, 80.71062276f, - 86.43856190f, 92.23866588f, 98.10749561f, 104.04192499f, - 110.03910002f, 116.09640474f, 122.21143267f, 128.38196256f, - 134.60593782f, 140.88144886f, 147.20671787f, 153.58008562f, - 160.00000000f, 166.46500594f, 172.97373660f, 179.52490559f, - 186.11730005f, 192.74977453f, 199.42124551f, 206.13068654f, - 212.87712380f, 219.65963219f, 226.47733176f, 233.32938445f, - 240.21499122f, 247.13338933f, 254.08384998f, 261.06567603f, - 268.07820003f, 275.12078236f, 282.19280949f, 289.29369244f, - 296.42286534f, 303.57978409f, 310.76392512f, 317.97478424f, - 325.21187564f, 332.47473081f, 339.76289772f, 347.07593991f, - 354.41343574f, 361.77497759f, 369.16017124f, 376.56863518f, - 384.00000000f, 391.45390785f, 398.93001188f, 406.42797576f, - 413.94747321f, 421.48818752f, 429.04981119f, 436.63204548f, - 444.23460010f, 451.85719280f, 459.49954906f, 467.16140179f, - 474.84249102f, 482.54256363f, 490.26137307f, 497.99867911f, - 505.75424759f, 513.52785023f, 521.31926438f, 529.12827280f, - 536.95466351f, 544.79822957f, 552.65876890f, 560.53608414f, - 568.42998244f, 576.34027536f, 584.26677867f, 592.20931226f, - 600.16769996f, 608.14176943f, 616.13135206f, 624.13628279f, - 632.15640007f, 640.19154569f, 648.24156472f, 656.30630539f, - 664.38561898f, 672.47935976f, 680.58738488f, 688.70955430f, - 696.84573069f, 704.99577935f, 713.15956818f, 721.33696754f, - 729.52785023f, 737.73209140f, 745.94956849f, 754.18016116f, - 762.42375127f, 770.68022275f, 778.94946161f, 787.23135586f, - 795.52579543f, 803.83267219f, 812.15187982f, 820.48331383f, - 828.82687147f, 837.18245171f, 845.54995518f, 853.92928416f, - 862.32034249f, 870.72303558f, 879.13727036f, 887.56295522f, - 896.00000000f, 904.44831595f, 912.90781569f, 921.37841320f, - 929.86002376f, 938.35256392f, 946.85595152f, 955.37010560f, - 963.89494641f, 972.43039537f, 980.97637504f, 989.53280911f, - 998.09962237f, 1006.67674069f, 1015.26409097f, 1023.86160116f, - 1032.46920021f, 1041.08681805f, 1049.71438560f, 1058.35183469f, - 1066.99909811f, 1075.65610955f, 1084.32280357f, 1092.99911564f, - 1101.68498204f, 1110.38033993f, 1119.08512727f, 1127.79928282f, - 1136.52274614f, 1145.25545758f, 1153.99735821f, 1162.74838989f, - 1171.50849518f, 1180.27761738f, 1189.05570047f, 1197.84268914f, - 1206.63852876f, 1215.44316535f, 1224.25654560f, 1233.07861684f, - 1241.90932703f, 1250.74862473f, 1259.59645914f, 1268.45278005f, - 1277.31753781f, 1286.19068338f, 1295.07216828f, 1303.96194457f, - 1312.85996488f, 1321.76618236f, 1330.68055071f, 1339.60302413f, - 1348.53355734f, 1357.47210556f, 1366.41862452f, 1375.37307041f, - 1384.33539991f, 1393.30557020f, 1402.28353887f, 1411.26926400f, - 1420.26270412f, 1429.26381818f, 1438.27256558f, 1447.28890615f, - 1456.31280014f, 1465.34420819f, 1474.38309138f, 1483.42941118f, - 1492.48312945f, 1501.54420843f, 1510.61261078f, 1519.68829949f, - 1528.77123795f, 1537.86138993f, 1546.95871952f, 1556.06319119f, - 1565.17476976f, 1574.29342040f, 1583.41910860f, 1592.55180020f, - 1601.69146137f, 1610.83805860f, 1619.99155871f, 1629.15192882f, - 1638.31913637f, 1647.49314911f, 1656.67393509f, 1665.86146266f, - 1675.05570047f, 1684.25661744f, 1693.46418280f, 1702.67836605f, - 1711.89913698f, 1721.12646563f, 1730.36032233f, 1739.60067768f, - 1748.84750254f, 1758.10076802f, 1767.36044551f, 1776.62650662f, - 1785.89892323f, 1795.17766747f, 1804.46271172f, 1813.75402857f, - 1823.05159087f, 1832.35537170f, 1841.66534438f, 1850.98148244f, - 1860.30375965f, 1869.63214999f, 1878.96662767f, 1888.30716711f, - 1897.65374295f, 1907.00633003f, 1916.36490342f, 1925.72943838f, - 1935.09991037f, 1944.47629506f, 1953.85856831f, 1963.24670620f, - 1972.64068498f, 1982.04048108f, 1991.44607117f, 2000.85743204f, - 2010.27454072f, 2019.69737440f, 2029.12591044f, 2038.56012640f -}; - -const VP8LPrefixCode kPrefixEncodeCode[PREFIX_LOOKUP_IDX_MAX] = { - { 0, 0}, { 0, 0}, { 1, 0}, { 2, 0}, { 3, 0}, { 4, 1}, { 4, 1}, { 5, 1}, - { 5, 1}, { 6, 2}, { 6, 2}, { 6, 2}, { 6, 2}, { 7, 2}, { 7, 2}, { 7, 2}, - { 7, 2}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, - { 8, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, - { 9, 3}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, - {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, - {10, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, - {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, - {11, 4}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, - {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, - {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, - {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, - {12, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, - {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, - {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, - {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, - {13, 5}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, - {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, - {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, - {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, - {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, - {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, - {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, - {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, - {14, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, - {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, - {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, - {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, - {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, - {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, - {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, - {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, - {15, 6}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, -}; - -const uint8_t kPrefixEncodeExtraBitsValue[PREFIX_LOOKUP_IDX_MAX] = { - 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, - 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126 -}; - -static float FastSLog2Slow(uint32_t v) { - assert(v >= LOG_LOOKUP_IDX_MAX); - if (v < APPROX_LOG_WITH_CORRECTION_MAX) { - int log_cnt = 0; - uint32_t y = 1; - int correction = 0; - const float v_f = (float)v; - const uint32_t orig_v = v; - do { - ++log_cnt; - v = v >> 1; - y = y << 1; - } while (v >= LOG_LOOKUP_IDX_MAX); - // vf = (2^log_cnt) * Xf; where y = 2^log_cnt and Xf < 256 - // Xf = floor(Xf) * (1 + (v % y) / v) - // log2(Xf) = log2(floor(Xf)) + log2(1 + (v % y) / v) - // The correction factor: log(1 + d) ~ d; for very small d values, so - // log2(1 + (v % y) / v) ~ LOG_2_RECIPROCAL * (v % y)/v - // LOG_2_RECIPROCAL ~ 23/16 - correction = (23 * (orig_v & (y - 1))) >> 4; - return v_f * (kLog2Table[v] + log_cnt) + correction; - } else { - return (float)(LOG_2_RECIPROCAL * v * log((double)v)); - } -} - -static float FastLog2Slow(uint32_t v) { - assert(v >= LOG_LOOKUP_IDX_MAX); - if (v < APPROX_LOG_WITH_CORRECTION_MAX) { - int log_cnt = 0; - uint32_t y = 1; - const uint32_t orig_v = v; - double log_2; - do { - ++log_cnt; - v = v >> 1; - y = y << 1; - } while (v >= LOG_LOOKUP_IDX_MAX); - log_2 = kLog2Table[v] + log_cnt; - if (orig_v >= APPROX_LOG_MAX) { - // Since the division is still expensive, add this correction factor only - // for large values of 'v'. - const int correction = (23 * (orig_v & (y - 1))) >> 4; - log_2 += (double)correction / orig_v; - } - return (float)log_2; - } else { - return (float)(LOG_2_RECIPROCAL * log((double)v)); - } -} - -// Mostly used to reduce code size + readability -static WEBP_INLINE int GetMin(int a, int b) { return (a > b) ? b : a; } - -//------------------------------------------------------------------------------ -// Methods to calculate Entropy (Shannon). - -static float PredictionCostSpatial(const int counts[256], int weight_0, - double exp_val) { - const int significant_symbols = 256 >> 4; - const double exp_decay_factor = 0.6; - double bits = weight_0 * counts[0]; - int i; - for (i = 1; i < significant_symbols; ++i) { - bits += exp_val * (counts[i] + counts[256 - i]); - exp_val *= exp_decay_factor; - } - return (float)(-0.1 * bits); -} - -// Compute the combined Shanon's entropy for distribution {X} and {X+Y} -static float CombinedShannonEntropy(const int X[256], const int Y[256]) { - int i; - double retval = 0.; - int sumX = 0, sumXY = 0; - for (i = 0; i < 256; ++i) { - const int x = X[i]; - if (x != 0) { - const int xy = x + Y[i]; - sumX += x; - retval -= VP8LFastSLog2(x); - sumXY += xy; - retval -= VP8LFastSLog2(xy); - } else if (Y[i] != 0) { - sumXY += Y[i]; - retval -= VP8LFastSLog2(Y[i]); - } - } - retval += VP8LFastSLog2(sumX) + VP8LFastSLog2(sumXY); - return (float)retval; -} - -static float PredictionCostSpatialHistogram(const int accumulated[4][256], - const int tile[4][256]) { - int i; - double retval = 0; - for (i = 0; i < 4; ++i) { - const double kExpValue = 0.94; - retval += PredictionCostSpatial(tile[i], 1, kExpValue); - retval += VP8LCombinedShannonEntropy(tile[i], accumulated[i]); - } - return (float)retval; -} - -void VP8LBitEntropyInit(VP8LBitEntropy* const entropy) { - entropy->entropy = 0.; - entropy->sum = 0; - entropy->nonzeros = 0; - entropy->max_val = 0; - entropy->nonzero_code = VP8L_NON_TRIVIAL_SYM; -} - -void VP8LBitsEntropyUnrefined(const uint32_t* const array, int n, - VP8LBitEntropy* const entropy) { - int i; - - VP8LBitEntropyInit(entropy); - - for (i = 0; i < n; ++i) { - if (array[i] != 0) { - entropy->sum += array[i]; - entropy->nonzero_code = i; - ++entropy->nonzeros; - entropy->entropy -= VP8LFastSLog2(array[i]); - if (entropy->max_val < array[i]) { - entropy->max_val = array[i]; - } - } - } - entropy->entropy += VP8LFastSLog2(entropy->sum); -} - -static WEBP_INLINE void GetEntropyUnrefinedHelper( - uint32_t val, int i, uint32_t* const val_prev, int* const i_prev, - VP8LBitEntropy* const bit_entropy, VP8LStreaks* const stats) { - const int streak = i - *i_prev; - - // Gather info for the bit entropy. - if (*val_prev != 0) { - bit_entropy->sum += (*val_prev) * streak; - bit_entropy->nonzeros += streak; - bit_entropy->nonzero_code = *i_prev; - bit_entropy->entropy -= VP8LFastSLog2(*val_prev) * streak; - if (bit_entropy->max_val < *val_prev) { - bit_entropy->max_val = *val_prev; - } - } - - // Gather info for the Huffman cost. - stats->counts[*val_prev != 0] += (streak > 3); - stats->streaks[*val_prev != 0][(streak > 3)] += streak; - - *val_prev = val; - *i_prev = i; -} - -void VP8LGetEntropyUnrefined(const uint32_t* const X, int length, - VP8LBitEntropy* const bit_entropy, - VP8LStreaks* const stats) { - int i; - int i_prev = 0; - uint32_t x_prev = X[0]; - - memset(stats, 0, sizeof(*stats)); - VP8LBitEntropyInit(bit_entropy); - - for (i = 1; i < length; ++i) { - const uint32_t x = X[i]; - if (x != x_prev) { - VP8LGetEntropyUnrefinedHelper(x, i, &x_prev, &i_prev, bit_entropy, stats); - } - } - VP8LGetEntropyUnrefinedHelper(0, i, &x_prev, &i_prev, bit_entropy, stats); - - bit_entropy->entropy += VP8LFastSLog2(bit_entropy->sum); -} - -void VP8LGetCombinedEntropyUnrefined(const uint32_t* const X, - const uint32_t* const Y, int length, - VP8LBitEntropy* const bit_entropy, - VP8LStreaks* const stats) { - int i = 1; - int i_prev = 0; - uint32_t xy_prev = X[0] + Y[0]; - - memset(stats, 0, sizeof(*stats)); - VP8LBitEntropyInit(bit_entropy); - - for (i = 1; i < length; ++i) { - const uint32_t xy = X[i] + Y[i]; - if (xy != xy_prev) { - VP8LGetEntropyUnrefinedHelper(xy, i, &xy_prev, &i_prev, bit_entropy, - stats); - } - } - VP8LGetEntropyUnrefinedHelper(0, i, &xy_prev, &i_prev, bit_entropy, stats); - - bit_entropy->entropy += VP8LFastSLog2(bit_entropy->sum); -} - -static WEBP_INLINE void UpdateHisto(int histo_argb[4][256], uint32_t argb) { - ++histo_argb[0][argb >> 24]; - ++histo_argb[1][(argb >> 16) & 0xff]; - ++histo_argb[2][(argb >> 8) & 0xff]; - ++histo_argb[3][argb & 0xff]; -} - -//------------------------------------------------------------------------------ - -static WEBP_INLINE uint32_t Predict(VP8LPredictorFunc pred_func, - int x, int y, - const uint32_t* current_row, - const uint32_t* upper_row) { - if (y == 0) { - return (x == 0) ? ARGB_BLACK : current_row[x - 1]; // Left. - } else if (x == 0) { - return upper_row[x]; // Top. - } else { - return pred_func(current_row[x - 1], upper_row + x); - } -} - -// Returns best predictor and updates the accumulated histogram. -static int GetBestPredictorForTile(int width, int height, - int tile_x, int tile_y, int bits, - int accumulated[4][256], - const uint32_t* const argb_scratch, - int exact) { - const int kNumPredModes = 14; - const int col_start = tile_x << bits; - const int row_start = tile_y << bits; - const int tile_size = 1 << bits; - const int max_y = GetMin(tile_size, height - row_start); - const int max_x = GetMin(tile_size, width - col_start); - float best_diff = MAX_DIFF_COST; - int best_mode = 0; - int mode; - int histo_stack_1[4][256]; - int histo_stack_2[4][256]; - // Need pointers to be able to swap arrays. - int (*histo_argb)[256] = histo_stack_1; - int (*best_histo)[256] = histo_stack_2; - - int i, j; - for (mode = 0; mode < kNumPredModes; ++mode) { - const uint32_t* current_row = argb_scratch; - const VP8LPredictorFunc pred_func = VP8LPredictors[mode]; - float cur_diff; - int y; - memset(histo_argb, 0, sizeof(histo_stack_1)); - for (y = 0; y < max_y; ++y) { - int x; - const int row = row_start + y; - const uint32_t* const upper_row = current_row; - current_row = upper_row + width; - for (x = 0; x < max_x; ++x) { - const int col = col_start + x; - const uint32_t predict = - Predict(pred_func, col, row, current_row, upper_row); - uint32_t residual = VP8LSubPixels(current_row[col], predict); - if (!exact && (current_row[col] & kMaskAlpha) == 0) { - residual &= kMaskAlpha; // See CopyTileWithPrediction. - } - UpdateHisto(histo_argb, residual); - } - } - cur_diff = PredictionCostSpatialHistogram( - (const int (*)[256])accumulated, (const int (*)[256])histo_argb); - if (cur_diff < best_diff) { - int (*tmp)[256] = histo_argb; - histo_argb = best_histo; - best_histo = tmp; - best_diff = cur_diff; - best_mode = mode; - } - } - - for (i = 0; i < 4; i++) { - for (j = 0; j < 256; j++) { - accumulated[i][j] += best_histo[i][j]; - } - } - - return best_mode; -} - -static void CopyImageWithPrediction(int width, int height, - int bits, uint32_t* const modes, - uint32_t* const argb_scratch, - uint32_t* const argb, - int low_effort, int exact) { - const int tiles_per_row = VP8LSubSampleSize(width, bits); - const int mask = (1 << bits) - 1; - // The row size is one pixel longer to allow the top right pixel to point to - // the leftmost pixel of the next row when at the right edge. - uint32_t* current_row = argb_scratch; - uint32_t* upper_row = argb_scratch + width + 1; - int y; - VP8LPredictorFunc pred_func = - low_effort ? VP8LPredictors[kPredLowEffort] : NULL; - - for (y = 0; y < height; ++y) { - int x; - uint32_t* tmp = upper_row; - upper_row = current_row; - current_row = tmp; - memcpy(current_row, argb + y * width, sizeof(*current_row) * width); - current_row[width] = (y + 1 < height) ? argb[(y + 1) * width] : ARGB_BLACK; - - if (low_effort) { - for (x = 0; x < width; ++x) { - const uint32_t predict = - Predict(pred_func, x, y, current_row, upper_row); - argb[y * width + x] = VP8LSubPixels(current_row[x], predict); - } - } else { - for (x = 0; x < width; ++x) { - uint32_t predict, residual; - if ((x & mask) == 0) { - const int mode = - (modes[(y >> bits) * tiles_per_row + (x >> bits)] >> 8) & 0xff; - pred_func = VP8LPredictors[mode]; - } - predict = Predict(pred_func, x, y, current_row, upper_row); - residual = VP8LSubPixels(current_row[x], predict); - if (!exact && (current_row[x] & kMaskAlpha) == 0) { - // If alpha is 0, cleanup RGB. We can choose the RGB values of the - // residual for best compression. The prediction of alpha itself can - // be non-zero and must be kept though. We choose RGB of the residual - // to be 0. - residual &= kMaskAlpha; - // Update input image so that next predictions use correct RGB value. - current_row[x] = predict & ~kMaskAlpha; - if (x == 0 && y != 0) upper_row[width] = current_row[x]; - } - argb[y * width + x] = residual; - } - } - } -} - -void VP8LResidualImage(int width, int height, int bits, int low_effort, - uint32_t* const argb, uint32_t* const argb_scratch, - uint32_t* const image, int exact) { - const int max_tile_size = 1 << bits; - const int tiles_per_row = VP8LSubSampleSize(width, bits); - const int tiles_per_col = VP8LSubSampleSize(height, bits); - uint32_t* const upper_row = argb_scratch; - uint32_t* const current_tile_rows = argb_scratch + width; - int tile_y; - int histo[4][256]; - if (low_effort) { - int i; - for (i = 0; i < tiles_per_row * tiles_per_col; ++i) { - image[i] = ARGB_BLACK | (kPredLowEffort << 8); - } - } else { - memset(histo, 0, sizeof(histo)); - for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) { - const int tile_y_offset = tile_y * max_tile_size; - const int this_tile_height = - (tile_y < tiles_per_col - 1) ? max_tile_size : height - tile_y_offset; - int tile_x; - if (tile_y > 0) { - memcpy(upper_row, current_tile_rows + (max_tile_size - 1) * width, - width * sizeof(*upper_row)); - } - memcpy(current_tile_rows, &argb[tile_y_offset * width], - this_tile_height * width * sizeof(*current_tile_rows)); - for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) { - const int pred = GetBestPredictorForTile(width, height, tile_x, tile_y, - bits, (int (*)[256])histo, argb_scratch, exact); - image[tile_y * tiles_per_row + tile_x] = ARGB_BLACK | (pred << 8); - } - } - } - - CopyImageWithPrediction(width, height, bits, - image, argb_scratch, argb, low_effort, exact); -} - -void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels) { - int i; - for (i = 0; i < num_pixels; ++i) { - const uint32_t argb = argb_data[i]; - const uint32_t green = (argb >> 8) & 0xff; - const uint32_t new_r = (((argb >> 16) & 0xff) - green) & 0xff; - const uint32_t new_b = ((argb & 0xff) - green) & 0xff; - argb_data[i] = (argb & 0xff00ff00) | (new_r << 16) | new_b; - } -} - -static WEBP_INLINE void MultipliersClear(VP8LMultipliers* const m) { - m->green_to_red_ = 0; - m->green_to_blue_ = 0; - m->red_to_blue_ = 0; -} - -static WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred, - int8_t color) { - return (uint32_t)((int)(color_pred) * color) >> 5; -} - -static WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code, - VP8LMultipliers* const m) { - m->green_to_red_ = (color_code >> 0) & 0xff; - m->green_to_blue_ = (color_code >> 8) & 0xff; - m->red_to_blue_ = (color_code >> 16) & 0xff; -} - -static WEBP_INLINE uint32_t MultipliersToColorCode( - const VP8LMultipliers* const m) { - return 0xff000000u | - ((uint32_t)(m->red_to_blue_) << 16) | - ((uint32_t)(m->green_to_blue_) << 8) | - m->green_to_red_; -} - -void VP8LTransformColor_C(const VP8LMultipliers* const m, uint32_t* data, - int num_pixels) { - int i; - for (i = 0; i < num_pixels; ++i) { - const uint32_t argb = data[i]; - const uint32_t green = argb >> 8; - const uint32_t red = argb >> 16; - uint32_t new_red = red; - uint32_t new_blue = argb; - new_red -= ColorTransformDelta(m->green_to_red_, green); - new_red &= 0xff; - new_blue -= ColorTransformDelta(m->green_to_blue_, green); - new_blue -= ColorTransformDelta(m->red_to_blue_, red); - new_blue &= 0xff; - data[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue); - } -} - -static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red, - uint32_t argb) { - const uint32_t green = argb >> 8; - uint32_t new_red = argb >> 16; - new_red -= ColorTransformDelta(green_to_red, green); - return (new_red & 0xff); -} - -static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue, - uint8_t red_to_blue, - uint32_t argb) { - const uint32_t green = argb >> 8; - const uint32_t red = argb >> 16; - uint8_t new_blue = argb; - new_blue -= ColorTransformDelta(green_to_blue, green); - new_blue -= ColorTransformDelta(red_to_blue, red); - return (new_blue & 0xff); -} - -static float PredictionCostCrossColor(const int accumulated[256], - const int counts[256]) { - // Favor low entropy, locally and globally. - // Favor small absolute values for PredictionCostSpatial - static const double kExpValue = 2.4; - return VP8LCombinedShannonEntropy(counts, accumulated) + - PredictionCostSpatial(counts, 3, kExpValue); -} - -void VP8LCollectColorRedTransforms_C(const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_red, int histo[]) { - while (tile_height-- > 0) { - int x; - for (x = 0; x < tile_width; ++x) { - ++histo[TransformColorRed(green_to_red, argb[x])]; - } - argb += stride; - } -} - -static float GetPredictionCostCrossColorRed( - const uint32_t* argb, int stride, int tile_width, int tile_height, - VP8LMultipliers prev_x, VP8LMultipliers prev_y, int green_to_red, - const int accumulated_red_histo[256]) { - int histo[256] = { 0 }; - float cur_diff; - - VP8LCollectColorRedTransforms(argb, stride, tile_width, tile_height, - green_to_red, histo); - - cur_diff = PredictionCostCrossColor(accumulated_red_histo, histo); - if ((uint8_t)green_to_red == prev_x.green_to_red_) { - cur_diff -= 3; // favor keeping the areas locally similar - } - if ((uint8_t)green_to_red == prev_y.green_to_red_) { - cur_diff -= 3; // favor keeping the areas locally similar - } - if (green_to_red == 0) { - cur_diff -= 3; - } - return cur_diff; -} - -static void GetBestGreenToRed( - const uint32_t* argb, int stride, int tile_width, int tile_height, - VP8LMultipliers prev_x, VP8LMultipliers prev_y, int quality, - const int accumulated_red_histo[256], VP8LMultipliers* const best_tx) { - const int kMaxIters = 4 + ((7 * quality) >> 8); // in range [4..6] - int green_to_red_best = 0; - int iter, offset; - float best_diff = GetPredictionCostCrossColorRed( - argb, stride, tile_width, tile_height, prev_x, prev_y, - green_to_red_best, accumulated_red_histo); - for (iter = 0; iter < kMaxIters; ++iter) { - // ColorTransformDelta is a 3.5 bit fixed point, so 32 is equal to - // one in color computation. Having initial delta here as 1 is sufficient - // to explore the range of (-2, 2). - const int delta = 32 >> iter; - // Try a negative and a positive delta from the best known value. - for (offset = -delta; offset <= delta; offset += 2 * delta) { - const int green_to_red_cur = offset + green_to_red_best; - const float cur_diff = GetPredictionCostCrossColorRed( - argb, stride, tile_width, tile_height, prev_x, prev_y, - green_to_red_cur, accumulated_red_histo); - if (cur_diff < best_diff) { - best_diff = cur_diff; - green_to_red_best = green_to_red_cur; - } - } - } - best_tx->green_to_red_ = green_to_red_best; -} - -void VP8LCollectColorBlueTransforms_C(const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_blue, int red_to_blue, - int histo[]) { - while (tile_height-- > 0) { - int x; - for (x = 0; x < tile_width; ++x) { - ++histo[TransformColorBlue(green_to_blue, red_to_blue, argb[x])]; - } - argb += stride; - } -} - -static float GetPredictionCostCrossColorBlue( - const uint32_t* argb, int stride, int tile_width, int tile_height, - VP8LMultipliers prev_x, VP8LMultipliers prev_y, - int green_to_blue, int red_to_blue, const int accumulated_blue_histo[256]) { - int histo[256] = { 0 }; - float cur_diff; - - VP8LCollectColorBlueTransforms(argb, stride, tile_width, tile_height, - green_to_blue, red_to_blue, histo); - - cur_diff = PredictionCostCrossColor(accumulated_blue_histo, histo); - if ((uint8_t)green_to_blue == prev_x.green_to_blue_) { - cur_diff -= 3; // favor keeping the areas locally similar - } - if ((uint8_t)green_to_blue == prev_y.green_to_blue_) { - cur_diff -= 3; // favor keeping the areas locally similar - } - if ((uint8_t)red_to_blue == prev_x.red_to_blue_) { - cur_diff -= 3; // favor keeping the areas locally similar - } - if ((uint8_t)red_to_blue == prev_y.red_to_blue_) { - cur_diff -= 3; // favor keeping the areas locally similar - } - if (green_to_blue == 0) { - cur_diff -= 3; - } - if (red_to_blue == 0) { - cur_diff -= 3; - } - return cur_diff; -} - -#define kGreenRedToBlueNumAxis 8 -#define kGreenRedToBlueMaxIters 7 -static void GetBestGreenRedToBlue( - const uint32_t* argb, int stride, int tile_width, int tile_height, - VP8LMultipliers prev_x, VP8LMultipliers prev_y, int quality, - const int accumulated_blue_histo[256], - VP8LMultipliers* const best_tx) { - const int8_t offset[kGreenRedToBlueNumAxis][2] = - {{0, -1}, {0, 1}, {-1, 0}, {1, 0}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}}; - const int8_t delta_lut[kGreenRedToBlueMaxIters] = { 16, 16, 8, 4, 2, 2, 2 }; - const int iters = - (quality < 25) ? 1 : (quality > 50) ? kGreenRedToBlueMaxIters : 4; - int green_to_blue_best = 0; - int red_to_blue_best = 0; - int iter; - // Initial value at origin: - float best_diff = GetPredictionCostCrossColorBlue( - argb, stride, tile_width, tile_height, prev_x, prev_y, - green_to_blue_best, red_to_blue_best, accumulated_blue_histo); - for (iter = 0; iter < iters; ++iter) { - const int delta = delta_lut[iter]; - int axis; - for (axis = 0; axis < kGreenRedToBlueNumAxis; ++axis) { - const int green_to_blue_cur = - offset[axis][0] * delta + green_to_blue_best; - const int red_to_blue_cur = offset[axis][1] * delta + red_to_blue_best; - const float cur_diff = GetPredictionCostCrossColorBlue( - argb, stride, tile_width, tile_height, prev_x, prev_y, - green_to_blue_cur, red_to_blue_cur, accumulated_blue_histo); - if (cur_diff < best_diff) { - best_diff = cur_diff; - green_to_blue_best = green_to_blue_cur; - red_to_blue_best = red_to_blue_cur; - } - if (quality < 25 && iter == 4) { - // Only axis aligned diffs for lower quality. - break; // next iter. - } - } - if (delta == 2 && green_to_blue_best == 0 && red_to_blue_best == 0) { - // Further iterations would not help. - break; // out of iter-loop. - } - } - best_tx->green_to_blue_ = green_to_blue_best; - best_tx->red_to_blue_ = red_to_blue_best; -} -#undef kGreenRedToBlueMaxIters -#undef kGreenRedToBlueNumAxis - -static VP8LMultipliers GetBestColorTransformForTile( - int tile_x, int tile_y, int bits, - VP8LMultipliers prev_x, - VP8LMultipliers prev_y, - int quality, int xsize, int ysize, - const int accumulated_red_histo[256], - const int accumulated_blue_histo[256], - const uint32_t* const argb) { - const int max_tile_size = 1 << bits; - const int tile_y_offset = tile_y * max_tile_size; - const int tile_x_offset = tile_x * max_tile_size; - const int all_x_max = GetMin(tile_x_offset + max_tile_size, xsize); - const int all_y_max = GetMin(tile_y_offset + max_tile_size, ysize); - const int tile_width = all_x_max - tile_x_offset; - const int tile_height = all_y_max - tile_y_offset; - const uint32_t* const tile_argb = argb + tile_y_offset * xsize - + tile_x_offset; - VP8LMultipliers best_tx; - MultipliersClear(&best_tx); - - GetBestGreenToRed(tile_argb, xsize, tile_width, tile_height, - prev_x, prev_y, quality, accumulated_red_histo, &best_tx); - GetBestGreenRedToBlue(tile_argb, xsize, tile_width, tile_height, - prev_x, prev_y, quality, accumulated_blue_histo, - &best_tx); - return best_tx; -} - -static void CopyTileWithColorTransform(int xsize, int ysize, - int tile_x, int tile_y, - int max_tile_size, - VP8LMultipliers color_transform, - uint32_t* argb) { - const int xscan = GetMin(max_tile_size, xsize - tile_x); - int yscan = GetMin(max_tile_size, ysize - tile_y); - argb += tile_y * xsize + tile_x; - while (yscan-- > 0) { - VP8LTransformColor(&color_transform, argb, xscan); - argb += xsize; - } -} - -void VP8LColorSpaceTransform(int width, int height, int bits, int quality, - uint32_t* const argb, uint32_t* image) { - const int max_tile_size = 1 << bits; - const int tile_xsize = VP8LSubSampleSize(width, bits); - const int tile_ysize = VP8LSubSampleSize(height, bits); - int accumulated_red_histo[256] = { 0 }; - int accumulated_blue_histo[256] = { 0 }; - int tile_x, tile_y; - VP8LMultipliers prev_x, prev_y; - MultipliersClear(&prev_y); - MultipliersClear(&prev_x); - for (tile_y = 0; tile_y < tile_ysize; ++tile_y) { - for (tile_x = 0; tile_x < tile_xsize; ++tile_x) { - int y; - const int tile_x_offset = tile_x * max_tile_size; - const int tile_y_offset = tile_y * max_tile_size; - const int all_x_max = GetMin(tile_x_offset + max_tile_size, width); - const int all_y_max = GetMin(tile_y_offset + max_tile_size, height); - const int offset = tile_y * tile_xsize + tile_x; - if (tile_y != 0) { - ColorCodeToMultipliers(image[offset - tile_xsize], &prev_y); - } - prev_x = GetBestColorTransformForTile(tile_x, tile_y, bits, - prev_x, prev_y, - quality, width, height, - accumulated_red_histo, - accumulated_blue_histo, - argb); - image[offset] = MultipliersToColorCode(&prev_x); - CopyTileWithColorTransform(width, height, tile_x_offset, tile_y_offset, - max_tile_size, prev_x, argb); - - // Gather accumulated histogram data. - for (y = tile_y_offset; y < all_y_max; ++y) { - int ix = y * width + tile_x_offset; - const int ix_end = ix + all_x_max - tile_x_offset; - for (; ix < ix_end; ++ix) { - const uint32_t pix = argb[ix]; - if (ix >= 2 && - pix == argb[ix - 2] && - pix == argb[ix - 1]) { - continue; // repeated pixels are handled by backward references - } - if (ix >= width + 2 && - argb[ix - 2] == argb[ix - width - 2] && - argb[ix - 1] == argb[ix - width - 1] && - pix == argb[ix - width]) { - continue; // repeated pixels are handled by backward references - } - ++accumulated_red_histo[(pix >> 16) & 0xff]; - ++accumulated_blue_histo[(pix >> 0) & 0xff]; - } - } - } - } -} - -//------------------------------------------------------------------------------ -// Bundles multiple (1, 2, 4 or 8) pixels into a single pixel. -void VP8LBundleColorMap(const uint8_t* const row, int width, - int xbits, uint32_t* const dst) { - int x; - if (xbits > 0) { - const int bit_depth = 1 << (3 - xbits); - const int mask = (1 << xbits) - 1; - uint32_t code = 0xff000000; - for (x = 0; x < width; ++x) { - const int xsub = x & mask; - if (xsub == 0) { - code = 0xff000000; - } - code |= row[x] << (8 + bit_depth * xsub); - dst[x >> xbits] = code; - } - } else { - for (x = 0; x < width; ++x) dst[x] = 0xff000000 | (row[x] << 8); - } -} - -//------------------------------------------------------------------------------ - -static double ExtraCost(const uint32_t* population, int length) { - int i; - double cost = 0.; - for (i = 2; i < length - 2; ++i) cost += (i >> 1) * population[i + 2]; - return cost; -} - -static double ExtraCostCombined(const uint32_t* X, const uint32_t* Y, - int length) { - int i; - double cost = 0.; - for (i = 2; i < length - 2; ++i) { - const int xy = X[i + 2] + Y[i + 2]; - cost += (i >> 1) * xy; - } - return cost; -} - -//------------------------------------------------------------------------------ - -static void HistogramAdd(const VP8LHistogram* const a, - const VP8LHistogram* const b, - VP8LHistogram* const out) { - int i; - const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_); - assert(a->palette_code_bits_ == b->palette_code_bits_); - if (b != out) { - for (i = 0; i < literal_size; ++i) { - out->literal_[i] = a->literal_[i] + b->literal_[i]; - } - for (i = 0; i < NUM_DISTANCE_CODES; ++i) { - out->distance_[i] = a->distance_[i] + b->distance_[i]; - } - for (i = 0; i < NUM_LITERAL_CODES; ++i) { - out->red_[i] = a->red_[i] + b->red_[i]; - out->blue_[i] = a->blue_[i] + b->blue_[i]; - out->alpha_[i] = a->alpha_[i] + b->alpha_[i]; - } - } else { - for (i = 0; i < literal_size; ++i) { - out->literal_[i] += a->literal_[i]; - } - for (i = 0; i < NUM_DISTANCE_CODES; ++i) { - out->distance_[i] += a->distance_[i]; - } - for (i = 0; i < NUM_LITERAL_CODES; ++i) { - out->red_[i] += a->red_[i]; - out->blue_[i] += a->blue_[i]; - out->alpha_[i] += a->alpha_[i]; - } - } -} - -//------------------------------------------------------------------------------ - -VP8LProcessBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed; - -VP8LTransformColorFunc VP8LTransformColor; - -VP8LCollectColorBlueTransformsFunc VP8LCollectColorBlueTransforms; -VP8LCollectColorRedTransformsFunc VP8LCollectColorRedTransforms; - -VP8LFastLog2SlowFunc VP8LFastLog2Slow; -VP8LFastLog2SlowFunc VP8LFastSLog2Slow; - -VP8LCostFunc VP8LExtraCost; -VP8LCostCombinedFunc VP8LExtraCostCombined; -VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy; - -GetEntropyUnrefinedHelperFunc VP8LGetEntropyUnrefinedHelper; - -VP8LHistogramAddFunc VP8LHistogramAdd; - -extern void VP8LEncDspInitSSE2(void); -extern void VP8LEncDspInitSSE41(void); -extern void VP8LEncDspInitNEON(void); -extern void VP8LEncDspInitMIPS32(void); -extern void VP8LEncDspInitMIPSdspR2(void); - -static volatile VP8CPUInfo lossless_enc_last_cpuinfo_used = - (VP8CPUInfo)&lossless_enc_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInit(void) { - if (lossless_enc_last_cpuinfo_used == VP8GetCPUInfo) return; - - VP8LDspInit(); - - VP8LSubtractGreenFromBlueAndRed = VP8LSubtractGreenFromBlueAndRed_C; - - VP8LTransformColor = VP8LTransformColor_C; - - VP8LCollectColorBlueTransforms = VP8LCollectColorBlueTransforms_C; - VP8LCollectColorRedTransforms = VP8LCollectColorRedTransforms_C; - - VP8LFastLog2Slow = FastLog2Slow; - VP8LFastSLog2Slow = FastSLog2Slow; - - VP8LExtraCost = ExtraCost; - VP8LExtraCostCombined = ExtraCostCombined; - VP8LCombinedShannonEntropy = CombinedShannonEntropy; - - VP8LGetEntropyUnrefinedHelper = GetEntropyUnrefinedHelper; - - VP8LHistogramAdd = HistogramAdd; - - // If defined, use CPUInfo() to overwrite some pointers with faster versions. - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - VP8LEncDspInitSSE2(); -#if defined(WEBP_USE_SSE41) - if (VP8GetCPUInfo(kSSE4_1)) { - VP8LEncDspInitSSE41(); - } -#endif - } -#endif -#if defined(WEBP_USE_NEON) - if (VP8GetCPUInfo(kNEON)) { - VP8LEncDspInitNEON(); - } -#endif -#if defined(WEBP_USE_MIPS32) - if (VP8GetCPUInfo(kMIPS32)) { - VP8LEncDspInitMIPS32(); - } -#endif -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - VP8LEncDspInitMIPSdspR2(); - } -#endif - } - lossless_enc_last_cpuinfo_used = VP8GetCPUInfo; -} - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/dsp/lossless_enc_mips32.c b/Example-Mac/Pods/libwebp/src/dsp/lossless_enc_mips32.c deleted file mode 100644 index 49c666d4..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/lossless_enc_mips32.c +++ /dev/null @@ -1,386 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// MIPS version of lossless functions -// -// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) -// Jovan Zelincevic (jovan.zelincevic@imgtec.com) - -#include "./dsp.h" -#include "./lossless.h" - -#if defined(WEBP_USE_MIPS32) - -#include -#include -#include -#include - -static float FastSLog2Slow(uint32_t v) { - assert(v >= LOG_LOOKUP_IDX_MAX); - if (v < APPROX_LOG_WITH_CORRECTION_MAX) { - uint32_t log_cnt, y, correction; - const int c24 = 24; - const float v_f = (float)v; - uint32_t temp; - - // Xf = 256 = 2^8 - // log_cnt is index of leading one in upper 24 bits - __asm__ volatile( - "clz %[log_cnt], %[v] \n\t" - "addiu %[y], $zero, 1 \n\t" - "subu %[log_cnt], %[c24], %[log_cnt] \n\t" - "sllv %[y], %[y], %[log_cnt] \n\t" - "srlv %[temp], %[v], %[log_cnt] \n\t" - : [log_cnt]"=&r"(log_cnt), [y]"=&r"(y), - [temp]"=r"(temp) - : [c24]"r"(c24), [v]"r"(v) - ); - - // vf = (2^log_cnt) * Xf; where y = 2^log_cnt and Xf < 256 - // Xf = floor(Xf) * (1 + (v % y) / v) - // log2(Xf) = log2(floor(Xf)) + log2(1 + (v % y) / v) - // The correction factor: log(1 + d) ~ d; for very small d values, so - // log2(1 + (v % y) / v) ~ LOG_2_RECIPROCAL * (v % y)/v - // LOG_2_RECIPROCAL ~ 23/16 - - // (v % y) = (v % 2^log_cnt) = v & (2^log_cnt - 1) - correction = (23 * (v & (y - 1))) >> 4; - return v_f * (kLog2Table[temp] + log_cnt) + correction; - } else { - return (float)(LOG_2_RECIPROCAL * v * log((double)v)); - } -} - -static float FastLog2Slow(uint32_t v) { - assert(v >= LOG_LOOKUP_IDX_MAX); - if (v < APPROX_LOG_WITH_CORRECTION_MAX) { - uint32_t log_cnt, y; - const int c24 = 24; - double log_2; - uint32_t temp; - - __asm__ volatile( - "clz %[log_cnt], %[v] \n\t" - "addiu %[y], $zero, 1 \n\t" - "subu %[log_cnt], %[c24], %[log_cnt] \n\t" - "sllv %[y], %[y], %[log_cnt] \n\t" - "srlv %[temp], %[v], %[log_cnt] \n\t" - : [log_cnt]"=&r"(log_cnt), [y]"=&r"(y), - [temp]"=r"(temp) - : [c24]"r"(c24), [v]"r"(v) - ); - - log_2 = kLog2Table[temp] + log_cnt; - if (v >= APPROX_LOG_MAX) { - // Since the division is still expensive, add this correction factor only - // for large values of 'v'. - - const uint32_t correction = (23 * (v & (y - 1))) >> 4; - log_2 += (double)correction / v; - } - return (float)log_2; - } else { - return (float)(LOG_2_RECIPROCAL * log((double)v)); - } -} - -// C version of this function: -// int i = 0; -// int64_t cost = 0; -// const uint32_t* pop = &population[4]; -// const uint32_t* LoopEnd = &population[length]; -// while (pop != LoopEnd) { -// ++i; -// cost += i * *pop; -// cost += i * *(pop + 1); -// pop += 2; -// } -// return (double)cost; -static double ExtraCost(const uint32_t* const population, int length) { - int i, temp0, temp1; - const uint32_t* pop = &population[4]; - const uint32_t* const LoopEnd = &population[length]; - - __asm__ volatile( - "mult $zero, $zero \n\t" - "xor %[i], %[i], %[i] \n\t" - "beq %[pop], %[LoopEnd], 2f \n\t" - "1: \n\t" - "lw %[temp0], 0(%[pop]) \n\t" - "lw %[temp1], 4(%[pop]) \n\t" - "addiu %[i], %[i], 1 \n\t" - "addiu %[pop], %[pop], 8 \n\t" - "madd %[i], %[temp0] \n\t" - "madd %[i], %[temp1] \n\t" - "bne %[pop], %[LoopEnd], 1b \n\t" - "2: \n\t" - "mfhi %[temp0] \n\t" - "mflo %[temp1] \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), - [i]"=&r"(i), [pop]"+r"(pop) - : [LoopEnd]"r"(LoopEnd) - : "memory", "hi", "lo" - ); - - return (double)((int64_t)temp0 << 32 | temp1); -} - -// C version of this function: -// int i = 0; -// int64_t cost = 0; -// const uint32_t* pX = &X[4]; -// const uint32_t* pY = &Y[4]; -// const uint32_t* LoopEnd = &X[length]; -// while (pX != LoopEnd) { -// const uint32_t xy0 = *pX + *pY; -// const uint32_t xy1 = *(pX + 1) + *(pY + 1); -// ++i; -// cost += i * xy0; -// cost += i * xy1; -// pX += 2; -// pY += 2; -// } -// return (double)cost; -static double ExtraCostCombined(const uint32_t* const X, - const uint32_t* const Y, int length) { - int i, temp0, temp1, temp2, temp3; - const uint32_t* pX = &X[4]; - const uint32_t* pY = &Y[4]; - const uint32_t* const LoopEnd = &X[length]; - - __asm__ volatile( - "mult $zero, $zero \n\t" - "xor %[i], %[i], %[i] \n\t" - "beq %[pX], %[LoopEnd], 2f \n\t" - "1: \n\t" - "lw %[temp0], 0(%[pX]) \n\t" - "lw %[temp1], 0(%[pY]) \n\t" - "lw %[temp2], 4(%[pX]) \n\t" - "lw %[temp3], 4(%[pY]) \n\t" - "addiu %[i], %[i], 1 \n\t" - "addu %[temp0], %[temp0], %[temp1] \n\t" - "addu %[temp2], %[temp2], %[temp3] \n\t" - "addiu %[pX], %[pX], 8 \n\t" - "addiu %[pY], %[pY], 8 \n\t" - "madd %[i], %[temp0] \n\t" - "madd %[i], %[temp2] \n\t" - "bne %[pX], %[LoopEnd], 1b \n\t" - "2: \n\t" - "mfhi %[temp0] \n\t" - "mflo %[temp1] \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), - [i]"=&r"(i), [pX]"+r"(pX), [pY]"+r"(pY) - : [LoopEnd]"r"(LoopEnd) - : "memory", "hi", "lo" - ); - - return (double)((int64_t)temp0 << 32 | temp1); -} - -#define HUFFMAN_COST_PASS \ - __asm__ volatile( \ - "sll %[temp1], %[temp0], 3 \n\t" \ - "addiu %[temp3], %[streak], -3 \n\t" \ - "addu %[temp2], %[pstreaks], %[temp1] \n\t" \ - "blez %[temp3], 1f \n\t" \ - "srl %[temp1], %[temp1], 1 \n\t" \ - "addu %[temp3], %[pcnts], %[temp1] \n\t" \ - "lw %[temp0], 4(%[temp2]) \n\t" \ - "lw %[temp1], 0(%[temp3]) \n\t" \ - "addu %[temp0], %[temp0], %[streak] \n\t" \ - "addiu %[temp1], %[temp1], 1 \n\t" \ - "sw %[temp0], 4(%[temp2]) \n\t" \ - "sw %[temp1], 0(%[temp3]) \n\t" \ - "b 2f \n\t" \ - "1: \n\t" \ - "lw %[temp0], 0(%[temp2]) \n\t" \ - "addu %[temp0], %[temp0], %[streak] \n\t" \ - "sw %[temp0], 0(%[temp2]) \n\t" \ - "2: \n\t" \ - : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \ - [temp3]"=&r"(temp3), [temp0]"+r"(temp0) \ - : [pstreaks]"r"(pstreaks), [pcnts]"r"(pcnts), \ - [streak]"r"(streak) \ - : "memory" \ - ); - -// Returns the various RLE counts -static WEBP_INLINE void GetEntropyUnrefinedHelper( - uint32_t val, int i, uint32_t* const val_prev, int* const i_prev, - VP8LBitEntropy* const bit_entropy, VP8LStreaks* const stats) { - int* const pstreaks = &stats->streaks[0][0]; - int* const pcnts = &stats->counts[0]; - int temp0, temp1, temp2, temp3; - const int streak = i - *i_prev; - - // Gather info for the bit entropy. - if (*val_prev != 0) { - bit_entropy->sum += (*val_prev) * streak; - bit_entropy->nonzeros += streak; - bit_entropy->nonzero_code = *i_prev; - bit_entropy->entropy -= VP8LFastSLog2(*val_prev) * streak; - if (bit_entropy->max_val < *val_prev) { - bit_entropy->max_val = *val_prev; - } - } - - // Gather info for the Huffman cost. - temp0 = (*val_prev != 0); - HUFFMAN_COST_PASS - - *val_prev = val; - *i_prev = i; -} - -#define ASM_START \ - __asm__ volatile( \ - ".set push \n\t" \ - ".set at \n\t" \ - ".set macro \n\t" \ - "1: \n\t" - -// P2 = P0 + P1 -// A..D - offsets -// E - temp variable to tell macro -// if pointer should be incremented -// literal_ and successive histograms could be unaligned -// so we must use ulw and usw -#define ADD_TO_OUT(A, B, C, D, E, P0, P1, P2) \ - "ulw %[temp0], " #A "(%[" #P0 "]) \n\t" \ - "ulw %[temp1], " #B "(%[" #P0 "]) \n\t" \ - "ulw %[temp2], " #C "(%[" #P0 "]) \n\t" \ - "ulw %[temp3], " #D "(%[" #P0 "]) \n\t" \ - "ulw %[temp4], " #A "(%[" #P1 "]) \n\t" \ - "ulw %[temp5], " #B "(%[" #P1 "]) \n\t" \ - "ulw %[temp6], " #C "(%[" #P1 "]) \n\t" \ - "ulw %[temp7], " #D "(%[" #P1 "]) \n\t" \ - "addu %[temp4], %[temp4], %[temp0] \n\t" \ - "addu %[temp5], %[temp5], %[temp1] \n\t" \ - "addu %[temp6], %[temp6], %[temp2] \n\t" \ - "addu %[temp7], %[temp7], %[temp3] \n\t" \ - "addiu %[" #P0 "], %[" #P0 "], 16 \n\t" \ - ".if " #E " == 1 \n\t" \ - "addiu %[" #P1 "], %[" #P1 "], 16 \n\t" \ - ".endif \n\t" \ - "usw %[temp4], " #A "(%[" #P2 "]) \n\t" \ - "usw %[temp5], " #B "(%[" #P2 "]) \n\t" \ - "usw %[temp6], " #C "(%[" #P2 "]) \n\t" \ - "usw %[temp7], " #D "(%[" #P2 "]) \n\t" \ - "addiu %[" #P2 "], %[" #P2 "], 16 \n\t" \ - "bne %[" #P0 "], %[LoopEnd], 1b \n\t" \ - ".set pop \n\t" \ - -#define ASM_END_COMMON_0 \ - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), \ - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), \ - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \ - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), \ - [pa]"+r"(pa), [pout]"+r"(pout) - -#define ASM_END_COMMON_1 \ - : [LoopEnd]"r"(LoopEnd) \ - : "memory", "at" \ - ); - -#define ASM_END_0 \ - ASM_END_COMMON_0 \ - , [pb]"+r"(pb) \ - ASM_END_COMMON_1 - -#define ASM_END_1 \ - ASM_END_COMMON_0 \ - ASM_END_COMMON_1 - -#define ADD_VECTOR(A, B, OUT, SIZE, EXTRA_SIZE) do { \ - const uint32_t* pa = (const uint32_t*)(A); \ - const uint32_t* pb = (const uint32_t*)(B); \ - uint32_t* pout = (uint32_t*)(OUT); \ - const uint32_t* const LoopEnd = pa + (SIZE); \ - assert((SIZE) % 4 == 0); \ - ASM_START \ - ADD_TO_OUT(0, 4, 8, 12, 1, pa, pb, pout) \ - ASM_END_0 \ - if ((EXTRA_SIZE) > 0) { \ - const int last = (EXTRA_SIZE); \ - int i; \ - for (i = 0; i < last; ++i) pout[i] = pa[i] + pb[i]; \ - } \ -} while (0) - -#define ADD_VECTOR_EQ(A, OUT, SIZE, EXTRA_SIZE) do { \ - const uint32_t* pa = (const uint32_t*)(A); \ - uint32_t* pout = (uint32_t*)(OUT); \ - const uint32_t* const LoopEnd = pa + (SIZE); \ - assert((SIZE) % 4 == 0); \ - ASM_START \ - ADD_TO_OUT(0, 4, 8, 12, 0, pa, pout, pout) \ - ASM_END_1 \ - if ((EXTRA_SIZE) > 0) { \ - const int last = (EXTRA_SIZE); \ - int i; \ - for (i = 0; i < last; ++i) pout[i] += pa[i]; \ - } \ -} while (0) - -static void HistogramAdd(const VP8LHistogram* const a, - const VP8LHistogram* const b, - VP8LHistogram* const out) { - uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; - const int extra_cache_size = VP8LHistogramNumCodes(a->palette_code_bits_) - - (NUM_LITERAL_CODES + NUM_LENGTH_CODES); - assert(a->palette_code_bits_ == b->palette_code_bits_); - - if (b != out) { - ADD_VECTOR(a->literal_, b->literal_, out->literal_, - NUM_LITERAL_CODES + NUM_LENGTH_CODES, extra_cache_size); - ADD_VECTOR(a->distance_, b->distance_, out->distance_, - NUM_DISTANCE_CODES, 0); - ADD_VECTOR(a->red_, b->red_, out->red_, NUM_LITERAL_CODES, 0); - ADD_VECTOR(a->blue_, b->blue_, out->blue_, NUM_LITERAL_CODES, 0); - ADD_VECTOR(a->alpha_, b->alpha_, out->alpha_, NUM_LITERAL_CODES, 0); - } else { - ADD_VECTOR_EQ(a->literal_, out->literal_, - NUM_LITERAL_CODES + NUM_LENGTH_CODES, extra_cache_size); - ADD_VECTOR_EQ(a->distance_, out->distance_, NUM_DISTANCE_CODES, 0); - ADD_VECTOR_EQ(a->red_, out->red_, NUM_LITERAL_CODES, 0); - ADD_VECTOR_EQ(a->blue_, out->blue_, NUM_LITERAL_CODES, 0); - ADD_VECTOR_EQ(a->alpha_, out->alpha_, NUM_LITERAL_CODES, 0); - } -} - -#undef ADD_VECTOR_EQ -#undef ADD_VECTOR -#undef ASM_END_1 -#undef ASM_END_0 -#undef ASM_END_COMMON_1 -#undef ASM_END_COMMON_0 -#undef ADD_TO_OUT -#undef ASM_START - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8LEncDspInitMIPS32(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMIPS32(void) { - VP8LFastSLog2Slow = FastSLog2Slow; - VP8LFastLog2Slow = FastLog2Slow; - VP8LExtraCost = ExtraCost; - VP8LExtraCostCombined = ExtraCostCombined; - VP8LGetEntropyUnrefinedHelper = GetEntropyUnrefinedHelper; - VP8LHistogramAdd = HistogramAdd; -} - -#else // !WEBP_USE_MIPS32 - -WEBP_DSP_INIT_STUB(VP8LEncDspInitMIPS32) - -#endif // WEBP_USE_MIPS32 diff --git a/Example-Mac/Pods/libwebp/src/dsp/lossless_enc_mips_dsp_r2.c b/Example-Mac/Pods/libwebp/src/dsp/lossless_enc_mips_dsp_r2.c deleted file mode 100644 index 0abf3c4f..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/lossless_enc_mips_dsp_r2.c +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Image transform methods for lossless encoder. -// -// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) -// Jovan Zelincevic (jovan.zelincevic@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS_DSP_R2) - -#include "./lossless.h" - -static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, - int num_pixels) { - uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; - uint32_t* const p_loop1_end = argb_data + (num_pixels & ~3); - uint32_t* const p_loop2_end = p_loop1_end + (num_pixels & 3); - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "beq %[argb_data], %[p_loop1_end], 3f \n\t" - " nop \n\t" - "0: \n\t" - "lw %[temp0], 0(%[argb_data]) \n\t" - "lw %[temp1], 4(%[argb_data]) \n\t" - "lw %[temp2], 8(%[argb_data]) \n\t" - "lw %[temp3], 12(%[argb_data]) \n\t" - "ext %[temp4], %[temp0], 8, 8 \n\t" - "ext %[temp5], %[temp1], 8, 8 \n\t" - "ext %[temp6], %[temp2], 8, 8 \n\t" - "ext %[temp7], %[temp3], 8, 8 \n\t" - "addiu %[argb_data], %[argb_data], 16 \n\t" - "replv.ph %[temp4], %[temp4] \n\t" - "replv.ph %[temp5], %[temp5] \n\t" - "replv.ph %[temp6], %[temp6] \n\t" - "replv.ph %[temp7], %[temp7] \n\t" - "subu.qb %[temp0], %[temp0], %[temp4] \n\t" - "subu.qb %[temp1], %[temp1], %[temp5] \n\t" - "subu.qb %[temp2], %[temp2], %[temp6] \n\t" - "subu.qb %[temp3], %[temp3], %[temp7] \n\t" - "sw %[temp0], -16(%[argb_data]) \n\t" - "sw %[temp1], -12(%[argb_data]) \n\t" - "sw %[temp2], -8(%[argb_data]) \n\t" - "bne %[argb_data], %[p_loop1_end], 0b \n\t" - " sw %[temp3], -4(%[argb_data]) \n\t" - "3: \n\t" - "beq %[argb_data], %[p_loop2_end], 2f \n\t" - " nop \n\t" - "1: \n\t" - "lw %[temp0], 0(%[argb_data]) \n\t" - "addiu %[argb_data], %[argb_data], 4 \n\t" - "ext %[temp4], %[temp0], 8, 8 \n\t" - "replv.ph %[temp4], %[temp4] \n\t" - "subu.qb %[temp0], %[temp0], %[temp4] \n\t" - "bne %[argb_data], %[p_loop2_end], 1b \n\t" - " sw %[temp0], -4(%[argb_data]) \n\t" - "2: \n\t" - ".set pop \n\t" - : [argb_data]"+&r"(argb_data), [temp0]"=&r"(temp0), - [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6), - [temp7]"=&r"(temp7) - : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) - : "memory" - ); -} - -static WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred, - int8_t color) { - return (uint32_t)((int)(color_pred) * color) >> 5; -} - -static void TransformColor(const VP8LMultipliers* const m, uint32_t* data, - int num_pixels) { - int temp0, temp1, temp2, temp3, temp4, temp5; - uint32_t argb, argb1, new_red, new_red1; - const uint32_t G_to_R = m->green_to_red_; - const uint32_t G_to_B = m->green_to_blue_; - const uint32_t R_to_B = m->red_to_blue_; - uint32_t* const p_loop_end = data + (num_pixels & ~1); - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "beq %[data], %[p_loop_end], 1f \n\t" - " nop \n\t" - "replv.ph %[temp0], %[G_to_R] \n\t" - "replv.ph %[temp1], %[G_to_B] \n\t" - "replv.ph %[temp2], %[R_to_B] \n\t" - "shll.ph %[temp0], %[temp0], 8 \n\t" - "shll.ph %[temp1], %[temp1], 8 \n\t" - "shll.ph %[temp2], %[temp2], 8 \n\t" - "shra.ph %[temp0], %[temp0], 8 \n\t" - "shra.ph %[temp1], %[temp1], 8 \n\t" - "shra.ph %[temp2], %[temp2], 8 \n\t" - "0: \n\t" - "lw %[argb], 0(%[data]) \n\t" - "lw %[argb1], 4(%[data]) \n\t" - "lhu %[new_red], 2(%[data]) \n\t" - "lhu %[new_red1], 6(%[data]) \n\t" - "precrq.qb.ph %[temp3], %[argb], %[argb1] \n\t" - "precr.qb.ph %[temp4], %[argb], %[argb1] \n\t" - "preceu.ph.qbra %[temp3], %[temp3] \n\t" - "preceu.ph.qbla %[temp4], %[temp4] \n\t" - "shll.ph %[temp3], %[temp3], 8 \n\t" - "shll.ph %[temp4], %[temp4], 8 \n\t" - "shra.ph %[temp3], %[temp3], 8 \n\t" - "shra.ph %[temp4], %[temp4], 8 \n\t" - "mul.ph %[temp5], %[temp3], %[temp0] \n\t" - "mul.ph %[temp3], %[temp3], %[temp1] \n\t" - "mul.ph %[temp4], %[temp4], %[temp2] \n\t" - "addiu %[data], %[data], 8 \n\t" - "ins %[new_red1], %[new_red], 16, 16 \n\t" - "ins %[argb1], %[argb], 16, 16 \n\t" - "shra.ph %[temp5], %[temp5], 5 \n\t" - "shra.ph %[temp3], %[temp3], 5 \n\t" - "shra.ph %[temp4], %[temp4], 5 \n\t" - "subu.ph %[new_red1], %[new_red1], %[temp5] \n\t" - "subu.ph %[argb1], %[argb1], %[temp3] \n\t" - "preceu.ph.qbra %[temp5], %[new_red1] \n\t" - "subu.ph %[argb1], %[argb1], %[temp4] \n\t" - "preceu.ph.qbra %[temp3], %[argb1] \n\t" - "sb %[temp5], -2(%[data]) \n\t" - "sb %[temp3], -4(%[data]) \n\t" - "sra %[temp5], %[temp5], 16 \n\t" - "sra %[temp3], %[temp3], 16 \n\t" - "sb %[temp5], -6(%[data]) \n\t" - "bne %[data], %[p_loop_end], 0b \n\t" - " sb %[temp3], -8(%[data]) \n\t" - "1: \n\t" - ".set pop \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [new_red1]"=&r"(new_red1), [new_red]"=&r"(new_red), - [argb]"=&r"(argb), [argb1]"=&r"(argb1), [data]"+&r"(data) - : [G_to_R]"r"(G_to_R), [R_to_B]"r"(R_to_B), - [G_to_B]"r"(G_to_B), [p_loop_end]"r"(p_loop_end) - : "memory", "hi", "lo" - ); - - if (num_pixels & 1) { - const uint32_t argb_ = data[0]; - const uint32_t green = argb_ >> 8; - const uint32_t red = argb_ >> 16; - uint32_t new_blue = argb_; - new_red = red; - new_red -= ColorTransformDelta(m->green_to_red_, green); - new_red &= 0xff; - new_blue -= ColorTransformDelta(m->green_to_blue_, green); - new_blue -= ColorTransformDelta(m->red_to_blue_, red); - new_blue &= 0xff; - data[0] = (argb_ & 0xff00ff00u) | (new_red << 16) | (new_blue); - } -} - -static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue, - uint8_t red_to_blue, - uint32_t argb) { - const uint32_t green = argb >> 8; - const uint32_t red = argb >> 16; - uint8_t new_blue = argb; - new_blue -= ColorTransformDelta(green_to_blue, green); - new_blue -= ColorTransformDelta(red_to_blue, red); - return (new_blue & 0xff); -} - -static void CollectColorBlueTransforms(const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_blue, int red_to_blue, - int histo[]) { - const int rtb = (red_to_blue << 16) | (red_to_blue & 0xffff); - const int gtb = (green_to_blue << 16) | (green_to_blue & 0xffff); - const uint32_t mask = 0xff00ffu; - while (tile_height-- > 0) { - int x; - const uint32_t* p_argb = argb; - argb += stride; - for (x = 0; x < (tile_width >> 1); ++x) { - int temp0, temp1, temp2, temp3, temp4, temp5, temp6; - __asm__ volatile ( - "lw %[temp0], 0(%[p_argb]) \n\t" - "lw %[temp1], 4(%[p_argb]) \n\t" - "precr.qb.ph %[temp2], %[temp0], %[temp1] \n\t" - "ins %[temp1], %[temp0], 16, 16 \n\t" - "shra.ph %[temp2], %[temp2], 8 \n\t" - "shra.ph %[temp3], %[temp1], 8 \n\t" - "mul.ph %[temp5], %[temp2], %[rtb] \n\t" - "mul.ph %[temp6], %[temp3], %[gtb] \n\t" - "and %[temp4], %[temp1], %[mask] \n\t" - "addiu %[p_argb], %[p_argb], 8 \n\t" - "shra.ph %[temp5], %[temp5], 5 \n\t" - "shra.ph %[temp6], %[temp6], 5 \n\t" - "subu.qb %[temp2], %[temp4], %[temp5] \n\t" - "subu.qb %[temp2], %[temp2], %[temp6] \n\t" - : [p_argb]"+&r"(p_argb), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), - [temp5]"=&r"(temp5), [temp6]"=&r"(temp6) - : [rtb]"r"(rtb), [gtb]"r"(gtb), [mask]"r"(mask) - : "memory", "hi", "lo" - ); - ++histo[(uint8_t)(temp2 >> 16)]; - ++histo[(uint8_t)temp2]; - } - if (tile_width & 1) { - ++histo[TransformColorBlue(green_to_blue, red_to_blue, *p_argb)]; - } - } -} - -static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red, - uint32_t argb) { - const uint32_t green = argb >> 8; - uint32_t new_red = argb >> 16; - new_red -= ColorTransformDelta(green_to_red, green); - return (new_red & 0xff); -} - -static void CollectColorRedTransforms(const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_red, int histo[]) { - const int gtr = (green_to_red << 16) | (green_to_red & 0xffff); - while (tile_height-- > 0) { - int x; - const uint32_t* p_argb = argb; - argb += stride; - for (x = 0; x < (tile_width >> 1); ++x) { - int temp0, temp1, temp2, temp3, temp4; - __asm__ volatile ( - "lw %[temp0], 0(%[p_argb]) \n\t" - "lw %[temp1], 4(%[p_argb]) \n\t" - "precrq.ph.w %[temp4], %[temp0], %[temp1] \n\t" - "ins %[temp1], %[temp0], 16, 16 \n\t" - "shra.ph %[temp3], %[temp1], 8 \n\t" - "mul.ph %[temp2], %[temp3], %[gtr] \n\t" - "addiu %[p_argb], %[p_argb], 8 \n\t" - "shra.ph %[temp2], %[temp2], 5 \n\t" - "subu.qb %[temp2], %[temp4], %[temp2] \n\t" - : [p_argb]"+&r"(p_argb), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4) - : [gtr]"r"(gtr) - : "memory", "hi", "lo" - ); - ++histo[(uint8_t)(temp2 >> 16)]; - ++histo[(uint8_t)temp2]; - } - if (tile_width & 1) { - ++histo[TransformColorRed(green_to_red, *p_argb)]; - } - } -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8LEncDspInitMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMIPSdspR2(void) { - VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed; - VP8LTransformColor = TransformColor; - VP8LCollectColorBlueTransforms = CollectColorBlueTransforms; - VP8LCollectColorRedTransforms = CollectColorRedTransforms; -} - -#else // !WEBP_USE_MIPS_DSP_R2 - -WEBP_DSP_INIT_STUB(VP8LEncDspInitMIPSdspR2) - -#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/Example-Mac/Pods/libwebp/src/dsp/lossless_enc_neon.c b/Example-Mac/Pods/libwebp/src/dsp/lossless_enc_neon.c deleted file mode 100644 index 4c56f259..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/lossless_enc_neon.c +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// NEON variant of methods for lossless encoder -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_NEON) - -#include - -#include "./lossless.h" -#include "./neon.h" - -//------------------------------------------------------------------------------ -// Subtract-Green Transform - -// vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use -// non-standard versions there. -#if defined(__APPLE__) && defined(__aarch64__) && \ - defined(__apple_build_version__) && (__apple_build_version__< 6020037) -#define USE_VTBLQ -#endif - -#ifdef USE_VTBLQ -// 255 = byte will be zeroed -static const uint8_t kGreenShuffle[16] = { - 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255 -}; - -static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb, - const uint8x16_t shuffle) { - return vcombine_u8(vtbl1q_u8(argb, vget_low_u8(shuffle)), - vtbl1q_u8(argb, vget_high_u8(shuffle))); -} -#else // !USE_VTBLQ -// 255 = byte will be zeroed -static const uint8_t kGreenShuffle[8] = { 1, 255, 1, 255, 5, 255, 5, 255 }; - -static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb, - const uint8x8_t shuffle) { - return vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle), - vtbl1_u8(vget_high_u8(argb), shuffle)); -} -#endif // USE_VTBLQ - -static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) { - const uint32_t* const end = argb_data + (num_pixels & ~3); -#ifdef USE_VTBLQ - const uint8x16_t shuffle = vld1q_u8(kGreenShuffle); -#else - const uint8x8_t shuffle = vld1_u8(kGreenShuffle); -#endif - for (; argb_data < end; argb_data += 4) { - const uint8x16_t argb = vld1q_u8((uint8_t*)argb_data); - const uint8x16_t greens = DoGreenShuffle(argb, shuffle); - vst1q_u8((uint8_t*)argb_data, vsubq_u8(argb, greens)); - } - // fallthrough and finish off with plain-C - VP8LSubtractGreenFromBlueAndRed_C(argb_data, num_pixels & 3); -} - -//------------------------------------------------------------------------------ -// Color Transform - -static void TransformColor(const VP8LMultipliers* const m, - uint32_t* argb_data, int num_pixels) { - // sign-extended multiplying constants, pre-shifted by 6. -#define CST(X) (((int16_t)(m->X << 8)) >> 6) - const int16_t rb[8] = { - CST(green_to_blue_), CST(green_to_red_), - CST(green_to_blue_), CST(green_to_red_), - CST(green_to_blue_), CST(green_to_red_), - CST(green_to_blue_), CST(green_to_red_) - }; - const int16x8_t mults_rb = vld1q_s16(rb); - const int16_t b2[8] = { - 0, CST(red_to_blue_), 0, CST(red_to_blue_), - 0, CST(red_to_blue_), 0, CST(red_to_blue_), - }; - const int16x8_t mults_b2 = vld1q_s16(b2); -#undef CST -#ifdef USE_VTBLQ - static const uint8_t kg0g0[16] = { - 255, 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13 - }; - const uint8x16_t shuffle = vld1q_u8(kg0g0); -#else - static const uint8_t k0g0g[8] = { 255, 1, 255, 1, 255, 5, 255, 5 }; - const uint8x8_t shuffle = vld1_u8(k0g0g); -#endif - const uint32x4_t mask_rb = vdupq_n_u32(0x00ff00ffu); // red-blue masks - int i; - for (i = 0; i + 4 <= num_pixels; i += 4) { - const uint8x16_t in = vld1q_u8((uint8_t*)(argb_data + i)); - // 0 g 0 g - const uint8x16_t greens = DoGreenShuffle(in, shuffle); - // x dr x db1 - const int16x8_t A = vqdmulhq_s16(vreinterpretq_s16_u8(greens), mults_rb); - // r 0 b 0 - const int16x8_t B = vshlq_n_s16(vreinterpretq_s16_u8(in), 8); - // x db2 0 0 - const int16x8_t C = vqdmulhq_s16(B, mults_b2); - // 0 0 x db2 - const uint32x4_t D = vshrq_n_u32(vreinterpretq_u32_s16(C), 16); - // x dr x db - const int8x16_t E = vaddq_s8(vreinterpretq_s8_u32(D), - vreinterpretq_s8_s16(A)); - // 0 dr 0 db - const uint32x4_t F = vandq_u32(vreinterpretq_u32_s8(E), mask_rb); - const int8x16_t out = vsubq_s8(vreinterpretq_s8_u8(in), - vreinterpretq_s8_u32(F)); - vst1q_s8((int8_t*)(argb_data + i), out); - } - // fallthrough and finish off with plain-C - VP8LTransformColor_C(m, argb_data + i, num_pixels - i); -} - -#undef USE_VTBLQ - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8LEncDspInitNEON(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitNEON(void) { - VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed; - VP8LTransformColor = TransformColor; -} - -#else // !WEBP_USE_NEON - -WEBP_DSP_INIT_STUB(VP8LEncDspInitNEON) - -#endif // WEBP_USE_NEON diff --git a/Example-Mac/Pods/libwebp/src/dsp/lossless_enc_sse2.c b/Example-Mac/Pods/libwebp/src/dsp/lossless_enc_sse2.c deleted file mode 100644 index e8c98341..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/lossless_enc_sse2.c +++ /dev/null @@ -1,345 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// SSE2 variant of methods for lossless encoder -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE2) -#include -#include -#include "./lossless.h" - -// For sign-extended multiplying constants, pre-shifted by 5: -#define CST_5b(X) (((int16_t)((uint16_t)X << 8)) >> 5) - -//------------------------------------------------------------------------------ -// Subtract-Green Transform - -static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) { - int i; - for (i = 0; i + 4 <= num_pixels; i += 4) { - const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb - const __m128i A = _mm_srli_epi16(in, 8); // 0 a 0 g - const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0)); - const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // 0g0g - const __m128i out = _mm_sub_epi8(in, C); - _mm_storeu_si128((__m128i*)&argb_data[i], out); - } - // fallthrough and finish off with plain-C - VP8LSubtractGreenFromBlueAndRed_C(argb_data + i, num_pixels - i); -} - -//------------------------------------------------------------------------------ -// Color Transform - -static void TransformColor(const VP8LMultipliers* const m, - uint32_t* argb_data, int num_pixels) { - const __m128i mults_rb = _mm_set_epi16( - CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_), - CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_), - CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_), - CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_)); - const __m128i mults_b2 = _mm_set_epi16( - CST_5b(m->red_to_blue_), 0, CST_5b(m->red_to_blue_), 0, - CST_5b(m->red_to_blue_), 0, CST_5b(m->red_to_blue_), 0); - const __m128i mask_ag = _mm_set1_epi32(0xff00ff00); // alpha-green masks - const __m128i mask_rb = _mm_set1_epi32(0x00ff00ff); // red-blue masks - int i; - for (i = 0; i + 4 <= num_pixels; i += 4) { - const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb - const __m128i A = _mm_and_si128(in, mask_ag); // a 0 g 0 - const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0)); - const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // g0g0 - const __m128i D = _mm_mulhi_epi16(C, mults_rb); // x dr x db1 - const __m128i E = _mm_slli_epi16(in, 8); // r 0 b 0 - const __m128i F = _mm_mulhi_epi16(E, mults_b2); // x db2 0 0 - const __m128i G = _mm_srli_epi32(F, 16); // 0 0 x db2 - const __m128i H = _mm_add_epi8(G, D); // x dr x db - const __m128i I = _mm_and_si128(H, mask_rb); // 0 dr 0 db - const __m128i out = _mm_sub_epi8(in, I); - _mm_storeu_si128((__m128i*)&argb_data[i], out); - } - // fallthrough and finish off with plain-C - VP8LTransformColor_C(m, argb_data + i, num_pixels - i); -} - -//------------------------------------------------------------------------------ -#define SPAN 8 -static void CollectColorBlueTransforms(const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_blue, int red_to_blue, - int histo[]) { - const __m128i mults_r = _mm_set_epi16( - CST_5b(red_to_blue), 0, CST_5b(red_to_blue), 0, - CST_5b(red_to_blue), 0, CST_5b(red_to_blue), 0); - const __m128i mults_g = _mm_set_epi16( - 0, CST_5b(green_to_blue), 0, CST_5b(green_to_blue), - 0, CST_5b(green_to_blue), 0, CST_5b(green_to_blue)); - const __m128i mask_g = _mm_set1_epi32(0x00ff00); // green mask - const __m128i mask_b = _mm_set1_epi32(0x0000ff); // blue mask - int y; - for (y = 0; y < tile_height; ++y) { - const uint32_t* const src = argb + y * stride; - int i, x; - for (x = 0; x + SPAN <= tile_width; x += SPAN) { - uint16_t values[SPAN]; - const __m128i in0 = _mm_loadu_si128((__m128i*)&src[x + 0]); - const __m128i in1 = _mm_loadu_si128((__m128i*)&src[x + SPAN / 2]); - const __m128i A0 = _mm_slli_epi16(in0, 8); // r 0 | b 0 - const __m128i A1 = _mm_slli_epi16(in1, 8); - const __m128i B0 = _mm_and_si128(in0, mask_g); // 0 0 | g 0 - const __m128i B1 = _mm_and_si128(in1, mask_g); - const __m128i C0 = _mm_mulhi_epi16(A0, mults_r); // x db | 0 0 - const __m128i C1 = _mm_mulhi_epi16(A1, mults_r); - const __m128i D0 = _mm_mulhi_epi16(B0, mults_g); // 0 0 | x db - const __m128i D1 = _mm_mulhi_epi16(B1, mults_g); - const __m128i E0 = _mm_sub_epi8(in0, D0); // x x | x b' - const __m128i E1 = _mm_sub_epi8(in1, D1); - const __m128i F0 = _mm_srli_epi32(C0, 16); // 0 0 | x db - const __m128i F1 = _mm_srli_epi32(C1, 16); - const __m128i G0 = _mm_sub_epi8(E0, F0); // 0 0 | x b' - const __m128i G1 = _mm_sub_epi8(E1, F1); - const __m128i H0 = _mm_and_si128(G0, mask_b); // 0 0 | 0 b - const __m128i H1 = _mm_and_si128(G1, mask_b); - const __m128i I = _mm_packs_epi32(H0, H1); // 0 b' | 0 b' - _mm_storeu_si128((__m128i*)values, I); - for (i = 0; i < SPAN; ++i) ++histo[values[i]]; - } - } - { - const int left_over = tile_width & (SPAN - 1); - if (left_over > 0) { - VP8LCollectColorBlueTransforms_C(argb + tile_width - left_over, stride, - left_over, tile_height, - green_to_blue, red_to_blue, histo); - } - } -} - -static void CollectColorRedTransforms(const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_red, int histo[]) { - const __m128i mults_g = _mm_set_epi16( - 0, CST_5b(green_to_red), 0, CST_5b(green_to_red), - 0, CST_5b(green_to_red), 0, CST_5b(green_to_red)); - const __m128i mask_g = _mm_set1_epi32(0x00ff00); // green mask - const __m128i mask = _mm_set1_epi32(0xff); - - int y; - for (y = 0; y < tile_height; ++y) { - const uint32_t* const src = argb + y * stride; - int i, x; - for (x = 0; x + SPAN <= tile_width; x += SPAN) { - uint16_t values[SPAN]; - const __m128i in0 = _mm_loadu_si128((__m128i*)&src[x + 0]); - const __m128i in1 = _mm_loadu_si128((__m128i*)&src[x + SPAN / 2]); - const __m128i A0 = _mm_and_si128(in0, mask_g); // 0 0 | g 0 - const __m128i A1 = _mm_and_si128(in1, mask_g); - const __m128i B0 = _mm_srli_epi32(in0, 16); // 0 0 | x r - const __m128i B1 = _mm_srli_epi32(in1, 16); - const __m128i C0 = _mm_mulhi_epi16(A0, mults_g); // 0 0 | x dr - const __m128i C1 = _mm_mulhi_epi16(A1, mults_g); - const __m128i E0 = _mm_sub_epi8(B0, C0); // x x | x r' - const __m128i E1 = _mm_sub_epi8(B1, C1); - const __m128i F0 = _mm_and_si128(E0, mask); // 0 0 | 0 r' - const __m128i F1 = _mm_and_si128(E1, mask); - const __m128i I = _mm_packs_epi32(F0, F1); - _mm_storeu_si128((__m128i*)values, I); - for (i = 0; i < SPAN; ++i) ++histo[values[i]]; - } - } - { - const int left_over = tile_width & (SPAN - 1); - if (left_over > 0) { - VP8LCollectColorRedTransforms_C(argb + tile_width - left_over, stride, - left_over, tile_height, - green_to_red, histo); - } - } -} -#undef SPAN - -//------------------------------------------------------------------------------ - -#define LINE_SIZE 16 // 8 or 16 -static void AddVector(const uint32_t* a, const uint32_t* b, uint32_t* out, - int size) { - int i; - assert(size % LINE_SIZE == 0); - for (i = 0; i < size; i += LINE_SIZE) { - const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i + 0]); - const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]); -#if (LINE_SIZE == 16) - const __m128i a2 = _mm_loadu_si128((const __m128i*)&a[i + 8]); - const __m128i a3 = _mm_loadu_si128((const __m128i*)&a[i + 12]); -#endif - const __m128i b0 = _mm_loadu_si128((const __m128i*)&b[i + 0]); - const __m128i b1 = _mm_loadu_si128((const __m128i*)&b[i + 4]); -#if (LINE_SIZE == 16) - const __m128i b2 = _mm_loadu_si128((const __m128i*)&b[i + 8]); - const __m128i b3 = _mm_loadu_si128((const __m128i*)&b[i + 12]); -#endif - _mm_storeu_si128((__m128i*)&out[i + 0], _mm_add_epi32(a0, b0)); - _mm_storeu_si128((__m128i*)&out[i + 4], _mm_add_epi32(a1, b1)); -#if (LINE_SIZE == 16) - _mm_storeu_si128((__m128i*)&out[i + 8], _mm_add_epi32(a2, b2)); - _mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3)); -#endif - } -} - -static void AddVectorEq(const uint32_t* a, uint32_t* out, int size) { - int i; - assert(size % LINE_SIZE == 0); - for (i = 0; i < size; i += LINE_SIZE) { - const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i + 0]); - const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]); -#if (LINE_SIZE == 16) - const __m128i a2 = _mm_loadu_si128((const __m128i*)&a[i + 8]); - const __m128i a3 = _mm_loadu_si128((const __m128i*)&a[i + 12]); -#endif - const __m128i b0 = _mm_loadu_si128((const __m128i*)&out[i + 0]); - const __m128i b1 = _mm_loadu_si128((const __m128i*)&out[i + 4]); -#if (LINE_SIZE == 16) - const __m128i b2 = _mm_loadu_si128((const __m128i*)&out[i + 8]); - const __m128i b3 = _mm_loadu_si128((const __m128i*)&out[i + 12]); -#endif - _mm_storeu_si128((__m128i*)&out[i + 0], _mm_add_epi32(a0, b0)); - _mm_storeu_si128((__m128i*)&out[i + 4], _mm_add_epi32(a1, b1)); -#if (LINE_SIZE == 16) - _mm_storeu_si128((__m128i*)&out[i + 8], _mm_add_epi32(a2, b2)); - _mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3)); -#endif - } -} -#undef LINE_SIZE - -// Note we are adding uint32_t's as *signed* int32's (using _mm_add_epi32). But -// that's ok since the histogram values are less than 1<<28 (max picture size). -static void HistogramAdd(const VP8LHistogram* const a, - const VP8LHistogram* const b, - VP8LHistogram* const out) { - int i; - const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_); - assert(a->palette_code_bits_ == b->palette_code_bits_); - if (b != out) { - AddVector(a->literal_, b->literal_, out->literal_, NUM_LITERAL_CODES); - AddVector(a->red_, b->red_, out->red_, NUM_LITERAL_CODES); - AddVector(a->blue_, b->blue_, out->blue_, NUM_LITERAL_CODES); - AddVector(a->alpha_, b->alpha_, out->alpha_, NUM_LITERAL_CODES); - } else { - AddVectorEq(a->literal_, out->literal_, NUM_LITERAL_CODES); - AddVectorEq(a->red_, out->red_, NUM_LITERAL_CODES); - AddVectorEq(a->blue_, out->blue_, NUM_LITERAL_CODES); - AddVectorEq(a->alpha_, out->alpha_, NUM_LITERAL_CODES); - } - for (i = NUM_LITERAL_CODES; i < literal_size; ++i) { - out->literal_[i] = a->literal_[i] + b->literal_[i]; - } - for (i = 0; i < NUM_DISTANCE_CODES; ++i) { - out->distance_[i] = a->distance_[i] + b->distance_[i]; - } -} - -//------------------------------------------------------------------------------ -// Entropy - -// Checks whether the X or Y contribution is worth computing and adding. -// Used in loop unrolling. -#define ANALYZE_X_OR_Y(x_or_y, j) \ - do { \ - if (x_or_y[i + j] != 0) retval -= VP8LFastSLog2(x_or_y[i + j]); \ - } while (0) - -// Checks whether the X + Y contribution is worth computing and adding. -// Used in loop unrolling. -#define ANALYZE_XY(j) \ - do { \ - if (tmp[j] != 0) { \ - retval -= VP8LFastSLog2(tmp[j]); \ - ANALYZE_X_OR_Y(X, j); \ - } \ - } while (0) - -static float CombinedShannonEntropy(const int X[256], const int Y[256]) { - int i; - double retval = 0.; - int sumX, sumXY; - int32_t tmp[4]; - __m128i zero = _mm_setzero_si128(); - // Sums up X + Y, 4 ints at a time (and will merge it at the end for sumXY). - __m128i sumXY_128 = zero; - __m128i sumX_128 = zero; - - for (i = 0; i < 256; i += 4) { - const __m128i x = _mm_loadu_si128((const __m128i*)(X + i)); - const __m128i y = _mm_loadu_si128((const __m128i*)(Y + i)); - - // Check if any X is non-zero: this actually provides a speedup as X is - // usually sparse. - if (_mm_movemask_epi8(_mm_cmpeq_epi32(x, zero)) != 0xFFFF) { - const __m128i xy_128 = _mm_add_epi32(x, y); - sumXY_128 = _mm_add_epi32(sumXY_128, xy_128); - - sumX_128 = _mm_add_epi32(sumX_128, x); - - // Analyze the different X + Y. - _mm_storeu_si128((__m128i*)tmp, xy_128); - - ANALYZE_XY(0); - ANALYZE_XY(1); - ANALYZE_XY(2); - ANALYZE_XY(3); - } else { - // X is fully 0, so only deal with Y. - sumXY_128 = _mm_add_epi32(sumXY_128, y); - - ANALYZE_X_OR_Y(Y, 0); - ANALYZE_X_OR_Y(Y, 1); - ANALYZE_X_OR_Y(Y, 2); - ANALYZE_X_OR_Y(Y, 3); - } - } - - // Sum up sumX_128 to get sumX. - _mm_storeu_si128((__m128i*)tmp, sumX_128); - sumX = tmp[3] + tmp[2] + tmp[1] + tmp[0]; - - // Sum up sumXY_128 to get sumXY. - _mm_storeu_si128((__m128i*)tmp, sumXY_128); - sumXY = tmp[3] + tmp[2] + tmp[1] + tmp[0]; - - retval += VP8LFastSLog2(sumX) + VP8LFastSLog2(sumXY); - return (float)retval; -} -#undef ANALYZE_X_OR_Y -#undef ANALYZE_XY - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8LEncDspInitSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE2(void) { - VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed; - VP8LTransformColor = TransformColor; - VP8LCollectColorBlueTransforms = CollectColorBlueTransforms; - VP8LCollectColorRedTransforms = CollectColorRedTransforms; - VP8LHistogramAdd = HistogramAdd; - VP8LCombinedShannonEntropy = CombinedShannonEntropy; -} - -#else // !WEBP_USE_SSE2 - -WEBP_DSP_INIT_STUB(VP8LEncDspInitSSE2) - -#endif // WEBP_USE_SSE2 diff --git a/Example-Mac/Pods/libwebp/src/dsp/lossless_enc_sse41.c b/Example-Mac/Pods/libwebp/src/dsp/lossless_enc_sse41.c deleted file mode 100644 index 3e493198..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/lossless_enc_sse41.c +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// SSE4.1 variant of methods for lossless encoder -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE41) -#include -#include -#include "./lossless.h" - -//------------------------------------------------------------------------------ -// Subtract-Green Transform - -static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) { - int i; - const __m128i kCstShuffle = _mm_set_epi8(-1, 13, -1, 13, -1, 9, -1, 9, - -1, 5, -1, 5, -1, 1, -1, 1); - for (i = 0; i + 4 <= num_pixels; i += 4) { - const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); - const __m128i in_0g0g = _mm_shuffle_epi8(in, kCstShuffle); - const __m128i out = _mm_sub_epi8(in, in_0g0g); - _mm_storeu_si128((__m128i*)&argb_data[i], out); - } - // fallthrough and finish off with plain-C - VP8LSubtractGreenFromBlueAndRed_C(argb_data + i, num_pixels - i); -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8LEncDspInitSSE41(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE41(void) { - VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed; -} - -#else // !WEBP_USE_SSE41 - -WEBP_DSP_INIT_STUB(VP8LEncDspInitSSE41) - -#endif // WEBP_USE_SSE41 diff --git a/Example-Mac/Pods/libwebp/src/dsp/lossless_mips_dsp_r2.c b/Example-Mac/Pods/libwebp/src/dsp/lossless_mips_dsp_r2.c deleted file mode 100644 index 90aed7f1..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/lossless_mips_dsp_r2.c +++ /dev/null @@ -1,680 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Image transforms and color space conversion methods for lossless decoder. -// -// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) -// Jovan Zelincevic (jovan.zelincevic@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS_DSP_R2) - -#include "./lossless.h" - -#define MAP_COLOR_FUNCS(FUNC_NAME, TYPE, GET_INDEX, GET_VALUE) \ -static void FUNC_NAME(const TYPE* src, \ - const uint32_t* const color_map, \ - TYPE* dst, int y_start, int y_end, \ - int width) { \ - int y; \ - for (y = y_start; y < y_end; ++y) { \ - int x; \ - for (x = 0; x < (width >> 2); ++x) { \ - int tmp1, tmp2, tmp3, tmp4; \ - __asm__ volatile ( \ - ".ifc " #TYPE ", uint8_t \n\t" \ - "lbu %[tmp1], 0(%[src]) \n\t" \ - "lbu %[tmp2], 1(%[src]) \n\t" \ - "lbu %[tmp3], 2(%[src]) \n\t" \ - "lbu %[tmp4], 3(%[src]) \n\t" \ - "addiu %[src], %[src], 4 \n\t" \ - ".endif \n\t" \ - ".ifc " #TYPE ", uint32_t \n\t" \ - "lw %[tmp1], 0(%[src]) \n\t" \ - "lw %[tmp2], 4(%[src]) \n\t" \ - "lw %[tmp3], 8(%[src]) \n\t" \ - "lw %[tmp4], 12(%[src]) \n\t" \ - "ext %[tmp1], %[tmp1], 8, 8 \n\t" \ - "ext %[tmp2], %[tmp2], 8, 8 \n\t" \ - "ext %[tmp3], %[tmp3], 8, 8 \n\t" \ - "ext %[tmp4], %[tmp4], 8, 8 \n\t" \ - "addiu %[src], %[src], 16 \n\t" \ - ".endif \n\t" \ - "sll %[tmp1], %[tmp1], 2 \n\t" \ - "sll %[tmp2], %[tmp2], 2 \n\t" \ - "sll %[tmp3], %[tmp3], 2 \n\t" \ - "sll %[tmp4], %[tmp4], 2 \n\t" \ - "lwx %[tmp1], %[tmp1](%[color_map]) \n\t" \ - "lwx %[tmp2], %[tmp2](%[color_map]) \n\t" \ - "lwx %[tmp3], %[tmp3](%[color_map]) \n\t" \ - "lwx %[tmp4], %[tmp4](%[color_map]) \n\t" \ - ".ifc " #TYPE ", uint8_t \n\t" \ - "ext %[tmp1], %[tmp1], 8, 8 \n\t" \ - "ext %[tmp2], %[tmp2], 8, 8 \n\t" \ - "ext %[tmp3], %[tmp3], 8, 8 \n\t" \ - "ext %[tmp4], %[tmp4], 8, 8 \n\t" \ - "sb %[tmp1], 0(%[dst]) \n\t" \ - "sb %[tmp2], 1(%[dst]) \n\t" \ - "sb %[tmp3], 2(%[dst]) \n\t" \ - "sb %[tmp4], 3(%[dst]) \n\t" \ - "addiu %[dst], %[dst], 4 \n\t" \ - ".endif \n\t" \ - ".ifc " #TYPE ", uint32_t \n\t" \ - "sw %[tmp1], 0(%[dst]) \n\t" \ - "sw %[tmp2], 4(%[dst]) \n\t" \ - "sw %[tmp3], 8(%[dst]) \n\t" \ - "sw %[tmp4], 12(%[dst]) \n\t" \ - "addiu %[dst], %[dst], 16 \n\t" \ - ".endif \n\t" \ - : [tmp1]"=&r"(tmp1), [tmp2]"=&r"(tmp2), [tmp3]"=&r"(tmp3), \ - [tmp4]"=&r"(tmp4), [src]"+&r"(src), [dst]"+r"(dst) \ - : [color_map]"r"(color_map) \ - : "memory" \ - ); \ - } \ - for (x = 0; x < (width & 3); ++x) { \ - *dst++ = GET_VALUE(color_map[GET_INDEX(*src++)]); \ - } \ - } \ -} - -MAP_COLOR_FUNCS(MapARGB, uint32_t, VP8GetARGBIndex, VP8GetARGBValue) -MAP_COLOR_FUNCS(MapAlpha, uint8_t, VP8GetAlphaIndex, VP8GetAlphaValue) - -#undef MAP_COLOR_FUNCS - -static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1, - uint32_t c2) { - int temp0, temp1, temp2, temp3, temp4, temp5; - __asm__ volatile ( - "preceu.ph.qbr %[temp1], %[c0] \n\t" - "preceu.ph.qbl %[temp2], %[c0] \n\t" - "preceu.ph.qbr %[temp3], %[c1] \n\t" - "preceu.ph.qbl %[temp4], %[c1] \n\t" - "preceu.ph.qbr %[temp5], %[c2] \n\t" - "preceu.ph.qbl %[temp0], %[c2] \n\t" - "subq.ph %[temp3], %[temp3], %[temp5] \n\t" - "subq.ph %[temp4], %[temp4], %[temp0] \n\t" - "addq.ph %[temp1], %[temp1], %[temp3] \n\t" - "addq.ph %[temp2], %[temp2], %[temp4] \n\t" - "shll_s.ph %[temp1], %[temp1], 7 \n\t" - "shll_s.ph %[temp2], %[temp2], 7 \n\t" - "precrqu_s.qb.ph %[temp2], %[temp2], %[temp1] \n\t" - : [temp0]"=r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5) - : [c0]"r"(c0), [c1]"r"(c1), [c2]"r"(c2) - : "memory" - ); - return temp2; -} - -static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1, - uint32_t c2) { - int temp0, temp1, temp2, temp3, temp4, temp5; - __asm__ volatile ( - "adduh.qb %[temp5], %[c0], %[c1] \n\t" - "preceu.ph.qbr %[temp3], %[c2] \n\t" - "preceu.ph.qbr %[temp1], %[temp5] \n\t" - "preceu.ph.qbl %[temp2], %[temp5] \n\t" - "preceu.ph.qbl %[temp4], %[c2] \n\t" - "subq.ph %[temp3], %[temp1], %[temp3] \n\t" - "subq.ph %[temp4], %[temp2], %[temp4] \n\t" - "shrl.ph %[temp5], %[temp3], 15 \n\t" - "shrl.ph %[temp0], %[temp4], 15 \n\t" - "addq.ph %[temp3], %[temp3], %[temp5] \n\t" - "addq.ph %[temp4], %[temp0], %[temp4] \n\t" - "shra.ph %[temp3], %[temp3], 1 \n\t" - "shra.ph %[temp4], %[temp4], 1 \n\t" - "addq.ph %[temp1], %[temp1], %[temp3] \n\t" - "addq.ph %[temp2], %[temp2], %[temp4] \n\t" - "shll_s.ph %[temp1], %[temp1], 7 \n\t" - "shll_s.ph %[temp2], %[temp2], 7 \n\t" - "precrqu_s.qb.ph %[temp1], %[temp2], %[temp1] \n\t" - : [temp0]"=r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=r"(temp4), [temp5]"=&r"(temp5) - : [c0]"r"(c0), [c1]"r"(c1), [c2]"r"(c2) - : "memory" - ); - return temp1; -} - -static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) { - int temp0, temp1, temp2, temp3, temp4, temp5; - __asm__ volatile ( - "cmpgdu.lt.qb %[temp1], %[c], %[b] \n\t" - "pick.qb %[temp1], %[b], %[c] \n\t" - "pick.qb %[temp2], %[c], %[b] \n\t" - "cmpgdu.lt.qb %[temp4], %[c], %[a] \n\t" - "pick.qb %[temp4], %[a], %[c] \n\t" - "pick.qb %[temp5], %[c], %[a] \n\t" - "subu.qb %[temp3], %[temp1], %[temp2] \n\t" - "subu.qb %[temp0], %[temp4], %[temp5] \n\t" - "raddu.w.qb %[temp3], %[temp3] \n\t" - "raddu.w.qb %[temp0], %[temp0] \n\t" - "subu %[temp3], %[temp3], %[temp0] \n\t" - "slti %[temp0], %[temp3], 0x1 \n\t" - "movz %[a], %[b], %[temp0] \n\t" - : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp0]"=&r"(temp0), - [a]"+&r"(a) - : [b]"r"(b), [c]"r"(c) - ); - return a; -} - -static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) { - __asm__ volatile ( - "adduh.qb %[a0], %[a0], %[a1] \n\t" - : [a0]"+r"(a0) - : [a1]"r"(a1) - ); - return a0; -} - -static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) { - return Average2(Average2(a0, a2), a1); -} - -static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1, - uint32_t a2, uint32_t a3) { - return Average2(Average2(a0, a1), Average2(a2, a3)); -} - -static uint32_t Predictor5(uint32_t left, const uint32_t* const top) { - return Average3(left, top[0], top[1]); -} - -static uint32_t Predictor6(uint32_t left, const uint32_t* const top) { - return Average2(left, top[-1]); -} - -static uint32_t Predictor7(uint32_t left, const uint32_t* const top) { - return Average2(left, top[0]); -} - -static uint32_t Predictor8(uint32_t left, const uint32_t* const top) { - (void)left; - return Average2(top[-1], top[0]); -} - -static uint32_t Predictor9(uint32_t left, const uint32_t* const top) { - (void)left; - return Average2(top[0], top[1]); -} - -static uint32_t Predictor10(uint32_t left, const uint32_t* const top) { - return Average4(left, top[-1], top[0], top[1]); -} - -static uint32_t Predictor11(uint32_t left, const uint32_t* const top) { - return Select(top[0], left, top[-1]); -} - -static uint32_t Predictor12(uint32_t left, const uint32_t* const top) { - return ClampedAddSubtractFull(left, top[0], top[-1]); -} - -static uint32_t Predictor13(uint32_t left, const uint32_t* const top) { - return ClampedAddSubtractHalf(left, top[0], top[-1]); -} - -// Add green to blue and red channels (i.e. perform the inverse transform of -// 'subtract green'). -static void AddGreenToBlueAndRed(uint32_t* data, int num_pixels) { - uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; - uint32_t* const p_loop1_end = data + (num_pixels & ~3); - uint32_t* const p_loop2_end = data + num_pixels; - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "beq %[data], %[p_loop1_end], 3f \n\t" - " nop \n\t" - "0: \n\t" - "lw %[temp0], 0(%[data]) \n\t" - "lw %[temp1], 4(%[data]) \n\t" - "lw %[temp2], 8(%[data]) \n\t" - "lw %[temp3], 12(%[data]) \n\t" - "ext %[temp4], %[temp0], 8, 8 \n\t" - "ext %[temp5], %[temp1], 8, 8 \n\t" - "ext %[temp6], %[temp2], 8, 8 \n\t" - "ext %[temp7], %[temp3], 8, 8 \n\t" - "addiu %[data], %[data], 16 \n\t" - "replv.ph %[temp4], %[temp4] \n\t" - "replv.ph %[temp5], %[temp5] \n\t" - "replv.ph %[temp6], %[temp6] \n\t" - "replv.ph %[temp7], %[temp7] \n\t" - "addu.qb %[temp0], %[temp0], %[temp4] \n\t" - "addu.qb %[temp1], %[temp1], %[temp5] \n\t" - "addu.qb %[temp2], %[temp2], %[temp6] \n\t" - "addu.qb %[temp3], %[temp3], %[temp7] \n\t" - "sw %[temp0], -16(%[data]) \n\t" - "sw %[temp1], -12(%[data]) \n\t" - "sw %[temp2], -8(%[data]) \n\t" - "bne %[data], %[p_loop1_end], 0b \n\t" - " sw %[temp3], -4(%[data]) \n\t" - "3: \n\t" - "beq %[data], %[p_loop2_end], 2f \n\t" - " nop \n\t" - "1: \n\t" - "lw %[temp0], 0(%[data]) \n\t" - "addiu %[data], %[data], 4 \n\t" - "ext %[temp4], %[temp0], 8, 8 \n\t" - "replv.ph %[temp4], %[temp4] \n\t" - "addu.qb %[temp0], %[temp0], %[temp4] \n\t" - "bne %[data], %[p_loop2_end], 1b \n\t" - " sw %[temp0], -4(%[data]) \n\t" - "2: \n\t" - ".set pop \n\t" - : [data]"+&r"(data), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), - [temp5]"=&r"(temp5), [temp6]"=&r"(temp6), [temp7]"=&r"(temp7) - : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) - : "memory" - ); -} - -static void TransformColorInverse(const VP8LMultipliers* const m, - uint32_t* data, int num_pixels) { - int temp0, temp1, temp2, temp3, temp4, temp5; - uint32_t argb, argb1, new_red; - const uint32_t G_to_R = m->green_to_red_; - const uint32_t G_to_B = m->green_to_blue_; - const uint32_t R_to_B = m->red_to_blue_; - uint32_t* const p_loop_end = data + (num_pixels & ~1); - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "beq %[data], %[p_loop_end], 1f \n\t" - " nop \n\t" - "replv.ph %[temp0], %[G_to_R] \n\t" - "replv.ph %[temp1], %[G_to_B] \n\t" - "replv.ph %[temp2], %[R_to_B] \n\t" - "shll.ph %[temp0], %[temp0], 8 \n\t" - "shll.ph %[temp1], %[temp1], 8 \n\t" - "shll.ph %[temp2], %[temp2], 8 \n\t" - "shra.ph %[temp0], %[temp0], 8 \n\t" - "shra.ph %[temp1], %[temp1], 8 \n\t" - "shra.ph %[temp2], %[temp2], 8 \n\t" - "0: \n\t" - "lw %[argb], 0(%[data]) \n\t" - "lw %[argb1], 4(%[data]) \n\t" - "addiu %[data], %[data], 8 \n\t" - "precrq.qb.ph %[temp3], %[argb], %[argb1] \n\t" - "preceu.ph.qbra %[temp3], %[temp3] \n\t" - "shll.ph %[temp3], %[temp3], 8 \n\t" - "shra.ph %[temp3], %[temp3], 8 \n\t" - "mul.ph %[temp5], %[temp3], %[temp0] \n\t" - "mul.ph %[temp3], %[temp3], %[temp1] \n\t" - "precrq.ph.w %[new_red], %[argb], %[argb1] \n\t" - "ins %[argb1], %[argb], 16, 16 \n\t" - "shra.ph %[temp5], %[temp5], 5 \n\t" - "shra.ph %[temp3], %[temp3], 5 \n\t" - "addu.ph %[new_red], %[new_red], %[temp5] \n\t" - "addu.ph %[argb1], %[argb1], %[temp3] \n\t" - "preceu.ph.qbra %[temp5], %[new_red] \n\t" - "shll.ph %[temp4], %[temp5], 8 \n\t" - "shra.ph %[temp4], %[temp4], 8 \n\t" - "mul.ph %[temp4], %[temp4], %[temp2] \n\t" - "sb %[temp5], -2(%[data]) \n\t" - "sra %[temp5], %[temp5], 16 \n\t" - "shra.ph %[temp4], %[temp4], 5 \n\t" - "addu.ph %[argb1], %[argb1], %[temp4] \n\t" - "preceu.ph.qbra %[temp3], %[argb1] \n\t" - "sb %[temp5], -6(%[data]) \n\t" - "sb %[temp3], -4(%[data]) \n\t" - "sra %[temp3], %[temp3], 16 \n\t" - "bne %[data], %[p_loop_end], 0b \n\t" - " sb %[temp3], -8(%[data]) \n\t" - "1: \n\t" - ".set pop \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [new_red]"=&r"(new_red), [argb]"=&r"(argb), - [argb1]"=&r"(argb1), [data]"+&r"(data) - : [G_to_R]"r"(G_to_R), [R_to_B]"r"(R_to_B), - [G_to_B]"r"(G_to_B), [p_loop_end]"r"(p_loop_end) - : "memory", "hi", "lo" - ); - - // Fall-back to C-version for left-overs. - if (num_pixels & 1) VP8LTransformColorInverse_C(m, data, 1); -} - -static void ConvertBGRAToRGB(const uint32_t* src, - int num_pixels, uint8_t* dst) { - int temp0, temp1, temp2, temp3; - const uint32_t* const p_loop1_end = src + (num_pixels & ~3); - const uint32_t* const p_loop2_end = src + num_pixels; - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "beq %[src], %[p_loop1_end], 3f \n\t" - " nop \n\t" - "0: \n\t" - "lw %[temp3], 12(%[src]) \n\t" - "lw %[temp2], 8(%[src]) \n\t" - "lw %[temp1], 4(%[src]) \n\t" - "lw %[temp0], 0(%[src]) \n\t" - "ins %[temp3], %[temp2], 24, 8 \n\t" - "sll %[temp2], %[temp2], 8 \n\t" - "rotr %[temp3], %[temp3], 16 \n\t" - "ins %[temp2], %[temp1], 0, 16 \n\t" - "sll %[temp1], %[temp1], 8 \n\t" - "wsbh %[temp3], %[temp3] \n\t" - "balign %[temp0], %[temp1], 1 \n\t" - "wsbh %[temp2], %[temp2] \n\t" - "wsbh %[temp0], %[temp0] \n\t" - "usw %[temp3], 8(%[dst]) \n\t" - "rotr %[temp0], %[temp0], 16 \n\t" - "usw %[temp2], 4(%[dst]) \n\t" - "addiu %[src], %[src], 16 \n\t" - "usw %[temp0], 0(%[dst]) \n\t" - "bne %[src], %[p_loop1_end], 0b \n\t" - " addiu %[dst], %[dst], 12 \n\t" - "3: \n\t" - "beq %[src], %[p_loop2_end], 2f \n\t" - " nop \n\t" - "1: \n\t" - "lw %[temp0], 0(%[src]) \n\t" - "addiu %[src], %[src], 4 \n\t" - "wsbh %[temp1], %[temp0] \n\t" - "addiu %[dst], %[dst], 3 \n\t" - "ush %[temp1], -2(%[dst]) \n\t" - "sra %[temp0], %[temp0], 16 \n\t" - "bne %[src], %[p_loop2_end], 1b \n\t" - " sb %[temp0], -3(%[dst]) \n\t" - "2: \n\t" - ".set pop \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [dst]"+&r"(dst), [src]"+&r"(src) - : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) - : "memory" - ); -} - -static void ConvertBGRAToRGBA(const uint32_t* src, - int num_pixels, uint8_t* dst) { - int temp0, temp1, temp2, temp3; - const uint32_t* const p_loop1_end = src + (num_pixels & ~3); - const uint32_t* const p_loop2_end = src + num_pixels; - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "beq %[src], %[p_loop1_end], 3f \n\t" - " nop \n\t" - "0: \n\t" - "lw %[temp0], 0(%[src]) \n\t" - "lw %[temp1], 4(%[src]) \n\t" - "lw %[temp2], 8(%[src]) \n\t" - "lw %[temp3], 12(%[src]) \n\t" - "wsbh %[temp0], %[temp0] \n\t" - "wsbh %[temp1], %[temp1] \n\t" - "wsbh %[temp2], %[temp2] \n\t" - "wsbh %[temp3], %[temp3] \n\t" - "addiu %[src], %[src], 16 \n\t" - "balign %[temp0], %[temp0], 1 \n\t" - "balign %[temp1], %[temp1], 1 \n\t" - "balign %[temp2], %[temp2], 1 \n\t" - "balign %[temp3], %[temp3], 1 \n\t" - "usw %[temp0], 0(%[dst]) \n\t" - "usw %[temp1], 4(%[dst]) \n\t" - "usw %[temp2], 8(%[dst]) \n\t" - "usw %[temp3], 12(%[dst]) \n\t" - "bne %[src], %[p_loop1_end], 0b \n\t" - " addiu %[dst], %[dst], 16 \n\t" - "3: \n\t" - "beq %[src], %[p_loop2_end], 2f \n\t" - " nop \n\t" - "1: \n\t" - "lw %[temp0], 0(%[src]) \n\t" - "wsbh %[temp0], %[temp0] \n\t" - "addiu %[src], %[src], 4 \n\t" - "balign %[temp0], %[temp0], 1 \n\t" - "usw %[temp0], 0(%[dst]) \n\t" - "bne %[src], %[p_loop2_end], 1b \n\t" - " addiu %[dst], %[dst], 4 \n\t" - "2: \n\t" - ".set pop \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [dst]"+&r"(dst), [src]"+&r"(src) - : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) - : "memory" - ); -} - -static void ConvertBGRAToRGBA4444(const uint32_t* src, - int num_pixels, uint8_t* dst) { - int temp0, temp1, temp2, temp3, temp4, temp5; - const uint32_t* const p_loop1_end = src + (num_pixels & ~3); - const uint32_t* const p_loop2_end = src + num_pixels; - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "beq %[src], %[p_loop1_end], 3f \n\t" - " nop \n\t" - "0: \n\t" - "lw %[temp0], 0(%[src]) \n\t" - "lw %[temp1], 4(%[src]) \n\t" - "lw %[temp2], 8(%[src]) \n\t" - "lw %[temp3], 12(%[src]) \n\t" - "ext %[temp4], %[temp0], 28, 4 \n\t" - "ext %[temp5], %[temp0], 12, 4 \n\t" - "ins %[temp0], %[temp4], 0, 4 \n\t" - "ext %[temp4], %[temp1], 28, 4 \n\t" - "ins %[temp0], %[temp5], 16, 4 \n\t" - "ext %[temp5], %[temp1], 12, 4 \n\t" - "ins %[temp1], %[temp4], 0, 4 \n\t" - "ext %[temp4], %[temp2], 28, 4 \n\t" - "ins %[temp1], %[temp5], 16, 4 \n\t" - "ext %[temp5], %[temp2], 12, 4 \n\t" - "ins %[temp2], %[temp4], 0, 4 \n\t" - "ext %[temp4], %[temp3], 28, 4 \n\t" - "ins %[temp2], %[temp5], 16, 4 \n\t" - "ext %[temp5], %[temp3], 12, 4 \n\t" - "ins %[temp3], %[temp4], 0, 4 \n\t" - "precr.qb.ph %[temp1], %[temp1], %[temp0] \n\t" - "ins %[temp3], %[temp5], 16, 4 \n\t" - "addiu %[src], %[src], 16 \n\t" - "precr.qb.ph %[temp3], %[temp3], %[temp2] \n\t" -#ifdef WEBP_SWAP_16BIT_CSP - "usw %[temp1], 0(%[dst]) \n\t" - "usw %[temp3], 4(%[dst]) \n\t" -#else - "wsbh %[temp1], %[temp1] \n\t" - "wsbh %[temp3], %[temp3] \n\t" - "usw %[temp1], 0(%[dst]) \n\t" - "usw %[temp3], 4(%[dst]) \n\t" -#endif - "bne %[src], %[p_loop1_end], 0b \n\t" - " addiu %[dst], %[dst], 8 \n\t" - "3: \n\t" - "beq %[src], %[p_loop2_end], 2f \n\t" - " nop \n\t" - "1: \n\t" - "lw %[temp0], 0(%[src]) \n\t" - "ext %[temp4], %[temp0], 28, 4 \n\t" - "ext %[temp5], %[temp0], 12, 4 \n\t" - "ins %[temp0], %[temp4], 0, 4 \n\t" - "ins %[temp0], %[temp5], 16, 4 \n\t" - "addiu %[src], %[src], 4 \n\t" - "precr.qb.ph %[temp0], %[temp0], %[temp0] \n\t" -#ifdef WEBP_SWAP_16BIT_CSP - "ush %[temp0], 0(%[dst]) \n\t" -#else - "wsbh %[temp0], %[temp0] \n\t" - "ush %[temp0], 0(%[dst]) \n\t" -#endif - "bne %[src], %[p_loop2_end], 1b \n\t" - " addiu %[dst], %[dst], 2 \n\t" - "2: \n\t" - ".set pop \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [dst]"+&r"(dst), [src]"+&r"(src) - : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) - : "memory" - ); -} - -static void ConvertBGRAToRGB565(const uint32_t* src, - int num_pixels, uint8_t* dst) { - int temp0, temp1, temp2, temp3, temp4, temp5; - const uint32_t* const p_loop1_end = src + (num_pixels & ~3); - const uint32_t* const p_loop2_end = src + num_pixels; - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "beq %[src], %[p_loop1_end], 3f \n\t" - " nop \n\t" - "0: \n\t" - "lw %[temp0], 0(%[src]) \n\t" - "lw %[temp1], 4(%[src]) \n\t" - "lw %[temp2], 8(%[src]) \n\t" - "lw %[temp3], 12(%[src]) \n\t" - "ext %[temp4], %[temp0], 8, 16 \n\t" - "ext %[temp5], %[temp0], 5, 11 \n\t" - "ext %[temp0], %[temp0], 3, 5 \n\t" - "ins %[temp4], %[temp5], 0, 11 \n\t" - "ext %[temp5], %[temp1], 5, 11 \n\t" - "ins %[temp4], %[temp0], 0, 5 \n\t" - "ext %[temp0], %[temp1], 8, 16 \n\t" - "ext %[temp1], %[temp1], 3, 5 \n\t" - "ins %[temp0], %[temp5], 0, 11 \n\t" - "ext %[temp5], %[temp2], 5, 11 \n\t" - "ins %[temp0], %[temp1], 0, 5 \n\t" - "ext %[temp1], %[temp2], 8, 16 \n\t" - "ext %[temp2], %[temp2], 3, 5 \n\t" - "ins %[temp1], %[temp5], 0, 11 \n\t" - "ext %[temp5], %[temp3], 5, 11 \n\t" - "ins %[temp1], %[temp2], 0, 5 \n\t" - "ext %[temp2], %[temp3], 8, 16 \n\t" - "ext %[temp3], %[temp3], 3, 5 \n\t" - "ins %[temp2], %[temp5], 0, 11 \n\t" - "append %[temp0], %[temp4], 16 \n\t" - "ins %[temp2], %[temp3], 0, 5 \n\t" - "addiu %[src], %[src], 16 \n\t" - "append %[temp2], %[temp1], 16 \n\t" -#ifdef WEBP_SWAP_16BIT_CSP - "usw %[temp0], 0(%[dst]) \n\t" - "usw %[temp2], 4(%[dst]) \n\t" -#else - "wsbh %[temp0], %[temp0] \n\t" - "wsbh %[temp2], %[temp2] \n\t" - "usw %[temp0], 0(%[dst]) \n\t" - "usw %[temp2], 4(%[dst]) \n\t" -#endif - "bne %[src], %[p_loop1_end], 0b \n\t" - " addiu %[dst], %[dst], 8 \n\t" - "3: \n\t" - "beq %[src], %[p_loop2_end], 2f \n\t" - " nop \n\t" - "1: \n\t" - "lw %[temp0], 0(%[src]) \n\t" - "ext %[temp4], %[temp0], 8, 16 \n\t" - "ext %[temp5], %[temp0], 5, 11 \n\t" - "ext %[temp0], %[temp0], 3, 5 \n\t" - "ins %[temp4], %[temp5], 0, 11 \n\t" - "addiu %[src], %[src], 4 \n\t" - "ins %[temp4], %[temp0], 0, 5 \n\t" -#ifdef WEBP_SWAP_16BIT_CSP - "ush %[temp4], 0(%[dst]) \n\t" -#else - "wsbh %[temp4], %[temp4] \n\t" - "ush %[temp4], 0(%[dst]) \n\t" -#endif - "bne %[src], %[p_loop2_end], 1b \n\t" - " addiu %[dst], %[dst], 2 \n\t" - "2: \n\t" - ".set pop \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [dst]"+&r"(dst), [src]"+&r"(src) - : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) - : "memory" - ); -} - -static void ConvertBGRAToBGR(const uint32_t* src, - int num_pixels, uint8_t* dst) { - int temp0, temp1, temp2, temp3; - const uint32_t* const p_loop1_end = src + (num_pixels & ~3); - const uint32_t* const p_loop2_end = src + num_pixels; - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "beq %[src], %[p_loop1_end], 3f \n\t" - " nop \n\t" - "0: \n\t" - "lw %[temp0], 0(%[src]) \n\t" - "lw %[temp1], 4(%[src]) \n\t" - "lw %[temp2], 8(%[src]) \n\t" - "lw %[temp3], 12(%[src]) \n\t" - "ins %[temp0], %[temp1], 24, 8 \n\t" - "sra %[temp1], %[temp1], 8 \n\t" - "ins %[temp1], %[temp2], 16, 16 \n\t" - "sll %[temp2], %[temp2], 8 \n\t" - "balign %[temp3], %[temp2], 1 \n\t" - "addiu %[src], %[src], 16 \n\t" - "usw %[temp0], 0(%[dst]) \n\t" - "usw %[temp1], 4(%[dst]) \n\t" - "usw %[temp3], 8(%[dst]) \n\t" - "bne %[src], %[p_loop1_end], 0b \n\t" - " addiu %[dst], %[dst], 12 \n\t" - "3: \n\t" - "beq %[src], %[p_loop2_end], 2f \n\t" - " nop \n\t" - "1: \n\t" - "lw %[temp0], 0(%[src]) \n\t" - "addiu %[src], %[src], 4 \n\t" - "addiu %[dst], %[dst], 3 \n\t" - "ush %[temp0], -3(%[dst]) \n\t" - "sra %[temp0], %[temp0], 16 \n\t" - "bne %[src], %[p_loop2_end], 1b \n\t" - " sb %[temp0], -1(%[dst]) \n\t" - "2: \n\t" - ".set pop \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [dst]"+&r"(dst), [src]"+&r"(src) - : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) - : "memory" - ); -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8LDspInitMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitMIPSdspR2(void) { - VP8LMapColor32b = MapARGB; - VP8LMapColor8b = MapAlpha; - VP8LPredictors[5] = Predictor5; - VP8LPredictors[6] = Predictor6; - VP8LPredictors[7] = Predictor7; - VP8LPredictors[8] = Predictor8; - VP8LPredictors[9] = Predictor9; - VP8LPredictors[10] = Predictor10; - VP8LPredictors[11] = Predictor11; - VP8LPredictors[12] = Predictor12; - VP8LPredictors[13] = Predictor13; - VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed; - VP8LTransformColorInverse = TransformColorInverse; - VP8LConvertBGRAToRGB = ConvertBGRAToRGB; - VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA; - VP8LConvertBGRAToRGBA4444 = ConvertBGRAToRGBA4444; - VP8LConvertBGRAToRGB565 = ConvertBGRAToRGB565; - VP8LConvertBGRAToBGR = ConvertBGRAToBGR; -} - -#else // !WEBP_USE_MIPS_DSP_R2 - -WEBP_DSP_INIT_STUB(VP8LDspInitMIPSdspR2) - -#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/Example-Mac/Pods/libwebp/src/dsp/lossless_neon.c b/Example-Mac/Pods/libwebp/src/dsp/lossless_neon.c deleted file mode 100644 index 6faccb8f..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/lossless_neon.c +++ /dev/null @@ -1,269 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// NEON variant of methods for lossless decoder -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_NEON) - -#include - -#include "./lossless.h" -#include "./neon.h" - -//------------------------------------------------------------------------------ -// Colorspace conversion functions - -#if !defined(WORK_AROUND_GCC) -// gcc 4.6.0 had some trouble (NDK-r9) with this code. We only use it for -// gcc-4.8.x at least. -static void ConvertBGRAToRGBA(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const uint32_t* const end = src + (num_pixels & ~15); - for (; src < end; src += 16) { - uint8x16x4_t pixel = vld4q_u8((uint8_t*)src); - // swap B and R. (VSWP d0,d2 has no intrinsics equivalent!) - const uint8x16_t tmp = pixel.val[0]; - pixel.val[0] = pixel.val[2]; - pixel.val[2] = tmp; - vst4q_u8(dst, pixel); - dst += 64; - } - VP8LConvertBGRAToRGBA_C(src, num_pixels & 15, dst); // left-overs -} - -static void ConvertBGRAToBGR(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const uint32_t* const end = src + (num_pixels & ~15); - for (; src < end; src += 16) { - const uint8x16x4_t pixel = vld4q_u8((uint8_t*)src); - const uint8x16x3_t tmp = { { pixel.val[0], pixel.val[1], pixel.val[2] } }; - vst3q_u8(dst, tmp); - dst += 48; - } - VP8LConvertBGRAToBGR_C(src, num_pixels & 15, dst); // left-overs -} - -static void ConvertBGRAToRGB(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const uint32_t* const end = src + (num_pixels & ~15); - for (; src < end; src += 16) { - const uint8x16x4_t pixel = vld4q_u8((uint8_t*)src); - const uint8x16x3_t tmp = { { pixel.val[2], pixel.val[1], pixel.val[0] } }; - vst3q_u8(dst, tmp); - dst += 48; - } - VP8LConvertBGRAToRGB_C(src, num_pixels & 15, dst); // left-overs -} - -#else // WORK_AROUND_GCC - -// gcc-4.6.0 fallback - -static const uint8_t kRGBAShuffle[8] = { 2, 1, 0, 3, 6, 5, 4, 7 }; - -static void ConvertBGRAToRGBA(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const uint32_t* const end = src + (num_pixels & ~1); - const uint8x8_t shuffle = vld1_u8(kRGBAShuffle); - for (; src < end; src += 2) { - const uint8x8_t pixels = vld1_u8((uint8_t*)src); - vst1_u8(dst, vtbl1_u8(pixels, shuffle)); - dst += 8; - } - VP8LConvertBGRAToRGBA_C(src, num_pixels & 1, dst); // left-overs -} - -static const uint8_t kBGRShuffle[3][8] = { - { 0, 1, 2, 4, 5, 6, 8, 9 }, - { 10, 12, 13, 14, 16, 17, 18, 20 }, - { 21, 22, 24, 25, 26, 28, 29, 30 } -}; - -static void ConvertBGRAToBGR(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const uint32_t* const end = src + (num_pixels & ~7); - const uint8x8_t shuffle0 = vld1_u8(kBGRShuffle[0]); - const uint8x8_t shuffle1 = vld1_u8(kBGRShuffle[1]); - const uint8x8_t shuffle2 = vld1_u8(kBGRShuffle[2]); - for (; src < end; src += 8) { - uint8x8x4_t pixels; - INIT_VECTOR4(pixels, - vld1_u8((const uint8_t*)(src + 0)), - vld1_u8((const uint8_t*)(src + 2)), - vld1_u8((const uint8_t*)(src + 4)), - vld1_u8((const uint8_t*)(src + 6))); - vst1_u8(dst + 0, vtbl4_u8(pixels, shuffle0)); - vst1_u8(dst + 8, vtbl4_u8(pixels, shuffle1)); - vst1_u8(dst + 16, vtbl4_u8(pixels, shuffle2)); - dst += 8 * 3; - } - VP8LConvertBGRAToBGR_C(src, num_pixels & 7, dst); // left-overs -} - -static const uint8_t kRGBShuffle[3][8] = { - { 2, 1, 0, 6, 5, 4, 10, 9 }, - { 8, 14, 13, 12, 18, 17, 16, 22 }, - { 21, 20, 26, 25, 24, 30, 29, 28 } -}; - -static void ConvertBGRAToRGB(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const uint32_t* const end = src + (num_pixels & ~7); - const uint8x8_t shuffle0 = vld1_u8(kRGBShuffle[0]); - const uint8x8_t shuffle1 = vld1_u8(kRGBShuffle[1]); - const uint8x8_t shuffle2 = vld1_u8(kRGBShuffle[2]); - for (; src < end; src += 8) { - uint8x8x4_t pixels; - INIT_VECTOR4(pixels, - vld1_u8((const uint8_t*)(src + 0)), - vld1_u8((const uint8_t*)(src + 2)), - vld1_u8((const uint8_t*)(src + 4)), - vld1_u8((const uint8_t*)(src + 6))); - vst1_u8(dst + 0, vtbl4_u8(pixels, shuffle0)); - vst1_u8(dst + 8, vtbl4_u8(pixels, shuffle1)); - vst1_u8(dst + 16, vtbl4_u8(pixels, shuffle2)); - dst += 8 * 3; - } - VP8LConvertBGRAToRGB_C(src, num_pixels & 7, dst); // left-overs -} - -#endif // !WORK_AROUND_GCC - -//------------------------------------------------------------------------------ -// Subtract-Green Transform - -// vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use -// non-standard versions there. -#if defined(__APPLE__) && defined(__aarch64__) && \ - defined(__apple_build_version__) && (__apple_build_version__< 6020037) -#define USE_VTBLQ -#endif - -#ifdef USE_VTBLQ -// 255 = byte will be zeroed -static const uint8_t kGreenShuffle[16] = { - 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255 -}; - -static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb, - const uint8x16_t shuffle) { - return vcombine_u8(vtbl1q_u8(argb, vget_low_u8(shuffle)), - vtbl1q_u8(argb, vget_high_u8(shuffle))); -} -#else // !USE_VTBLQ -// 255 = byte will be zeroed -static const uint8_t kGreenShuffle[8] = { 1, 255, 1, 255, 5, 255, 5, 255 }; - -static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb, - const uint8x8_t shuffle) { - return vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle), - vtbl1_u8(vget_high_u8(argb), shuffle)); -} -#endif // USE_VTBLQ - -static void AddGreenToBlueAndRed(uint32_t* argb_data, int num_pixels) { - const uint32_t* const end = argb_data + (num_pixels & ~3); -#ifdef USE_VTBLQ - const uint8x16_t shuffle = vld1q_u8(kGreenShuffle); -#else - const uint8x8_t shuffle = vld1_u8(kGreenShuffle); -#endif - for (; argb_data < end; argb_data += 4) { - const uint8x16_t argb = vld1q_u8((uint8_t*)argb_data); - const uint8x16_t greens = DoGreenShuffle(argb, shuffle); - vst1q_u8((uint8_t*)argb_data, vaddq_u8(argb, greens)); - } - // fallthrough and finish off with plain-C - VP8LAddGreenToBlueAndRed_C(argb_data, num_pixels & 3); -} - -//------------------------------------------------------------------------------ -// Color Transform - -static void TransformColorInverse(const VP8LMultipliers* const m, - uint32_t* argb_data, int num_pixels) { - // sign-extended multiplying constants, pre-shifted by 6. -#define CST(X) (((int16_t)(m->X << 8)) >> 6) - const int16_t rb[8] = { - CST(green_to_blue_), CST(green_to_red_), - CST(green_to_blue_), CST(green_to_red_), - CST(green_to_blue_), CST(green_to_red_), - CST(green_to_blue_), CST(green_to_red_) - }; - const int16x8_t mults_rb = vld1q_s16(rb); - const int16_t b2[8] = { - 0, CST(red_to_blue_), 0, CST(red_to_blue_), - 0, CST(red_to_blue_), 0, CST(red_to_blue_), - }; - const int16x8_t mults_b2 = vld1q_s16(b2); -#undef CST -#ifdef USE_VTBLQ - static const uint8_t kg0g0[16] = { - 255, 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13 - }; - const uint8x16_t shuffle = vld1q_u8(kg0g0); -#else - static const uint8_t k0g0g[8] = { 255, 1, 255, 1, 255, 5, 255, 5 }; - const uint8x8_t shuffle = vld1_u8(k0g0g); -#endif - const uint32x4_t mask_ag = vdupq_n_u32(0xff00ff00u); - int i; - for (i = 0; i + 4 <= num_pixels; i += 4) { - const uint8x16_t in = vld1q_u8((uint8_t*)(argb_data + i)); - const uint32x4_t a0g0 = vandq_u32(vreinterpretq_u32_u8(in), mask_ag); - // 0 g 0 g - const uint8x16_t greens = DoGreenShuffle(in, shuffle); - // x dr x db1 - const int16x8_t A = vqdmulhq_s16(vreinterpretq_s16_u8(greens), mults_rb); - // x r' x b' - const int8x16_t B = vaddq_s8(vreinterpretq_s8_u8(in), - vreinterpretq_s8_s16(A)); - // r' 0 b' 0 - const int16x8_t C = vshlq_n_s16(vreinterpretq_s16_s8(B), 8); - // x db2 0 0 - const int16x8_t D = vqdmulhq_s16(C, mults_b2); - // 0 x db2 0 - const uint32x4_t E = vshrq_n_u32(vreinterpretq_u32_s16(D), 8); - // r' x b'' 0 - const int8x16_t F = vaddq_s8(vreinterpretq_s8_u32(E), - vreinterpretq_s8_s16(C)); - // 0 r' 0 b'' - const uint16x8_t G = vshrq_n_u16(vreinterpretq_u16_s8(F), 8); - const uint32x4_t out = vorrq_u32(vreinterpretq_u32_u16(G), a0g0); - vst1q_u32(argb_data + i, out); - } - // Fall-back to C-version for left-overs. - VP8LTransformColorInverse_C(m, argb_data + i, num_pixels - i); -} - -#undef USE_VTBLQ - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8LDspInitNEON(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitNEON(void) { - VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA; - VP8LConvertBGRAToBGR = ConvertBGRAToBGR; - VP8LConvertBGRAToRGB = ConvertBGRAToRGB; - - VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed; - VP8LTransformColorInverse = TransformColorInverse; -} - -#else // !WEBP_USE_NEON - -WEBP_DSP_INIT_STUB(VP8LDspInitNEON) - -#endif // WEBP_USE_NEON diff --git a/Example-Mac/Pods/libwebp/src/dsp/lossless_sse2.c b/Example-Mac/Pods/libwebp/src/dsp/lossless_sse2.c deleted file mode 100644 index 2d016c29..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/lossless_sse2.c +++ /dev/null @@ -1,372 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// SSE2 variant of methods for lossless decoder -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE2) -#include -#include -#include "./lossless.h" - -//------------------------------------------------------------------------------ -// Predictor Transform - -static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1, - uint32_t c2) { - const __m128i zero = _mm_setzero_si128(); - const __m128i C0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c0), zero); - const __m128i C1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c1), zero); - const __m128i C2 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c2), zero); - const __m128i V1 = _mm_add_epi16(C0, C1); - const __m128i V2 = _mm_sub_epi16(V1, C2); - const __m128i b = _mm_packus_epi16(V2, V2); - const uint32_t output = _mm_cvtsi128_si32(b); - return output; -} - -static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1, - uint32_t c2) { - const __m128i zero = _mm_setzero_si128(); - const __m128i C0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c0), zero); - const __m128i C1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c1), zero); - const __m128i B0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c2), zero); - const __m128i avg = _mm_add_epi16(C1, C0); - const __m128i A0 = _mm_srli_epi16(avg, 1); - const __m128i A1 = _mm_sub_epi16(A0, B0); - const __m128i BgtA = _mm_cmpgt_epi16(B0, A0); - const __m128i A2 = _mm_sub_epi16(A1, BgtA); - const __m128i A3 = _mm_srai_epi16(A2, 1); - const __m128i A4 = _mm_add_epi16(A0, A3); - const __m128i A5 = _mm_packus_epi16(A4, A4); - const uint32_t output = _mm_cvtsi128_si32(A5); - return output; -} - -static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) { - int pa_minus_pb; - const __m128i zero = _mm_setzero_si128(); - const __m128i A0 = _mm_cvtsi32_si128(a); - const __m128i B0 = _mm_cvtsi32_si128(b); - const __m128i C0 = _mm_cvtsi32_si128(c); - const __m128i AC0 = _mm_subs_epu8(A0, C0); - const __m128i CA0 = _mm_subs_epu8(C0, A0); - const __m128i BC0 = _mm_subs_epu8(B0, C0); - const __m128i CB0 = _mm_subs_epu8(C0, B0); - const __m128i AC = _mm_or_si128(AC0, CA0); - const __m128i BC = _mm_or_si128(BC0, CB0); - const __m128i pa = _mm_unpacklo_epi8(AC, zero); // |a - c| - const __m128i pb = _mm_unpacklo_epi8(BC, zero); // |b - c| - const __m128i diff = _mm_sub_epi16(pb, pa); - { - int16_t out[8]; - _mm_storeu_si128((__m128i*)out, diff); - pa_minus_pb = out[0] + out[1] + out[2] + out[3]; - } - return (pa_minus_pb <= 0) ? a : b; -} - -static WEBP_INLINE __m128i Average2_128i(uint32_t a0, uint32_t a1) { - const __m128i zero = _mm_setzero_si128(); - const __m128i A0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(a0), zero); - const __m128i A1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(a1), zero); - const __m128i sum = _mm_add_epi16(A1, A0); - const __m128i avg = _mm_srli_epi16(sum, 1); - return avg; -} - -static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) { - const __m128i avg = Average2_128i(a0, a1); - const __m128i A2 = _mm_packus_epi16(avg, avg); - const uint32_t output = _mm_cvtsi128_si32(A2); - return output; -} - -static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) { - const __m128i zero = _mm_setzero_si128(); - const __m128i avg1 = Average2_128i(a0, a2); - const __m128i A1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(a1), zero); - const __m128i sum = _mm_add_epi16(avg1, A1); - const __m128i avg2 = _mm_srli_epi16(sum, 1); - const __m128i A2 = _mm_packus_epi16(avg2, avg2); - const uint32_t output = _mm_cvtsi128_si32(A2); - return output; -} - -static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1, - uint32_t a2, uint32_t a3) { - const __m128i avg1 = Average2_128i(a0, a1); - const __m128i avg2 = Average2_128i(a2, a3); - const __m128i sum = _mm_add_epi16(avg2, avg1); - const __m128i avg3 = _mm_srli_epi16(sum, 1); - const __m128i A0 = _mm_packus_epi16(avg3, avg3); - const uint32_t output = _mm_cvtsi128_si32(A0); - return output; -} - -static uint32_t Predictor5(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average3(left, top[0], top[1]); - return pred; -} -static uint32_t Predictor6(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2(left, top[-1]); - return pred; -} -static uint32_t Predictor7(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2(left, top[0]); - return pred; -} -static uint32_t Predictor8(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2(top[-1], top[0]); - (void)left; - return pred; -} -static uint32_t Predictor9(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2(top[0], top[1]); - (void)left; - return pred; -} -static uint32_t Predictor10(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average4(left, top[-1], top[0], top[1]); - return pred; -} -static uint32_t Predictor11(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Select(top[0], left, top[-1]); - return pred; -} -static uint32_t Predictor12(uint32_t left, const uint32_t* const top) { - const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]); - return pred; -} -static uint32_t Predictor13(uint32_t left, const uint32_t* const top) { - const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]); - return pred; -} - -//------------------------------------------------------------------------------ -// Subtract-Green Transform - -static void AddGreenToBlueAndRed(uint32_t* argb_data, int num_pixels) { - int i; - for (i = 0; i + 4 <= num_pixels; i += 4) { - const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb - const __m128i A = _mm_srli_epi16(in, 8); // 0 a 0 g - const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0)); - const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // 0g0g - const __m128i out = _mm_add_epi8(in, C); - _mm_storeu_si128((__m128i*)&argb_data[i], out); - } - // fallthrough and finish off with plain-C - VP8LAddGreenToBlueAndRed_C(argb_data + i, num_pixels - i); -} - -//------------------------------------------------------------------------------ -// Color Transform - -static void TransformColorInverse(const VP8LMultipliers* const m, - uint32_t* argb_data, int num_pixels) { - // sign-extended multiplying constants, pre-shifted by 5. -#define CST(X) (((int16_t)(m->X << 8)) >> 5) // sign-extend - const __m128i mults_rb = _mm_set_epi16( - CST(green_to_red_), CST(green_to_blue_), - CST(green_to_red_), CST(green_to_blue_), - CST(green_to_red_), CST(green_to_blue_), - CST(green_to_red_), CST(green_to_blue_)); - const __m128i mults_b2 = _mm_set_epi16( - CST(red_to_blue_), 0, CST(red_to_blue_), 0, - CST(red_to_blue_), 0, CST(red_to_blue_), 0); -#undef CST - const __m128i mask_ag = _mm_set1_epi32(0xff00ff00); // alpha-green masks - int i; - for (i = 0; i + 4 <= num_pixels; i += 4) { - const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb - const __m128i A = _mm_and_si128(in, mask_ag); // a 0 g 0 - const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0)); - const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // g0g0 - const __m128i D = _mm_mulhi_epi16(C, mults_rb); // x dr x db1 - const __m128i E = _mm_add_epi8(in, D); // x r' x b' - const __m128i F = _mm_slli_epi16(E, 8); // r' 0 b' 0 - const __m128i G = _mm_mulhi_epi16(F, mults_b2); // x db2 0 0 - const __m128i H = _mm_srli_epi32(G, 8); // 0 x db2 0 - const __m128i I = _mm_add_epi8(H, F); // r' x b'' 0 - const __m128i J = _mm_srli_epi16(I, 8); // 0 r' 0 b'' - const __m128i out = _mm_or_si128(J, A); - _mm_storeu_si128((__m128i*)&argb_data[i], out); - } - // Fall-back to C-version for left-overs. - VP8LTransformColorInverse_C(m, argb_data + i, num_pixels - i); -} - -//------------------------------------------------------------------------------ -// Color-space conversion functions - -static void ConvertBGRAToRGBA(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const __m128i* in = (const __m128i*)src; - __m128i* out = (__m128i*)dst; - while (num_pixels >= 8) { - const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3 - const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7 - const __m128i v0l = _mm_unpacklo_epi8(bgra0, bgra4); // b0b4g0g4r0r4a0a4... - const __m128i v0h = _mm_unpackhi_epi8(bgra0, bgra4); // b2b6g2g6r2r6a2a6... - const __m128i v1l = _mm_unpacklo_epi8(v0l, v0h); // b0b2b4b6g0g2g4g6... - const __m128i v1h = _mm_unpackhi_epi8(v0l, v0h); // b1b3b5b7g1g3g5g7... - const __m128i v2l = _mm_unpacklo_epi8(v1l, v1h); // b0...b7 | g0...g7 - const __m128i v2h = _mm_unpackhi_epi8(v1l, v1h); // r0...r7 | a0...a7 - const __m128i ga0 = _mm_unpackhi_epi64(v2l, v2h); // g0...g7 | a0...a7 - const __m128i rb0 = _mm_unpacklo_epi64(v2h, v2l); // r0...r7 | b0...b7 - const __m128i rg0 = _mm_unpacklo_epi8(rb0, ga0); // r0g0r1g1 ... r6g6r7g7 - const __m128i ba0 = _mm_unpackhi_epi8(rb0, ga0); // b0a0b1a1 ... b6a6b7a7 - const __m128i rgba0 = _mm_unpacklo_epi16(rg0, ba0); // rgba0|rgba1... - const __m128i rgba4 = _mm_unpackhi_epi16(rg0, ba0); // rgba4|rgba5... - _mm_storeu_si128(out++, rgba0); - _mm_storeu_si128(out++, rgba4); - num_pixels -= 8; - } - // left-overs - VP8LConvertBGRAToRGBA_C((const uint32_t*)in, num_pixels, (uint8_t*)out); -} - -static void ConvertBGRAToRGBA4444(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const __m128i mask_0x0f = _mm_set1_epi8(0x0f); - const __m128i mask_0xf0 = _mm_set1_epi8(0xf0); - const __m128i* in = (const __m128i*)src; - __m128i* out = (__m128i*)dst; - while (num_pixels >= 8) { - const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3 - const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7 - const __m128i v0l = _mm_unpacklo_epi8(bgra0, bgra4); // b0b4g0g4r0r4a0a4... - const __m128i v0h = _mm_unpackhi_epi8(bgra0, bgra4); // b2b6g2g6r2r6a2a6... - const __m128i v1l = _mm_unpacklo_epi8(v0l, v0h); // b0b2b4b6g0g2g4g6... - const __m128i v1h = _mm_unpackhi_epi8(v0l, v0h); // b1b3b5b7g1g3g5g7... - const __m128i v2l = _mm_unpacklo_epi8(v1l, v1h); // b0...b7 | g0...g7 - const __m128i v2h = _mm_unpackhi_epi8(v1l, v1h); // r0...r7 | a0...a7 - const __m128i ga0 = _mm_unpackhi_epi64(v2l, v2h); // g0...g7 | a0...a7 - const __m128i rb0 = _mm_unpacklo_epi64(v2h, v2l); // r0...r7 | b0...b7 - const __m128i ga1 = _mm_srli_epi16(ga0, 4); // g0-|g1-|...|a6-|a7- - const __m128i rb1 = _mm_and_si128(rb0, mask_0xf0); // -r0|-r1|...|-b6|-a7 - const __m128i ga2 = _mm_and_si128(ga1, mask_0x0f); // g0-|g1-|...|a6-|a7- - const __m128i rgba0 = _mm_or_si128(ga2, rb1); // rg0..rg7 | ba0..ba7 - const __m128i rgba1 = _mm_srli_si128(rgba0, 8); // ba0..ba7 | 0 -#ifdef WEBP_SWAP_16BIT_CSP - const __m128i rgba = _mm_unpacklo_epi8(rgba1, rgba0); // barg0...barg7 -#else - const __m128i rgba = _mm_unpacklo_epi8(rgba0, rgba1); // rgba0...rgba7 -#endif - _mm_storeu_si128(out++, rgba); - num_pixels -= 8; - } - // left-overs - VP8LConvertBGRAToRGBA4444_C((const uint32_t*)in, num_pixels, (uint8_t*)out); -} - -static void ConvertBGRAToRGB565(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const __m128i mask_0xe0 = _mm_set1_epi8(0xe0); - const __m128i mask_0xf8 = _mm_set1_epi8(0xf8); - const __m128i mask_0x07 = _mm_set1_epi8(0x07); - const __m128i* in = (const __m128i*)src; - __m128i* out = (__m128i*)dst; - while (num_pixels >= 8) { - const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3 - const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7 - const __m128i v0l = _mm_unpacklo_epi8(bgra0, bgra4); // b0b4g0g4r0r4a0a4... - const __m128i v0h = _mm_unpackhi_epi8(bgra0, bgra4); // b2b6g2g6r2r6a2a6... - const __m128i v1l = _mm_unpacklo_epi8(v0l, v0h); // b0b2b4b6g0g2g4g6... - const __m128i v1h = _mm_unpackhi_epi8(v0l, v0h); // b1b3b5b7g1g3g5g7... - const __m128i v2l = _mm_unpacklo_epi8(v1l, v1h); // b0...b7 | g0...g7 - const __m128i v2h = _mm_unpackhi_epi8(v1l, v1h); // r0...r7 | a0...a7 - const __m128i ga0 = _mm_unpackhi_epi64(v2l, v2h); // g0...g7 | a0...a7 - const __m128i rb0 = _mm_unpacklo_epi64(v2h, v2l); // r0...r7 | b0...b7 - const __m128i rb1 = _mm_and_si128(rb0, mask_0xf8); // -r0..-r7|-b0..-b7 - const __m128i g_lo1 = _mm_srli_epi16(ga0, 5); - const __m128i g_lo2 = _mm_and_si128(g_lo1, mask_0x07); // g0-...g7-|xx (3b) - const __m128i g_hi1 = _mm_slli_epi16(ga0, 3); - const __m128i g_hi2 = _mm_and_si128(g_hi1, mask_0xe0); // -g0...-g7|xx (3b) - const __m128i b0 = _mm_srli_si128(rb1, 8); // -b0...-b7|0 - const __m128i rg1 = _mm_or_si128(rb1, g_lo2); // gr0...gr7|xx - const __m128i b1 = _mm_srli_epi16(b0, 3); - const __m128i gb1 = _mm_or_si128(b1, g_hi2); // bg0...bg7|xx -#ifdef WEBP_SWAP_16BIT_CSP - const __m128i rgba = _mm_unpacklo_epi8(gb1, rg1); // rggb0...rggb7 -#else - const __m128i rgba = _mm_unpacklo_epi8(rg1, gb1); // bgrb0...bgrb7 -#endif - _mm_storeu_si128(out++, rgba); - num_pixels -= 8; - } - // left-overs - VP8LConvertBGRAToRGB565_C((const uint32_t*)in, num_pixels, (uint8_t*)out); -} - -static void ConvertBGRAToBGR(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const __m128i mask_l = _mm_set_epi32(0, 0x00ffffff, 0, 0x00ffffff); - const __m128i mask_h = _mm_set_epi32(0x00ffffff, 0, 0x00ffffff, 0); - const __m128i* in = (const __m128i*)src; - const uint8_t* const end = dst + num_pixels * 3; - // the last storel_epi64 below writes 8 bytes starting at offset 18 - while (dst + 26 <= end) { - const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3 - const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7 - const __m128i a0l = _mm_and_si128(bgra0, mask_l); // bgr0|0|bgr0|0 - const __m128i a4l = _mm_and_si128(bgra4, mask_l); // bgr0|0|bgr0|0 - const __m128i a0h = _mm_and_si128(bgra0, mask_h); // 0|bgr0|0|bgr0 - const __m128i a4h = _mm_and_si128(bgra4, mask_h); // 0|bgr0|0|bgr0 - const __m128i b0h = _mm_srli_epi64(a0h, 8); // 000b|gr00|000b|gr00 - const __m128i b4h = _mm_srli_epi64(a4h, 8); // 000b|gr00|000b|gr00 - const __m128i c0 = _mm_or_si128(a0l, b0h); // rgbrgb00|rgbrgb00 - const __m128i c4 = _mm_or_si128(a4l, b4h); // rgbrgb00|rgbrgb00 - const __m128i c2 = _mm_srli_si128(c0, 8); - const __m128i c6 = _mm_srli_si128(c4, 8); - _mm_storel_epi64((__m128i*)(dst + 0), c0); - _mm_storel_epi64((__m128i*)(dst + 6), c2); - _mm_storel_epi64((__m128i*)(dst + 12), c4); - _mm_storel_epi64((__m128i*)(dst + 18), c6); - dst += 24; - num_pixels -= 8; - } - // left-overs - VP8LConvertBGRAToBGR_C((const uint32_t*)in, num_pixels, dst); -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8LDspInitSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitSSE2(void) { - VP8LPredictors[5] = Predictor5; - VP8LPredictors[6] = Predictor6; - VP8LPredictors[7] = Predictor7; - VP8LPredictors[8] = Predictor8; - VP8LPredictors[9] = Predictor9; - VP8LPredictors[10] = Predictor10; - VP8LPredictors[11] = Predictor11; - VP8LPredictors[12] = Predictor12; - VP8LPredictors[13] = Predictor13; - - VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed; - VP8LTransformColorInverse = TransformColorInverse; - - VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA; - VP8LConvertBGRAToRGBA4444 = ConvertBGRAToRGBA4444; - VP8LConvertBGRAToRGB565 = ConvertBGRAToRGB565; - VP8LConvertBGRAToBGR = ConvertBGRAToBGR; -} - -#else // !WEBP_USE_SSE2 - -WEBP_DSP_INIT_STUB(VP8LDspInitSSE2) - -#endif // WEBP_USE_SSE2 diff --git a/Example-Mac/Pods/libwebp/src/dsp/mips_macro.h b/Example-Mac/Pods/libwebp/src/dsp/mips_macro.h deleted file mode 100644 index 44aba9b7..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/mips_macro.h +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// MIPS common macros - -#ifndef WEBP_DSP_MIPS_MACRO_H_ -#define WEBP_DSP_MIPS_MACRO_H_ - -#if defined(__GNUC__) && defined(__ANDROID__) && LOCAL_GCC_VERSION == 0x409 -#define WORK_AROUND_GCC -#endif - -#define STR(s) #s -#define XSTR(s) STR(s) - -// O0[31..16 | 15..0] = I0[31..16 | 15..0] + I1[31..16 | 15..0] -// O1[31..16 | 15..0] = I0[31..16 | 15..0] - I1[31..16 | 15..0] -// O - output -// I - input (macro doesn't change it) -#define ADD_SUB_HALVES(O0, O1, \ - I0, I1) \ - "addq.ph %[" #O0 "], %[" #I0 "], %[" #I1 "] \n\t" \ - "subq.ph %[" #O1 "], %[" #I0 "], %[" #I1 "] \n\t" - -// O - output -// I - input (macro doesn't change it) -// I[0/1] - offset in bytes -#define LOAD_IN_X2(O0, O1, \ - I0, I1) \ - "lh %[" #O0 "], " #I0 "(%[in]) \n\t" \ - "lh %[" #O1 "], " #I1 "(%[in]) \n\t" - -// I0 - location -// I1..I9 - offsets in bytes -#define LOAD_WITH_OFFSET_X4(O0, O1, O2, O3, \ - I0, I1, I2, I3, I4, I5, I6, I7, I8, I9) \ - "ulw %[" #O0 "], " #I1 "+" XSTR(I9) "*" #I5 "(%[" #I0 "]) \n\t" \ - "ulw %[" #O1 "], " #I2 "+" XSTR(I9) "*" #I6 "(%[" #I0 "]) \n\t" \ - "ulw %[" #O2 "], " #I3 "+" XSTR(I9) "*" #I7 "(%[" #I0 "]) \n\t" \ - "ulw %[" #O3 "], " #I4 "+" XSTR(I9) "*" #I8 "(%[" #I0 "]) \n\t" - -// O - output -// IO - input/output -// I - input (macro doesn't change it) -#define MUL_SHIFT_SUM(O0, O1, O2, O3, O4, O5, O6, O7, \ - IO0, IO1, IO2, IO3, \ - I0, I1, I2, I3, I4, I5, I6, I7) \ - "mul %[" #O0 "], %[" #I0 "], %[kC2] \n\t" \ - "mul %[" #O1 "], %[" #I0 "], %[kC1] \n\t" \ - "mul %[" #O2 "], %[" #I1 "], %[kC2] \n\t" \ - "mul %[" #O3 "], %[" #I1 "], %[kC1] \n\t" \ - "mul %[" #O4 "], %[" #I2 "], %[kC2] \n\t" \ - "mul %[" #O5 "], %[" #I2 "], %[kC1] \n\t" \ - "mul %[" #O6 "], %[" #I3 "], %[kC2] \n\t" \ - "mul %[" #O7 "], %[" #I3 "], %[kC1] \n\t" \ - "sra %[" #O0 "], %[" #O0 "], 16 \n\t" \ - "sra %[" #O1 "], %[" #O1 "], 16 \n\t" \ - "sra %[" #O2 "], %[" #O2 "], 16 \n\t" \ - "sra %[" #O3 "], %[" #O3 "], 16 \n\t" \ - "sra %[" #O4 "], %[" #O4 "], 16 \n\t" \ - "sra %[" #O5 "], %[" #O5 "], 16 \n\t" \ - "sra %[" #O6 "], %[" #O6 "], 16 \n\t" \ - "sra %[" #O7 "], %[" #O7 "], 16 \n\t" \ - "addu %[" #IO0 "], %[" #IO0 "], %[" #I4 "] \n\t" \ - "addu %[" #IO1 "], %[" #IO1 "], %[" #I5 "] \n\t" \ - "subu %[" #IO2 "], %[" #IO2 "], %[" #I6 "] \n\t" \ - "subu %[" #IO3 "], %[" #IO3 "], %[" #I7 "] \n\t" - -// O - output -// I - input (macro doesn't change it) -#define INSERT_HALF_X2(O0, O1, \ - I0, I1) \ - "ins %[" #O0 "], %[" #I0 "], 16, 16 \n\t" \ - "ins %[" #O1 "], %[" #I1 "], 16, 16 \n\t" - -// O - output -// I - input (macro doesn't change it) -#define SRA_16(O0, O1, O2, O3, \ - I0, I1, I2, I3) \ - "sra %[" #O0 "], %[" #I0 "], 16 \n\t" \ - "sra %[" #O1 "], %[" #I1 "], 16 \n\t" \ - "sra %[" #O2 "], %[" #I2 "], 16 \n\t" \ - "sra %[" #O3 "], %[" #I3 "], 16 \n\t" - -// temp0[31..16 | 15..0] = temp8[31..16 | 15..0] + temp12[31..16 | 15..0] -// temp1[31..16 | 15..0] = temp8[31..16 | 15..0] - temp12[31..16 | 15..0] -// temp0[31..16 | 15..0] = temp0[31..16 >> 3 | 15..0 >> 3] -// temp1[31..16 | 15..0] = temp1[31..16 >> 3 | 15..0 >> 3] -// O - output -// I - input (macro doesn't change it) -#define SHIFT_R_SUM_X2(O0, O1, O2, O3, O4, O5, O6, O7, \ - I0, I1, I2, I3, I4, I5, I6, I7) \ - "addq.ph %[" #O0 "], %[" #I0 "], %[" #I4 "] \n\t" \ - "subq.ph %[" #O1 "], %[" #I0 "], %[" #I4 "] \n\t" \ - "addq.ph %[" #O2 "], %[" #I1 "], %[" #I5 "] \n\t" \ - "subq.ph %[" #O3 "], %[" #I1 "], %[" #I5 "] \n\t" \ - "addq.ph %[" #O4 "], %[" #I2 "], %[" #I6 "] \n\t" \ - "subq.ph %[" #O5 "], %[" #I2 "], %[" #I6 "] \n\t" \ - "addq.ph %[" #O6 "], %[" #I3 "], %[" #I7 "] \n\t" \ - "subq.ph %[" #O7 "], %[" #I3 "], %[" #I7 "] \n\t" \ - "shra.ph %[" #O0 "], %[" #O0 "], 3 \n\t" \ - "shra.ph %[" #O1 "], %[" #O1 "], 3 \n\t" \ - "shra.ph %[" #O2 "], %[" #O2 "], 3 \n\t" \ - "shra.ph %[" #O3 "], %[" #O3 "], 3 \n\t" \ - "shra.ph %[" #O4 "], %[" #O4 "], 3 \n\t" \ - "shra.ph %[" #O5 "], %[" #O5 "], 3 \n\t" \ - "shra.ph %[" #O6 "], %[" #O6 "], 3 \n\t" \ - "shra.ph %[" #O7 "], %[" #O7 "], 3 \n\t" - -// precrq.ph.w temp0, temp8, temp2 -// temp0 = temp8[31..16] | temp2[31..16] -// ins temp2, temp8, 16, 16 -// temp2 = temp8[31..16] | temp2[15..0] -// O - output -// IO - input/output -// I - input (macro doesn't change it) -#define PACK_2_HALVES_TO_WORD(O0, O1, O2, O3, \ - IO0, IO1, IO2, IO3, \ - I0, I1, I2, I3) \ - "precrq.ph.w %[" #O0 "], %[" #I0 "], %[" #IO0 "] \n\t" \ - "precrq.ph.w %[" #O1 "], %[" #I1 "], %[" #IO1 "] \n\t" \ - "ins %[" #IO0 "], %[" #I0 "], 16, 16 \n\t" \ - "ins %[" #IO1 "], %[" #I1 "], 16, 16 \n\t" \ - "precrq.ph.w %[" #O2 "], %[" #I2 "], %[" #IO2 "] \n\t" \ - "precrq.ph.w %[" #O3 "], %[" #I3 "], %[" #IO3 "] \n\t" \ - "ins %[" #IO2 "], %[" #I2 "], 16, 16 \n\t" \ - "ins %[" #IO3 "], %[" #I3 "], 16, 16 \n\t" - -// preceu.ph.qbr temp0, temp8 -// temp0 = 0 | 0 | temp8[23..16] | temp8[7..0] -// preceu.ph.qbl temp1, temp8 -// temp1 = temp8[23..16] | temp8[7..0] | 0 | 0 -// O - output -// I - input (macro doesn't change it) -#define CONVERT_2_BYTES_TO_HALF(O0, O1, O2, O3, O4, O5, O6, O7, \ - I0, I1, I2, I3) \ - "preceu.ph.qbr %[" #O0 "], %[" #I0 "] \n\t" \ - "preceu.ph.qbl %[" #O1 "], %[" #I0 "] \n\t" \ - "preceu.ph.qbr %[" #O2 "], %[" #I1 "] \n\t" \ - "preceu.ph.qbl %[" #O3 "], %[" #I1 "] \n\t" \ - "preceu.ph.qbr %[" #O4 "], %[" #I2 "] \n\t" \ - "preceu.ph.qbl %[" #O5 "], %[" #I2 "] \n\t" \ - "preceu.ph.qbr %[" #O6 "], %[" #I3 "] \n\t" \ - "preceu.ph.qbl %[" #O7 "], %[" #I3 "] \n\t" - -// temp0[31..16 | 15..0] = temp0[31..16 | 15..0] + temp8[31..16 | 15..0] -// temp0[31..16 | 15..0] = temp0[31..16 <<(s) 7 | 15..0 <<(s) 7] -// temp1..temp7 same as temp0 -// precrqu_s.qb.ph temp0, temp1, temp0: -// temp0 = temp1[31..24] | temp1[15..8] | temp0[31..24] | temp0[15..8] -// store temp0 to dst -// IO - input/output -// I - input (macro doesn't change it) -#define STORE_SAT_SUM_X2(IO0, IO1, IO2, IO3, IO4, IO5, IO6, IO7, \ - I0, I1, I2, I3, I4, I5, I6, I7, \ - I8, I9, I10, I11, I12, I13) \ - "addq.ph %[" #IO0 "], %[" #IO0 "], %[" #I0 "] \n\t" \ - "addq.ph %[" #IO1 "], %[" #IO1 "], %[" #I1 "] \n\t" \ - "addq.ph %[" #IO2 "], %[" #IO2 "], %[" #I2 "] \n\t" \ - "addq.ph %[" #IO3 "], %[" #IO3 "], %[" #I3 "] \n\t" \ - "addq.ph %[" #IO4 "], %[" #IO4 "], %[" #I4 "] \n\t" \ - "addq.ph %[" #IO5 "], %[" #IO5 "], %[" #I5 "] \n\t" \ - "addq.ph %[" #IO6 "], %[" #IO6 "], %[" #I6 "] \n\t" \ - "addq.ph %[" #IO7 "], %[" #IO7 "], %[" #I7 "] \n\t" \ - "shll_s.ph %[" #IO0 "], %[" #IO0 "], 7 \n\t" \ - "shll_s.ph %[" #IO1 "], %[" #IO1 "], 7 \n\t" \ - "shll_s.ph %[" #IO2 "], %[" #IO2 "], 7 \n\t" \ - "shll_s.ph %[" #IO3 "], %[" #IO3 "], 7 \n\t" \ - "shll_s.ph %[" #IO4 "], %[" #IO4 "], 7 \n\t" \ - "shll_s.ph %[" #IO5 "], %[" #IO5 "], 7 \n\t" \ - "shll_s.ph %[" #IO6 "], %[" #IO6 "], 7 \n\t" \ - "shll_s.ph %[" #IO7 "], %[" #IO7 "], 7 \n\t" \ - "precrqu_s.qb.ph %[" #IO0 "], %[" #IO1 "], %[" #IO0 "] \n\t" \ - "precrqu_s.qb.ph %[" #IO2 "], %[" #IO3 "], %[" #IO2 "] \n\t" \ - "precrqu_s.qb.ph %[" #IO4 "], %[" #IO5 "], %[" #IO4 "] \n\t" \ - "precrqu_s.qb.ph %[" #IO6 "], %[" #IO7 "], %[" #IO6 "] \n\t" \ - "usw %[" #IO0 "], " XSTR(I13) "*" #I9 "(%[" #I8 "]) \n\t" \ - "usw %[" #IO2 "], " XSTR(I13) "*" #I10 "(%[" #I8 "]) \n\t" \ - "usw %[" #IO4 "], " XSTR(I13) "*" #I11 "(%[" #I8 "]) \n\t" \ - "usw %[" #IO6 "], " XSTR(I13) "*" #I12 "(%[" #I8 "]) \n\t" - -#define OUTPUT_EARLY_CLOBBER_REGS_10() \ - : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), \ - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6), \ - [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), [temp9]"=&r"(temp9), \ - [temp10]"=&r"(temp10) - -#define OUTPUT_EARLY_CLOBBER_REGS_18() \ - OUTPUT_EARLY_CLOBBER_REGS_10(), \ - [temp11]"=&r"(temp11), [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), \ - [temp14]"=&r"(temp14), [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), \ - [temp17]"=&r"(temp17), [temp18]"=&r"(temp18) - -#endif // WEBP_DSP_MIPS_MACRO_H_ diff --git a/Example-Mac/Pods/libwebp/src/dsp/neon.h b/Example-Mac/Pods/libwebp/src/dsp/neon.h deleted file mode 100644 index 0a062668..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/neon.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// NEON common code. - -#ifndef WEBP_DSP_NEON_H_ -#define WEBP_DSP_NEON_H_ - -#include - -#include "./dsp.h" - -// Right now, some intrinsics functions seem slower, so we disable them -// everywhere except aarch64 where the inline assembly is incompatible. -#if defined(__aarch64__) -#define WEBP_USE_INTRINSICS // use intrinsics when possible -#endif - -#define INIT_VECTOR2(v, a, b) do { \ - v.val[0] = a; \ - v.val[1] = b; \ -} while (0) - -#define INIT_VECTOR3(v, a, b, c) do { \ - v.val[0] = a; \ - v.val[1] = b; \ - v.val[2] = c; \ -} while (0) - -#define INIT_VECTOR4(v, a, b, c, d) do { \ - v.val[0] = a; \ - v.val[1] = b; \ - v.val[2] = c; \ - v.val[3] = d; \ -} while (0) - -// if using intrinsics, this flag avoids some functions that make gcc-4.6.3 -// crash ("internal compiler error: in immed_double_const, at emit-rtl."). -// (probably similar to gcc.gnu.org/bugzilla/show_bug.cgi?id=48183) -#if !(LOCAL_GCC_PREREQ(4,8) || defined(__aarch64__)) -#define WORK_AROUND_GCC -#endif - -static WEBP_INLINE int32x4x4_t Transpose4x4(const int32x4x4_t rows) { - uint64x2x2_t row01, row23; - - row01.val[0] = vreinterpretq_u64_s32(rows.val[0]); - row01.val[1] = vreinterpretq_u64_s32(rows.val[1]); - row23.val[0] = vreinterpretq_u64_s32(rows.val[2]); - row23.val[1] = vreinterpretq_u64_s32(rows.val[3]); - // Transpose 64-bit values (there's no vswp equivalent) - { - const uint64x1_t row0h = vget_high_u64(row01.val[0]); - const uint64x1_t row2l = vget_low_u64(row23.val[0]); - const uint64x1_t row1h = vget_high_u64(row01.val[1]); - const uint64x1_t row3l = vget_low_u64(row23.val[1]); - row01.val[0] = vcombine_u64(vget_low_u64(row01.val[0]), row2l); - row23.val[0] = vcombine_u64(row0h, vget_high_u64(row23.val[0])); - row01.val[1] = vcombine_u64(vget_low_u64(row01.val[1]), row3l); - row23.val[1] = vcombine_u64(row1h, vget_high_u64(row23.val[1])); - } - { - const int32x4x2_t out01 = vtrnq_s32(vreinterpretq_s32_u64(row01.val[0]), - vreinterpretq_s32_u64(row01.val[1])); - const int32x4x2_t out23 = vtrnq_s32(vreinterpretq_s32_u64(row23.val[0]), - vreinterpretq_s32_u64(row23.val[1])); - int32x4x4_t out; - out.val[0] = out01.val[0]; - out.val[1] = out01.val[1]; - out.val[2] = out23.val[0]; - out.val[3] = out23.val[1]; - return out; - } -} - -#endif // WEBP_DSP_NEON_H_ diff --git a/Example-Mac/Pods/libwebp/src/dsp/rescaler.c b/Example-Mac/Pods/libwebp/src/dsp/rescaler.c deleted file mode 100644 index bc743d5d..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/rescaler.c +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Rescaling functions -// -// Author: Skal (pascal.massimino@gmail.com) - -#include - -#include "./dsp.h" -#include "../utils/rescaler.h" - -//------------------------------------------------------------------------------ -// Implementations of critical functions ImportRow / ExportRow - -#define ROUNDER (WEBP_RESCALER_ONE >> 1) -#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) - -//------------------------------------------------------------------------------ -// Row import - -void WebPRescalerImportRowExpandC(WebPRescaler* const wrk, const uint8_t* src) { - const int x_stride = wrk->num_channels; - const int x_out_max = wrk->dst_width * wrk->num_channels; - int channel; - assert(!WebPRescalerInputDone(wrk)); - assert(wrk->x_expand); - for (channel = 0; channel < x_stride; ++channel) { - int x_in = channel; - int x_out = channel; - // simple bilinear interpolation - int accum = wrk->x_add; - int left = src[x_in]; - int right = (wrk->src_width > 1) ? src[x_in + x_stride] : left; - x_in += x_stride; - while (1) { - wrk->frow[x_out] = right * wrk->x_add + (left - right) * accum; - x_out += x_stride; - if (x_out >= x_out_max) break; - accum -= wrk->x_sub; - if (accum < 0) { - left = right; - x_in += x_stride; - assert(x_in < wrk->src_width * x_stride); - right = src[x_in]; - accum += wrk->x_add; - } - } - assert(wrk->x_sub == 0 /* <- special case for src_width=1 */ || accum == 0); - } -} - -void WebPRescalerImportRowShrinkC(WebPRescaler* const wrk, const uint8_t* src) { - const int x_stride = wrk->num_channels; - const int x_out_max = wrk->dst_width * wrk->num_channels; - int channel; - assert(!WebPRescalerInputDone(wrk)); - assert(!wrk->x_expand); - for (channel = 0; channel < x_stride; ++channel) { - int x_in = channel; - int x_out = channel; - uint32_t sum = 0; - int accum = 0; - while (x_out < x_out_max) { - uint32_t base = 0; - accum += wrk->x_add; - while (accum > 0) { - accum -= wrk->x_sub; - assert(x_in < wrk->src_width * x_stride); - base = src[x_in]; - sum += base; - x_in += x_stride; - } - { // Emit next horizontal pixel. - const rescaler_t frac = base * (-accum); - wrk->frow[x_out] = sum * wrk->x_sub - frac; - // fresh fractional start for next pixel - sum = (int)MULT_FIX(frac, wrk->fx_scale); - } - x_out += x_stride; - } - assert(accum == 0); - } -} - -//------------------------------------------------------------------------------ -// Row export - -void WebPRescalerExportRowExpandC(WebPRescaler* const wrk) { - int x_out; - uint8_t* const dst = wrk->dst; - rescaler_t* const irow = wrk->irow; - const int x_out_max = wrk->dst_width * wrk->num_channels; - const rescaler_t* const frow = wrk->frow; - assert(!WebPRescalerOutputDone(wrk)); - assert(wrk->y_accum <= 0); - assert(wrk->y_expand); - assert(wrk->y_sub != 0); - if (wrk->y_accum == 0) { - for (x_out = 0; x_out < x_out_max; ++x_out) { - const uint32_t J = frow[x_out]; - const int v = (int)MULT_FIX(J, wrk->fy_scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - } - } else { - const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub); - const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); - for (x_out = 0; x_out < x_out_max; ++x_out) { - const uint64_t I = (uint64_t)A * frow[x_out] - + (uint64_t)B * irow[x_out]; - const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX); - const int v = (int)MULT_FIX(J, wrk->fy_scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - } - } -} - -void WebPRescalerExportRowShrinkC(WebPRescaler* const wrk) { - int x_out; - uint8_t* const dst = wrk->dst; - rescaler_t* const irow = wrk->irow; - const int x_out_max = wrk->dst_width * wrk->num_channels; - const rescaler_t* const frow = wrk->frow; - const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum); - assert(!WebPRescalerOutputDone(wrk)); - assert(wrk->y_accum <= 0); - assert(!wrk->y_expand); - if (yscale) { - for (x_out = 0; x_out < x_out_max; ++x_out) { - const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale); - const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - irow[x_out] = frac; // new fractional start - } - } else { - for (x_out = 0; x_out < x_out_max; ++x_out) { - const int v = (int)MULT_FIX(irow[x_out], wrk->fxy_scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - irow[x_out] = 0; - } - } -} - -#undef MULT_FIX -#undef ROUNDER - -//------------------------------------------------------------------------------ -// Main entry calls - -void WebPRescalerImportRow(WebPRescaler* const wrk, const uint8_t* src) { - assert(!WebPRescalerInputDone(wrk)); - if (!wrk->x_expand) { - WebPRescalerImportRowShrink(wrk, src); - } else { - WebPRescalerImportRowExpand(wrk, src); - } -} - -void WebPRescalerExportRow(WebPRescaler* const wrk) { - if (wrk->y_accum <= 0) { - assert(!WebPRescalerOutputDone(wrk)); - if (wrk->y_expand) { - WebPRescalerExportRowExpand(wrk); - } else if (wrk->fxy_scale) { - WebPRescalerExportRowShrink(wrk); - } else { // very special case for src = dst = 1x1 - int i; - assert(wrk->src_width == 1 && wrk->dst_width <= 2); - assert(wrk->src_height == 1 && wrk->dst_height == 1); - for (i = 0; i < wrk->num_channels * wrk->dst_width; ++i) { - wrk->dst[i] = wrk->irow[i]; - wrk->irow[i] = 0; - } - } - wrk->y_accum += wrk->y_add; - wrk->dst += wrk->dst_stride; - ++wrk->dst_y; - } -} - -//------------------------------------------------------------------------------ - -WebPRescalerImportRowFunc WebPRescalerImportRowExpand; -WebPRescalerImportRowFunc WebPRescalerImportRowShrink; - -WebPRescalerExportRowFunc WebPRescalerExportRowExpand; -WebPRescalerExportRowFunc WebPRescalerExportRowShrink; - -extern void WebPRescalerDspInitSSE2(void); -extern void WebPRescalerDspInitMIPS32(void); -extern void WebPRescalerDspInitMIPSdspR2(void); -extern void WebPRescalerDspInitNEON(void); - -static volatile VP8CPUInfo rescaler_last_cpuinfo_used = - (VP8CPUInfo)&rescaler_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInit(void) { - if (rescaler_last_cpuinfo_used == VP8GetCPUInfo) return; - - WebPRescalerImportRowExpand = WebPRescalerImportRowExpandC; - WebPRescalerImportRowShrink = WebPRescalerImportRowShrinkC; - WebPRescalerExportRowExpand = WebPRescalerExportRowExpandC; - WebPRescalerExportRowShrink = WebPRescalerExportRowShrinkC; - - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - WebPRescalerDspInitSSE2(); - } -#endif -#if defined(WEBP_USE_NEON) - if (VP8GetCPUInfo(kNEON)) { - WebPRescalerDspInitNEON(); - } -#endif -#if defined(WEBP_USE_MIPS32) - if (VP8GetCPUInfo(kMIPS32)) { - WebPRescalerDspInitMIPS32(); - } -#endif -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - WebPRescalerDspInitMIPSdspR2(); - } -#endif - } - rescaler_last_cpuinfo_used = VP8GetCPUInfo; -} diff --git a/Example-Mac/Pods/libwebp/src/dsp/rescaler_mips32.c b/Example-Mac/Pods/libwebp/src/dsp/rescaler_mips32.c deleted file mode 100644 index ddaa3913..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/rescaler_mips32.c +++ /dev/null @@ -1,291 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// MIPS version of rescaling functions -// -// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS32) - -#include -#include "../utils/rescaler.h" - -//------------------------------------------------------------------------------ -// Row import - -static void ImportRowShrink(WebPRescaler* const wrk, const uint8_t* src) { - const int x_stride = wrk->num_channels; - const int x_out_max = wrk->dst_width * wrk->num_channels; - const int fx_scale = wrk->fx_scale; - const int x_add = wrk->x_add; - const int x_sub = wrk->x_sub; - const int x_stride1 = x_stride << 2; - int channel; - assert(!wrk->x_expand); - assert(!WebPRescalerInputDone(wrk)); - - for (channel = 0; channel < x_stride; ++channel) { - const uint8_t* src1 = src + channel; - rescaler_t* frow = wrk->frow + channel; - int temp1, temp2, temp3; - int base, frac, sum; - int accum, accum1; - int loop_c = x_out_max - channel; - - __asm__ volatile ( - "li %[temp1], 0x8000 \n\t" - "li %[temp2], 0x10000 \n\t" - "li %[sum], 0 \n\t" - "li %[accum], 0 \n\t" - "1: \n\t" - "addu %[accum], %[accum], %[x_add] \n\t" - "li %[base], 0 \n\t" - "blez %[accum], 3f \n\t" - "2: \n\t" - "lbu %[base], 0(%[src1]) \n\t" - "subu %[accum], %[accum], %[x_sub] \n\t" - "addu %[src1], %[src1], %[x_stride] \n\t" - "addu %[sum], %[sum], %[base] \n\t" - "bgtz %[accum], 2b \n\t" - "3: \n\t" - "negu %[accum1], %[accum] \n\t" - "mul %[frac], %[base], %[accum1] \n\t" - "mul %[temp3], %[sum], %[x_sub] \n\t" - "subu %[loop_c], %[loop_c], %[x_stride] \n\t" - "mult %[temp1], %[temp2] \n\t" - "maddu %[frac], %[fx_scale] \n\t" - "mfhi %[sum] \n\t" - "subu %[temp3], %[temp3], %[frac] \n\t" - "sw %[temp3], 0(%[frow]) \n\t" - "addu %[frow], %[frow], %[x_stride1] \n\t" - "bgtz %[loop_c], 1b \n\t" - : [accum]"=&r"(accum), [src1]"+r"(src1), [temp3]"=&r"(temp3), - [sum]"=&r"(sum), [base]"=&r"(base), [frac]"=&r"(frac), - [frow]"+r"(frow), [accum1]"=&r"(accum1), - [temp2]"=&r"(temp2), [temp1]"=&r"(temp1) - : [x_stride]"r"(x_stride), [fx_scale]"r"(fx_scale), - [x_sub]"r"(x_sub), [x_add]"r"(x_add), - [loop_c]"r"(loop_c), [x_stride1]"r"(x_stride1) - : "memory", "hi", "lo" - ); - assert(accum == 0); - } -} - -static void ImportRowExpand(WebPRescaler* const wrk, const uint8_t* src) { - const int x_stride = wrk->num_channels; - const int x_out_max = wrk->dst_width * wrk->num_channels; - const int x_add = wrk->x_add; - const int x_sub = wrk->x_sub; - const int src_width = wrk->src_width; - const int x_stride1 = x_stride << 2; - int channel; - assert(wrk->x_expand); - assert(!WebPRescalerInputDone(wrk)); - - for (channel = 0; channel < x_stride; ++channel) { - const uint8_t* src1 = src + channel; - rescaler_t* frow = wrk->frow + channel; - int temp1, temp2, temp3, temp4; - int frac; - int accum; - int x_out = channel; - - __asm__ volatile ( - "addiu %[temp3], %[src_width], -1 \n\t" - "lbu %[temp2], 0(%[src1]) \n\t" - "addu %[src1], %[src1], %[x_stride] \n\t" - "bgtz %[temp3], 0f \n\t" - "addiu %[temp1], %[temp2], 0 \n\t" - "b 3f \n\t" - "0: \n\t" - "lbu %[temp1], 0(%[src1]) \n\t" - "3: \n\t" - "addiu %[accum], %[x_add], 0 \n\t" - "1: \n\t" - "subu %[temp3], %[temp2], %[temp1] \n\t" - "mul %[temp3], %[temp3], %[accum] \n\t" - "mul %[temp4], %[temp1], %[x_add] \n\t" - "addu %[temp3], %[temp4], %[temp3] \n\t" - "sw %[temp3], 0(%[frow]) \n\t" - "addu %[frow], %[frow], %[x_stride1] \n\t" - "addu %[x_out], %[x_out], %[x_stride] \n\t" - "subu %[temp3], %[x_out], %[x_out_max] \n\t" - "bgez %[temp3], 2f \n\t" - "subu %[accum], %[accum], %[x_sub] \n\t" - "bgez %[accum], 4f \n\t" - "addiu %[temp2], %[temp1], 0 \n\t" - "addu %[src1], %[src1], %[x_stride] \n\t" - "lbu %[temp1], 0(%[src1]) \n\t" - "addu %[accum], %[accum], %[x_add] \n\t" - "4: \n\t" - "b 1b \n\t" - "2: \n\t" - : [src1]"+r"(src1), [accum]"=&r"(accum), [temp1]"=&r"(temp1), - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), - [x_out]"+r"(x_out), [frac]"=&r"(frac), [frow]"+r"(frow) - : [x_stride]"r"(x_stride), [x_add]"r"(x_add), [x_sub]"r"(x_sub), - [x_stride1]"r"(x_stride1), [src_width]"r"(src_width), - [x_out_max]"r"(x_out_max) - : "memory", "hi", "lo" - ); - assert(wrk->x_sub == 0 /* <- special case for src_width=1 */ || accum == 0); - } -} - -//------------------------------------------------------------------------------ -// Row export - -static void ExportRowExpand(WebPRescaler* const wrk) { - uint8_t* dst = wrk->dst; - rescaler_t* irow = wrk->irow; - const int x_out_max = wrk->dst_width * wrk->num_channels; - const rescaler_t* frow = wrk->frow; - int temp0, temp1, temp3, temp4, temp5, loop_end; - const int temp2 = (int)wrk->fy_scale; - const int temp6 = x_out_max << 2; - assert(!WebPRescalerOutputDone(wrk)); - assert(wrk->y_accum <= 0); - assert(wrk->y_expand); - assert(wrk->y_sub != 0); - if (wrk->y_accum == 0) { - __asm__ volatile ( - "li %[temp3], 0x10000 \n\t" - "li %[temp4], 0x8000 \n\t" - "addu %[loop_end], %[frow], %[temp6] \n\t" - "1: \n\t" - "lw %[temp0], 0(%[frow]) \n\t" - "addiu %[dst], %[dst], 1 \n\t" - "addiu %[frow], %[frow], 4 \n\t" - "mult %[temp3], %[temp4] \n\t" - "maddu %[temp0], %[temp2] \n\t" - "mfhi %[temp5] \n\t" - "sb %[temp5], -1(%[dst]) \n\t" - "bne %[frow], %[loop_end], 1b \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), - [dst]"+r"(dst), [loop_end]"=&r"(loop_end) - : [temp2]"r"(temp2), [temp6]"r"(temp6) - : "memory", "hi", "lo" - ); - } else { - const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub); - const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); - __asm__ volatile ( - "li %[temp3], 0x10000 \n\t" - "li %[temp4], 0x8000 \n\t" - "addu %[loop_end], %[frow], %[temp6] \n\t" - "1: \n\t" - "lw %[temp0], 0(%[frow]) \n\t" - "lw %[temp1], 0(%[irow]) \n\t" - "addiu %[dst], %[dst], 1 \n\t" - "mult %[temp3], %[temp4] \n\t" - "maddu %[A], %[temp0] \n\t" - "maddu %[B], %[temp1] \n\t" - "addiu %[frow], %[frow], 4 \n\t" - "addiu %[irow], %[irow], 4 \n\t" - "mfhi %[temp5] \n\t" - "mult %[temp3], %[temp4] \n\t" - "maddu %[temp5], %[temp2] \n\t" - "mfhi %[temp5] \n\t" - "sb %[temp5], -1(%[dst]) \n\t" - "bne %[frow], %[loop_end], 1b \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), - [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end) - : [temp2]"r"(temp2), [temp6]"r"(temp6), [A]"r"(A), [B]"r"(B) - : "memory", "hi", "lo" - ); - } -} - -static void ExportRowShrink(WebPRescaler* const wrk) { - const int x_out_max = wrk->dst_width * wrk->num_channels; - uint8_t* dst = wrk->dst; - rescaler_t* irow = wrk->irow; - const rescaler_t* frow = wrk->frow; - const int yscale = wrk->fy_scale * (-wrk->y_accum); - int temp0, temp1, temp3, temp4, temp5, loop_end; - const int temp2 = (int)wrk->fxy_scale; - const int temp6 = x_out_max << 2; - - assert(!WebPRescalerOutputDone(wrk)); - assert(wrk->y_accum <= 0); - assert(!wrk->y_expand); - assert(wrk->fxy_scale != 0); - if (yscale) { - __asm__ volatile ( - "li %[temp3], 0x10000 \n\t" - "li %[temp4], 0x8000 \n\t" - "addu %[loop_end], %[frow], %[temp6] \n\t" - "1: \n\t" - "lw %[temp0], 0(%[frow]) \n\t" - "mult %[temp3], %[temp4] \n\t" - "addiu %[frow], %[frow], 4 \n\t" - "maddu %[temp0], %[yscale] \n\t" - "mfhi %[temp1] \n\t" - "lw %[temp0], 0(%[irow]) \n\t" - "addiu %[dst], %[dst], 1 \n\t" - "addiu %[irow], %[irow], 4 \n\t" - "subu %[temp0], %[temp0], %[temp1] \n\t" - "mult %[temp3], %[temp4] \n\t" - "maddu %[temp0], %[temp2] \n\t" - "mfhi %[temp5] \n\t" - "sw %[temp1], -4(%[irow]) \n\t" - "sb %[temp5], -1(%[dst]) \n\t" - "bne %[frow], %[loop_end], 1b \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), - [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end) - : [temp2]"r"(temp2), [yscale]"r"(yscale), [temp6]"r"(temp6) - : "memory", "hi", "lo" - ); - } else { - __asm__ volatile ( - "li %[temp3], 0x10000 \n\t" - "li %[temp4], 0x8000 \n\t" - "addu %[loop_end], %[irow], %[temp6] \n\t" - "1: \n\t" - "lw %[temp0], 0(%[irow]) \n\t" - "addiu %[dst], %[dst], 1 \n\t" - "addiu %[irow], %[irow], 4 \n\t" - "mult %[temp3], %[temp4] \n\t" - "maddu %[temp0], %[temp2] \n\t" - "mfhi %[temp5] \n\t" - "sw $zero, -4(%[irow]) \n\t" - "sb %[temp5], -1(%[dst]) \n\t" - "bne %[irow], %[loop_end], 1b \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [irow]"+r"(irow), - [dst]"+r"(dst), [loop_end]"=&r"(loop_end) - : [temp2]"r"(temp2), [temp6]"r"(temp6) - : "memory", "hi", "lo" - ); - } -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void WebPRescalerDspInitMIPS32(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPS32(void) { - WebPRescalerImportRowExpand = ImportRowExpand; - WebPRescalerImportRowShrink = ImportRowShrink; - WebPRescalerExportRowExpand = ExportRowExpand; - WebPRescalerExportRowShrink = ExportRowShrink; -} - -#else // !WEBP_USE_MIPS32 - -WEBP_DSP_INIT_STUB(WebPRescalerDspInitMIPS32) - -#endif // WEBP_USE_MIPS32 diff --git a/Example-Mac/Pods/libwebp/src/dsp/rescaler_mips_dsp_r2.c b/Example-Mac/Pods/libwebp/src/dsp/rescaler_mips_dsp_r2.c deleted file mode 100644 index b457d0a3..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/rescaler_mips_dsp_r2.c +++ /dev/null @@ -1,314 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// MIPS version of rescaling functions -// -// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS_DSP_R2) - -#include -#include "../utils/rescaler.h" - -#define ROUNDER (WEBP_RESCALER_ONE >> 1) -#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) - -//------------------------------------------------------------------------------ -// Row export - -static void ExportRowShrink(WebPRescaler* const wrk) { - int i; - const int x_out_max = wrk->dst_width * wrk->num_channels; - uint8_t* dst = wrk->dst; - rescaler_t* irow = wrk->irow; - const rescaler_t* frow = wrk->frow; - const int yscale = wrk->fy_scale * (-wrk->y_accum); - int temp0, temp1, temp2, temp3, temp4, temp5, loop_end; - const int temp7 = (int)wrk->fxy_scale; - const int temp6 = (x_out_max & ~0x3) << 2; - assert(!WebPRescalerOutputDone(wrk)); - assert(wrk->y_accum <= 0); - assert(!wrk->y_expand); - assert(wrk->fxy_scale != 0); - if (yscale) { - if (x_out_max >= 4) { - int temp8, temp9, temp10, temp11; - __asm__ volatile ( - "li %[temp3], 0x10000 \n\t" - "li %[temp4], 0x8000 \n\t" - "addu %[loop_end], %[frow], %[temp6] \n\t" - "1: \n\t" - "lw %[temp0], 0(%[frow]) \n\t" - "lw %[temp1], 4(%[frow]) \n\t" - "lw %[temp2], 8(%[frow]) \n\t" - "lw %[temp5], 12(%[frow]) \n\t" - "mult $ac0, %[temp3], %[temp4] \n\t" - "maddu $ac0, %[temp0], %[yscale] \n\t" - "mult $ac1, %[temp3], %[temp4] \n\t" - "maddu $ac1, %[temp1], %[yscale] \n\t" - "mult $ac2, %[temp3], %[temp4] \n\t" - "maddu $ac2, %[temp2], %[yscale] \n\t" - "mult $ac3, %[temp3], %[temp4] \n\t" - "maddu $ac3, %[temp5], %[yscale] \n\t" - "addiu %[frow], %[frow], 16 \n\t" - "mfhi %[temp0], $ac0 \n\t" - "mfhi %[temp1], $ac1 \n\t" - "mfhi %[temp2], $ac2 \n\t" - "mfhi %[temp5], $ac3 \n\t" - "lw %[temp8], 0(%[irow]) \n\t" - "lw %[temp9], 4(%[irow]) \n\t" - "lw %[temp10], 8(%[irow]) \n\t" - "lw %[temp11], 12(%[irow]) \n\t" - "addiu %[dst], %[dst], 4 \n\t" - "addiu %[irow], %[irow], 16 \n\t" - "subu %[temp8], %[temp8], %[temp0] \n\t" - "subu %[temp9], %[temp9], %[temp1] \n\t" - "subu %[temp10], %[temp10], %[temp2] \n\t" - "subu %[temp11], %[temp11], %[temp5] \n\t" - "mult $ac0, %[temp3], %[temp4] \n\t" - "maddu $ac0, %[temp8], %[temp7] \n\t" - "mult $ac1, %[temp3], %[temp4] \n\t" - "maddu $ac1, %[temp9], %[temp7] \n\t" - "mult $ac2, %[temp3], %[temp4] \n\t" - "maddu $ac2, %[temp10], %[temp7] \n\t" - "mult $ac3, %[temp3], %[temp4] \n\t" - "maddu $ac3, %[temp11], %[temp7] \n\t" - "mfhi %[temp8], $ac0 \n\t" - "mfhi %[temp9], $ac1 \n\t" - "mfhi %[temp10], $ac2 \n\t" - "mfhi %[temp11], $ac3 \n\t" - "sw %[temp0], -16(%[irow]) \n\t" - "sw %[temp1], -12(%[irow]) \n\t" - "sw %[temp2], -8(%[irow]) \n\t" - "sw %[temp5], -4(%[irow]) \n\t" - "sb %[temp8], -4(%[dst]) \n\t" - "sb %[temp9], -3(%[dst]) \n\t" - "sb %[temp10], -2(%[dst]) \n\t" - "sb %[temp11], -1(%[dst]) \n\t" - "bne %[frow], %[loop_end], 1b \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), - [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end), - [temp8]"=&r"(temp8), [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), - [temp11]"=&r"(temp11), [temp2]"=&r"(temp2) - : [temp7]"r"(temp7), [yscale]"r"(yscale), [temp6]"r"(temp6) - : "memory", "hi", "lo", "$ac1hi", "$ac1lo", - "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo" - ); - } - for (i = 0; i < (x_out_max & 0x3); ++i) { - const uint32_t frac = (uint32_t)MULT_FIX(*frow++, yscale); - const int v = (int)MULT_FIX(*irow - frac, wrk->fxy_scale); - assert(v >= 0 && v <= 255); - *dst++ = v; - *irow++ = frac; // new fractional start - } - } else { - if (x_out_max >= 4) { - __asm__ volatile ( - "li %[temp3], 0x10000 \n\t" - "li %[temp4], 0x8000 \n\t" - "addu %[loop_end], %[irow], %[temp6] \n\t" - "1: \n\t" - "lw %[temp0], 0(%[irow]) \n\t" - "lw %[temp1], 4(%[irow]) \n\t" - "lw %[temp2], 8(%[irow]) \n\t" - "lw %[temp5], 12(%[irow]) \n\t" - "addiu %[dst], %[dst], 4 \n\t" - "addiu %[irow], %[irow], 16 \n\t" - "mult $ac0, %[temp3], %[temp4] \n\t" - "maddu $ac0, %[temp0], %[temp7] \n\t" - "mult $ac1, %[temp3], %[temp4] \n\t" - "maddu $ac1, %[temp1], %[temp7] \n\t" - "mult $ac2, %[temp3], %[temp4] \n\t" - "maddu $ac2, %[temp2], %[temp7] \n\t" - "mult $ac3, %[temp3], %[temp4] \n\t" - "maddu $ac3, %[temp5], %[temp7] \n\t" - "mfhi %[temp0], $ac0 \n\t" - "mfhi %[temp1], $ac1 \n\t" - "mfhi %[temp2], $ac2 \n\t" - "mfhi %[temp5], $ac3 \n\t" - "sw $zero, -16(%[irow]) \n\t" - "sw $zero, -12(%[irow]) \n\t" - "sw $zero, -8(%[irow]) \n\t" - "sw $zero, -4(%[irow]) \n\t" - "sb %[temp0], -4(%[dst]) \n\t" - "sb %[temp1], -3(%[dst]) \n\t" - "sb %[temp2], -2(%[dst]) \n\t" - "sb %[temp5], -1(%[dst]) \n\t" - "bne %[irow], %[loop_end], 1b \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [irow]"+r"(irow), - [dst]"+r"(dst), [loop_end]"=&r"(loop_end), [temp2]"=&r"(temp2) - : [temp7]"r"(temp7), [temp6]"r"(temp6) - : "memory", "hi", "lo", "$ac1hi", "$ac1lo", - "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo" - ); - } - for (i = 0; i < (x_out_max & 0x3); ++i) { - const int v = (int)MULT_FIX(*irow, wrk->fxy_scale); - assert(v >= 0 && v <= 255); - *dst++ = v; - *irow++ = 0; - } - } -} - -static void ExportRowExpand(WebPRescaler* const wrk) { - int i; - uint8_t* dst = wrk->dst; - rescaler_t* irow = wrk->irow; - const int x_out_max = wrk->dst_width * wrk->num_channels; - const rescaler_t* frow = wrk->frow; - int temp0, temp1, temp2, temp3, temp4, temp5, loop_end; - const int temp6 = (x_out_max & ~0x3) << 2; - const int temp7 = (int)wrk->fy_scale; - assert(!WebPRescalerOutputDone(wrk)); - assert(wrk->y_accum <= 0); - assert(wrk->y_expand); - assert(wrk->y_sub != 0); - if (wrk->y_accum == 0) { - if (x_out_max >= 4) { - __asm__ volatile ( - "li %[temp4], 0x10000 \n\t" - "li %[temp5], 0x8000 \n\t" - "addu %[loop_end], %[frow], %[temp6] \n\t" - "1: \n\t" - "lw %[temp0], 0(%[frow]) \n\t" - "lw %[temp1], 4(%[frow]) \n\t" - "lw %[temp2], 8(%[frow]) \n\t" - "lw %[temp3], 12(%[frow]) \n\t" - "addiu %[dst], %[dst], 4 \n\t" - "addiu %[frow], %[frow], 16 \n\t" - "mult $ac0, %[temp4], %[temp5] \n\t" - "maddu $ac0, %[temp0], %[temp7] \n\t" - "mult $ac1, %[temp4], %[temp5] \n\t" - "maddu $ac1, %[temp1], %[temp7] \n\t" - "mult $ac2, %[temp4], %[temp5] \n\t" - "maddu $ac2, %[temp2], %[temp7] \n\t" - "mult $ac3, %[temp4], %[temp5] \n\t" - "maddu $ac3, %[temp3], %[temp7] \n\t" - "mfhi %[temp0], $ac0 \n\t" - "mfhi %[temp1], $ac1 \n\t" - "mfhi %[temp2], $ac2 \n\t" - "mfhi %[temp3], $ac3 \n\t" - "sb %[temp0], -4(%[dst]) \n\t" - "sb %[temp1], -3(%[dst]) \n\t" - "sb %[temp2], -2(%[dst]) \n\t" - "sb %[temp3], -1(%[dst]) \n\t" - "bne %[frow], %[loop_end], 1b \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), - [dst]"+r"(dst), [loop_end]"=&r"(loop_end), [temp2]"=&r"(temp2) - : [temp7]"r"(temp7), [temp6]"r"(temp6) - : "memory", "hi", "lo", "$ac1hi", "$ac1lo", - "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo" - ); - } - for (i = 0; i < (x_out_max & 0x3); ++i) { - const uint32_t J = *frow++; - const int v = (int)MULT_FIX(J, wrk->fy_scale); - assert(v >= 0 && v <= 255); - *dst++ = v; - } - } else { - const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub); - const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); - if (x_out_max >= 4) { - int temp8, temp9, temp10, temp11; - __asm__ volatile ( - "li %[temp8], 0x10000 \n\t" - "li %[temp9], 0x8000 \n\t" - "addu %[loop_end], %[frow], %[temp6] \n\t" - "1: \n\t" - "lw %[temp0], 0(%[frow]) \n\t" - "lw %[temp1], 4(%[frow]) \n\t" - "lw %[temp2], 8(%[frow]) \n\t" - "lw %[temp3], 12(%[frow]) \n\t" - "lw %[temp4], 0(%[irow]) \n\t" - "lw %[temp5], 4(%[irow]) \n\t" - "lw %[temp10], 8(%[irow]) \n\t" - "lw %[temp11], 12(%[irow]) \n\t" - "addiu %[dst], %[dst], 4 \n\t" - "mult $ac0, %[temp8], %[temp9] \n\t" - "maddu $ac0, %[A], %[temp0] \n\t" - "maddu $ac0, %[B], %[temp4] \n\t" - "mult $ac1, %[temp8], %[temp9] \n\t" - "maddu $ac1, %[A], %[temp1] \n\t" - "maddu $ac1, %[B], %[temp5] \n\t" - "mult $ac2, %[temp8], %[temp9] \n\t" - "maddu $ac2, %[A], %[temp2] \n\t" - "maddu $ac2, %[B], %[temp10] \n\t" - "mult $ac3, %[temp8], %[temp9] \n\t" - "maddu $ac3, %[A], %[temp3] \n\t" - "maddu $ac3, %[B], %[temp11] \n\t" - "addiu %[frow], %[frow], 16 \n\t" - "addiu %[irow], %[irow], 16 \n\t" - "mfhi %[temp0], $ac0 \n\t" - "mfhi %[temp1], $ac1 \n\t" - "mfhi %[temp2], $ac2 \n\t" - "mfhi %[temp3], $ac3 \n\t" - "mult $ac0, %[temp8], %[temp9] \n\t" - "maddu $ac0, %[temp0], %[temp7] \n\t" - "mult $ac1, %[temp8], %[temp9] \n\t" - "maddu $ac1, %[temp1], %[temp7] \n\t" - "mult $ac2, %[temp8], %[temp9] \n\t" - "maddu $ac2, %[temp2], %[temp7] \n\t" - "mult $ac3, %[temp8], %[temp9] \n\t" - "maddu $ac3, %[temp3], %[temp7] \n\t" - "mfhi %[temp0], $ac0 \n\t" - "mfhi %[temp1], $ac1 \n\t" - "mfhi %[temp2], $ac2 \n\t" - "mfhi %[temp3], $ac3 \n\t" - "sb %[temp0], -4(%[dst]) \n\t" - "sb %[temp1], -3(%[dst]) \n\t" - "sb %[temp2], -2(%[dst]) \n\t" - "sb %[temp3], -1(%[dst]) \n\t" - "bne %[frow], %[loop_end], 1b \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), - [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end), - [temp8]"=&r"(temp8), [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), - [temp11]"=&r"(temp11), [temp2]"=&r"(temp2) - : [temp7]"r"(temp7), [temp6]"r"(temp6), [A]"r"(A), [B]"r"(B) - : "memory", "hi", "lo", "$ac1hi", "$ac1lo", - "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo" - ); - } - for (i = 0; i < (x_out_max & 0x3); ++i) { - const uint64_t I = (uint64_t)A * *frow++ - + (uint64_t)B * *irow++; - const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX); - const int v = (int)MULT_FIX(J, wrk->fy_scale); - assert(v >= 0 && v <= 255); - *dst++ = v; - } - } -} - -#undef MULT_FIX -#undef ROUNDER - -//------------------------------------------------------------------------------ -// Entry point - -extern void WebPRescalerDspInitMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPSdspR2(void) { - WebPRescalerExportRowExpand = ExportRowExpand; - WebPRescalerExportRowShrink = ExportRowShrink; -} - -#else // !WEBP_USE_MIPS_DSP_R2 - -WEBP_DSP_INIT_STUB(WebPRescalerDspInitMIPSdspR2) - -#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/Example-Mac/Pods/libwebp/src/dsp/rescaler_neon.c b/Example-Mac/Pods/libwebp/src/dsp/rescaler_neon.c deleted file mode 100644 index 16fd450e..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/rescaler_neon.c +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// NEON version of rescaling functions -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_NEON) - -#include -#include -#include "./neon.h" -#include "../utils/rescaler.h" - -#define ROUNDER (WEBP_RESCALER_ONE >> 1) -#define MULT_FIX_C(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) - -#define LOAD_32x4(SRC, DST) const uint32x4_t DST = vld1q_u32((SRC)) -#define LOAD_32x8(SRC, DST0, DST1) \ - LOAD_32x4(SRC + 0, DST0); \ - LOAD_32x4(SRC + 4, DST1) - -#define STORE_32x8(SRC0, SRC1, DST) do { \ - vst1q_u32((DST) + 0, SRC0); \ - vst1q_u32((DST) + 4, SRC1); \ -} while (0); - -#if (WEBP_RESCALER_RFIX == 32) -#define MAKE_HALF_CST(C) vdupq_n_s32((int32_t)((C) >> 1)) -#define MULT_FIX(A, B) /* note: B is actualy scale>>1. See MAKE_HALF_CST */ \ - vreinterpretq_u32_s32(vqrdmulhq_s32(vreinterpretq_s32_u32((A)), (B))) -#else -#error "MULT_FIX/WEBP_RESCALER_RFIX need some more work" -#endif - -static uint32x4_t Interpolate(const rescaler_t* const frow, - const rescaler_t* const irow, - uint32_t A, uint32_t B) { - LOAD_32x4(frow, A0); - LOAD_32x4(irow, B0); - const uint64x2_t C0 = vmull_n_u32(vget_low_u32(A0), A); - const uint64x2_t C1 = vmull_n_u32(vget_high_u32(A0), A); - const uint64x2_t D0 = vmlal_n_u32(C0, vget_low_u32(B0), B); - const uint64x2_t D1 = vmlal_n_u32(C1, vget_high_u32(B0), B); - const uint32x4_t E = vcombine_u32( - vrshrn_n_u64(D0, WEBP_RESCALER_RFIX), - vrshrn_n_u64(D1, WEBP_RESCALER_RFIX)); - return E; -} - -static void RescalerExportRowExpand(WebPRescaler* const wrk) { - int x_out; - uint8_t* const dst = wrk->dst; - rescaler_t* const irow = wrk->irow; - const int x_out_max = wrk->dst_width * wrk->num_channels; - const int max_span = x_out_max & ~7; - const rescaler_t* const frow = wrk->frow; - const uint32_t fy_scale = wrk->fy_scale; - const int32x4_t fy_scale_half = MAKE_HALF_CST(fy_scale); - assert(!WebPRescalerOutputDone(wrk)); - assert(wrk->y_accum <= 0); - assert(wrk->y_expand); - assert(wrk->y_sub != 0); - if (wrk->y_accum == 0) { - for (x_out = 0; x_out < max_span; x_out += 8) { - LOAD_32x4(frow + x_out + 0, A0); - LOAD_32x4(frow + x_out + 4, A1); - const uint32x4_t B0 = MULT_FIX(A0, fy_scale_half); - const uint32x4_t B1 = MULT_FIX(A1, fy_scale_half); - const uint16x4_t C0 = vmovn_u32(B0); - const uint16x4_t C1 = vmovn_u32(B1); - const uint8x8_t D = vmovn_u16(vcombine_u16(C0, C1)); - vst1_u8(dst + x_out, D); - } - for (; x_out < x_out_max; ++x_out) { - const uint32_t J = frow[x_out]; - const int v = (int)MULT_FIX_C(J, fy_scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - } - } else { - const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub); - const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); - for (x_out = 0; x_out < max_span; x_out += 8) { - const uint32x4_t C0 = - Interpolate(frow + x_out + 0, irow + x_out + 0, A, B); - const uint32x4_t C1 = - Interpolate(frow + x_out + 4, irow + x_out + 4, A, B); - const uint32x4_t D0 = MULT_FIX(C0, fy_scale_half); - const uint32x4_t D1 = MULT_FIX(C1, fy_scale_half); - const uint16x4_t E0 = vmovn_u32(D0); - const uint16x4_t E1 = vmovn_u32(D1); - const uint8x8_t F = vmovn_u16(vcombine_u16(E0, E1)); - vst1_u8(dst + x_out, F); - } - for (; x_out < x_out_max; ++x_out) { - const uint64_t I = (uint64_t)A * frow[x_out] - + (uint64_t)B * irow[x_out]; - const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX); - const int v = (int)MULT_FIX_C(J, fy_scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - } - } -} - -static void RescalerExportRowShrink(WebPRescaler* const wrk) { - int x_out; - uint8_t* const dst = wrk->dst; - rescaler_t* const irow = wrk->irow; - const int x_out_max = wrk->dst_width * wrk->num_channels; - const int max_span = x_out_max & ~7; - const rescaler_t* const frow = wrk->frow; - const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum); - const uint32_t fxy_scale = wrk->fxy_scale; - const uint32x4_t zero = vdupq_n_u32(0); - const int32x4_t yscale_half = MAKE_HALF_CST(yscale); - const int32x4_t fxy_scale_half = MAKE_HALF_CST(fxy_scale); - assert(!WebPRescalerOutputDone(wrk)); - assert(wrk->y_accum <= 0); - assert(!wrk->y_expand); - if (yscale) { - for (x_out = 0; x_out < max_span; x_out += 8) { - LOAD_32x8(frow + x_out, in0, in1); - LOAD_32x8(irow + x_out, in2, in3); - const uint32x4_t A0 = MULT_FIX(in0, yscale_half); - const uint32x4_t A1 = MULT_FIX(in1, yscale_half); - const uint32x4_t B0 = vqsubq_u32(in2, A0); - const uint32x4_t B1 = vqsubq_u32(in3, A1); - const uint32x4_t C0 = MULT_FIX(B0, fxy_scale_half); - const uint32x4_t C1 = MULT_FIX(B1, fxy_scale_half); - const uint16x4_t D0 = vmovn_u32(C0); - const uint16x4_t D1 = vmovn_u32(C1); - const uint8x8_t E = vmovn_u16(vcombine_u16(D0, D1)); - vst1_u8(dst + x_out, E); - STORE_32x8(A0, A1, irow + x_out); - } - for (; x_out < x_out_max; ++x_out) { - const uint32_t frac = (uint32_t)MULT_FIX_C(frow[x_out], yscale); - const int v = (int)MULT_FIX_C(irow[x_out] - frac, wrk->fxy_scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - irow[x_out] = frac; // new fractional start - } - } else { - for (x_out = 0; x_out < max_span; x_out += 8) { - LOAD_32x8(irow + x_out, in0, in1); - const uint32x4_t A0 = MULT_FIX(in0, fxy_scale_half); - const uint32x4_t A1 = MULT_FIX(in1, fxy_scale_half); - const uint16x4_t B0 = vmovn_u32(A0); - const uint16x4_t B1 = vmovn_u32(A1); - const uint8x8_t C = vmovn_u16(vcombine_u16(B0, B1)); - vst1_u8(dst + x_out, C); - STORE_32x8(zero, zero, irow + x_out); - } - for (; x_out < x_out_max; ++x_out) { - const int v = (int)MULT_FIX_C(irow[x_out], fxy_scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - irow[x_out] = 0; - } - } -} - -//------------------------------------------------------------------------------ - -extern void WebPRescalerDspInitNEON(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitNEON(void) { - WebPRescalerExportRowExpand = RescalerExportRowExpand; - WebPRescalerExportRowShrink = RescalerExportRowShrink; -} - -#else // !WEBP_USE_NEON - -WEBP_DSP_INIT_STUB(WebPRescalerDspInitNEON) - -#endif // WEBP_USE_NEON diff --git a/Example-Mac/Pods/libwebp/src/dsp/rescaler_sse2.c b/Example-Mac/Pods/libwebp/src/dsp/rescaler_sse2.c deleted file mode 100644 index 5ea4ddb2..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/rescaler_sse2.c +++ /dev/null @@ -1,374 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// SSE2 Rescaling functions -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE2) -#include - -#include -#include "../utils/rescaler.h" - -//------------------------------------------------------------------------------ -// Implementations of critical functions ImportRow / ExportRow - -#define ROUNDER (WEBP_RESCALER_ONE >> 1) -#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) - -// input: 8 bytes ABCDEFGH -> output: A0E0B0F0C0G0D0H0 -static void LoadTwoPixels(const uint8_t* const src, __m128i* out) { - const __m128i zero = _mm_setzero_si128(); - const __m128i A = _mm_loadl_epi64((const __m128i*)(src)); // ABCDEFGH - const __m128i B = _mm_unpacklo_epi8(A, zero); // A0B0C0D0E0F0G0H0 - const __m128i C = _mm_srli_si128(B, 8); // E0F0G0H0 - *out = _mm_unpacklo_epi16(B, C); -} - -// input: 8 bytes ABCDEFGH -> output: A0B0C0D0E0F0G0H0 -static void LoadHeightPixels(const uint8_t* const src, __m128i* out) { - const __m128i zero = _mm_setzero_si128(); - const __m128i A = _mm_loadl_epi64((const __m128i*)(src)); // ABCDEFGH - *out = _mm_unpacklo_epi8(A, zero); -} - -static void RescalerImportRowExpandSSE2(WebPRescaler* const wrk, - const uint8_t* src) { - rescaler_t* frow = wrk->frow; - const rescaler_t* const frow_end = frow + wrk->dst_width * wrk->num_channels; - const int x_add = wrk->x_add; - int accum = x_add; - __m128i cur_pixels; - - assert(!WebPRescalerInputDone(wrk)); - assert(wrk->x_expand); - if (wrk->num_channels == 4) { - if (wrk->src_width < 2) { - WebPRescalerImportRowExpandC(wrk, src); - return; - } - LoadTwoPixels(src, &cur_pixels); - src += 4; - while (1) { - const __m128i mult = _mm_set1_epi32(((x_add - accum) << 16) | accum); - const __m128i out = _mm_madd_epi16(cur_pixels, mult); - _mm_storeu_si128((__m128i*)frow, out); - frow += 4; - if (frow >= frow_end) break; - accum -= wrk->x_sub; - if (accum < 0) { - LoadTwoPixels(src, &cur_pixels); - src += 4; - accum += x_add; - } - } - } else { - int left; - const uint8_t* const src_limit = src + wrk->src_width - 8; - if (wrk->src_width < 8) { - WebPRescalerImportRowExpandC(wrk, src); - return; - } - LoadHeightPixels(src, &cur_pixels); - src += 7; - left = 7; - while (1) { - const __m128i mult = _mm_cvtsi32_si128(((x_add - accum) << 16) | accum); - const __m128i out = _mm_madd_epi16(cur_pixels, mult); - assert(sizeof(*frow) == sizeof(uint32_t)); - WebPUint32ToMem((uint8_t*)frow, _mm_cvtsi128_si32(out)); - frow += 1; - if (frow >= frow_end) break; - accum -= wrk->x_sub; - if (accum < 0) { - if (--left) { - cur_pixels = _mm_srli_si128(cur_pixels, 2); - } else if (src <= src_limit) { - LoadHeightPixels(src, &cur_pixels); - src += 7; - left = 7; - } else { // tail - cur_pixels = _mm_srli_si128(cur_pixels, 2); - cur_pixels = _mm_insert_epi16(cur_pixels, src[1], 1); - src += 1; - left = 1; - } - accum += x_add; - } - } - } - assert(accum == 0); -} - -static void RescalerImportRowShrinkSSE2(WebPRescaler* const wrk, - const uint8_t* src) { - const int x_sub = wrk->x_sub; - int accum = 0; - const __m128i zero = _mm_setzero_si128(); - const __m128i mult0 = _mm_set1_epi16(x_sub); - const __m128i mult1 = _mm_set1_epi32(wrk->fx_scale); - const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER); - __m128i sum = zero; - rescaler_t* frow = wrk->frow; - const rescaler_t* const frow_end = wrk->frow + 4 * wrk->dst_width; - - if (wrk->num_channels != 4 || wrk->x_add > (x_sub << 7)) { - WebPRescalerImportRowShrinkC(wrk, src); - return; - } - assert(!WebPRescalerInputDone(wrk)); - assert(!wrk->x_expand); - - for (; frow < frow_end; frow += 4) { - __m128i base = zero; - accum += wrk->x_add; - while (accum > 0) { - const __m128i A = _mm_cvtsi32_si128(WebPMemToUint32(src)); - src += 4; - base = _mm_unpacklo_epi8(A, zero); - // To avoid overflow, we need: base * x_add / x_sub < 32768 - // => x_add < x_sub << 7. That's a 1/128 reduction ratio limit. - sum = _mm_add_epi16(sum, base); - accum -= x_sub; - } - { // Emit next horizontal pixel. - const __m128i mult = _mm_set1_epi16(-accum); - const __m128i frac0 = _mm_mullo_epi16(base, mult); // 16b x 16b -> 32b - const __m128i frac1 = _mm_mulhi_epu16(base, mult); - const __m128i frac = _mm_unpacklo_epi16(frac0, frac1); // frac is 32b - const __m128i A0 = _mm_mullo_epi16(sum, mult0); - const __m128i A1 = _mm_mulhi_epu16(sum, mult0); - const __m128i B0 = _mm_unpacklo_epi16(A0, A1); // sum * x_sub - const __m128i frow_out = _mm_sub_epi32(B0, frac); // sum * x_sub - frac - const __m128i D0 = _mm_srli_epi64(frac, 32); - const __m128i D1 = _mm_mul_epu32(frac, mult1); // 32b x 16b -> 64b - const __m128i D2 = _mm_mul_epu32(D0, mult1); - const __m128i E1 = _mm_add_epi64(D1, rounder); - const __m128i E2 = _mm_add_epi64(D2, rounder); - const __m128i F1 = _mm_shuffle_epi32(E1, 1 | (3 << 2)); - const __m128i F2 = _mm_shuffle_epi32(E2, 1 | (3 << 2)); - const __m128i G = _mm_unpacklo_epi32(F1, F2); - sum = _mm_packs_epi32(G, zero); - _mm_storeu_si128((__m128i*)frow, frow_out); - } - } - assert(accum == 0); -} - -//------------------------------------------------------------------------------ -// Row export - -// load *src as epi64, multiply by mult and store result in [out0 ... out3] -static WEBP_INLINE void LoadDispatchAndMult(const rescaler_t* const src, - const __m128i* const mult, - __m128i* const out0, - __m128i* const out1, - __m128i* const out2, - __m128i* const out3) { - const __m128i A0 = _mm_loadu_si128((const __m128i*)(src + 0)); - const __m128i A1 = _mm_loadu_si128((const __m128i*)(src + 4)); - const __m128i A2 = _mm_srli_epi64(A0, 32); - const __m128i A3 = _mm_srli_epi64(A1, 32); - if (mult != NULL) { - *out0 = _mm_mul_epu32(A0, *mult); - *out1 = _mm_mul_epu32(A1, *mult); - *out2 = _mm_mul_epu32(A2, *mult); - *out3 = _mm_mul_epu32(A3, *mult); - } else { - *out0 = A0; - *out1 = A1; - *out2 = A2; - *out3 = A3; - } -} - -static WEBP_INLINE void ProcessRow(const __m128i* const A0, - const __m128i* const A1, - const __m128i* const A2, - const __m128i* const A3, - const __m128i* const mult, - uint8_t* const dst) { - const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER); - const __m128i mask = _mm_set_epi32(0xffffffffu, 0, 0xffffffffu, 0); - const __m128i B0 = _mm_mul_epu32(*A0, *mult); - const __m128i B1 = _mm_mul_epu32(*A1, *mult); - const __m128i B2 = _mm_mul_epu32(*A2, *mult); - const __m128i B3 = _mm_mul_epu32(*A3, *mult); - const __m128i C0 = _mm_add_epi64(B0, rounder); - const __m128i C1 = _mm_add_epi64(B1, rounder); - const __m128i C2 = _mm_add_epi64(B2, rounder); - const __m128i C3 = _mm_add_epi64(B3, rounder); - const __m128i D0 = _mm_srli_epi64(C0, WEBP_RESCALER_RFIX); - const __m128i D1 = _mm_srli_epi64(C1, WEBP_RESCALER_RFIX); -#if (WEBP_RESCALER_FIX < 32) - const __m128i D2 = - _mm_and_si128(_mm_slli_epi64(C2, 32 - WEBP_RESCALER_RFIX), mask); - const __m128i D3 = - _mm_and_si128(_mm_slli_epi64(C3, 32 - WEBP_RESCALER_RFIX), mask); -#else - const __m128i D2 = _mm_and_si128(C2, mask); - const __m128i D3 = _mm_and_si128(C3, mask); -#endif - const __m128i E0 = _mm_or_si128(D0, D2); - const __m128i E1 = _mm_or_si128(D1, D3); - const __m128i F = _mm_packs_epi32(E0, E1); - const __m128i G = _mm_packus_epi16(F, F); - _mm_storel_epi64((__m128i*)dst, G); -} - -static void RescalerExportRowExpandSSE2(WebPRescaler* const wrk) { - int x_out; - uint8_t* const dst = wrk->dst; - rescaler_t* const irow = wrk->irow; - const int x_out_max = wrk->dst_width * wrk->num_channels; - const rescaler_t* const frow = wrk->frow; - const __m128i mult = _mm_set_epi32(0, wrk->fy_scale, 0, wrk->fy_scale); - - assert(!WebPRescalerOutputDone(wrk)); - assert(wrk->y_accum <= 0 && wrk->y_sub + wrk->y_accum >= 0); - assert(wrk->y_expand); - if (wrk->y_accum == 0) { - for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) { - __m128i A0, A1, A2, A3; - LoadDispatchAndMult(frow + x_out, NULL, &A0, &A1, &A2, &A3); - ProcessRow(&A0, &A1, &A2, &A3, &mult, dst + x_out); - } - for (; x_out < x_out_max; ++x_out) { - const uint32_t J = frow[x_out]; - const int v = (int)MULT_FIX(J, wrk->fy_scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - } - } else { - const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub); - const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); - const __m128i mA = _mm_set_epi32(0, A, 0, A); - const __m128i mB = _mm_set_epi32(0, B, 0, B); - const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER); - for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) { - __m128i A0, A1, A2, A3, B0, B1, B2, B3; - LoadDispatchAndMult(frow + x_out, &mA, &A0, &A1, &A2, &A3); - LoadDispatchAndMult(irow + x_out, &mB, &B0, &B1, &B2, &B3); - { - const __m128i C0 = _mm_add_epi64(A0, B0); - const __m128i C1 = _mm_add_epi64(A1, B1); - const __m128i C2 = _mm_add_epi64(A2, B2); - const __m128i C3 = _mm_add_epi64(A3, B3); - const __m128i D0 = _mm_add_epi64(C0, rounder); - const __m128i D1 = _mm_add_epi64(C1, rounder); - const __m128i D2 = _mm_add_epi64(C2, rounder); - const __m128i D3 = _mm_add_epi64(C3, rounder); - const __m128i E0 = _mm_srli_epi64(D0, WEBP_RESCALER_RFIX); - const __m128i E1 = _mm_srli_epi64(D1, WEBP_RESCALER_RFIX); - const __m128i E2 = _mm_srli_epi64(D2, WEBP_RESCALER_RFIX); - const __m128i E3 = _mm_srli_epi64(D3, WEBP_RESCALER_RFIX); - ProcessRow(&E0, &E1, &E2, &E3, &mult, dst + x_out); - } - } - for (; x_out < x_out_max; ++x_out) { - const uint64_t I = (uint64_t)A * frow[x_out] - + (uint64_t)B * irow[x_out]; - const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX); - const int v = (int)MULT_FIX(J, wrk->fy_scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - } - } -} - -static void RescalerExportRowShrinkSSE2(WebPRescaler* const wrk) { - int x_out; - uint8_t* const dst = wrk->dst; - rescaler_t* const irow = wrk->irow; - const int x_out_max = wrk->dst_width * wrk->num_channels; - const rescaler_t* const frow = wrk->frow; - const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum); - assert(!WebPRescalerOutputDone(wrk)); - assert(wrk->y_accum <= 0); - assert(!wrk->y_expand); - if (yscale) { - const int scale_xy = wrk->fxy_scale; - const __m128i mult_xy = _mm_set_epi32(0, scale_xy, 0, scale_xy); - const __m128i mult_y = _mm_set_epi32(0, yscale, 0, yscale); - const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER); - for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) { - __m128i A0, A1, A2, A3, B0, B1, B2, B3; - LoadDispatchAndMult(irow + x_out, NULL, &A0, &A1, &A2, &A3); - LoadDispatchAndMult(frow + x_out, &mult_y, &B0, &B1, &B2, &B3); - { - const __m128i C0 = _mm_add_epi64(B0, rounder); - const __m128i C1 = _mm_add_epi64(B1, rounder); - const __m128i C2 = _mm_add_epi64(B2, rounder); - const __m128i C3 = _mm_add_epi64(B3, rounder); - const __m128i D0 = _mm_srli_epi64(C0, WEBP_RESCALER_RFIX); // = frac - const __m128i D1 = _mm_srli_epi64(C1, WEBP_RESCALER_RFIX); - const __m128i D2 = _mm_srli_epi64(C2, WEBP_RESCALER_RFIX); - const __m128i D3 = _mm_srli_epi64(C3, WEBP_RESCALER_RFIX); - const __m128i E0 = _mm_sub_epi64(A0, D0); // irow[x] - frac - const __m128i E1 = _mm_sub_epi64(A1, D1); - const __m128i E2 = _mm_sub_epi64(A2, D2); - const __m128i E3 = _mm_sub_epi64(A3, D3); - const __m128i F2 = _mm_slli_epi64(D2, 32); - const __m128i F3 = _mm_slli_epi64(D3, 32); - const __m128i G0 = _mm_or_si128(D0, F2); - const __m128i G1 = _mm_or_si128(D1, F3); - _mm_storeu_si128((__m128i*)(irow + x_out + 0), G0); - _mm_storeu_si128((__m128i*)(irow + x_out + 4), G1); - ProcessRow(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out); - } - } - for (; x_out < x_out_max; ++x_out) { - const uint32_t frac = (int)MULT_FIX(frow[x_out], yscale); - const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - irow[x_out] = frac; // new fractional start - } - } else { - const uint32_t scale = wrk->fxy_scale; - const __m128i mult = _mm_set_epi32(0, scale, 0, scale); - const __m128i zero = _mm_setzero_si128(); - for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) { - __m128i A0, A1, A2, A3; - LoadDispatchAndMult(irow + x_out, NULL, &A0, &A1, &A2, &A3); - _mm_storeu_si128((__m128i*)(irow + x_out + 0), zero); - _mm_storeu_si128((__m128i*)(irow + x_out + 4), zero); - ProcessRow(&A0, &A1, &A2, &A3, &mult, dst + x_out); - } - for (; x_out < x_out_max; ++x_out) { - const int v = (int)MULT_FIX(irow[x_out], scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - irow[x_out] = 0; - } - } -} - -#undef MULT_FIX -#undef ROUNDER - -//------------------------------------------------------------------------------ - -extern void WebPRescalerDspInitSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitSSE2(void) { - WebPRescalerImportRowExpand = RescalerImportRowExpandSSE2; - WebPRescalerImportRowShrink = RescalerImportRowShrinkSSE2; - WebPRescalerExportRowExpand = RescalerExportRowExpandSSE2; - WebPRescalerExportRowShrink = RescalerExportRowShrinkSSE2; -} - -#else // !WEBP_USE_SSE2 - -WEBP_DSP_INIT_STUB(WebPRescalerDspInitSSE2) - -#endif // WEBP_USE_SSE2 diff --git a/Example-Mac/Pods/libwebp/src/dsp/upsampling.c b/Example-Mac/Pods/libwebp/src/dsp/upsampling.c deleted file mode 100644 index 651274fc..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/upsampling.c +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// YUV to RGB upsampling functions. -// -// Author: somnath@google.com (Somnath Banerjee) - -#include "./dsp.h" -#include "./yuv.h" - -#include - -//------------------------------------------------------------------------------ -// Fancy upsampler - -#ifdef FANCY_UPSAMPLING - -// Fancy upsampling functions to convert YUV to RGB -WebPUpsampleLinePairFunc WebPUpsamplers[MODE_LAST]; - -// Given samples laid out in a square as: -// [a b] -// [c d] -// we interpolate u/v as: -// ([9*a + 3*b + 3*c + d 3*a + 9*b + 3*c + d] + [8 8]) / 16 -// ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16 - -// We process u and v together stashed into 32bit (16bit each). -#define LOAD_UV(u, v) ((u) | ((v) << 16)) - -#define UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ -static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ - const uint8_t* top_u, const uint8_t* top_v, \ - const uint8_t* cur_u, const uint8_t* cur_v, \ - uint8_t* top_dst, uint8_t* bottom_dst, int len) { \ - int x; \ - const int last_pixel_pair = (len - 1) >> 1; \ - uint32_t tl_uv = LOAD_UV(top_u[0], top_v[0]); /* top-left sample */ \ - uint32_t l_uv = LOAD_UV(cur_u[0], cur_v[0]); /* left-sample */ \ - assert(top_y != NULL); \ - { \ - const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ - FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \ - } \ - if (bottom_y != NULL) { \ - const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ - FUNC(bottom_y[0], uv0 & 0xff, (uv0 >> 16), bottom_dst); \ - } \ - for (x = 1; x <= last_pixel_pair; ++x) { \ - const uint32_t t_uv = LOAD_UV(top_u[x], top_v[x]); /* top sample */ \ - const uint32_t uv = LOAD_UV(cur_u[x], cur_v[x]); /* sample */ \ - /* precompute invariant values associated with first and second diagonals*/\ - const uint32_t avg = tl_uv + t_uv + l_uv + uv + 0x00080008u; \ - const uint32_t diag_12 = (avg + 2 * (t_uv + l_uv)) >> 3; \ - const uint32_t diag_03 = (avg + 2 * (tl_uv + uv)) >> 3; \ - { \ - const uint32_t uv0 = (diag_12 + tl_uv) >> 1; \ - const uint32_t uv1 = (diag_03 + t_uv) >> 1; \ - FUNC(top_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ - top_dst + (2 * x - 1) * XSTEP); \ - FUNC(top_y[2 * x - 0], uv1 & 0xff, (uv1 >> 16), \ - top_dst + (2 * x - 0) * XSTEP); \ - } \ - if (bottom_y != NULL) { \ - const uint32_t uv0 = (diag_03 + l_uv) >> 1; \ - const uint32_t uv1 = (diag_12 + uv) >> 1; \ - FUNC(bottom_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ - bottom_dst + (2 * x - 1) * XSTEP); \ - FUNC(bottom_y[2 * x + 0], uv1 & 0xff, (uv1 >> 16), \ - bottom_dst + (2 * x + 0) * XSTEP); \ - } \ - tl_uv = t_uv; \ - l_uv = uv; \ - } \ - if (!(len & 1)) { \ - { \ - const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ - FUNC(top_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ - top_dst + (len - 1) * XSTEP); \ - } \ - if (bottom_y != NULL) { \ - const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ - FUNC(bottom_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ - bottom_dst + (len - 1) * XSTEP); \ - } \ - } \ -} - -// All variants implemented. -UPSAMPLE_FUNC(UpsampleRgbLinePair, VP8YuvToRgb, 3) -UPSAMPLE_FUNC(UpsampleBgrLinePair, VP8YuvToBgr, 3) -UPSAMPLE_FUNC(UpsampleRgbaLinePair, VP8YuvToRgba, 4) -UPSAMPLE_FUNC(UpsampleBgraLinePair, VP8YuvToBgra, 4) -UPSAMPLE_FUNC(UpsampleArgbLinePair, VP8YuvToArgb, 4) -UPSAMPLE_FUNC(UpsampleRgba4444LinePair, VP8YuvToRgba4444, 2) -UPSAMPLE_FUNC(UpsampleRgb565LinePair, VP8YuvToRgb565, 2) - -#undef LOAD_UV -#undef UPSAMPLE_FUNC - -#endif // FANCY_UPSAMPLING - -//------------------------------------------------------------------------------ - -#if !defined(FANCY_UPSAMPLING) -#define DUAL_SAMPLE_FUNC(FUNC_NAME, FUNC) \ -static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bot_y, \ - const uint8_t* top_u, const uint8_t* top_v, \ - const uint8_t* bot_u, const uint8_t* bot_v, \ - uint8_t* top_dst, uint8_t* bot_dst, int len) { \ - const int half_len = len >> 1; \ - int x; \ - assert(top_dst != NULL); \ - { \ - for (x = 0; x < half_len; ++x) { \ - FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x + 0); \ - FUNC(top_y[2 * x + 1], top_u[x], top_v[x], top_dst + 8 * x + 4); \ - } \ - if (len & 1) FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x); \ - } \ - if (bot_dst != NULL) { \ - for (x = 0; x < half_len; ++x) { \ - FUNC(bot_y[2 * x + 0], bot_u[x], bot_v[x], bot_dst + 8 * x + 0); \ - FUNC(bot_y[2 * x + 1], bot_u[x], bot_v[x], bot_dst + 8 * x + 4); \ - } \ - if (len & 1) FUNC(bot_y[2 * x + 0], bot_u[x], bot_v[x], bot_dst + 8 * x); \ - } \ -} - -DUAL_SAMPLE_FUNC(DualLineSamplerBGRA, VP8YuvToBgra) -DUAL_SAMPLE_FUNC(DualLineSamplerARGB, VP8YuvToArgb) -#undef DUAL_SAMPLE_FUNC - -#endif // !FANCY_UPSAMPLING - -WebPUpsampleLinePairFunc WebPGetLinePairConverter(int alpha_is_last) { - WebPInitUpsamplers(); - VP8YUVInit(); -#ifdef FANCY_UPSAMPLING - return WebPUpsamplers[alpha_is_last ? MODE_BGRA : MODE_ARGB]; -#else - return (alpha_is_last ? DualLineSamplerBGRA : DualLineSamplerARGB); -#endif -} - -//------------------------------------------------------------------------------ -// YUV444 converter - -#define YUV444_FUNC(FUNC_NAME, FUNC, XSTEP) \ -extern void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ - uint8_t* dst, int len); \ -void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ - uint8_t* dst, int len) { \ - int i; \ - for (i = 0; i < len; ++i) FUNC(y[i], u[i], v[i], &dst[i * XSTEP]); \ -} - -YUV444_FUNC(WebPYuv444ToRgbC, VP8YuvToRgb, 3) -YUV444_FUNC(WebPYuv444ToBgrC, VP8YuvToBgr, 3) -YUV444_FUNC(WebPYuv444ToRgbaC, VP8YuvToRgba, 4) -YUV444_FUNC(WebPYuv444ToBgraC, VP8YuvToBgra, 4) -YUV444_FUNC(WebPYuv444ToArgbC, VP8YuvToArgb, 4) -YUV444_FUNC(WebPYuv444ToRgba4444C, VP8YuvToRgba4444, 2) -YUV444_FUNC(WebPYuv444ToRgb565C, VP8YuvToRgb565, 2) - -#undef YUV444_FUNC - -WebPYUV444Converter WebPYUV444Converters[MODE_LAST]; - -extern void WebPInitYUV444ConvertersMIPSdspR2(void); -extern void WebPInitYUV444ConvertersSSE2(void); - -static volatile VP8CPUInfo upsampling_last_cpuinfo_used1 = - (VP8CPUInfo)&upsampling_last_cpuinfo_used1; - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444Converters(void) { - if (upsampling_last_cpuinfo_used1 == VP8GetCPUInfo) return; - - WebPYUV444Converters[MODE_RGB] = WebPYuv444ToRgbC; - WebPYUV444Converters[MODE_RGBA] = WebPYuv444ToRgbaC; - WebPYUV444Converters[MODE_BGR] = WebPYuv444ToBgrC; - WebPYUV444Converters[MODE_BGRA] = WebPYuv444ToBgraC; - WebPYUV444Converters[MODE_ARGB] = WebPYuv444ToArgbC; - WebPYUV444Converters[MODE_RGBA_4444] = WebPYuv444ToRgba4444C; - WebPYUV444Converters[MODE_RGB_565] = WebPYuv444ToRgb565C; - WebPYUV444Converters[MODE_rgbA] = WebPYuv444ToRgbaC; - WebPYUV444Converters[MODE_bgrA] = WebPYuv444ToBgraC; - WebPYUV444Converters[MODE_Argb] = WebPYuv444ToArgbC; - WebPYUV444Converters[MODE_rgbA_4444] = WebPYuv444ToRgba4444C; - - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - WebPInitYUV444ConvertersSSE2(); - } -#endif -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - WebPInitYUV444ConvertersMIPSdspR2(); - } -#endif - } - upsampling_last_cpuinfo_used1 = VP8GetCPUInfo; -} - -//------------------------------------------------------------------------------ -// Main calls - -extern void WebPInitUpsamplersSSE2(void); -extern void WebPInitUpsamplersNEON(void); -extern void WebPInitUpsamplersMIPSdspR2(void); - -static volatile VP8CPUInfo upsampling_last_cpuinfo_used2 = - (VP8CPUInfo)&upsampling_last_cpuinfo_used2; - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplers(void) { - if (upsampling_last_cpuinfo_used2 == VP8GetCPUInfo) return; - -#ifdef FANCY_UPSAMPLING - WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; - WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; - WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair; - WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair; - WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair; - - // If defined, use CPUInfo() to overwrite some pointers with faster versions. - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - WebPInitUpsamplersSSE2(); - } -#endif -#if defined(WEBP_USE_NEON) - if (VP8GetCPUInfo(kNEON)) { - WebPInitUpsamplersNEON(); - } -#endif -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - WebPInitUpsamplersMIPSdspR2(); - } -#endif - } -#endif // FANCY_UPSAMPLING - upsampling_last_cpuinfo_used2 = VP8GetCPUInfo; -} - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/dsp/upsampling_mips_dsp_r2.c b/Example-Mac/Pods/libwebp/src/dsp/upsampling_mips_dsp_r2.c deleted file mode 100644 index d4ccbe0a..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/upsampling_mips_dsp_r2.c +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// YUV to RGB upsampling functions. -// -// Author(s): Branimir Vasic (branimir.vasic@imgtec.com) -// Djordje Pesut (djordje.pesut@imgtec.com) - -#include "./dsp.h" - -// Code is disabled for now, in favor of the plain-C version -// TODO(djordje.pesut): adapt the code to reflect the C-version. -#if 0 // defined(WEBP_USE_MIPS_DSP_R2) - -#include -#include "./yuv.h" - -#if !defined(WEBP_YUV_USE_TABLE) - -#define YUV_TO_RGB(Y, U, V, R, G, B) do { \ - const int t1 = kYScale * Y; \ - const int t2 = kVToG * V; \ - R = kVToR * V; \ - G = kUToG * U; \ - B = kUToB * U; \ - R = t1 + R; \ - G = t1 - G; \ - B = t1 + B; \ - R = R + kRCst; \ - G = G - t2 + kGCst; \ - B = B + kBCst; \ - __asm__ volatile ( \ - "shll_s.w %[" #R "], %[" #R "], 9 \n\t" \ - "shll_s.w %[" #G "], %[" #G "], 9 \n\t" \ - "shll_s.w %[" #B "], %[" #B "], 9 \n\t" \ - "precrqu_s.qb.ph %[" #R "], %[" #R "], $zero \n\t" \ - "precrqu_s.qb.ph %[" #G "], %[" #G "], $zero \n\t" \ - "precrqu_s.qb.ph %[" #B "], %[" #B "], $zero \n\t" \ - "srl %[" #R "], %[" #R "], 24 \n\t" \ - "srl %[" #G "], %[" #G "], 24 \n\t" \ - "srl %[" #B "], %[" #B "], 24 \n\t" \ - : [R]"+r"(R), [G]"+r"(G), [B]"+r"(B) \ - : \ - ); \ - } while (0) - -static WEBP_INLINE void YuvToRgb(int y, int u, int v, uint8_t* const rgb) { - int r, g, b; - YUV_TO_RGB(y, u, v, r, g, b); - rgb[0] = r; - rgb[1] = g; - rgb[2] = b; -} -static WEBP_INLINE void YuvToBgr(int y, int u, int v, uint8_t* const bgr) { - int r, g, b; - YUV_TO_RGB(y, u, v, r, g, b); - bgr[0] = b; - bgr[1] = g; - bgr[2] = r; -} -static WEBP_INLINE void YuvToRgb565(int y, int u, int v, uint8_t* const rgb) { - int r, g, b; - YUV_TO_RGB(y, u, v, r, g, b); - { - const int rg = (r & 0xf8) | (g >> 5); - const int gb = ((g << 3) & 0xe0) | (b >> 3); -#ifdef WEBP_SWAP_16BIT_CSP - rgb[0] = gb; - rgb[1] = rg; -#else - rgb[0] = rg; - rgb[1] = gb; -#endif - } -} -static WEBP_INLINE void YuvToRgba4444(int y, int u, int v, - uint8_t* const argb) { - int r, g, b; - YUV_TO_RGB(y, u, v, r, g, b); - { - const int rg = (r & 0xf0) | (g >> 4); - const int ba = (b & 0xf0) | 0x0f; // overwrite the lower 4 bits -#ifdef WEBP_SWAP_16BIT_CSP - argb[0] = ba; - argb[1] = rg; -#else - argb[0] = rg; - argb[1] = ba; -#endif - } -} -#endif // WEBP_YUV_USE_TABLE - -//----------------------------------------------------------------------------- -// Alpha handling variants - -static WEBP_INLINE void YuvToArgb(uint8_t y, uint8_t u, uint8_t v, - uint8_t* const argb) { - int r, g, b; - YUV_TO_RGB(y, u, v, r, g, b); - argb[0] = 0xff; - argb[1] = r; - argb[2] = g; - argb[3] = b; -} -static WEBP_INLINE void YuvToBgra(uint8_t y, uint8_t u, uint8_t v, - uint8_t* const bgra) { - int r, g, b; - YUV_TO_RGB(y, u, v, r, g, b); - bgra[0] = b; - bgra[1] = g; - bgra[2] = r; - bgra[3] = 0xff; -} -static WEBP_INLINE void YuvToRgba(uint8_t y, uint8_t u, uint8_t v, - uint8_t* const rgba) { - int r, g, b; - YUV_TO_RGB(y, u, v, r, g, b); - rgba[0] = r; - rgba[1] = g; - rgba[2] = b; - rgba[3] = 0xff; -} - -//------------------------------------------------------------------------------ -// Fancy upsampler - -#ifdef FANCY_UPSAMPLING - -// Given samples laid out in a square as: -// [a b] -// [c d] -// we interpolate u/v as: -// ([9*a + 3*b + 3*c + d 3*a + 9*b + 3*c + d] + [8 8]) / 16 -// ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16 - -// We process u and v together stashed into 32bit (16bit each). -#define LOAD_UV(u, v) ((u) | ((v) << 16)) - -#define UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ -static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ - const uint8_t* top_u, const uint8_t* top_v, \ - const uint8_t* cur_u, const uint8_t* cur_v, \ - uint8_t* top_dst, uint8_t* bottom_dst, int len) { \ - int x; \ - const int last_pixel_pair = (len - 1) >> 1; \ - uint32_t tl_uv = LOAD_UV(top_u[0], top_v[0]); /* top-left sample */ \ - uint32_t l_uv = LOAD_UV(cur_u[0], cur_v[0]); /* left-sample */ \ - assert(top_y != NULL); \ - { \ - const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ - FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \ - } \ - if (bottom_y != NULL) { \ - const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ - FUNC(bottom_y[0], uv0 & 0xff, (uv0 >> 16), bottom_dst); \ - } \ - for (x = 1; x <= last_pixel_pair; ++x) { \ - const uint32_t t_uv = LOAD_UV(top_u[x], top_v[x]); /* top sample */ \ - const uint32_t uv = LOAD_UV(cur_u[x], cur_v[x]); /* sample */ \ - /* precompute invariant values associated with first and second diagonals*/\ - const uint32_t avg = tl_uv + t_uv + l_uv + uv + 0x00080008u; \ - const uint32_t diag_12 = (avg + 2 * (t_uv + l_uv)) >> 3; \ - const uint32_t diag_03 = (avg + 2 * (tl_uv + uv)) >> 3; \ - { \ - const uint32_t uv0 = (diag_12 + tl_uv) >> 1; \ - const uint32_t uv1 = (diag_03 + t_uv) >> 1; \ - FUNC(top_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ - top_dst + (2 * x - 1) * XSTEP); \ - FUNC(top_y[2 * x - 0], uv1 & 0xff, (uv1 >> 16), \ - top_dst + (2 * x - 0) * XSTEP); \ - } \ - if (bottom_y != NULL) { \ - const uint32_t uv0 = (diag_03 + l_uv) >> 1; \ - const uint32_t uv1 = (diag_12 + uv) >> 1; \ - FUNC(bottom_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ - bottom_dst + (2 * x - 1) * XSTEP); \ - FUNC(bottom_y[2 * x + 0], uv1 & 0xff, (uv1 >> 16), \ - bottom_dst + (2 * x + 0) * XSTEP); \ - } \ - tl_uv = t_uv; \ - l_uv = uv; \ - } \ - if (!(len & 1)) { \ - { \ - const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ - FUNC(top_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ - top_dst + (len - 1) * XSTEP); \ - } \ - if (bottom_y != NULL) { \ - const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ - FUNC(bottom_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ - bottom_dst + (len - 1) * XSTEP); \ - } \ - } \ -} - -// All variants implemented. -UPSAMPLE_FUNC(UpsampleRgbLinePair, YuvToRgb, 3) -UPSAMPLE_FUNC(UpsampleBgrLinePair, YuvToBgr, 3) -UPSAMPLE_FUNC(UpsampleRgbaLinePair, YuvToRgba, 4) -UPSAMPLE_FUNC(UpsampleBgraLinePair, YuvToBgra, 4) -UPSAMPLE_FUNC(UpsampleArgbLinePair, YuvToArgb, 4) -UPSAMPLE_FUNC(UpsampleRgba4444LinePair, YuvToRgba4444, 2) -UPSAMPLE_FUNC(UpsampleRgb565LinePair, YuvToRgb565, 2) - -#undef LOAD_UV -#undef UPSAMPLE_FUNC - -//------------------------------------------------------------------------------ -// Entry point - -extern void WebPInitUpsamplersMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersMIPSdspR2(void) { - WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; - WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; - WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair; - WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair; - WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair; -} - -#endif // FANCY_UPSAMPLING - -//------------------------------------------------------------------------------ -// YUV444 converter - -#define YUV444_FUNC(FUNC_NAME, FUNC, XSTEP) \ -static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ - uint8_t* dst, int len) { \ - int i; \ - for (i = 0; i < len; ++i) FUNC(y[i], u[i], v[i], &dst[i * XSTEP]); \ -} - -YUV444_FUNC(Yuv444ToRgb, YuvToRgb, 3) -YUV444_FUNC(Yuv444ToBgr, YuvToBgr, 3) -YUV444_FUNC(Yuv444ToRgba, YuvToRgba, 4) -YUV444_FUNC(Yuv444ToBgra, YuvToBgra, 4) -YUV444_FUNC(Yuv444ToArgb, YuvToArgb, 4) -YUV444_FUNC(Yuv444ToRgba4444, YuvToRgba4444, 2) -YUV444_FUNC(Yuv444ToRgb565, YuvToRgb565, 2) - -#undef YUV444_FUNC - -//------------------------------------------------------------------------------ -// Entry point - -extern void WebPInitYUV444ConvertersMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444ConvertersMIPSdspR2(void) { - WebPYUV444Converters[MODE_RGB] = Yuv444ToRgb; - WebPYUV444Converters[MODE_RGBA] = Yuv444ToRgba; - WebPYUV444Converters[MODE_BGR] = Yuv444ToBgr; - WebPYUV444Converters[MODE_BGRA] = Yuv444ToBgra; - WebPYUV444Converters[MODE_ARGB] = Yuv444ToArgb; - WebPYUV444Converters[MODE_RGBA_4444] = Yuv444ToRgba4444; - WebPYUV444Converters[MODE_RGB_565] = Yuv444ToRgb565; - WebPYUV444Converters[MODE_rgbA] = Yuv444ToRgba; - WebPYUV444Converters[MODE_bgrA] = Yuv444ToBgra; - WebPYUV444Converters[MODE_Argb] = Yuv444ToArgb; - WebPYUV444Converters[MODE_rgbA_4444] = Yuv444ToRgba4444; -} - -#else // !WEBP_USE_MIPS_DSP_R2 - -WEBP_DSP_INIT_STUB(WebPInitYUV444ConvertersMIPSdspR2) - -#endif // WEBP_USE_MIPS_DSP_R2 - -#if 1 // !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_MIPS_DSP_R2)) -WEBP_DSP_INIT_STUB(WebPInitUpsamplersMIPSdspR2) -#endif diff --git a/Example-Mac/Pods/libwebp/src/dsp/upsampling_neon.c b/Example-Mac/Pods/libwebp/src/dsp/upsampling_neon.c deleted file mode 100644 index 2b0c99bd..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/upsampling_neon.c +++ /dev/null @@ -1,300 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// NEON version of YUV to RGB upsampling functions. -// -// Author: mans@mansr.com (Mans Rullgard) -// Based on SSE code by: somnath@google.com (Somnath Banerjee) - -#include "./dsp.h" - -#if defined(WEBP_USE_NEON) - -#include -#include -#include -#include "./neon.h" -#include "./yuv.h" - -#ifdef FANCY_UPSAMPLING - -//----------------------------------------------------------------------------- -// U/V upsampling - -// Loads 9 pixels each from rows r1 and r2 and generates 16 pixels. -#define UPSAMPLE_16PIXELS(r1, r2, out) { \ - uint8x8_t a = vld1_u8(r1); \ - uint8x8_t b = vld1_u8(r1 + 1); \ - uint8x8_t c = vld1_u8(r2); \ - uint8x8_t d = vld1_u8(r2 + 1); \ - \ - uint16x8_t al = vshll_n_u8(a, 1); \ - uint16x8_t bl = vshll_n_u8(b, 1); \ - uint16x8_t cl = vshll_n_u8(c, 1); \ - uint16x8_t dl = vshll_n_u8(d, 1); \ - \ - uint8x8_t diag1, diag2; \ - uint16x8_t sl; \ - \ - /* a + b + c + d */ \ - sl = vaddl_u8(a, b); \ - sl = vaddw_u8(sl, c); \ - sl = vaddw_u8(sl, d); \ - \ - al = vaddq_u16(sl, al); /* 3a + b + c + d */ \ - bl = vaddq_u16(sl, bl); /* a + 3b + c + d */ \ - \ - al = vaddq_u16(al, dl); /* 3a + b + c + 3d */ \ - bl = vaddq_u16(bl, cl); /* a + 3b + 3c + d */ \ - \ - diag2 = vshrn_n_u16(al, 3); \ - diag1 = vshrn_n_u16(bl, 3); \ - \ - a = vrhadd_u8(a, diag1); \ - b = vrhadd_u8(b, diag2); \ - c = vrhadd_u8(c, diag2); \ - d = vrhadd_u8(d, diag1); \ - \ - { \ - uint8x8x2_t a_b, c_d; \ - INIT_VECTOR2(a_b, a, b); \ - INIT_VECTOR2(c_d, c, d); \ - vst2_u8(out, a_b); \ - vst2_u8(out + 32, c_d); \ - } \ -} - -// Turn the macro into a function for reducing code-size when non-critical -static void Upsample16Pixels(const uint8_t *r1, const uint8_t *r2, - uint8_t *out) { - UPSAMPLE_16PIXELS(r1, r2, out); -} - -#define UPSAMPLE_LAST_BLOCK(tb, bb, num_pixels, out) { \ - uint8_t r1[9], r2[9]; \ - memcpy(r1, (tb), (num_pixels)); \ - memcpy(r2, (bb), (num_pixels)); \ - /* replicate last byte */ \ - memset(r1 + (num_pixels), r1[(num_pixels) - 1], 9 - (num_pixels)); \ - memset(r2 + (num_pixels), r2[(num_pixels) - 1], 9 - (num_pixels)); \ - Upsample16Pixels(r1, r2, out); \ -} - -//----------------------------------------------------------------------------- -// YUV->RGB conversion - -// note: we represent the 33050 large constant as 32768 + 282 -static const int16_t kCoeffs1[4] = { 19077, 26149, 6419, 13320 }; - -#define v255 vdup_n_u8(255) -#define v_0x0f vdup_n_u8(15) - -#define STORE_Rgb(out, r, g, b) do { \ - uint8x8x3_t r_g_b; \ - INIT_VECTOR3(r_g_b, r, g, b); \ - vst3_u8(out, r_g_b); \ -} while (0) - -#define STORE_Bgr(out, r, g, b) do { \ - uint8x8x3_t b_g_r; \ - INIT_VECTOR3(b_g_r, b, g, r); \ - vst3_u8(out, b_g_r); \ -} while (0) - -#define STORE_Rgba(out, r, g, b) do { \ - uint8x8x4_t r_g_b_v255; \ - INIT_VECTOR4(r_g_b_v255, r, g, b, v255); \ - vst4_u8(out, r_g_b_v255); \ -} while (0) - -#define STORE_Bgra(out, r, g, b) do { \ - uint8x8x4_t b_g_r_v255; \ - INIT_VECTOR4(b_g_r_v255, b, g, r, v255); \ - vst4_u8(out, b_g_r_v255); \ -} while (0) - -#define STORE_Argb(out, r, g, b) do { \ - uint8x8x4_t v255_r_g_b; \ - INIT_VECTOR4(v255_r_g_b, v255, r, g, b); \ - vst4_u8(out, v255_r_g_b); \ -} while (0) - -#if !defined(WEBP_SWAP_16BIT_CSP) -#define ZIP_U8(lo, hi) vzip_u8((lo), (hi)) -#else -#define ZIP_U8(lo, hi) vzip_u8((hi), (lo)) -#endif - -#define STORE_Rgba4444(out, r, g, b) do { \ - const uint8x8_t r1 = vshl_n_u8(vshr_n_u8(r, 4), 4); /* 4bits */ \ - const uint8x8_t g1 = vshr_n_u8(g, 4); \ - const uint8x8_t ba = vorr_u8(b, v_0x0f); \ - const uint8x8_t rg = vorr_u8(r1, g1); \ - const uint8x8x2_t rgba4444 = ZIP_U8(rg, ba); \ - vst1q_u8(out, vcombine_u8(rgba4444.val[0], rgba4444.val[1])); \ -} while (0) - -#define STORE_Rgb565(out, r, g, b) do { \ - const uint8x8_t r1 = vshl_n_u8(vshr_n_u8(r, 3), 3); /* 5bits */ \ - const uint8x8_t g1 = vshr_n_u8(g, 5); /* upper 3bits */\ - const uint8x8_t g2 = vshl_n_u8(vshr_n_u8(g, 2), 5); /* lower 3bits */\ - const uint8x8_t b1 = vshr_n_u8(b, 3); /* 5bits */ \ - const uint8x8_t rg = vorr_u8(r1, g1); \ - const uint8x8_t gb = vorr_u8(g2, b1); \ - const uint8x8x2_t rgb565 = ZIP_U8(rg, gb); \ - vst1q_u8(out, vcombine_u8(rgb565.val[0], rgb565.val[1])); \ -} while (0) - -#define CONVERT8(FMT, XSTEP, N, src_y, src_uv, out, cur_x) do { \ - int i; \ - for (i = 0; i < N; i += 8) { \ - const int off = ((cur_x) + i) * XSTEP; \ - const uint8x8_t y = vld1_u8((src_y) + (cur_x) + i); \ - const uint8x8_t u = vld1_u8((src_uv) + i + 0); \ - const uint8x8_t v = vld1_u8((src_uv) + i + 16); \ - const int16x8_t Y0 = vreinterpretq_s16_u16(vshll_n_u8(y, 7)); \ - const int16x8_t U0 = vreinterpretq_s16_u16(vshll_n_u8(u, 7)); \ - const int16x8_t V0 = vreinterpretq_s16_u16(vshll_n_u8(v, 7)); \ - const int16x8_t Y1 = vqdmulhq_lane_s16(Y0, coeff1, 0); \ - const int16x8_t R0 = vqdmulhq_lane_s16(V0, coeff1, 1); \ - const int16x8_t G0 = vqdmulhq_lane_s16(U0, coeff1, 2); \ - const int16x8_t G1 = vqdmulhq_lane_s16(V0, coeff1, 3); \ - const int16x8_t B0 = vqdmulhq_n_s16(U0, 282); \ - const int16x8_t R1 = vqaddq_s16(Y1, R_Rounder); \ - const int16x8_t G2 = vqaddq_s16(Y1, G_Rounder); \ - const int16x8_t B1 = vqaddq_s16(Y1, B_Rounder); \ - const int16x8_t R2 = vqaddq_s16(R0, R1); \ - const int16x8_t G3 = vqaddq_s16(G0, G1); \ - const int16x8_t B2 = vqaddq_s16(B0, B1); \ - const int16x8_t G4 = vqsubq_s16(G2, G3); \ - const int16x8_t B3 = vqaddq_s16(B2, U0); \ - const uint8x8_t R = vqshrun_n_s16(R2, YUV_FIX2); \ - const uint8x8_t G = vqshrun_n_s16(G4, YUV_FIX2); \ - const uint8x8_t B = vqshrun_n_s16(B3, YUV_FIX2); \ - STORE_ ## FMT(out + off, R, G, B); \ - } \ -} while (0) - -#define CONVERT1(FUNC, XSTEP, N, src_y, src_uv, rgb, cur_x) { \ - int i; \ - for (i = 0; i < N; i++) { \ - const int off = ((cur_x) + i) * XSTEP; \ - const int y = src_y[(cur_x) + i]; \ - const int u = (src_uv)[i]; \ - const int v = (src_uv)[i + 16]; \ - FUNC(y, u, v, rgb + off); \ - } \ -} - -#define CONVERT2RGB_8(FMT, XSTEP, top_y, bottom_y, uv, \ - top_dst, bottom_dst, cur_x, len) { \ - CONVERT8(FMT, XSTEP, len, top_y, uv, top_dst, cur_x); \ - if (bottom_y != NULL) { \ - CONVERT8(FMT, XSTEP, len, bottom_y, (uv) + 32, bottom_dst, cur_x); \ - } \ -} - -#define CONVERT2RGB_1(FUNC, XSTEP, top_y, bottom_y, uv, \ - top_dst, bottom_dst, cur_x, len) { \ - CONVERT1(FUNC, XSTEP, len, top_y, uv, top_dst, cur_x); \ - if (bottom_y != NULL) { \ - CONVERT1(FUNC, XSTEP, len, bottom_y, (uv) + 32, bottom_dst, cur_x); \ - } \ -} - -#define NEON_UPSAMPLE_FUNC(FUNC_NAME, FMT, XSTEP) \ -static void FUNC_NAME(const uint8_t *top_y, const uint8_t *bottom_y, \ - const uint8_t *top_u, const uint8_t *top_v, \ - const uint8_t *cur_u, const uint8_t *cur_v, \ - uint8_t *top_dst, uint8_t *bottom_dst, int len) { \ - int block; \ - /* 16 byte aligned array to cache reconstructed u and v */ \ - uint8_t uv_buf[2 * 32 + 15]; \ - uint8_t *const r_uv = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \ - const int uv_len = (len + 1) >> 1; \ - /* 9 pixels must be read-able for each block */ \ - const int num_blocks = (uv_len - 1) >> 3; \ - const int leftover = uv_len - num_blocks * 8; \ - const int last_pos = 1 + 16 * num_blocks; \ - \ - const int u_diag = ((top_u[0] + cur_u[0]) >> 1) + 1; \ - const int v_diag = ((top_v[0] + cur_v[0]) >> 1) + 1; \ - \ - const int16x4_t coeff1 = vld1_s16(kCoeffs1); \ - const int16x8_t R_Rounder = vdupq_n_s16(-14234); \ - const int16x8_t G_Rounder = vdupq_n_s16(8708); \ - const int16x8_t B_Rounder = vdupq_n_s16(-17685); \ - \ - /* Treat the first pixel in regular way */ \ - assert(top_y != NULL); \ - { \ - const int u0 = (top_u[0] + u_diag) >> 1; \ - const int v0 = (top_v[0] + v_diag) >> 1; \ - VP8YuvTo ## FMT(top_y[0], u0, v0, top_dst); \ - } \ - if (bottom_y != NULL) { \ - const int u0 = (cur_u[0] + u_diag) >> 1; \ - const int v0 = (cur_v[0] + v_diag) >> 1; \ - VP8YuvTo ## FMT(bottom_y[0], u0, v0, bottom_dst); \ - } \ - \ - for (block = 0; block < num_blocks; ++block) { \ - UPSAMPLE_16PIXELS(top_u, cur_u, r_uv); \ - UPSAMPLE_16PIXELS(top_v, cur_v, r_uv + 16); \ - CONVERT2RGB_8(FMT, XSTEP, top_y, bottom_y, r_uv, \ - top_dst, bottom_dst, 16 * block + 1, 16); \ - top_u += 8; \ - cur_u += 8; \ - top_v += 8; \ - cur_v += 8; \ - } \ - \ - UPSAMPLE_LAST_BLOCK(top_u, cur_u, leftover, r_uv); \ - UPSAMPLE_LAST_BLOCK(top_v, cur_v, leftover, r_uv + 16); \ - CONVERT2RGB_1(VP8YuvTo ## FMT, XSTEP, top_y, bottom_y, r_uv, \ - top_dst, bottom_dst, last_pos, len - last_pos); \ -} - -// NEON variants of the fancy upsampler. -NEON_UPSAMPLE_FUNC(UpsampleRgbLinePair, Rgb, 3) -NEON_UPSAMPLE_FUNC(UpsampleBgrLinePair, Bgr, 3) -NEON_UPSAMPLE_FUNC(UpsampleRgbaLinePair, Rgba, 4) -NEON_UPSAMPLE_FUNC(UpsampleBgraLinePair, Bgra, 4) -NEON_UPSAMPLE_FUNC(UpsampleArgbLinePair, Argb, 4) -NEON_UPSAMPLE_FUNC(UpsampleRgba4444LinePair, Rgba4444, 2) -NEON_UPSAMPLE_FUNC(UpsampleRgb565LinePair, Rgb565, 2) - -//------------------------------------------------------------------------------ -// Entry point - -extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; - -extern void WebPInitUpsamplersNEON(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersNEON(void) { - WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; - WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; - WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair; - WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair; - WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair; -} - -#endif // FANCY_UPSAMPLING - -#endif // WEBP_USE_NEON - -#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_NEON)) -WEBP_DSP_INIT_STUB(WebPInitUpsamplersNEON) -#endif diff --git a/Example-Mac/Pods/libwebp/src/dsp/upsampling_sse2.c b/Example-Mac/Pods/libwebp/src/dsp/upsampling_sse2.c deleted file mode 100644 index b5b66890..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/upsampling_sse2.c +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// SSE2 version of YUV to RGB upsampling functions. -// -// Author: somnath@google.com (Somnath Banerjee) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE2) - -#include -#include -#include -#include "./yuv.h" - -#ifdef FANCY_UPSAMPLING - -// We compute (9*a + 3*b + 3*c + d + 8) / 16 as follows -// u = (9*a + 3*b + 3*c + d + 8) / 16 -// = (a + (a + 3*b + 3*c + d) / 8 + 1) / 2 -// = (a + m + 1) / 2 -// where m = (a + 3*b + 3*c + d) / 8 -// = ((a + b + c + d) / 2 + b + c) / 4 -// -// Let's say k = (a + b + c + d) / 4. -// We can compute k as -// k = (s + t + 1) / 2 - ((a^d) | (b^c) | (s^t)) & 1 -// where s = (a + d + 1) / 2 and t = (b + c + 1) / 2 -// -// Then m can be written as -// m = (k + t + 1) / 2 - (((b^c) & (s^t)) | (k^t)) & 1 - -// Computes out = (k + in + 1) / 2 - ((ij & (s^t)) | (k^in)) & 1 -#define GET_M(ij, in, out) do { \ - const __m128i tmp0 = _mm_avg_epu8(k, (in)); /* (k + in + 1) / 2 */ \ - const __m128i tmp1 = _mm_and_si128((ij), st); /* (ij) & (s^t) */ \ - const __m128i tmp2 = _mm_xor_si128(k, (in)); /* (k^in) */ \ - const __m128i tmp3 = _mm_or_si128(tmp1, tmp2); /* ((ij) & (s^t)) | (k^in) */\ - const __m128i tmp4 = _mm_and_si128(tmp3, one); /* & 1 -> lsb_correction */ \ - (out) = _mm_sub_epi8(tmp0, tmp4); /* (k + in + 1) / 2 - lsb_correction */ \ -} while (0) - -// pack and store two alternating pixel rows -#define PACK_AND_STORE(a, b, da, db, out) do { \ - const __m128i t_a = _mm_avg_epu8(a, da); /* (9a + 3b + 3c + d + 8) / 16 */ \ - const __m128i t_b = _mm_avg_epu8(b, db); /* (3a + 9b + c + 3d + 8) / 16 */ \ - const __m128i t_1 = _mm_unpacklo_epi8(t_a, t_b); \ - const __m128i t_2 = _mm_unpackhi_epi8(t_a, t_b); \ - _mm_store_si128(((__m128i*)(out)) + 0, t_1); \ - _mm_store_si128(((__m128i*)(out)) + 1, t_2); \ -} while (0) - -// Loads 17 pixels each from rows r1 and r2 and generates 32 pixels. -#define UPSAMPLE_32PIXELS(r1, r2, out) { \ - const __m128i one = _mm_set1_epi8(1); \ - const __m128i a = _mm_loadu_si128((const __m128i*)&(r1)[0]); \ - const __m128i b = _mm_loadu_si128((const __m128i*)&(r1)[1]); \ - const __m128i c = _mm_loadu_si128((const __m128i*)&(r2)[0]); \ - const __m128i d = _mm_loadu_si128((const __m128i*)&(r2)[1]); \ - \ - const __m128i s = _mm_avg_epu8(a, d); /* s = (a + d + 1) / 2 */ \ - const __m128i t = _mm_avg_epu8(b, c); /* t = (b + c + 1) / 2 */ \ - const __m128i st = _mm_xor_si128(s, t); /* st = s^t */ \ - \ - const __m128i ad = _mm_xor_si128(a, d); /* ad = a^d */ \ - const __m128i bc = _mm_xor_si128(b, c); /* bc = b^c */ \ - \ - const __m128i t1 = _mm_or_si128(ad, bc); /* (a^d) | (b^c) */ \ - const __m128i t2 = _mm_or_si128(t1, st); /* (a^d) | (b^c) | (s^t) */ \ - const __m128i t3 = _mm_and_si128(t2, one); /* (a^d) | (b^c) | (s^t) & 1 */ \ - const __m128i t4 = _mm_avg_epu8(s, t); \ - const __m128i k = _mm_sub_epi8(t4, t3); /* k = (a + b + c + d) / 4 */ \ - __m128i diag1, diag2; \ - \ - GET_M(bc, t, diag1); /* diag1 = (a + 3b + 3c + d) / 8 */ \ - GET_M(ad, s, diag2); /* diag2 = (3a + b + c + 3d) / 8 */ \ - \ - /* pack the alternate pixels */ \ - PACK_AND_STORE(a, b, diag1, diag2, out + 0); /* store top */ \ - PACK_AND_STORE(c, d, diag2, diag1, out + 2 * 32); /* store bottom */ \ -} - -// Turn the macro into a function for reducing code-size when non-critical -static void Upsample32Pixels(const uint8_t r1[], const uint8_t r2[], - uint8_t* const out) { - UPSAMPLE_32PIXELS(r1, r2, out); -} - -#define UPSAMPLE_LAST_BLOCK(tb, bb, num_pixels, out) { \ - uint8_t r1[17], r2[17]; \ - memcpy(r1, (tb), (num_pixels)); \ - memcpy(r2, (bb), (num_pixels)); \ - /* replicate last byte */ \ - memset(r1 + (num_pixels), r1[(num_pixels) - 1], 17 - (num_pixels)); \ - memset(r2 + (num_pixels), r2[(num_pixels) - 1], 17 - (num_pixels)); \ - /* using the shared function instead of the macro saves ~3k code size */ \ - Upsample32Pixels(r1, r2, out); \ -} - -#define CONVERT2RGB(FUNC, XSTEP, top_y, bottom_y, \ - top_dst, bottom_dst, cur_x, num_pixels) { \ - int n; \ - for (n = 0; n < (num_pixels); ++n) { \ - FUNC(top_y[(cur_x) + n], r_u[n], r_v[n], \ - top_dst + ((cur_x) + n) * XSTEP); \ - } \ - if (bottom_y != NULL) { \ - for (n = 0; n < (num_pixels); ++n) { \ - FUNC(bottom_y[(cur_x) + n], r_u[64 + n], r_v[64 + n], \ - bottom_dst + ((cur_x) + n) * XSTEP); \ - } \ - } \ -} - -#define CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, \ - top_dst, bottom_dst, cur_x) do { \ - FUNC##32(top_y + (cur_x), r_u, r_v, top_dst + (cur_x) * XSTEP); \ - if (bottom_y != NULL) { \ - FUNC##32(bottom_y + (cur_x), r_u + 64, r_v + 64, \ - bottom_dst + (cur_x) * XSTEP); \ - } \ -} while (0) - -#define SSE2_UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ -static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ - const uint8_t* top_u, const uint8_t* top_v, \ - const uint8_t* cur_u, const uint8_t* cur_v, \ - uint8_t* top_dst, uint8_t* bottom_dst, int len) { \ - int uv_pos, pos; \ - /* 16byte-aligned array to cache reconstructed u and v */ \ - uint8_t uv_buf[4 * 32 + 15]; \ - uint8_t* const r_u = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \ - uint8_t* const r_v = r_u + 32; \ - \ - assert(top_y != NULL); \ - { /* Treat the first pixel in regular way */ \ - const int u_diag = ((top_u[0] + cur_u[0]) >> 1) + 1; \ - const int v_diag = ((top_v[0] + cur_v[0]) >> 1) + 1; \ - const int u0_t = (top_u[0] + u_diag) >> 1; \ - const int v0_t = (top_v[0] + v_diag) >> 1; \ - FUNC(top_y[0], u0_t, v0_t, top_dst); \ - if (bottom_y != NULL) { \ - const int u0_b = (cur_u[0] + u_diag) >> 1; \ - const int v0_b = (cur_v[0] + v_diag) >> 1; \ - FUNC(bottom_y[0], u0_b, v0_b, bottom_dst); \ - } \ - } \ - /* For UPSAMPLE_32PIXELS, 17 u/v values must be read-able for each block */ \ - for (pos = 1, uv_pos = 0; pos + 32 + 1 <= len; pos += 32, uv_pos += 16) { \ - UPSAMPLE_32PIXELS(top_u + uv_pos, cur_u + uv_pos, r_u); \ - UPSAMPLE_32PIXELS(top_v + uv_pos, cur_v + uv_pos, r_v); \ - CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, top_dst, bottom_dst, pos); \ - } \ - if (len > 1) { \ - const int left_over = ((len + 1) >> 1) - (pos >> 1); \ - assert(left_over > 0); \ - UPSAMPLE_LAST_BLOCK(top_u + uv_pos, cur_u + uv_pos, left_over, r_u); \ - UPSAMPLE_LAST_BLOCK(top_v + uv_pos, cur_v + uv_pos, left_over, r_v); \ - CONVERT2RGB(FUNC, XSTEP, top_y, bottom_y, top_dst, bottom_dst, \ - pos, len - pos); \ - } \ -} - -// SSE2 variants of the fancy upsampler. -SSE2_UPSAMPLE_FUNC(UpsampleRgbLinePair, VP8YuvToRgb, 3) -SSE2_UPSAMPLE_FUNC(UpsampleBgrLinePair, VP8YuvToBgr, 3) -SSE2_UPSAMPLE_FUNC(UpsampleRgbaLinePair, VP8YuvToRgba, 4) -SSE2_UPSAMPLE_FUNC(UpsampleBgraLinePair, VP8YuvToBgra, 4) -SSE2_UPSAMPLE_FUNC(UpsampleArgbLinePair, VP8YuvToArgb, 4) -SSE2_UPSAMPLE_FUNC(UpsampleRgba4444LinePair, VP8YuvToRgba4444, 2) -SSE2_UPSAMPLE_FUNC(UpsampleRgb565LinePair, VP8YuvToRgb565, 2) - -#undef GET_M -#undef PACK_AND_STORE -#undef UPSAMPLE_32PIXELS -#undef UPSAMPLE_LAST_BLOCK -#undef CONVERT2RGB -#undef CONVERT2RGB_32 -#undef SSE2_UPSAMPLE_FUNC - -//------------------------------------------------------------------------------ -// Entry point - -extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; - -extern void WebPInitUpsamplersSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersSSE2(void) { - WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; - WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; - WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair; - WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair; - WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair; -} - -#endif // FANCY_UPSAMPLING - -//------------------------------------------------------------------------------ - -extern WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */]; -extern void WebPInitYUV444ConvertersSSE2(void); - -#define YUV444_FUNC(FUNC_NAME, CALL, XSTEP) \ -extern void WebP##FUNC_NAME##C(const uint8_t* y, const uint8_t* u, \ - const uint8_t* v, uint8_t* dst, int len); \ -static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ - uint8_t* dst, int len) { \ - int i; \ - const int max_len = len & ~31; \ - for (i = 0; i < max_len; i += 32) CALL(y + i, u + i, v + i, dst + i * XSTEP);\ - if (i < len) { /* C-fallback */ \ - WebP##FUNC_NAME##C(y + i, u + i, v + i, dst + i * XSTEP, len - i); \ - } \ -} - -YUV444_FUNC(Yuv444ToRgba, VP8YuvToRgba32, 4); -YUV444_FUNC(Yuv444ToBgra, VP8YuvToBgra32, 4); -YUV444_FUNC(Yuv444ToRgb, VP8YuvToRgb32, 3); -YUV444_FUNC(Yuv444ToBgr, VP8YuvToBgr32, 3); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444ConvertersSSE2(void) { - WebPYUV444Converters[MODE_RGBA] = Yuv444ToRgba; - WebPYUV444Converters[MODE_BGRA] = Yuv444ToBgra; - WebPYUV444Converters[MODE_RGB] = Yuv444ToRgb; - WebPYUV444Converters[MODE_BGR] = Yuv444ToBgr; -} - -#else - -WEBP_DSP_INIT_STUB(WebPInitYUV444ConvertersSSE2) - -#endif // WEBP_USE_SSE2 - -#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_SSE2)) -WEBP_DSP_INIT_STUB(WebPInitUpsamplersSSE2) -#endif diff --git a/Example-Mac/Pods/libwebp/src/dsp/yuv.c b/Example-Mac/Pods/libwebp/src/dsp/yuv.c deleted file mode 100644 index f50a2531..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/yuv.c +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// YUV->RGB conversion functions -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./yuv.h" - -#if defined(WEBP_YUV_USE_TABLE) - -static int done = 0; - -static WEBP_INLINE uint8_t clip(int v, int max_value) { - return v < 0 ? 0 : v > max_value ? max_value : v; -} - -int16_t VP8kVToR[256], VP8kUToB[256]; -int32_t VP8kVToG[256], VP8kUToG[256]; -uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN]; -uint8_t VP8kClip4Bits[YUV_RANGE_MAX - YUV_RANGE_MIN]; - -WEBP_TSAN_IGNORE_FUNCTION void VP8YUVInit(void) { - int i; - if (done) { - return; - } -#ifndef USE_YUVj - for (i = 0; i < 256; ++i) { - VP8kVToR[i] = (89858 * (i - 128) + YUV_HALF) >> YUV_FIX; - VP8kUToG[i] = -22014 * (i - 128) + YUV_HALF; - VP8kVToG[i] = -45773 * (i - 128); - VP8kUToB[i] = (113618 * (i - 128) + YUV_HALF) >> YUV_FIX; - } - for (i = YUV_RANGE_MIN; i < YUV_RANGE_MAX; ++i) { - const int k = ((i - 16) * 76283 + YUV_HALF) >> YUV_FIX; - VP8kClip[i - YUV_RANGE_MIN] = clip(k, 255); - VP8kClip4Bits[i - YUV_RANGE_MIN] = clip((k + 8) >> 4, 15); - } -#else - for (i = 0; i < 256; ++i) { - VP8kVToR[i] = (91881 * (i - 128) + YUV_HALF) >> YUV_FIX; - VP8kUToG[i] = -22554 * (i - 128) + YUV_HALF; - VP8kVToG[i] = -46802 * (i - 128); - VP8kUToB[i] = (116130 * (i - 128) + YUV_HALF) >> YUV_FIX; - } - for (i = YUV_RANGE_MIN; i < YUV_RANGE_MAX; ++i) { - const int k = i; - VP8kClip[i - YUV_RANGE_MIN] = clip(k, 255); - VP8kClip4Bits[i - YUV_RANGE_MIN] = clip((k + 8) >> 4, 15); - } -#endif - - done = 1; -} - -#else - -WEBP_TSAN_IGNORE_FUNCTION void VP8YUVInit(void) {} - -#endif // WEBP_YUV_USE_TABLE - -//----------------------------------------------------------------------------- -// Plain-C version - -#define ROW_FUNC(FUNC_NAME, FUNC, XSTEP) \ -static void FUNC_NAME(const uint8_t* y, \ - const uint8_t* u, const uint8_t* v, \ - uint8_t* dst, int len) { \ - const uint8_t* const end = dst + (len & ~1) * XSTEP; \ - while (dst != end) { \ - FUNC(y[0], u[0], v[0], dst); \ - FUNC(y[1], u[0], v[0], dst + XSTEP); \ - y += 2; \ - ++u; \ - ++v; \ - dst += 2 * XSTEP; \ - } \ - if (len & 1) { \ - FUNC(y[0], u[0], v[0], dst); \ - } \ -} \ - -// All variants implemented. -ROW_FUNC(YuvToRgbRow, VP8YuvToRgb, 3) -ROW_FUNC(YuvToBgrRow, VP8YuvToBgr, 3) -ROW_FUNC(YuvToRgbaRow, VP8YuvToRgba, 4) -ROW_FUNC(YuvToBgraRow, VP8YuvToBgra, 4) -ROW_FUNC(YuvToArgbRow, VP8YuvToArgb, 4) -ROW_FUNC(YuvToRgba4444Row, VP8YuvToRgba4444, 2) -ROW_FUNC(YuvToRgb565Row, VP8YuvToRgb565, 2) - -#undef ROW_FUNC - -// Main call for processing a plane with a WebPSamplerRowFunc function: -void WebPSamplerProcessPlane(const uint8_t* y, int y_stride, - const uint8_t* u, const uint8_t* v, int uv_stride, - uint8_t* dst, int dst_stride, - int width, int height, WebPSamplerRowFunc func) { - int j; - for (j = 0; j < height; ++j) { - func(y, u, v, dst, width); - y += y_stride; - if (j & 1) { - u += uv_stride; - v += uv_stride; - } - dst += dst_stride; - } -} - -//----------------------------------------------------------------------------- -// Main call - -WebPSamplerRowFunc WebPSamplers[MODE_LAST]; - -extern void WebPInitSamplersSSE2(void); -extern void WebPInitSamplersMIPS32(void); -extern void WebPInitSamplersMIPSdspR2(void); - -static volatile VP8CPUInfo yuv_last_cpuinfo_used = - (VP8CPUInfo)&yuv_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplers(void) { - if (yuv_last_cpuinfo_used == VP8GetCPUInfo) return; - - WebPSamplers[MODE_RGB] = YuvToRgbRow; - WebPSamplers[MODE_RGBA] = YuvToRgbaRow; - WebPSamplers[MODE_BGR] = YuvToBgrRow; - WebPSamplers[MODE_BGRA] = YuvToBgraRow; - WebPSamplers[MODE_ARGB] = YuvToArgbRow; - WebPSamplers[MODE_RGBA_4444] = YuvToRgba4444Row; - WebPSamplers[MODE_RGB_565] = YuvToRgb565Row; - WebPSamplers[MODE_rgbA] = YuvToRgbaRow; - WebPSamplers[MODE_bgrA] = YuvToBgraRow; - WebPSamplers[MODE_Argb] = YuvToArgbRow; - WebPSamplers[MODE_rgbA_4444] = YuvToRgba4444Row; - - // If defined, use CPUInfo() to overwrite some pointers with faster versions. - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - WebPInitSamplersSSE2(); - } -#endif // WEBP_USE_SSE2 -#if defined(WEBP_USE_MIPS32) - if (VP8GetCPUInfo(kMIPS32)) { - WebPInitSamplersMIPS32(); - } -#endif // WEBP_USE_MIPS32 -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - WebPInitSamplersMIPSdspR2(); - } -#endif // WEBP_USE_MIPS_DSP_R2 - } - yuv_last_cpuinfo_used = VP8GetCPUInfo; -} - -//----------------------------------------------------------------------------- -// ARGB -> YUV converters - -static void ConvertARGBToY(const uint32_t* argb, uint8_t* y, int width) { - int i; - for (i = 0; i < width; ++i) { - const uint32_t p = argb[i]; - y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff, - YUV_HALF); - } -} - -void WebPConvertARGBToUV_C(const uint32_t* argb, uint8_t* u, uint8_t* v, - int src_width, int do_store) { - // No rounding. Last pixel is dealt with separately. - const int uv_width = src_width >> 1; - int i; - for (i = 0; i < uv_width; ++i) { - const uint32_t v0 = argb[2 * i + 0]; - const uint32_t v1 = argb[2 * i + 1]; - // VP8RGBToU/V expects four accumulated pixels. Hence we need to - // scale r/g/b value by a factor 2. We just shift v0/v1 one bit less. - const int r = ((v0 >> 15) & 0x1fe) + ((v1 >> 15) & 0x1fe); - const int g = ((v0 >> 7) & 0x1fe) + ((v1 >> 7) & 0x1fe); - const int b = ((v0 << 1) & 0x1fe) + ((v1 << 1) & 0x1fe); - const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2); - const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2); - if (do_store) { - u[i] = tmp_u; - v[i] = tmp_v; - } else { - // Approximated average-of-four. But it's an acceptable diff. - u[i] = (u[i] + tmp_u + 1) >> 1; - v[i] = (v[i] + tmp_v + 1) >> 1; - } - } - if (src_width & 1) { // last pixel - const uint32_t v0 = argb[2 * i + 0]; - const int r = (v0 >> 14) & 0x3fc; - const int g = (v0 >> 6) & 0x3fc; - const int b = (v0 << 2) & 0x3fc; - const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2); - const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2); - if (do_store) { - u[i] = tmp_u; - v[i] = tmp_v; - } else { - u[i] = (u[i] + tmp_u + 1) >> 1; - v[i] = (v[i] + tmp_v + 1) >> 1; - } - } -} - -//----------------------------------------------------------------------------- - -static void ConvertRGB24ToY(const uint8_t* rgb, uint8_t* y, int width) { - int i; - for (i = 0; i < width; ++i, rgb += 3) { - y[i] = VP8RGBToY(rgb[0], rgb[1], rgb[2], YUV_HALF); - } -} - -static void ConvertBGR24ToY(const uint8_t* bgr, uint8_t* y, int width) { - int i; - for (i = 0; i < width; ++i, bgr += 3) { - y[i] = VP8RGBToY(bgr[2], bgr[1], bgr[0], YUV_HALF); - } -} - -void WebPConvertRGBA32ToUV_C(const uint16_t* rgb, - uint8_t* u, uint8_t* v, int width) { - int i; - for (i = 0; i < width; i += 1, rgb += 4) { - const int r = rgb[0], g = rgb[1], b = rgb[2]; - u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2); - v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2); - } -} - -//----------------------------------------------------------------------------- - -void (*WebPConvertRGB24ToY)(const uint8_t* rgb, uint8_t* y, int width); -void (*WebPConvertBGR24ToY)(const uint8_t* bgr, uint8_t* y, int width); -void (*WebPConvertRGBA32ToUV)(const uint16_t* rgb, - uint8_t* u, uint8_t* v, int width); - -void (*WebPConvertARGBToY)(const uint32_t* argb, uint8_t* y, int width); -void (*WebPConvertARGBToUV)(const uint32_t* argb, uint8_t* u, uint8_t* v, - int src_width, int do_store); - -static volatile VP8CPUInfo rgba_to_yuv_last_cpuinfo_used = - (VP8CPUInfo)&rgba_to_yuv_last_cpuinfo_used; - -extern void WebPInitConvertARGBToYUVSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUV(void) { - if (rgba_to_yuv_last_cpuinfo_used == VP8GetCPUInfo) return; - - WebPConvertARGBToY = ConvertARGBToY; - WebPConvertARGBToUV = WebPConvertARGBToUV_C; - - WebPConvertRGB24ToY = ConvertRGB24ToY; - WebPConvertBGR24ToY = ConvertBGR24ToY; - - WebPConvertRGBA32ToUV = WebPConvertRGBA32ToUV_C; - - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - WebPInitConvertARGBToYUVSSE2(); - } -#endif // WEBP_USE_SSE2 - } - rgba_to_yuv_last_cpuinfo_used = VP8GetCPUInfo; -} diff --git a/Example-Mac/Pods/libwebp/src/dsp/yuv.h b/Example-Mac/Pods/libwebp/src/dsp/yuv.h deleted file mode 100644 index 01c40fcb..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/yuv.h +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// inline YUV<->RGB conversion function -// -// The exact naming is Y'CbCr, following the ITU-R BT.601 standard. -// More information at: http://en.wikipedia.org/wiki/YCbCr -// Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16 -// U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128 -// V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128 -// We use 16bit fixed point operations for RGB->YUV conversion (YUV_FIX). -// -// For the Y'CbCr to RGB conversion, the BT.601 specification reads: -// R = 1.164 * (Y-16) + 1.596 * (V-128) -// G = 1.164 * (Y-16) - 0.813 * (V-128) - 0.391 * (U-128) -// B = 1.164 * (Y-16) + 2.018 * (U-128) -// where Y is in the [16,235] range, and U/V in the [16,240] range. -// -// The fixed-point implementation used here is: -// R = (19077 . y + 26149 . v - 14234) >> 6 -// G = (19077 . y - 6419 . u - 13320 . v + 8708) >> 6 -// B = (19077 . y + 33050 . u - 17685) >> 6 -// where the '.' operator is the mulhi_epu16 variant: -// a . b = ((a << 8) * b) >> 16 -// that preserves 8 bits of fractional precision before final descaling. - -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_DSP_YUV_H_ -#define WEBP_DSP_YUV_H_ - -#include "./dsp.h" -#include "../dec/decode_vp8.h" - -#if defined(WEBP_EXPERIMENTAL_FEATURES) -// Do NOT activate this feature for real compression. This is only experimental! -// This flag is for comparison purpose against JPEG's "YUVj" natural colorspace. -// This colorspace is close to Rec.601's Y'CbCr model with the notable -// difference of allowing larger range for luma/chroma. -// See http://en.wikipedia.org/wiki/YCbCr#JPEG_conversion paragraph, and its -// difference with http://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion -// #define USE_YUVj -#endif - -//------------------------------------------------------------------------------ -// YUV -> RGB conversion - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - YUV_FIX = 16, // fixed-point precision for RGB->YUV - YUV_HALF = 1 << (YUV_FIX - 1), - YUV_MASK = (256 << YUV_FIX) - 1, - YUV_RANGE_MIN = -227, // min value of r/g/b output - YUV_RANGE_MAX = 256 + 226, // max value of r/g/b output - - YUV_FIX2 = 6, // fixed-point precision for YUV->RGB - YUV_HALF2 = 1 << YUV_FIX2 >> 1, - YUV_MASK2 = (256 << YUV_FIX2) - 1 -}; - -//------------------------------------------------------------------------------ -// slower on x86 by ~7-8%, but bit-exact with the SSE2/NEON version - -static WEBP_INLINE int MultHi(int v, int coeff) { // _mm_mulhi_epu16 emulation - return (v * coeff) >> 8; -} - -static WEBP_INLINE int VP8Clip8(int v) { - return ((v & ~YUV_MASK2) == 0) ? (v >> YUV_FIX2) : (v < 0) ? 0 : 255; -} - -static WEBP_INLINE int VP8YUVToR(int y, int v) { - return VP8Clip8(MultHi(y, 19077) + MultHi(v, 26149) - 14234); -} - -static WEBP_INLINE int VP8YUVToG(int y, int u, int v) { - return VP8Clip8(MultHi(y, 19077) - MultHi(u, 6419) - MultHi(v, 13320) + 8708); -} - -static WEBP_INLINE int VP8YUVToB(int y, int u) { - return VP8Clip8(MultHi(y, 19077) + MultHi(u, 33050) - 17685); -} - -static WEBP_INLINE void VP8YuvToRgb(int y, int u, int v, - uint8_t* const rgb) { - rgb[0] = VP8YUVToR(y, v); - rgb[1] = VP8YUVToG(y, u, v); - rgb[2] = VP8YUVToB(y, u); -} - -static WEBP_INLINE void VP8YuvToBgr(int y, int u, int v, - uint8_t* const bgr) { - bgr[0] = VP8YUVToB(y, u); - bgr[1] = VP8YUVToG(y, u, v); - bgr[2] = VP8YUVToR(y, v); -} - -static WEBP_INLINE void VP8YuvToRgb565(int y, int u, int v, - uint8_t* const rgb) { - const int r = VP8YUVToR(y, v); // 5 usable bits - const int g = VP8YUVToG(y, u, v); // 6 usable bits - const int b = VP8YUVToB(y, u); // 5 usable bits - const int rg = (r & 0xf8) | (g >> 5); - const int gb = ((g << 3) & 0xe0) | (b >> 3); -#ifdef WEBP_SWAP_16BIT_CSP - rgb[0] = gb; - rgb[1] = rg; -#else - rgb[0] = rg; - rgb[1] = gb; -#endif -} - -static WEBP_INLINE void VP8YuvToRgba4444(int y, int u, int v, - uint8_t* const argb) { - const int r = VP8YUVToR(y, v); // 4 usable bits - const int g = VP8YUVToG(y, u, v); // 4 usable bits - const int b = VP8YUVToB(y, u); // 4 usable bits - const int rg = (r & 0xf0) | (g >> 4); - const int ba = (b & 0xf0) | 0x0f; // overwrite the lower 4 bits -#ifdef WEBP_SWAP_16BIT_CSP - argb[0] = ba; - argb[1] = rg; -#else - argb[0] = rg; - argb[1] = ba; -#endif -} - -//----------------------------------------------------------------------------- -// Alpha handling variants - -static WEBP_INLINE void VP8YuvToArgb(uint8_t y, uint8_t u, uint8_t v, - uint8_t* const argb) { - argb[0] = 0xff; - VP8YuvToRgb(y, u, v, argb + 1); -} - -static WEBP_INLINE void VP8YuvToBgra(uint8_t y, uint8_t u, uint8_t v, - uint8_t* const bgra) { - VP8YuvToBgr(y, u, v, bgra); - bgra[3] = 0xff; -} - -static WEBP_INLINE void VP8YuvToRgba(uint8_t y, uint8_t u, uint8_t v, - uint8_t* const rgba) { - VP8YuvToRgb(y, u, v, rgba); - rgba[3] = 0xff; -} - -// Must be called before everything, to initialize the tables. -void VP8YUVInit(void); - -//----------------------------------------------------------------------------- -// SSE2 extra functions (mostly for upsampling_sse2.c) - -#if defined(WEBP_USE_SSE2) - -// Process 32 pixels and store the result (16b, 24b or 32b per pixel) in *dst. -void VP8YuvToRgba32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst); -void VP8YuvToRgb32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst); -void VP8YuvToBgra32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst); -void VP8YuvToBgr32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst); -void VP8YuvToArgb32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst); -void VP8YuvToRgba444432(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst); -void VP8YuvToRgb56532(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst); - -#endif // WEBP_USE_SSE2 - -//------------------------------------------------------------------------------ -// RGB -> YUV conversion - -// Stub functions that can be called with various rounding values: -static WEBP_INLINE int VP8ClipUV(int uv, int rounding) { - uv = (uv + rounding + (128 << (YUV_FIX + 2))) >> (YUV_FIX + 2); - return ((uv & ~0xff) == 0) ? uv : (uv < 0) ? 0 : 255; -} - -#ifndef USE_YUVj - -static WEBP_INLINE int VP8RGBToY(int r, int g, int b, int rounding) { - const int luma = 16839 * r + 33059 * g + 6420 * b; - return (luma + rounding + (16 << YUV_FIX)) >> YUV_FIX; // no need to clip -} - -static WEBP_INLINE int VP8RGBToU(int r, int g, int b, int rounding) { - const int u = -9719 * r - 19081 * g + 28800 * b; - return VP8ClipUV(u, rounding); -} - -static WEBP_INLINE int VP8RGBToV(int r, int g, int b, int rounding) { - const int v = +28800 * r - 24116 * g - 4684 * b; - return VP8ClipUV(v, rounding); -} - -#else - -// This JPEG-YUV colorspace, only for comparison! -// These are also 16bit precision coefficients from Rec.601, but with full -// [0..255] output range. -static WEBP_INLINE int VP8RGBToY(int r, int g, int b, int rounding) { - const int luma = 19595 * r + 38470 * g + 7471 * b; - return (luma + rounding) >> YUV_FIX; // no need to clip -} - -static WEBP_INLINE int VP8RGBToU(int r, int g, int b, int rounding) { - const int u = -11058 * r - 21710 * g + 32768 * b; - return VP8ClipUV(u, rounding); -} - -static WEBP_INLINE int VP8RGBToV(int r, int g, int b, int rounding) { - const int v = 32768 * r - 27439 * g - 5329 * b; - return VP8ClipUV(v, rounding); -} - -#endif // USE_YUVj - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_DSP_YUV_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/dsp/yuv_mips32.c b/Example-Mac/Pods/libwebp/src/dsp/yuv_mips32.c deleted file mode 100644 index b8fe512f..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/yuv_mips32.c +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// MIPS version of YUV to RGB upsampling functions. -// -// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) -// Jovan Zelincevic (jovan.zelincevic@imgtec.com) - -#include "./dsp.h" - -// Code is disabled for now, in favor of the plain-C version -#if 0 // defined(WEBP_USE_MIPS32) - -#include "./yuv.h" - -//------------------------------------------------------------------------------ -// simple point-sampling - -#define ROW_FUNC(FUNC_NAME, XSTEP, R, G, B, A) \ -static void FUNC_NAME(const uint8_t* y, \ - const uint8_t* u, const uint8_t* v, \ - uint8_t* dst, int len) { \ - int i, r, g, b; \ - int temp0, temp1, temp2, temp3, temp4; \ - for (i = 0; i < (len >> 1); i++) { \ - temp1 = kVToR * v[0]; \ - temp3 = kVToG * v[0]; \ - temp2 = kUToG * u[0]; \ - temp4 = kUToB * u[0]; \ - temp0 = kYScale * y[0]; \ - temp1 += kRCst; \ - temp3 -= kGCst; \ - temp2 += temp3; \ - temp4 += kBCst; \ - r = VP8Clip8(temp0 + temp1); \ - g = VP8Clip8(temp0 - temp2); \ - b = VP8Clip8(temp0 + temp4); \ - temp0 = kYScale * y[1]; \ - dst[R] = r; \ - dst[G] = g; \ - dst[B] = b; \ - if (A) dst[A] = 0xff; \ - r = VP8Clip8(temp0 + temp1); \ - g = VP8Clip8(temp0 - temp2); \ - b = VP8Clip8(temp0 + temp4); \ - dst[R + XSTEP] = r; \ - dst[G + XSTEP] = g; \ - dst[B + XSTEP] = b; \ - if (A) dst[A + XSTEP] = 0xff; \ - y += 2; \ - ++u; \ - ++v; \ - dst += 2 * XSTEP; \ - } \ - if (len & 1) { \ - temp1 = kVToR * v[0]; \ - temp3 = kVToG * v[0]; \ - temp2 = kUToG * u[0]; \ - temp4 = kUToB * u[0]; \ - temp0 = kYScale * y[0]; \ - temp1 += kRCst; \ - temp3 -= kGCst; \ - temp2 += temp3; \ - temp4 += kBCst; \ - r = VP8Clip8(temp0 + temp1); \ - g = VP8Clip8(temp0 - temp2); \ - b = VP8Clip8(temp0 + temp4); \ - dst[R] = r; \ - dst[G] = g; \ - dst[B] = b; \ - if (A) dst[A] = 0xff; \ - } \ -} - -ROW_FUNC(YuvToRgbRow, 3, 0, 1, 2, 0) -ROW_FUNC(YuvToRgbaRow, 4, 0, 1, 2, 3) -ROW_FUNC(YuvToBgrRow, 3, 2, 1, 0, 0) -ROW_FUNC(YuvToBgraRow, 4, 2, 1, 0, 3) - -#undef ROW_FUNC - -//------------------------------------------------------------------------------ -// Entry point - -extern void WebPInitSamplersMIPS32(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersMIPS32(void) { - WebPSamplers[MODE_RGB] = YuvToRgbRow; - WebPSamplers[MODE_RGBA] = YuvToRgbaRow; - WebPSamplers[MODE_BGR] = YuvToBgrRow; - WebPSamplers[MODE_BGRA] = YuvToBgraRow; -} - -#else // !WEBP_USE_MIPS32 - -WEBP_DSP_INIT_STUB(WebPInitSamplersMIPS32) - -#endif // WEBP_USE_MIPS32 diff --git a/Example-Mac/Pods/libwebp/src/dsp/yuv_mips_dsp_r2.c b/Example-Mac/Pods/libwebp/src/dsp/yuv_mips_dsp_r2.c deleted file mode 100644 index dea0fdb8..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/yuv_mips_dsp_r2.c +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// MIPS DSPr2 version of YUV to RGB upsampling functions. -// -// Author(s): Branimir Vasic (branimir.vasic@imgtec.com) -// Djordje Pesut (djordje.pesut@imgtec.com) - -#include "./dsp.h" - -// Code is disabled for now, in favor of the plain-C version -#if 0 // defined(WEBP_USE_MIPS_DSP_R2) - -#include "./yuv.h" - -//------------------------------------------------------------------------------ -// simple point-sampling - -#define ROW_FUNC_PART_1() \ - "lbu %[temp3], 0(%[v]) \n\t" \ - "lbu %[temp4], 0(%[u]) \n\t" \ - "lbu %[temp0], 0(%[y]) \n\t" \ - "mul %[temp1], %[t_con_1], %[temp3] \n\t" \ - "mul %[temp3], %[t_con_2], %[temp3] \n\t" \ - "mul %[temp2], %[t_con_3], %[temp4] \n\t" \ - "mul %[temp4], %[t_con_4], %[temp4] \n\t" \ - "mul %[temp0], %[t_con_5], %[temp0] \n\t" \ - "addu %[temp1], %[temp1], %[t_con_6] \n\t" \ - "subu %[temp3], %[temp3], %[t_con_7] \n\t" \ - "addu %[temp2], %[temp2], %[temp3] \n\t" \ - "addu %[temp4], %[temp4], %[t_con_8] \n\t" \ - -#define ROW_FUNC_PART_2(R, G, B, K) \ - "addu %[temp5], %[temp0], %[temp1] \n\t" \ - "subu %[temp6], %[temp0], %[temp2] \n\t" \ - "addu %[temp7], %[temp0], %[temp4] \n\t" \ -".if " #K " \n\t" \ - "lbu %[temp0], 1(%[y]) \n\t" \ -".endif \n\t" \ - "shll_s.w %[temp5], %[temp5], 9 \n\t" \ - "shll_s.w %[temp6], %[temp6], 9 \n\t" \ -".if " #K " \n\t" \ - "mul %[temp0], %[t_con_5], %[temp0] \n\t" \ -".endif \n\t" \ - "shll_s.w %[temp7], %[temp7], 9 \n\t" \ - "precrqu_s.qb.ph %[temp5], %[temp5], $zero \n\t" \ - "precrqu_s.qb.ph %[temp6], %[temp6], $zero \n\t" \ - "precrqu_s.qb.ph %[temp7], %[temp7], $zero \n\t" \ - "srl %[temp5], %[temp5], 24 \n\t" \ - "srl %[temp6], %[temp6], 24 \n\t" \ - "srl %[temp7], %[temp7], 24 \n\t" \ - "sb %[temp5], " #R "(%[dst]) \n\t" \ - "sb %[temp6], " #G "(%[dst]) \n\t" \ - "sb %[temp7], " #B "(%[dst]) \n\t" \ - -#define ASM_CLOBBER_LIST() \ - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \ - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \ - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7) \ - : [t_con_1]"r"(t_con_1), [t_con_2]"r"(t_con_2), [t_con_3]"r"(t_con_3), \ - [t_con_4]"r"(t_con_4), [t_con_5]"r"(t_con_5), [t_con_6]"r"(t_con_6), \ - [u]"r"(u), [v]"r"(v), [y]"r"(y), [dst]"r"(dst), \ - [t_con_7]"r"(t_con_7), [t_con_8]"r"(t_con_8) \ - : "memory", "hi", "lo" \ - -#define ROW_FUNC(FUNC_NAME, XSTEP, R, G, B, A) \ -static void FUNC_NAME(const uint8_t* y, \ - const uint8_t* u, const uint8_t* v, \ - uint8_t* dst, int len) { \ - int i; \ - uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; \ - const int t_con_1 = kVToR; \ - const int t_con_2 = kVToG; \ - const int t_con_3 = kUToG; \ - const int t_con_4 = kUToB; \ - const int t_con_5 = kYScale; \ - const int t_con_6 = kRCst; \ - const int t_con_7 = kGCst; \ - const int t_con_8 = kBCst; \ - for (i = 0; i < (len >> 1); i++) { \ - __asm__ volatile ( \ - ROW_FUNC_PART_1() \ - ROW_FUNC_PART_2(R, G, B, 1) \ - ROW_FUNC_PART_2(R + XSTEP, G + XSTEP, B + XSTEP, 0) \ - ASM_CLOBBER_LIST() \ - ); \ - if (A) dst[A] = dst[A + XSTEP] = 0xff; \ - y += 2; \ - ++u; \ - ++v; \ - dst += 2 * XSTEP; \ - } \ - if (len & 1) { \ - __asm__ volatile ( \ - ROW_FUNC_PART_1() \ - ROW_FUNC_PART_2(R, G, B, 0) \ - ASM_CLOBBER_LIST() \ - ); \ - if (A) dst[A] = 0xff; \ - } \ -} - -ROW_FUNC(YuvToRgbRow, 3, 0, 1, 2, 0) -ROW_FUNC(YuvToRgbaRow, 4, 0, 1, 2, 3) -ROW_FUNC(YuvToBgrRow, 3, 2, 1, 0, 0) -ROW_FUNC(YuvToBgraRow, 4, 2, 1, 0, 3) - -#undef ROW_FUNC -#undef ASM_CLOBBER_LIST -#undef ROW_FUNC_PART_2 -#undef ROW_FUNC_PART_1 - -//------------------------------------------------------------------------------ -// Entry point - -extern void WebPInitSamplersMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersMIPSdspR2(void) { - WebPSamplers[MODE_RGB] = YuvToRgbRow; - WebPSamplers[MODE_RGBA] = YuvToRgbaRow; - WebPSamplers[MODE_BGR] = YuvToBgrRow; - WebPSamplers[MODE_BGRA] = YuvToBgraRow; -} - -#else // !WEBP_USE_MIPS_DSP_R2 - -WEBP_DSP_INIT_STUB(WebPInitSamplersMIPSdspR2) - -#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/Example-Mac/Pods/libwebp/src/dsp/yuv_sse2.c b/Example-Mac/Pods/libwebp/src/dsp/yuv_sse2.c deleted file mode 100644 index f72fe324..00000000 --- a/Example-Mac/Pods/libwebp/src/dsp/yuv_sse2.c +++ /dev/null @@ -1,774 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// YUV->RGB conversion functions -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./yuv.h" - -#if defined(WEBP_USE_SSE2) - -#include - -//----------------------------------------------------------------------------- -// Convert spans of 32 pixels to various RGB formats for the fancy upsampler. - -// These constants are 14b fixed-point version of ITU-R BT.601 constants. -// R = (19077 * y + 26149 * v - 14234) >> 6 -// G = (19077 * y - 6419 * u - 13320 * v + 8708) >> 6 -// B = (19077 * y + 33050 * u - 17685) >> 6 -static void ConvertYUV444ToRGB(const __m128i* const Y0, - const __m128i* const U0, - const __m128i* const V0, - __m128i* const R, - __m128i* const G, - __m128i* const B) { - const __m128i k19077 = _mm_set1_epi16(19077); - const __m128i k26149 = _mm_set1_epi16(26149); - const __m128i k14234 = _mm_set1_epi16(14234); - const __m128i k33050 = _mm_set1_epi16(33050); - const __m128i k17685 = _mm_set1_epi16(17685); - const __m128i k6419 = _mm_set1_epi16(6419); - const __m128i k13320 = _mm_set1_epi16(13320); - const __m128i k8708 = _mm_set1_epi16(8708); - - const __m128i Y1 = _mm_mulhi_epu16(*Y0, k19077); - - const __m128i R0 = _mm_mulhi_epu16(*V0, k26149); - const __m128i R1 = _mm_sub_epi16(Y1, k14234); - const __m128i R2 = _mm_add_epi16(R1, R0); - - const __m128i G0 = _mm_mulhi_epu16(*U0, k6419); - const __m128i G1 = _mm_mulhi_epu16(*V0, k13320); - const __m128i G2 = _mm_add_epi16(Y1, k8708); - const __m128i G3 = _mm_add_epi16(G0, G1); - const __m128i G4 = _mm_sub_epi16(G2, G3); - - // be careful with the saturated *unsigned* arithmetic here! - const __m128i B0 = _mm_mulhi_epu16(*U0, k33050); - const __m128i B1 = _mm_adds_epu16(B0, Y1); - const __m128i B2 = _mm_subs_epu16(B1, k17685); - - // use logical shift for B2, which can be larger than 32767 - *R = _mm_srai_epi16(R2, 6); // range: [-14234, 30815] - *G = _mm_srai_epi16(G4, 6); // range: [-10953, 27710] - *B = _mm_srli_epi16(B2, 6); // range: [0, 34238] -} - -// Load the bytes into the *upper* part of 16b words. That's "<< 8", basically. -static WEBP_INLINE __m128i Load_HI_16(const uint8_t* src) { - const __m128i zero = _mm_setzero_si128(); - return _mm_unpacklo_epi8(zero, _mm_loadl_epi64((const __m128i*)src)); -} - -// Load and replicate the U/V samples -static WEBP_INLINE __m128i Load_UV_HI_8(const uint8_t* src) { - const __m128i zero = _mm_setzero_si128(); - const __m128i tmp0 = _mm_cvtsi32_si128(*(const uint32_t*)src); - const __m128i tmp1 = _mm_unpacklo_epi8(zero, tmp0); - return _mm_unpacklo_epi16(tmp1, tmp1); // replicate samples -} - -// Convert 32 samples of YUV444 to R/G/B -static void YUV444ToRGB(const uint8_t* const y, - const uint8_t* const u, - const uint8_t* const v, - __m128i* const R, __m128i* const G, __m128i* const B) { - const __m128i Y0 = Load_HI_16(y), U0 = Load_HI_16(u), V0 = Load_HI_16(v); - ConvertYUV444ToRGB(&Y0, &U0, &V0, R, G, B); -} - -// Convert 32 samples of YUV420 to R/G/B -static void YUV420ToRGB(const uint8_t* const y, - const uint8_t* const u, - const uint8_t* const v, - __m128i* const R, __m128i* const G, __m128i* const B) { - const __m128i Y0 = Load_HI_16(y), U0 = Load_UV_HI_8(u), V0 = Load_UV_HI_8(v); - ConvertYUV444ToRGB(&Y0, &U0, &V0, R, G, B); -} - -// Pack R/G/B/A results into 32b output. -static WEBP_INLINE void PackAndStore4(const __m128i* const R, - const __m128i* const G, - const __m128i* const B, - const __m128i* const A, - uint8_t* const dst) { - const __m128i rb = _mm_packus_epi16(*R, *B); - const __m128i ga = _mm_packus_epi16(*G, *A); - const __m128i rg = _mm_unpacklo_epi8(rb, ga); - const __m128i ba = _mm_unpackhi_epi8(rb, ga); - const __m128i RGBA_lo = _mm_unpacklo_epi16(rg, ba); - const __m128i RGBA_hi = _mm_unpackhi_epi16(rg, ba); - _mm_storeu_si128((__m128i*)(dst + 0), RGBA_lo); - _mm_storeu_si128((__m128i*)(dst + 16), RGBA_hi); -} - -// Pack R/G/B/A results into 16b output. -static WEBP_INLINE void PackAndStore4444(const __m128i* const R, - const __m128i* const G, - const __m128i* const B, - const __m128i* const A, - uint8_t* const dst) { -#if !defined(WEBP_SWAP_16BIT_CSP) - const __m128i rg0 = _mm_packus_epi16(*R, *G); - const __m128i ba0 = _mm_packus_epi16(*B, *A); -#else - const __m128i rg0 = _mm_packus_epi16(*B, *A); - const __m128i ba0 = _mm_packus_epi16(*R, *G); -#endif - const __m128i mask_0xf0 = _mm_set1_epi8(0xf0); - const __m128i rb1 = _mm_unpacklo_epi8(rg0, ba0); // rbrbrbrbrb... - const __m128i ga1 = _mm_unpackhi_epi8(rg0, ba0); // gagagagaga... - const __m128i rb2 = _mm_and_si128(rb1, mask_0xf0); - const __m128i ga2 = _mm_srli_epi16(_mm_and_si128(ga1, mask_0xf0), 4); - const __m128i rgba4444 = _mm_or_si128(rb2, ga2); - _mm_storeu_si128((__m128i*)dst, rgba4444); -} - -// Pack R/G/B results into 16b output. -static WEBP_INLINE void PackAndStore565(const __m128i* const R, - const __m128i* const G, - const __m128i* const B, - uint8_t* const dst) { - const __m128i r0 = _mm_packus_epi16(*R, *R); - const __m128i g0 = _mm_packus_epi16(*G, *G); - const __m128i b0 = _mm_packus_epi16(*B, *B); - const __m128i r1 = _mm_and_si128(r0, _mm_set1_epi8(0xf8)); - const __m128i b1 = _mm_and_si128(_mm_srli_epi16(b0, 3), _mm_set1_epi8(0x1f)); - const __m128i g1 = _mm_srli_epi16(_mm_and_si128(g0, _mm_set1_epi8(0xe0)), 5); - const __m128i g2 = _mm_slli_epi16(_mm_and_si128(g0, _mm_set1_epi8(0x1c)), 3); - const __m128i rg = _mm_or_si128(r1, g1); - const __m128i gb = _mm_or_si128(g2, b1); -#if !defined(WEBP_SWAP_16BIT_CSP) - const __m128i rgb565 = _mm_unpacklo_epi8(rg, gb); -#else - const __m128i rgb565 = _mm_unpacklo_epi8(gb, rg); -#endif - _mm_storeu_si128((__m128i*)dst, rgb565); -} - -// Function used several times in PlanarTo24b. -// It samples the in buffer as follows: one every two unsigned char is stored -// at the beginning of the buffer, while the other half is stored at the end. -static WEBP_INLINE void PlanarTo24bHelper(const __m128i* const in /*in[6]*/, - __m128i* const out /*out[6]*/) { - const __m128i v_mask = _mm_set1_epi16(0x00ff); - - // Take one every two upper 8b values. - out[0] = _mm_packus_epi16(_mm_and_si128(in[0], v_mask), - _mm_and_si128(in[1], v_mask)); - out[1] = _mm_packus_epi16(_mm_and_si128(in[2], v_mask), - _mm_and_si128(in[3], v_mask)); - out[2] = _mm_packus_epi16(_mm_and_si128(in[4], v_mask), - _mm_and_si128(in[5], v_mask)); - // Take one every two lower 8b values. - out[3] = _mm_packus_epi16(_mm_srli_epi16(in[0], 8), _mm_srli_epi16(in[1], 8)); - out[4] = _mm_packus_epi16(_mm_srli_epi16(in[2], 8), _mm_srli_epi16(in[3], 8)); - out[5] = _mm_packus_epi16(_mm_srli_epi16(in[4], 8), _mm_srli_epi16(in[5], 8)); -} - -// Pack the planar buffers -// rrrr... rrrr... gggg... gggg... bbbb... bbbb.... -// triplet by triplet in the output buffer rgb as rgbrgbrgbrgb ... -static WEBP_INLINE void PlanarTo24b(__m128i* const in /*in[6]*/, uint8_t* rgb) { - // The input is 6 registers of sixteen 8b but for the sake of explanation, - // let's take 6 registers of four 8b values. - // To pack, we will keep taking one every two 8b integer and move it - // around as follows: - // Input: - // r0r1r2r3 | r4r5r6r7 | g0g1g2g3 | g4g5g6g7 | b0b1b2b3 | b4b5b6b7 - // Split the 6 registers in two sets of 3 registers: the first set as the even - // 8b bytes, the second the odd ones: - // r0r2r4r6 | g0g2g4g6 | b0b2b4b6 | r1r3r5r7 | g1g3g5g7 | b1b3b5b7 - // Repeat the same permutations twice more: - // r0r4g0g4 | b0b4r1r5 | g1g5b1b5 | r2r6g2g6 | b2b6r3r7 | g3g7b3b7 - // r0g0b0r1 | g1b1r2g2 | b2r3g3b3 | r4g4b4r5 | g5b5r6g6 | b6r7g7b7 - __m128i tmp[6]; - PlanarTo24bHelper(in, tmp); - PlanarTo24bHelper(tmp, in); - PlanarTo24bHelper(in, tmp); - // We need to do it two more times than the example as we have sixteen bytes. - PlanarTo24bHelper(tmp, in); - PlanarTo24bHelper(in, tmp); - - _mm_storeu_si128((__m128i*)(rgb + 0), tmp[0]); - _mm_storeu_si128((__m128i*)(rgb + 16), tmp[1]); - _mm_storeu_si128((__m128i*)(rgb + 32), tmp[2]); - _mm_storeu_si128((__m128i*)(rgb + 48), tmp[3]); - _mm_storeu_si128((__m128i*)(rgb + 64), tmp[4]); - _mm_storeu_si128((__m128i*)(rgb + 80), tmp[5]); -} -#undef MK_UINT32 - -void VP8YuvToRgba32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst) { - const __m128i kAlpha = _mm_set1_epi16(255); - int n; - for (n = 0; n < 32; n += 8, dst += 32) { - __m128i R, G, B; - YUV444ToRGB(y + n, u + n, v + n, &R, &G, &B); - PackAndStore4(&R, &G, &B, &kAlpha, dst); - } -} - -void VP8YuvToBgra32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst) { - const __m128i kAlpha = _mm_set1_epi16(255); - int n; - for (n = 0; n < 32; n += 8, dst += 32) { - __m128i R, G, B; - YUV444ToRGB(y + n, u + n, v + n, &R, &G, &B); - PackAndStore4(&B, &G, &R, &kAlpha, dst); - } -} - -void VP8YuvToArgb32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst) { - const __m128i kAlpha = _mm_set1_epi16(255); - int n; - for (n = 0; n < 32; n += 8, dst += 32) { - __m128i R, G, B; - YUV444ToRGB(y + n, u + n, v + n, &R, &G, &B); - PackAndStore4(&kAlpha, &R, &G, &B, dst); - } -} - -void VP8YuvToRgba444432(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst) { - const __m128i kAlpha = _mm_set1_epi16(255); - int n; - for (n = 0; n < 32; n += 8, dst += 16) { - __m128i R, G, B; - YUV444ToRGB(y + n, u + n, v + n, &R, &G, &B); - PackAndStore4444(&R, &G, &B, &kAlpha, dst); - } -} - -void VP8YuvToRgb56532(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst) { - int n; - for (n = 0; n < 32; n += 8, dst += 16) { - __m128i R, G, B; - YUV444ToRGB(y + n, u + n, v + n, &R, &G, &B); - PackAndStore565(&R, &G, &B, dst); - } -} - -void VP8YuvToRgb32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst) { - __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; - __m128i rgb[6]; - - YUV444ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0); - YUV444ToRGB(y + 8, u + 8, v + 8, &R1, &G1, &B1); - YUV444ToRGB(y + 16, u + 16, v + 16, &R2, &G2, &B2); - YUV444ToRGB(y + 24, u + 24, v + 24, &R3, &G3, &B3); - - // Cast to 8b and store as RRRRGGGGBBBB. - rgb[0] = _mm_packus_epi16(R0, R1); - rgb[1] = _mm_packus_epi16(R2, R3); - rgb[2] = _mm_packus_epi16(G0, G1); - rgb[3] = _mm_packus_epi16(G2, G3); - rgb[4] = _mm_packus_epi16(B0, B1); - rgb[5] = _mm_packus_epi16(B2, B3); - - // Pack as RGBRGBRGBRGB. - PlanarTo24b(rgb, dst); -} - -void VP8YuvToBgr32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst) { - __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; - __m128i bgr[6]; - - YUV444ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0); - YUV444ToRGB(y + 8, u + 8, v + 8, &R1, &G1, &B1); - YUV444ToRGB(y + 16, u + 16, v + 16, &R2, &G2, &B2); - YUV444ToRGB(y + 24, u + 24, v + 24, &R3, &G3, &B3); - - // Cast to 8b and store as BBBBGGGGRRRR. - bgr[0] = _mm_packus_epi16(B0, B1); - bgr[1] = _mm_packus_epi16(B2, B3); - bgr[2] = _mm_packus_epi16(G0, G1); - bgr[3] = _mm_packus_epi16(G2, G3); - bgr[4] = _mm_packus_epi16(R0, R1); - bgr[5] = _mm_packus_epi16(R2, R3); - - // Pack as BGRBGRBGRBGR. - PlanarTo24b(bgr, dst); -} - -//----------------------------------------------------------------------------- -// Arbitrary-length row conversion functions - -static void YuvToRgbaRow(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst, int len) { - const __m128i kAlpha = _mm_set1_epi16(255); - int n; - for (n = 0; n + 8 <= len; n += 8, dst += 32) { - __m128i R, G, B; - YUV420ToRGB(y, u, v, &R, &G, &B); - PackAndStore4(&R, &G, &B, &kAlpha, dst); - y += 8; - u += 4; - v += 4; - } - for (; n < len; ++n) { // Finish off - VP8YuvToRgba(y[0], u[0], v[0], dst); - dst += 4; - y += 1; - u += (n & 1); - v += (n & 1); - } -} - -static void YuvToBgraRow(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst, int len) { - const __m128i kAlpha = _mm_set1_epi16(255); - int n; - for (n = 0; n + 8 <= len; n += 8, dst += 32) { - __m128i R, G, B; - YUV420ToRGB(y, u, v, &R, &G, &B); - PackAndStore4(&B, &G, &R, &kAlpha, dst); - y += 8; - u += 4; - v += 4; - } - for (; n < len; ++n) { // Finish off - VP8YuvToBgra(y[0], u[0], v[0], dst); - dst += 4; - y += 1; - u += (n & 1); - v += (n & 1); - } -} - -static void YuvToArgbRow(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst, int len) { - const __m128i kAlpha = _mm_set1_epi16(255); - int n; - for (n = 0; n + 8 <= len; n += 8, dst += 32) { - __m128i R, G, B; - YUV420ToRGB(y, u, v, &R, &G, &B); - PackAndStore4(&kAlpha, &R, &G, &B, dst); - y += 8; - u += 4; - v += 4; - } - for (; n < len; ++n) { // Finish off - VP8YuvToArgb(y[0], u[0], v[0], dst); - dst += 4; - y += 1; - u += (n & 1); - v += (n & 1); - } -} - -static void YuvToRgbRow(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst, int len) { - int n; - for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) { - __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; - __m128i rgb[6]; - - YUV420ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0); - YUV420ToRGB(y + 8, u + 4, v + 4, &R1, &G1, &B1); - YUV420ToRGB(y + 16, u + 8, v + 8, &R2, &G2, &B2); - YUV420ToRGB(y + 24, u + 12, v + 12, &R3, &G3, &B3); - - // Cast to 8b and store as RRRRGGGGBBBB. - rgb[0] = _mm_packus_epi16(R0, R1); - rgb[1] = _mm_packus_epi16(R2, R3); - rgb[2] = _mm_packus_epi16(G0, G1); - rgb[3] = _mm_packus_epi16(G2, G3); - rgb[4] = _mm_packus_epi16(B0, B1); - rgb[5] = _mm_packus_epi16(B2, B3); - - // Pack as RGBRGBRGBRGB. - PlanarTo24b(rgb, dst); - - y += 32; - u += 16; - v += 16; - } - for (; n < len; ++n) { // Finish off - VP8YuvToRgb(y[0], u[0], v[0], dst); - dst += 3; - y += 1; - u += (n & 1); - v += (n & 1); - } -} - -static void YuvToBgrRow(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst, int len) { - int n; - for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) { - __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; - __m128i bgr[6]; - - YUV420ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0); - YUV420ToRGB(y + 8, u + 4, v + 4, &R1, &G1, &B1); - YUV420ToRGB(y + 16, u + 8, v + 8, &R2, &G2, &B2); - YUV420ToRGB(y + 24, u + 12, v + 12, &R3, &G3, &B3); - - // Cast to 8b and store as BBBBGGGGRRRR. - bgr[0] = _mm_packus_epi16(B0, B1); - bgr[1] = _mm_packus_epi16(B2, B3); - bgr[2] = _mm_packus_epi16(G0, G1); - bgr[3] = _mm_packus_epi16(G2, G3); - bgr[4] = _mm_packus_epi16(R0, R1); - bgr[5] = _mm_packus_epi16(R2, R3); - - // Pack as BGRBGRBGRBGR. - PlanarTo24b(bgr, dst); - - y += 32; - u += 16; - v += 16; - } - for (; n < len; ++n) { // Finish off - VP8YuvToBgr(y[0], u[0], v[0], dst); - dst += 3; - y += 1; - u += (n & 1); - v += (n & 1); - } -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void WebPInitSamplersSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersSSE2(void) { - WebPSamplers[MODE_RGB] = YuvToRgbRow; - WebPSamplers[MODE_RGBA] = YuvToRgbaRow; - WebPSamplers[MODE_BGR] = YuvToBgrRow; - WebPSamplers[MODE_BGRA] = YuvToBgraRow; - WebPSamplers[MODE_ARGB] = YuvToArgbRow; -} - -//------------------------------------------------------------------------------ -// RGB24/32 -> YUV converters - -// Load eight 16b-words from *src. -#define LOAD_16(src) _mm_loadu_si128((const __m128i*)(src)) -// Store either 16b-words into *dst -#define STORE_16(V, dst) _mm_storeu_si128((__m128i*)(dst), (V)) - -// Function that inserts a value of the second half of the in buffer in between -// every two char of the first half. -static WEBP_INLINE void RGB24PackedToPlanarHelper( - const __m128i* const in /*in[6]*/, __m128i* const out /*out[6]*/) { - out[0] = _mm_unpacklo_epi8(in[0], in[3]); - out[1] = _mm_unpackhi_epi8(in[0], in[3]); - out[2] = _mm_unpacklo_epi8(in[1], in[4]); - out[3] = _mm_unpackhi_epi8(in[1], in[4]); - out[4] = _mm_unpacklo_epi8(in[2], in[5]); - out[5] = _mm_unpackhi_epi8(in[2], in[5]); -} - -// Unpack the 8b input rgbrgbrgbrgb ... as contiguous registers: -// rrrr... rrrr... gggg... gggg... bbbb... bbbb.... -// Similar to PlanarTo24bHelper(), but in reverse order. -static WEBP_INLINE void RGB24PackedToPlanar(const uint8_t* const rgb, - __m128i* const out /*out[6]*/) { - __m128i tmp[6]; - tmp[0] = _mm_loadu_si128((const __m128i*)(rgb + 0)); - tmp[1] = _mm_loadu_si128((const __m128i*)(rgb + 16)); - tmp[2] = _mm_loadu_si128((const __m128i*)(rgb + 32)); - tmp[3] = _mm_loadu_si128((const __m128i*)(rgb + 48)); - tmp[4] = _mm_loadu_si128((const __m128i*)(rgb + 64)); - tmp[5] = _mm_loadu_si128((const __m128i*)(rgb + 80)); - - RGB24PackedToPlanarHelper(tmp, out); - RGB24PackedToPlanarHelper(out, tmp); - RGB24PackedToPlanarHelper(tmp, out); - RGB24PackedToPlanarHelper(out, tmp); - RGB24PackedToPlanarHelper(tmp, out); -} - -// Convert 8 packed ARGB to r[], g[], b[] -static WEBP_INLINE void RGB32PackedToPlanar(const uint32_t* const argb, - __m128i* const r, - __m128i* const g, - __m128i* const b) { - const __m128i zero = _mm_setzero_si128(); - const __m128i in0 = LOAD_16(argb + 0); // argb3 | argb2 | argb1 | argb0 - const __m128i in1 = LOAD_16(argb + 4); // argb7 | argb6 | argb5 | argb4 - // column-wise transpose - const __m128i A0 = _mm_unpacklo_epi8(in0, in1); - const __m128i A1 = _mm_unpackhi_epi8(in0, in1); - const __m128i B0 = _mm_unpacklo_epi8(A0, A1); - const __m128i B1 = _mm_unpackhi_epi8(A0, A1); - // C0 = g7 g6 ... g1 g0 | b7 b6 ... b1 b0 - // C1 = a7 a6 ... a1 a0 | r7 r6 ... r1 r0 - const __m128i C0 = _mm_unpacklo_epi8(B0, B1); - const __m128i C1 = _mm_unpackhi_epi8(B0, B1); - // store 16b - *r = _mm_unpacklo_epi8(C1, zero); - *g = _mm_unpackhi_epi8(C0, zero); - *b = _mm_unpacklo_epi8(C0, zero); -} - -// This macro computes (RG * MULT_RG + GB * MULT_GB + ROUNDER) >> DESCALE_FIX -// It's a macro and not a function because we need to use immediate values with -// srai_epi32, e.g. -#define TRANSFORM(RG_LO, RG_HI, GB_LO, GB_HI, MULT_RG, MULT_GB, \ - ROUNDER, DESCALE_FIX, OUT) do { \ - const __m128i V0_lo = _mm_madd_epi16(RG_LO, MULT_RG); \ - const __m128i V0_hi = _mm_madd_epi16(RG_HI, MULT_RG); \ - const __m128i V1_lo = _mm_madd_epi16(GB_LO, MULT_GB); \ - const __m128i V1_hi = _mm_madd_epi16(GB_HI, MULT_GB); \ - const __m128i V2_lo = _mm_add_epi32(V0_lo, V1_lo); \ - const __m128i V2_hi = _mm_add_epi32(V0_hi, V1_hi); \ - const __m128i V3_lo = _mm_add_epi32(V2_lo, ROUNDER); \ - const __m128i V3_hi = _mm_add_epi32(V2_hi, ROUNDER); \ - const __m128i V5_lo = _mm_srai_epi32(V3_lo, DESCALE_FIX); \ - const __m128i V5_hi = _mm_srai_epi32(V3_hi, DESCALE_FIX); \ - (OUT) = _mm_packs_epi32(V5_lo, V5_hi); \ -} while (0) - -#define MK_CST_16(A, B) _mm_set_epi16((B), (A), (B), (A), (B), (A), (B), (A)) -static WEBP_INLINE void ConvertRGBToY(const __m128i* const R, - const __m128i* const G, - const __m128i* const B, - __m128i* const Y) { - const __m128i kRG_y = MK_CST_16(16839, 33059 - 16384); - const __m128i kGB_y = MK_CST_16(16384, 6420); - const __m128i kHALF_Y = _mm_set1_epi32((16 << YUV_FIX) + YUV_HALF); - - const __m128i RG_lo = _mm_unpacklo_epi16(*R, *G); - const __m128i RG_hi = _mm_unpackhi_epi16(*R, *G); - const __m128i GB_lo = _mm_unpacklo_epi16(*G, *B); - const __m128i GB_hi = _mm_unpackhi_epi16(*G, *B); - TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_y, kGB_y, kHALF_Y, YUV_FIX, *Y); -} - -static WEBP_INLINE void ConvertRGBToUV(const __m128i* const R, - const __m128i* const G, - const __m128i* const B, - __m128i* const U, __m128i* const V) { - const __m128i kRG_u = MK_CST_16(-9719, -19081); - const __m128i kGB_u = MK_CST_16(0, 28800); - const __m128i kRG_v = MK_CST_16(28800, 0); - const __m128i kGB_v = MK_CST_16(-24116, -4684); - const __m128i kHALF_UV = _mm_set1_epi32(((128 << YUV_FIX) + YUV_HALF) << 2); - - const __m128i RG_lo = _mm_unpacklo_epi16(*R, *G); - const __m128i RG_hi = _mm_unpackhi_epi16(*R, *G); - const __m128i GB_lo = _mm_unpacklo_epi16(*G, *B); - const __m128i GB_hi = _mm_unpackhi_epi16(*G, *B); - TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_u, kGB_u, - kHALF_UV, YUV_FIX + 2, *U); - TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_v, kGB_v, - kHALF_UV, YUV_FIX + 2, *V); -} - -#undef MK_CST_16 -#undef TRANSFORM - -static void ConvertRGB24ToY(const uint8_t* rgb, uint8_t* y, int width) { - const int max_width = width & ~31; - int i; - for (i = 0; i < max_width; rgb += 3 * 16 * 2) { - __m128i rgb_plane[6]; - int j; - - RGB24PackedToPlanar(rgb, rgb_plane); - - for (j = 0; j < 2; ++j, i += 16) { - const __m128i zero = _mm_setzero_si128(); - __m128i r, g, b, Y0, Y1; - - // Convert to 16-bit Y. - r = _mm_unpacklo_epi8(rgb_plane[0 + j], zero); - g = _mm_unpacklo_epi8(rgb_plane[2 + j], zero); - b = _mm_unpacklo_epi8(rgb_plane[4 + j], zero); - ConvertRGBToY(&r, &g, &b, &Y0); - - // Convert to 16-bit Y. - r = _mm_unpackhi_epi8(rgb_plane[0 + j], zero); - g = _mm_unpackhi_epi8(rgb_plane[2 + j], zero); - b = _mm_unpackhi_epi8(rgb_plane[4 + j], zero); - ConvertRGBToY(&r, &g, &b, &Y1); - - // Cast to 8-bit and store. - STORE_16(_mm_packus_epi16(Y0, Y1), y + i); - } - } - for (; i < width; ++i, rgb += 3) { // left-over - y[i] = VP8RGBToY(rgb[0], rgb[1], rgb[2], YUV_HALF); - } -} - -static void ConvertBGR24ToY(const uint8_t* bgr, uint8_t* y, int width) { - const int max_width = width & ~31; - int i; - for (i = 0; i < max_width; bgr += 3 * 16 * 2) { - __m128i bgr_plane[6]; - int j; - - RGB24PackedToPlanar(bgr, bgr_plane); - - for (j = 0; j < 2; ++j, i += 16) { - const __m128i zero = _mm_setzero_si128(); - __m128i r, g, b, Y0, Y1; - - // Convert to 16-bit Y. - b = _mm_unpacklo_epi8(bgr_plane[0 + j], zero); - g = _mm_unpacklo_epi8(bgr_plane[2 + j], zero); - r = _mm_unpacklo_epi8(bgr_plane[4 + j], zero); - ConvertRGBToY(&r, &g, &b, &Y0); - - // Convert to 16-bit Y. - b = _mm_unpackhi_epi8(bgr_plane[0 + j], zero); - g = _mm_unpackhi_epi8(bgr_plane[2 + j], zero); - r = _mm_unpackhi_epi8(bgr_plane[4 + j], zero); - ConvertRGBToY(&r, &g, &b, &Y1); - - // Cast to 8-bit and store. - STORE_16(_mm_packus_epi16(Y0, Y1), y + i); - } - } - for (; i < width; ++i, bgr += 3) { // left-over - y[i] = VP8RGBToY(bgr[2], bgr[1], bgr[0], YUV_HALF); - } -} - -static void ConvertARGBToY(const uint32_t* argb, uint8_t* y, int width) { - const int max_width = width & ~15; - int i; - for (i = 0; i < max_width; i += 16) { - __m128i r, g, b, Y0, Y1; - RGB32PackedToPlanar(&argb[i + 0], &r, &g, &b); - ConvertRGBToY(&r, &g, &b, &Y0); - RGB32PackedToPlanar(&argb[i + 8], &r, &g, &b); - ConvertRGBToY(&r, &g, &b, &Y1); - STORE_16(_mm_packus_epi16(Y0, Y1), y + i); - } - for (; i < width; ++i) { // left-over - const uint32_t p = argb[i]; - y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff, - YUV_HALF); - } -} - -// Horizontal add (doubled) of two 16b values, result is 16b. -// in: A | B | C | D | ... -> out: 2*(A+B) | 2*(C+D) | ... -static void HorizontalAddPack(const __m128i* const A, const __m128i* const B, - __m128i* const out) { - const __m128i k2 = _mm_set1_epi16(2); - const __m128i C = _mm_madd_epi16(*A, k2); - const __m128i D = _mm_madd_epi16(*B, k2); - *out = _mm_packs_epi32(C, D); -} - -static void ConvertARGBToUV(const uint32_t* argb, uint8_t* u, uint8_t* v, - int src_width, int do_store) { - const int max_width = src_width & ~31; - int i; - for (i = 0; i < max_width; i += 32, u += 16, v += 16) { - __m128i r0, g0, b0, r1, g1, b1, U0, V0, U1, V1; - RGB32PackedToPlanar(&argb[i + 0], &r0, &g0, &b0); - RGB32PackedToPlanar(&argb[i + 8], &r1, &g1, &b1); - HorizontalAddPack(&r0, &r1, &r0); - HorizontalAddPack(&g0, &g1, &g0); - HorizontalAddPack(&b0, &b1, &b0); - ConvertRGBToUV(&r0, &g0, &b0, &U0, &V0); - - RGB32PackedToPlanar(&argb[i + 16], &r0, &g0, &b0); - RGB32PackedToPlanar(&argb[i + 24], &r1, &g1, &b1); - HorizontalAddPack(&r0, &r1, &r0); - HorizontalAddPack(&g0, &g1, &g0); - HorizontalAddPack(&b0, &b1, &b0); - ConvertRGBToUV(&r0, &g0, &b0, &U1, &V1); - - U0 = _mm_packus_epi16(U0, U1); - V0 = _mm_packus_epi16(V0, V1); - if (!do_store) { - const __m128i prev_u = LOAD_16(u); - const __m128i prev_v = LOAD_16(v); - U0 = _mm_avg_epu8(U0, prev_u); - V0 = _mm_avg_epu8(V0, prev_v); - } - STORE_16(U0, u); - STORE_16(V0, v); - } - if (i < src_width) { // left-over - WebPConvertARGBToUV_C(argb + i, u, v, src_width - i, do_store); - } -} - -// Convert 16 packed ARGB 16b-values to r[], g[], b[] -static WEBP_INLINE void RGBA32PackedToPlanar_16b(const uint16_t* const rgbx, - __m128i* const r, - __m128i* const g, - __m128i* const b) { - const __m128i in0 = LOAD_16(rgbx + 0); // r0 | g0 | b0 |x| r1 | g1 | b1 |x - const __m128i in1 = LOAD_16(rgbx + 8); // r2 | g2 | b2 |x| r3 | g3 | b3 |x - const __m128i in2 = LOAD_16(rgbx + 16); // r4 | ... - const __m128i in3 = LOAD_16(rgbx + 24); // r6 | ... - // column-wise transpose - const __m128i A0 = _mm_unpacklo_epi16(in0, in1); - const __m128i A1 = _mm_unpackhi_epi16(in0, in1); - const __m128i A2 = _mm_unpacklo_epi16(in2, in3); - const __m128i A3 = _mm_unpackhi_epi16(in2, in3); - const __m128i B0 = _mm_unpacklo_epi16(A0, A1); // r0 r1 r2 r3 | g0 g1 .. - const __m128i B1 = _mm_unpackhi_epi16(A0, A1); // b0 b1 b2 b3 | x x x x - const __m128i B2 = _mm_unpacklo_epi16(A2, A3); // r4 r5 r6 r7 | g4 g5 .. - const __m128i B3 = _mm_unpackhi_epi16(A2, A3); // b4 b5 b6 b7 | x x x x - *r = _mm_unpacklo_epi64(B0, B2); - *g = _mm_unpackhi_epi64(B0, B2); - *b = _mm_unpacklo_epi64(B1, B3); -} - -static void ConvertRGBA32ToUV(const uint16_t* rgb, - uint8_t* u, uint8_t* v, int width) { - const int max_width = width & ~15; - const uint16_t* const last_rgb = rgb + 4 * max_width; - while (rgb < last_rgb) { - __m128i r, g, b, U0, V0, U1, V1; - RGBA32PackedToPlanar_16b(rgb + 0, &r, &g, &b); - ConvertRGBToUV(&r, &g, &b, &U0, &V0); - RGBA32PackedToPlanar_16b(rgb + 32, &r, &g, &b); - ConvertRGBToUV(&r, &g, &b, &U1, &V1); - STORE_16(_mm_packus_epi16(U0, U1), u); - STORE_16(_mm_packus_epi16(V0, V1), v); - u += 16; - v += 16; - rgb += 2 * 32; - } - if (max_width < width) { // left-over - WebPConvertRGBA32ToUV_C(rgb, u, v, width - max_width); - } -} - -//------------------------------------------------------------------------------ - -extern void WebPInitConvertARGBToYUVSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUVSSE2(void) { - WebPConvertARGBToY = ConvertARGBToY; - WebPConvertARGBToUV = ConvertARGBToUV; - - WebPConvertRGB24ToY = ConvertRGB24ToY; - WebPConvertBGR24ToY = ConvertBGR24ToY; - - WebPConvertRGBA32ToUV = ConvertRGBA32ToUV; -} - -#else // !WEBP_USE_SSE2 - -WEBP_DSP_INIT_STUB(WebPInitSamplersSSE2) -WEBP_DSP_INIT_STUB(WebPInitConvertARGBToYUVSSE2) - -#endif // WEBP_USE_SSE2 diff --git a/Example-Mac/Pods/libwebp/src/enc/alpha.c b/Example-Mac/Pods/libwebp/src/enc/alpha.c deleted file mode 100644 index 3c970b00..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/alpha.c +++ /dev/null @@ -1,430 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Alpha-plane compression. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include - -#include "./vp8enci.h" -#include "../dsp/dsp.h" -#include "../utils/filters.h" -#include "../utils/quant_levels.h" -#include "../utils/utils.h" -#include "../webp/format_constants.h" - -// ----------------------------------------------------------------------------- -// Encodes the given alpha data via specified compression method 'method'. -// The pre-processing (quantization) is performed if 'quality' is less than 100. -// For such cases, the encoding is lossy. The valid range is [0, 100] for -// 'quality' and [0, 1] for 'method': -// 'method = 0' - No compression; -// 'method = 1' - Use lossless coder on the alpha plane only -// 'filter' values [0, 4] correspond to prediction modes none, horizontal, -// vertical & gradient filters. The prediction mode 4 will try all the -// prediction modes 0 to 3 and pick the best one. -// 'effort_level': specifies how much effort must be spent to try and reduce -// the compressed output size. In range 0 (quick) to 6 (slow). -// -// 'output' corresponds to the buffer containing compressed alpha data. -// This buffer is allocated by this method and caller should call -// WebPSafeFree(*output) when done. -// 'output_size' corresponds to size of this compressed alpha buffer. -// -// Returns 1 on successfully encoding the alpha and -// 0 if either: -// invalid quality or method, or -// memory allocation for the compressed data fails. - -#include "../enc/vp8li.h" - -static int EncodeLossless(const uint8_t* const data, int width, int height, - int effort_level, // in [0..6] range - VP8LBitWriter* const bw, - WebPAuxStats* const stats) { - int ok = 0; - WebPConfig config; - WebPPicture picture; - - WebPPictureInit(&picture); - picture.width = width; - picture.height = height; - picture.use_argb = 1; - picture.stats = stats; - if (!WebPPictureAlloc(&picture)) return 0; - - // Transfer the alpha values to the green channel. - WebPDispatchAlphaToGreen(data, width, picture.width, picture.height, - picture.argb, picture.argb_stride); - - WebPConfigInit(&config); - config.lossless = 1; - // Enable exact, or it would alter RGB values of transparent alpha, which is - // normally OK but not here since we are not encoding the input image but an - // internal encoding-related image containing necessary exact information in - // RGB channels. - config.exact = 1; - config.method = effort_level; // impact is very small - // Set a low default quality for encoding alpha. Ensure that Alpha quality at - // lower methods (3 and below) is less than the threshold for triggering - // costly 'BackwardReferencesTraceBackwards'. - config.quality = 8.f * effort_level; - assert(config.quality >= 0 && config.quality <= 100.f); - - ok = (VP8LEncodeStream(&config, &picture, bw) == VP8_ENC_OK); - WebPPictureFree(&picture); - ok = ok && !bw->error_; - if (!ok) { - VP8LBitWriterWipeOut(bw); - return 0; - } - return 1; -} - -// ----------------------------------------------------------------------------- - -// Small struct to hold the result of a filter mode compression attempt. -typedef struct { - size_t score; - VP8BitWriter bw; - WebPAuxStats stats; -} FilterTrial; - -// This function always returns an initialized 'bw' object, even upon error. -static int EncodeAlphaInternal(const uint8_t* const data, int width, int height, - int method, int filter, int reduce_levels, - int effort_level, // in [0..6] range - uint8_t* const tmp_alpha, - FilterTrial* result) { - int ok = 0; - const uint8_t* alpha_src; - WebPFilterFunc filter_func; - uint8_t header; - const size_t data_size = width * height; - const uint8_t* output = NULL; - size_t output_size = 0; - VP8LBitWriter tmp_bw; - - assert((uint64_t)data_size == (uint64_t)width * height); // as per spec - assert(filter >= 0 && filter < WEBP_FILTER_LAST); - assert(method >= ALPHA_NO_COMPRESSION); - assert(method <= ALPHA_LOSSLESS_COMPRESSION); - assert(sizeof(header) == ALPHA_HEADER_LEN); - // TODO(skal): have a common function and #define's to validate alpha params. - - filter_func = WebPFilters[filter]; - if (filter_func != NULL) { - filter_func(data, width, height, width, tmp_alpha); - alpha_src = tmp_alpha; - } else { - alpha_src = data; - } - - if (method != ALPHA_NO_COMPRESSION) { - ok = VP8LBitWriterInit(&tmp_bw, data_size >> 3); - ok = ok && EncodeLossless(alpha_src, width, height, effort_level, - &tmp_bw, &result->stats); - if (ok) { - output = VP8LBitWriterFinish(&tmp_bw); - output_size = VP8LBitWriterNumBytes(&tmp_bw); - if (output_size > data_size) { - // compressed size is larger than source! Revert to uncompressed mode. - method = ALPHA_NO_COMPRESSION; - VP8LBitWriterWipeOut(&tmp_bw); - } - } else { - VP8LBitWriterWipeOut(&tmp_bw); - return 0; - } - } - - if (method == ALPHA_NO_COMPRESSION) { - output = alpha_src; - output_size = data_size; - ok = 1; - } - - // Emit final result. - header = method | (filter << 2); - if (reduce_levels) header |= ALPHA_PREPROCESSED_LEVELS << 4; - - VP8BitWriterInit(&result->bw, ALPHA_HEADER_LEN + output_size); - ok = ok && VP8BitWriterAppend(&result->bw, &header, ALPHA_HEADER_LEN); - ok = ok && VP8BitWriterAppend(&result->bw, output, output_size); - - if (method != ALPHA_NO_COMPRESSION) { - VP8LBitWriterWipeOut(&tmp_bw); - } - ok = ok && !result->bw.error_; - result->score = VP8BitWriterSize(&result->bw); - return ok; -} - -// ----------------------------------------------------------------------------- - -static int GetNumColors(const uint8_t* data, int width, int height, - int stride) { - int j; - int colors = 0; - uint8_t color[256] = { 0 }; - - for (j = 0; j < height; ++j) { - int i; - const uint8_t* const p = data + j * stride; - for (i = 0; i < width; ++i) { - color[p[i]] = 1; - } - } - for (j = 0; j < 256; ++j) { - if (color[j] > 0) ++colors; - } - return colors; -} - -#define FILTER_TRY_NONE (1 << WEBP_FILTER_NONE) -#define FILTER_TRY_ALL ((1 << WEBP_FILTER_LAST) - 1) - -// Given the input 'filter' option, return an OR'd bit-set of filters to try. -static uint32_t GetFilterMap(const uint8_t* alpha, int width, int height, - int filter, int effort_level) { - uint32_t bit_map = 0U; - if (filter == WEBP_FILTER_FAST) { - // Quick estimate of the best candidate. - int try_filter_none = (effort_level > 3); - const int kMinColorsForFilterNone = 16; - const int kMaxColorsForFilterNone = 192; - const int num_colors = GetNumColors(alpha, width, height, width); - // For low number of colors, NONE yields better compression. - filter = (num_colors <= kMinColorsForFilterNone) - ? WEBP_FILTER_NONE - : WebPEstimateBestFilter(alpha, width, height, width); - bit_map |= 1 << filter; - // For large number of colors, try FILTER_NONE in addition to the best - // filter as well. - if (try_filter_none || num_colors > kMaxColorsForFilterNone) { - bit_map |= FILTER_TRY_NONE; - } - } else if (filter == WEBP_FILTER_NONE) { - bit_map = FILTER_TRY_NONE; - } else { // WEBP_FILTER_BEST -> try all - bit_map = FILTER_TRY_ALL; - } - return bit_map; -} - -static void InitFilterTrial(FilterTrial* const score) { - score->score = (size_t)~0U; - VP8BitWriterInit(&score->bw, 0); -} - -static int ApplyFiltersAndEncode(const uint8_t* alpha, int width, int height, - size_t data_size, int method, int filter, - int reduce_levels, int effort_level, - uint8_t** const output, - size_t* const output_size, - WebPAuxStats* const stats) { - int ok = 1; - FilterTrial best; - uint32_t try_map = - GetFilterMap(alpha, width, height, filter, effort_level); - InitFilterTrial(&best); - - if (try_map != FILTER_TRY_NONE) { - uint8_t* filtered_alpha = (uint8_t*)WebPSafeMalloc(1ULL, data_size); - if (filtered_alpha == NULL) return 0; - - for (filter = WEBP_FILTER_NONE; ok && try_map; ++filter, try_map >>= 1) { - if (try_map & 1) { - FilterTrial trial; - ok = EncodeAlphaInternal(alpha, width, height, method, filter, - reduce_levels, effort_level, filtered_alpha, - &trial); - if (ok && trial.score < best.score) { - VP8BitWriterWipeOut(&best.bw); - best = trial; - } else { - VP8BitWriterWipeOut(&trial.bw); - } - } - } - WebPSafeFree(filtered_alpha); - } else { - ok = EncodeAlphaInternal(alpha, width, height, method, WEBP_FILTER_NONE, - reduce_levels, effort_level, NULL, &best); - } - if (ok) { - if (stats != NULL) { - stats->lossless_features = best.stats.lossless_features; - stats->histogram_bits = best.stats.histogram_bits; - stats->transform_bits = best.stats.transform_bits; - stats->cache_bits = best.stats.cache_bits; - stats->palette_size = best.stats.palette_size; - stats->lossless_size = best.stats.lossless_size; - stats->lossless_hdr_size = best.stats.lossless_hdr_size; - stats->lossless_data_size = best.stats.lossless_data_size; - } - *output_size = VP8BitWriterSize(&best.bw); - *output = VP8BitWriterBuf(&best.bw); - } else { - VP8BitWriterWipeOut(&best.bw); - } - return ok; -} - -static int EncodeAlpha(VP8Encoder* const enc, - int quality, int method, int filter, - int effort_level, - uint8_t** const output, size_t* const output_size) { - const WebPPicture* const pic = enc->pic_; - const int width = pic->width; - const int height = pic->height; - - uint8_t* quant_alpha = NULL; - const size_t data_size = width * height; - uint64_t sse = 0; - int ok = 1; - const int reduce_levels = (quality < 100); - - // quick sanity checks - assert((uint64_t)data_size == (uint64_t)width * height); // as per spec - assert(enc != NULL && pic != NULL && pic->a != NULL); - assert(output != NULL && output_size != NULL); - assert(width > 0 && height > 0); - assert(pic->a_stride >= width); - assert(filter >= WEBP_FILTER_NONE && filter <= WEBP_FILTER_FAST); - - if (quality < 0 || quality > 100) { - return 0; - } - - if (method < ALPHA_NO_COMPRESSION || method > ALPHA_LOSSLESS_COMPRESSION) { - return 0; - } - - if (method == ALPHA_NO_COMPRESSION) { - // Don't filter, as filtering will make no impact on compressed size. - filter = WEBP_FILTER_NONE; - } - - quant_alpha = (uint8_t*)WebPSafeMalloc(1ULL, data_size); - if (quant_alpha == NULL) { - return 0; - } - - // Extract alpha data (width x height) from raw_data (stride x height). - WebPCopyPlane(pic->a, pic->a_stride, quant_alpha, width, width, height); - - if (reduce_levels) { // No Quantization required for 'quality = 100'. - // 16 alpha levels gives quite a low MSE w.r.t original alpha plane hence - // mapped to moderate quality 70. Hence Quality:[0, 70] -> Levels:[2, 16] - // and Quality:]70, 100] -> Levels:]16, 256]. - const int alpha_levels = (quality <= 70) ? (2 + quality / 5) - : (16 + (quality - 70) * 8); - ok = QuantizeLevels(quant_alpha, width, height, alpha_levels, &sse); - } - - if (ok) { - VP8FiltersInit(); - ok = ApplyFiltersAndEncode(quant_alpha, width, height, data_size, method, - filter, reduce_levels, effort_level, output, - output_size, pic->stats); - if (pic->stats != NULL) { // need stats? - pic->stats->coded_size += (int)(*output_size); - enc->sse_[3] = sse; - } - } - - WebPSafeFree(quant_alpha); - return ok; -} - -//------------------------------------------------------------------------------ -// Main calls - -static int CompressAlphaJob(VP8Encoder* const enc, void* dummy) { - const WebPConfig* config = enc->config_; - uint8_t* alpha_data = NULL; - size_t alpha_size = 0; - const int effort_level = config->method; // maps to [0..6] - const WEBP_FILTER_TYPE filter = - (config->alpha_filtering == 0) ? WEBP_FILTER_NONE : - (config->alpha_filtering == 1) ? WEBP_FILTER_FAST : - WEBP_FILTER_BEST; - if (!EncodeAlpha(enc, config->alpha_quality, config->alpha_compression, - filter, effort_level, &alpha_data, &alpha_size)) { - return 0; - } - if (alpha_size != (uint32_t)alpha_size) { // Sanity check. - WebPSafeFree(alpha_data); - return 0; - } - enc->alpha_data_size_ = (uint32_t)alpha_size; - enc->alpha_data_ = alpha_data; - (void)dummy; - return 1; -} - -void VP8EncInitAlpha(VP8Encoder* const enc) { - WebPInitAlphaProcessing(); - enc->has_alpha_ = WebPPictureHasTransparency(enc->pic_); - enc->alpha_data_ = NULL; - enc->alpha_data_size_ = 0; - if (enc->thread_level_ > 0) { - WebPWorker* const worker = &enc->alpha_worker_; - WebPGetWorkerInterface()->Init(worker); - worker->data1 = enc; - worker->data2 = NULL; - worker->hook = (WebPWorkerHook)CompressAlphaJob; - } -} - -int VP8EncStartAlpha(VP8Encoder* const enc) { - if (enc->has_alpha_) { - if (enc->thread_level_ > 0) { - WebPWorker* const worker = &enc->alpha_worker_; - // Makes sure worker is good to go. - if (!WebPGetWorkerInterface()->Reset(worker)) { - return 0; - } - WebPGetWorkerInterface()->Launch(worker); - return 1; - } else { - return CompressAlphaJob(enc, NULL); // just do the job right away - } - } - return 1; -} - -int VP8EncFinishAlpha(VP8Encoder* const enc) { - if (enc->has_alpha_) { - if (enc->thread_level_ > 0) { - WebPWorker* const worker = &enc->alpha_worker_; - if (!WebPGetWorkerInterface()->Sync(worker)) return 0; // error - } - } - return WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_); -} - -int VP8EncDeleteAlpha(VP8Encoder* const enc) { - int ok = 1; - if (enc->thread_level_ > 0) { - WebPWorker* const worker = &enc->alpha_worker_; - // finish anything left in flight - ok = WebPGetWorkerInterface()->Sync(worker); - // still need to end the worker, even if !ok - WebPGetWorkerInterface()->End(worker); - } - WebPSafeFree(enc->alpha_data_); - enc->alpha_data_ = NULL; - enc->alpha_data_size_ = 0; - enc->has_alpha_ = 0; - return ok; -} diff --git a/Example-Mac/Pods/libwebp/src/enc/analysis.c b/Example-Mac/Pods/libwebp/src/enc/analysis.c deleted file mode 100644 index b55128fd..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/analysis.c +++ /dev/null @@ -1,501 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Macroblock analysis -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include -#include - -#include "./vp8enci.h" -#include "./cost.h" -#include "../utils/utils.h" - -#define MAX_ITERS_K_MEANS 6 - -//------------------------------------------------------------------------------ -// Smooth the segment map by replacing isolated block by the majority of its -// neighbours. - -static void SmoothSegmentMap(VP8Encoder* const enc) { - int n, x, y; - const int w = enc->mb_w_; - const int h = enc->mb_h_; - const int majority_cnt_3_x_3_grid = 5; - uint8_t* const tmp = (uint8_t*)WebPSafeMalloc(w * h, sizeof(*tmp)); - assert((uint64_t)(w * h) == (uint64_t)w * h); // no overflow, as per spec - - if (tmp == NULL) return; - for (y = 1; y < h - 1; ++y) { - for (x = 1; x < w - 1; ++x) { - int cnt[NUM_MB_SEGMENTS] = { 0 }; - const VP8MBInfo* const mb = &enc->mb_info_[x + w * y]; - int majority_seg = mb->segment_; - // Check the 8 neighbouring segment values. - cnt[mb[-w - 1].segment_]++; // top-left - cnt[mb[-w + 0].segment_]++; // top - cnt[mb[-w + 1].segment_]++; // top-right - cnt[mb[ - 1].segment_]++; // left - cnt[mb[ + 1].segment_]++; // right - cnt[mb[ w - 1].segment_]++; // bottom-left - cnt[mb[ w + 0].segment_]++; // bottom - cnt[mb[ w + 1].segment_]++; // bottom-right - for (n = 0; n < NUM_MB_SEGMENTS; ++n) { - if (cnt[n] >= majority_cnt_3_x_3_grid) { - majority_seg = n; - break; - } - } - tmp[x + y * w] = majority_seg; - } - } - for (y = 1; y < h - 1; ++y) { - for (x = 1; x < w - 1; ++x) { - VP8MBInfo* const mb = &enc->mb_info_[x + w * y]; - mb->segment_ = tmp[x + y * w]; - } - } - WebPSafeFree(tmp); -} - -//------------------------------------------------------------------------------ -// set segment susceptibility alpha_ / beta_ - -static WEBP_INLINE int clip(int v, int m, int M) { - return (v < m) ? m : (v > M) ? M : v; -} - -static void SetSegmentAlphas(VP8Encoder* const enc, - const int centers[NUM_MB_SEGMENTS], - int mid) { - const int nb = enc->segment_hdr_.num_segments_; - int min = centers[0], max = centers[0]; - int n; - - if (nb > 1) { - for (n = 0; n < nb; ++n) { - if (min > centers[n]) min = centers[n]; - if (max < centers[n]) max = centers[n]; - } - } - if (max == min) max = min + 1; - assert(mid <= max && mid >= min); - for (n = 0; n < nb; ++n) { - const int alpha = 255 * (centers[n] - mid) / (max - min); - const int beta = 255 * (centers[n] - min) / (max - min); - enc->dqm_[n].alpha_ = clip(alpha, -127, 127); - enc->dqm_[n].beta_ = clip(beta, 0, 255); - } -} - -//------------------------------------------------------------------------------ -// Compute susceptibility based on DCT-coeff histograms: -// the higher, the "easier" the macroblock is to compress. - -#define MAX_ALPHA 255 // 8b of precision for susceptibilities. -#define ALPHA_SCALE (2 * MAX_ALPHA) // scaling factor for alpha. -#define DEFAULT_ALPHA (-1) -#define IS_BETTER_ALPHA(alpha, best_alpha) ((alpha) > (best_alpha)) - -static int FinalAlphaValue(int alpha) { - alpha = MAX_ALPHA - alpha; - return clip(alpha, 0, MAX_ALPHA); -} - -static int GetAlpha(const VP8Histogram* const histo) { - // 'alpha' will later be clipped to [0..MAX_ALPHA] range, clamping outer - // values which happen to be mostly noise. This leaves the maximum precision - // for handling the useful small values which contribute most. - const int max_value = histo->max_value; - const int last_non_zero = histo->last_non_zero; - const int alpha = - (max_value > 1) ? ALPHA_SCALE * last_non_zero / max_value : 0; - return alpha; -} - -static void InitHistogram(VP8Histogram* const histo) { - histo->max_value = 0; - histo->last_non_zero = 1; -} - -static void MergeHistograms(const VP8Histogram* const in, - VP8Histogram* const out) { - if (in->max_value > out->max_value) { - out->max_value = in->max_value; - } - if (in->last_non_zero > out->last_non_zero) { - out->last_non_zero = in->last_non_zero; - } -} - -//------------------------------------------------------------------------------ -// Simplified k-Means, to assign Nb segments based on alpha-histogram - -static void AssignSegments(VP8Encoder* const enc, - const int alphas[MAX_ALPHA + 1]) { - // 'num_segments_' is previously validated and <= NUM_MB_SEGMENTS, but an - // explicit check is needed to avoid spurious warning about 'n + 1' exceeding - // array bounds of 'centers' with some compilers (noticed with gcc-4.9). - const int nb = (enc->segment_hdr_.num_segments_ < NUM_MB_SEGMENTS) ? - enc->segment_hdr_.num_segments_ : NUM_MB_SEGMENTS; - int centers[NUM_MB_SEGMENTS]; - int weighted_average = 0; - int map[MAX_ALPHA + 1]; - int a, n, k; - int min_a = 0, max_a = MAX_ALPHA, range_a; - // 'int' type is ok for histo, and won't overflow - int accum[NUM_MB_SEGMENTS], dist_accum[NUM_MB_SEGMENTS]; - - assert(nb >= 1); - assert(nb <= NUM_MB_SEGMENTS); - - // bracket the input - for (n = 0; n <= MAX_ALPHA && alphas[n] == 0; ++n) {} - min_a = n; - for (n = MAX_ALPHA; n > min_a && alphas[n] == 0; --n) {} - max_a = n; - range_a = max_a - min_a; - - // Spread initial centers evenly - for (k = 0, n = 1; k < nb; ++k, n += 2) { - assert(n < 2 * nb); - centers[k] = min_a + (n * range_a) / (2 * nb); - } - - for (k = 0; k < MAX_ITERS_K_MEANS; ++k) { // few iters are enough - int total_weight; - int displaced; - // Reset stats - for (n = 0; n < nb; ++n) { - accum[n] = 0; - dist_accum[n] = 0; - } - // Assign nearest center for each 'a' - n = 0; // track the nearest center for current 'a' - for (a = min_a; a <= max_a; ++a) { - if (alphas[a]) { - while (n + 1 < nb && abs(a - centers[n + 1]) < abs(a - centers[n])) { - n++; - } - map[a] = n; - // accumulate contribution into best centroid - dist_accum[n] += a * alphas[a]; - accum[n] += alphas[a]; - } - } - // All point are classified. Move the centroids to the - // center of their respective cloud. - displaced = 0; - weighted_average = 0; - total_weight = 0; - for (n = 0; n < nb; ++n) { - if (accum[n]) { - const int new_center = (dist_accum[n] + accum[n] / 2) / accum[n]; - displaced += abs(centers[n] - new_center); - centers[n] = new_center; - weighted_average += new_center * accum[n]; - total_weight += accum[n]; - } - } - weighted_average = (weighted_average + total_weight / 2) / total_weight; - if (displaced < 5) break; // no need to keep on looping... - } - - // Map each original value to the closest centroid - for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { - VP8MBInfo* const mb = &enc->mb_info_[n]; - const int alpha = mb->alpha_; - mb->segment_ = map[alpha]; - mb->alpha_ = centers[map[alpha]]; // for the record. - } - - if (nb > 1) { - const int smooth = (enc->config_->preprocessing & 1); - if (smooth) SmoothSegmentMap(enc); - } - - SetSegmentAlphas(enc, centers, weighted_average); // pick some alphas. -} - -//------------------------------------------------------------------------------ -// Macroblock analysis: collect histogram for each mode, deduce the maximal -// susceptibility and set best modes for this macroblock. -// Segment assignment is done later. - -// Number of modes to inspect for alpha_ evaluation. We don't need to test all -// the possible modes during the analysis phase: we risk falling into a local -// optimum, or be subject to boundary effect -#define MAX_INTRA16_MODE 2 -#define MAX_INTRA4_MODE 2 -#define MAX_UV_MODE 2 - -static int MBAnalyzeBestIntra16Mode(VP8EncIterator* const it) { - const int max_mode = MAX_INTRA16_MODE; - int mode; - int best_alpha = DEFAULT_ALPHA; - int best_mode = 0; - - VP8MakeLuma16Preds(it); - for (mode = 0; mode < max_mode; ++mode) { - VP8Histogram histo; - int alpha; - - InitHistogram(&histo); - VP8CollectHistogram(it->yuv_in_ + Y_OFF_ENC, - it->yuv_p_ + VP8I16ModeOffsets[mode], - 0, 16, &histo); - alpha = GetAlpha(&histo); - if (IS_BETTER_ALPHA(alpha, best_alpha)) { - best_alpha = alpha; - best_mode = mode; - } - } - VP8SetIntra16Mode(it, best_mode); - return best_alpha; -} - -static int MBAnalyzeBestIntra4Mode(VP8EncIterator* const it, - int best_alpha) { - uint8_t modes[16]; - const int max_mode = MAX_INTRA4_MODE; - int i4_alpha; - VP8Histogram total_histo; - int cur_histo = 0; - InitHistogram(&total_histo); - - VP8IteratorStartI4(it); - do { - int mode; - int best_mode_alpha = DEFAULT_ALPHA; - VP8Histogram histos[2]; - const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_]; - - VP8MakeIntra4Preds(it); - for (mode = 0; mode < max_mode; ++mode) { - int alpha; - - InitHistogram(&histos[cur_histo]); - VP8CollectHistogram(src, it->yuv_p_ + VP8I4ModeOffsets[mode], - 0, 1, &histos[cur_histo]); - alpha = GetAlpha(&histos[cur_histo]); - if (IS_BETTER_ALPHA(alpha, best_mode_alpha)) { - best_mode_alpha = alpha; - modes[it->i4_] = mode; - cur_histo ^= 1; // keep track of best histo so far. - } - } - // accumulate best histogram - MergeHistograms(&histos[cur_histo ^ 1], &total_histo); - // Note: we reuse the original samples for predictors - } while (VP8IteratorRotateI4(it, it->yuv_in_ + Y_OFF_ENC)); - - i4_alpha = GetAlpha(&total_histo); - if (IS_BETTER_ALPHA(i4_alpha, best_alpha)) { - VP8SetIntra4Mode(it, modes); - best_alpha = i4_alpha; - } - return best_alpha; -} - -static int MBAnalyzeBestUVMode(VP8EncIterator* const it) { - int best_alpha = DEFAULT_ALPHA; - int best_mode = 0; - const int max_mode = MAX_UV_MODE; - int mode; - - VP8MakeChroma8Preds(it); - for (mode = 0; mode < max_mode; ++mode) { - VP8Histogram histo; - int alpha; - InitHistogram(&histo); - VP8CollectHistogram(it->yuv_in_ + U_OFF_ENC, - it->yuv_p_ + VP8UVModeOffsets[mode], - 16, 16 + 4 + 4, &histo); - alpha = GetAlpha(&histo); - if (IS_BETTER_ALPHA(alpha, best_alpha)) { - best_alpha = alpha; - best_mode = mode; - } - } - VP8SetIntraUVMode(it, best_mode); - return best_alpha; -} - -static void MBAnalyze(VP8EncIterator* const it, - int alphas[MAX_ALPHA + 1], - int* const alpha, int* const uv_alpha) { - const VP8Encoder* const enc = it->enc_; - int best_alpha, best_uv_alpha; - - VP8SetIntra16Mode(it, 0); // default: Intra16, DC_PRED - VP8SetSkip(it, 0); // not skipped - VP8SetSegment(it, 0); // default segment, spec-wise. - - best_alpha = MBAnalyzeBestIntra16Mode(it); - if (enc->method_ >= 5) { - // We go and make a fast decision for intra4/intra16. - // It's usually not a good and definitive pick, but helps seeding the stats - // about level bit-cost. - // TODO(skal): improve criterion. - best_alpha = MBAnalyzeBestIntra4Mode(it, best_alpha); - } - best_uv_alpha = MBAnalyzeBestUVMode(it); - - // Final susceptibility mix - best_alpha = (3 * best_alpha + best_uv_alpha + 2) >> 2; - best_alpha = FinalAlphaValue(best_alpha); - alphas[best_alpha]++; - it->mb_->alpha_ = best_alpha; // for later remapping. - - // Accumulate for later complexity analysis. - *alpha += best_alpha; // mixed susceptibility (not just luma) - *uv_alpha += best_uv_alpha; -} - -static void DefaultMBInfo(VP8MBInfo* const mb) { - mb->type_ = 1; // I16x16 - mb->uv_mode_ = 0; - mb->skip_ = 0; // not skipped - mb->segment_ = 0; // default segment - mb->alpha_ = 0; -} - -//------------------------------------------------------------------------------ -// Main analysis loop: -// Collect all susceptibilities for each macroblock and record their -// distribution in alphas[]. Segments is assigned a-posteriori, based on -// this histogram. -// We also pick an intra16 prediction mode, which shouldn't be considered -// final except for fast-encode settings. We can also pick some intra4 modes -// and decide intra4/intra16, but that's usually almost always a bad choice at -// this stage. - -static void ResetAllMBInfo(VP8Encoder* const enc) { - int n; - for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { - DefaultMBInfo(&enc->mb_info_[n]); - } - // Default susceptibilities. - enc->dqm_[0].alpha_ = 0; - enc->dqm_[0].beta_ = 0; - // Note: we can't compute this alpha_ / uv_alpha_ -> set to default value. - enc->alpha_ = 0; - enc->uv_alpha_ = 0; - WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_); -} - -// struct used to collect job result -typedef struct { - WebPWorker worker; - int alphas[MAX_ALPHA + 1]; - int alpha, uv_alpha; - VP8EncIterator it; - int delta_progress; -} SegmentJob; - -// main work call -static int DoSegmentsJob(SegmentJob* const job, VP8EncIterator* const it) { - int ok = 1; - if (!VP8IteratorIsDone(it)) { - uint8_t tmp[32 + WEBP_ALIGN_CST]; - uint8_t* const scratch = (uint8_t*)WEBP_ALIGN(tmp); - do { - // Let's pretend we have perfect lossless reconstruction. - VP8IteratorImport(it, scratch); - MBAnalyze(it, job->alphas, &job->alpha, &job->uv_alpha); - ok = VP8IteratorProgress(it, job->delta_progress); - } while (ok && VP8IteratorNext(it)); - } - return ok; -} - -static void MergeJobs(const SegmentJob* const src, SegmentJob* const dst) { - int i; - for (i = 0; i <= MAX_ALPHA; ++i) dst->alphas[i] += src->alphas[i]; - dst->alpha += src->alpha; - dst->uv_alpha += src->uv_alpha; -} - -// initialize the job struct with some TODOs -static void InitSegmentJob(VP8Encoder* const enc, SegmentJob* const job, - int start_row, int end_row) { - WebPGetWorkerInterface()->Init(&job->worker); - job->worker.data1 = job; - job->worker.data2 = &job->it; - job->worker.hook = (WebPWorkerHook)DoSegmentsJob; - VP8IteratorInit(enc, &job->it); - VP8IteratorSetRow(&job->it, start_row); - VP8IteratorSetCountDown(&job->it, (end_row - start_row) * enc->mb_w_); - memset(job->alphas, 0, sizeof(job->alphas)); - job->alpha = 0; - job->uv_alpha = 0; - // only one of both jobs can record the progress, since we don't - // expect the user's hook to be multi-thread safe - job->delta_progress = (start_row == 0) ? 20 : 0; -} - -// main entry point -int VP8EncAnalyze(VP8Encoder* const enc) { - int ok = 1; - const int do_segments = - enc->config_->emulate_jpeg_size || // We need the complexity evaluation. - (enc->segment_hdr_.num_segments_ > 1) || - (enc->method_ == 0); // for method 0, we need preds_[] to be filled. - if (do_segments) { - const int last_row = enc->mb_h_; - // We give a little more than a half work to the main thread. - const int split_row = (9 * last_row + 15) >> 4; - const int total_mb = last_row * enc->mb_w_; -#ifdef WEBP_USE_THREAD - const int kMinSplitRow = 2; // minimal rows needed for mt to be worth it - const int do_mt = (enc->thread_level_ > 0) && (split_row >= kMinSplitRow); -#else - const int do_mt = 0; -#endif - const WebPWorkerInterface* const worker_interface = - WebPGetWorkerInterface(); - SegmentJob main_job; - if (do_mt) { - SegmentJob side_job; - // Note the use of '&' instead of '&&' because we must call the functions - // no matter what. - InitSegmentJob(enc, &main_job, 0, split_row); - InitSegmentJob(enc, &side_job, split_row, last_row); - // we don't need to call Reset() on main_job.worker, since we're calling - // WebPWorkerExecute() on it - ok &= worker_interface->Reset(&side_job.worker); - // launch the two jobs in parallel - if (ok) { - worker_interface->Launch(&side_job.worker); - worker_interface->Execute(&main_job.worker); - ok &= worker_interface->Sync(&side_job.worker); - ok &= worker_interface->Sync(&main_job.worker); - } - worker_interface->End(&side_job.worker); - if (ok) MergeJobs(&side_job, &main_job); // merge results together - } else { - // Even for single-thread case, we use the generic Worker tools. - InitSegmentJob(enc, &main_job, 0, last_row); - worker_interface->Execute(&main_job.worker); - ok &= worker_interface->Sync(&main_job.worker); - } - worker_interface->End(&main_job.worker); - if (ok) { - enc->alpha_ = main_job.alpha / total_mb; - enc->uv_alpha_ = main_job.uv_alpha / total_mb; - AssignSegments(enc, main_job.alphas); - } - } else { // Use only one default segment. - ResetAllMBInfo(enc); - } - return ok; -} - diff --git a/Example-Mac/Pods/libwebp/src/enc/backward_references.c b/Example-Mac/Pods/libwebp/src/enc/backward_references.c deleted file mode 100644 index c39437dd..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/backward_references.c +++ /dev/null @@ -1,1093 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Jyrki Alakuijala (jyrki@google.com) -// - -#include -#include - -#include "./backward_references.h" -#include "./histogram.h" -#include "../dsp/lossless.h" -#include "../dsp/dsp.h" -#include "../utils/color_cache.h" -#include "../utils/utils.h" - -#define VALUES_IN_BYTE 256 - -#define MIN_BLOCK_SIZE 256 // minimum block size for backward references - -#define MAX_ENTROPY (1e30f) - -// 1M window (4M bytes) minus 120 special codes for short distances. -#define WINDOW_SIZE ((1 << 20) - 120) - -// Bounds for the match length. -#define MIN_LENGTH 2 -#define MAX_LENGTH 4096 - -// ----------------------------------------------------------------------------- - -static const uint8_t plane_to_code_lut[128] = { - 96, 73, 55, 39, 23, 13, 5, 1, 255, 255, 255, 255, 255, 255, 255, 255, - 101, 78, 58, 42, 26, 16, 8, 2, 0, 3, 9, 17, 27, 43, 59, 79, - 102, 86, 62, 46, 32, 20, 10, 6, 4, 7, 11, 21, 33, 47, 63, 87, - 105, 90, 70, 52, 37, 28, 18, 14, 12, 15, 19, 29, 38, 53, 71, 91, - 110, 99, 82, 66, 48, 35, 30, 24, 22, 25, 31, 36, 49, 67, 83, 100, - 115, 108, 94, 76, 64, 50, 44, 40, 34, 41, 45, 51, 65, 77, 95, 109, - 118, 113, 103, 92, 80, 68, 60, 56, 54, 57, 61, 69, 81, 93, 104, 114, - 119, 116, 111, 106, 97, 88, 84, 74, 72, 75, 85, 89, 98, 107, 112, 117 -}; - -static int DistanceToPlaneCode(int xsize, int dist) { - const int yoffset = dist / xsize; - const int xoffset = dist - yoffset * xsize; - if (xoffset <= 8 && yoffset < 8) { - return plane_to_code_lut[yoffset * 16 + 8 - xoffset] + 1; - } else if (xoffset > xsize - 8 && yoffset < 7) { - return plane_to_code_lut[(yoffset + 1) * 16 + 8 + (xsize - xoffset)] + 1; - } - return dist + 120; -} - -// Returns the exact index where array1 and array2 are different if this -// index is strictly superior to best_len_match. Otherwise, it returns 0. -// If no two elements are the same, it returns max_limit. -static WEBP_INLINE int FindMatchLength(const uint32_t* const array1, - const uint32_t* const array2, - int best_len_match, - int max_limit) { - int match_len; - - // Before 'expensive' linear match, check if the two arrays match at the - // current best length index. - if (array1[best_len_match] != array2[best_len_match]) return 0; - -#if defined(WEBP_USE_SSE2) - // Check if anything is different up to best_len_match excluded. - // memcmp seems to be slower on ARM so it is disabled for now. - if (memcmp(array1, array2, best_len_match * sizeof(*array1))) return 0; - match_len = best_len_match + 1; -#else - match_len = 0; -#endif - - while (match_len < max_limit && array1[match_len] == array2[match_len]) { - ++match_len; - } - return match_len; -} - -// ----------------------------------------------------------------------------- -// VP8LBackwardRefs - -struct PixOrCopyBlock { - PixOrCopyBlock* next_; // next block (or NULL) - PixOrCopy* start_; // data start - int size_; // currently used size -}; - -static void ClearBackwardRefs(VP8LBackwardRefs* const refs) { - assert(refs != NULL); - if (refs->tail_ != NULL) { - *refs->tail_ = refs->free_blocks_; // recycle all blocks at once - } - refs->free_blocks_ = refs->refs_; - refs->tail_ = &refs->refs_; - refs->last_block_ = NULL; - refs->refs_ = NULL; -} - -void VP8LBackwardRefsClear(VP8LBackwardRefs* const refs) { - assert(refs != NULL); - ClearBackwardRefs(refs); - while (refs->free_blocks_ != NULL) { - PixOrCopyBlock* const next = refs->free_blocks_->next_; - WebPSafeFree(refs->free_blocks_); - refs->free_blocks_ = next; - } -} - -void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size) { - assert(refs != NULL); - memset(refs, 0, sizeof(*refs)); - refs->tail_ = &refs->refs_; - refs->block_size_ = - (block_size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : block_size; -} - -VP8LRefsCursor VP8LRefsCursorInit(const VP8LBackwardRefs* const refs) { - VP8LRefsCursor c; - c.cur_block_ = refs->refs_; - if (refs->refs_ != NULL) { - c.cur_pos = c.cur_block_->start_; - c.last_pos_ = c.cur_pos + c.cur_block_->size_; - } else { - c.cur_pos = NULL; - c.last_pos_ = NULL; - } - return c; -} - -void VP8LRefsCursorNextBlock(VP8LRefsCursor* const c) { - PixOrCopyBlock* const b = c->cur_block_->next_; - c->cur_pos = (b == NULL) ? NULL : b->start_; - c->last_pos_ = (b == NULL) ? NULL : b->start_ + b->size_; - c->cur_block_ = b; -} - -// Create a new block, either from the free list or allocated -static PixOrCopyBlock* BackwardRefsNewBlock(VP8LBackwardRefs* const refs) { - PixOrCopyBlock* b = refs->free_blocks_; - if (b == NULL) { // allocate new memory chunk - const size_t total_size = - sizeof(*b) + refs->block_size_ * sizeof(*b->start_); - b = (PixOrCopyBlock*)WebPSafeMalloc(1ULL, total_size); - if (b == NULL) { - refs->error_ |= 1; - return NULL; - } - b->start_ = (PixOrCopy*)((uint8_t*)b + sizeof(*b)); // not always aligned - } else { // recycle from free-list - refs->free_blocks_ = b->next_; - } - *refs->tail_ = b; - refs->tail_ = &b->next_; - refs->last_block_ = b; - b->next_ = NULL; - b->size_ = 0; - return b; -} - -static WEBP_INLINE void BackwardRefsCursorAdd(VP8LBackwardRefs* const refs, - const PixOrCopy v) { - PixOrCopyBlock* b = refs->last_block_; - if (b == NULL || b->size_ == refs->block_size_) { - b = BackwardRefsNewBlock(refs); - if (b == NULL) return; // refs->error_ is set - } - b->start_[b->size_++] = v; -} - -int VP8LBackwardRefsCopy(const VP8LBackwardRefs* const src, - VP8LBackwardRefs* const dst) { - const PixOrCopyBlock* b = src->refs_; - ClearBackwardRefs(dst); - assert(src->block_size_ == dst->block_size_); - while (b != NULL) { - PixOrCopyBlock* const new_b = BackwardRefsNewBlock(dst); - if (new_b == NULL) return 0; // dst->error_ is set - memcpy(new_b->start_, b->start_, b->size_ * sizeof(*b->start_)); - new_b->size_ = b->size_; - b = b->next_; - } - return 1; -} - -// ----------------------------------------------------------------------------- -// Hash chains - -// initialize as empty -static void HashChainReset(VP8LHashChain* const p) { - assert(p != NULL); - // Set the int32_t arrays to -1. - memset(p->chain_, 0xff, p->size_ * sizeof(*p->chain_)); - memset(p->hash_to_first_index_, 0xff, - HASH_SIZE * sizeof(*p->hash_to_first_index_)); -} - -int VP8LHashChainInit(VP8LHashChain* const p, int size) { - assert(p->size_ == 0); - assert(p->chain_ == NULL); - assert(size > 0); - p->chain_ = (int*)WebPSafeMalloc(size, sizeof(*p->chain_)); - if (p->chain_ == NULL) return 0; - p->size_ = size; - HashChainReset(p); - return 1; -} - -void VP8LHashChainClear(VP8LHashChain* const p) { - assert(p != NULL); - WebPSafeFree(p->chain_); - p->size_ = 0; - p->chain_ = NULL; -} - -// ----------------------------------------------------------------------------- - -#define HASH_MULTIPLIER_HI (0xc6a4a793U) -#define HASH_MULTIPLIER_LO (0x5bd1e996U) - -static WEBP_INLINE uint32_t GetPixPairHash64(const uint32_t* const argb) { - uint32_t key; - key = argb[1] * HASH_MULTIPLIER_HI; - key += argb[0] * HASH_MULTIPLIER_LO; - key = key >> (32 - HASH_BITS); - return key; -} - -// Insertion of two pixels at a time. -static void HashChainInsert(VP8LHashChain* const p, - const uint32_t* const argb, int pos) { - const uint32_t hash_code = GetPixPairHash64(argb); - p->chain_[pos] = p->hash_to_first_index_[hash_code]; - p->hash_to_first_index_[hash_code] = pos; -} - -// Returns the maximum number of hash chain lookups to do for a -// given compression quality. Return value in range [6, 86]. -static int GetMaxItersForQuality(int quality, int low_effort) { - return (low_effort ? 6 : 8) + (quality * quality) / 128; -} - -static int GetWindowSizeForHashChain(int quality, int xsize) { - const int max_window_size = (quality > 75) ? WINDOW_SIZE - : (quality > 50) ? (xsize << 8) - : (quality > 25) ? (xsize << 6) - : (xsize << 4); - assert(xsize > 0); - return (max_window_size > WINDOW_SIZE) ? WINDOW_SIZE : max_window_size; -} - -static WEBP_INLINE int MaxFindCopyLength(int len) { - return (len < MAX_LENGTH) ? len : MAX_LENGTH; -} - -static void HashChainFindOffset(const VP8LHashChain* const p, int base_position, - const uint32_t* const argb, int len, - int window_size, int* const distance_ptr) { - const uint32_t* const argb_start = argb + base_position; - const int min_pos = - (base_position > window_size) ? base_position - window_size : 0; - int pos; - assert(len <= MAX_LENGTH); - for (pos = p->hash_to_first_index_[GetPixPairHash64(argb_start)]; - pos >= min_pos; - pos = p->chain_[pos]) { - const int curr_length = - FindMatchLength(argb + pos, argb_start, len - 1, len); - if (curr_length == len) break; - } - *distance_ptr = base_position - pos; -} - -static int HashChainFindCopy(const VP8LHashChain* const p, - int base_position, - const uint32_t* const argb, int max_len, - int window_size, int iter_max, - int* const distance_ptr, - int* const length_ptr) { - const uint32_t* const argb_start = argb + base_position; - int iter = iter_max; - int best_length = 0; - int best_distance = 0; - const int min_pos = - (base_position > window_size) ? base_position - window_size : 0; - int pos; - int length_max = 256; - if (max_len < length_max) { - length_max = max_len; - } - for (pos = p->hash_to_first_index_[GetPixPairHash64(argb_start)]; - pos >= min_pos; - pos = p->chain_[pos]) { - int curr_length; - int distance; - if (--iter < 0) { - break; - } - - curr_length = FindMatchLength(argb + pos, argb_start, best_length, max_len); - if (best_length < curr_length) { - distance = base_position - pos; - best_length = curr_length; - best_distance = distance; - if (curr_length >= length_max) { - break; - } - } - } - *distance_ptr = best_distance; - *length_ptr = best_length; - return (best_length >= MIN_LENGTH); -} - -static WEBP_INLINE void AddSingleLiteral(uint32_t pixel, int use_color_cache, - VP8LColorCache* const hashers, - VP8LBackwardRefs* const refs) { - PixOrCopy v; - if (use_color_cache) { - const uint32_t key = VP8LColorCacheGetIndex(hashers, pixel); - if (VP8LColorCacheLookup(hashers, key) == pixel) { - v = PixOrCopyCreateCacheIdx(key); - } else { - v = PixOrCopyCreateLiteral(pixel); - VP8LColorCacheSet(hashers, key, pixel); - } - } else { - v = PixOrCopyCreateLiteral(pixel); - } - BackwardRefsCursorAdd(refs, v); -} - -static int BackwardReferencesRle(int xsize, int ysize, - const uint32_t* const argb, - int cache_bits, VP8LBackwardRefs* const refs) { - const int pix_count = xsize * ysize; - int i, k; - const int use_color_cache = (cache_bits > 0); - VP8LColorCache hashers; - - if (use_color_cache && !VP8LColorCacheInit(&hashers, cache_bits)) { - return 0; - } - ClearBackwardRefs(refs); - // Add first pixel as literal. - AddSingleLiteral(argb[0], use_color_cache, &hashers, refs); - i = 1; - while (i < pix_count) { - const int max_len = MaxFindCopyLength(pix_count - i); - const int kMinLength = 4; - const int rle_len = FindMatchLength(argb + i, argb + i - 1, 0, max_len); - const int prev_row_len = (i < xsize) ? 0 : - FindMatchLength(argb + i, argb + i - xsize, 0, max_len); - if (rle_len >= prev_row_len && rle_len >= kMinLength) { - BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(1, rle_len)); - // We don't need to update the color cache here since it is always the - // same pixel being copied, and that does not change the color cache - // state. - i += rle_len; - } else if (prev_row_len >= kMinLength) { - BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(xsize, prev_row_len)); - if (use_color_cache) { - for (k = 0; k < prev_row_len; ++k) { - VP8LColorCacheInsert(&hashers, argb[i + k]); - } - } - i += prev_row_len; - } else { - AddSingleLiteral(argb[i], use_color_cache, &hashers, refs); - i++; - } - } - if (use_color_cache) VP8LColorCacheClear(&hashers); - return !refs->error_; -} - -static int BackwardReferencesLz77(int xsize, int ysize, - const uint32_t* const argb, int cache_bits, - int quality, int low_effort, - VP8LHashChain* const hash_chain, - VP8LBackwardRefs* const refs) { - int i; - int ok = 0; - int cc_init = 0; - const int use_color_cache = (cache_bits > 0); - const int pix_count = xsize * ysize; - VP8LColorCache hashers; - int iter_max = GetMaxItersForQuality(quality, low_effort); - const int window_size = GetWindowSizeForHashChain(quality, xsize); - int min_matches = 32; - - if (use_color_cache) { - cc_init = VP8LColorCacheInit(&hashers, cache_bits); - if (!cc_init) goto Error; - } - ClearBackwardRefs(refs); - HashChainReset(hash_chain); - for (i = 0; i < pix_count - 2; ) { - // Alternative#1: Code the pixels starting at 'i' using backward reference. - int offset = 0; - int len = 0; - const int max_len = MaxFindCopyLength(pix_count - i); - HashChainFindCopy(hash_chain, i, argb, max_len, window_size, - iter_max, &offset, &len); - if (len > MIN_LENGTH || (len == MIN_LENGTH && offset <= 512)) { - int offset2 = 0; - int len2 = 0; - int k; - min_matches = 8; - HashChainInsert(hash_chain, &argb[i], i); - if ((len < (max_len >> 2)) && !low_effort) { - // Evaluate Alternative#2: Insert the pixel at 'i' as literal, and code - // the pixels starting at 'i + 1' using backward reference. - HashChainFindCopy(hash_chain, i + 1, argb, max_len - 1, - window_size, iter_max, &offset2, - &len2); - if (len2 > len + 1) { - AddSingleLiteral(argb[i], use_color_cache, &hashers, refs); - i++; // Backward reference to be done for next pixel. - len = len2; - offset = offset2; - } - } - BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len)); - if (use_color_cache) { - for (k = 0; k < len; ++k) { - VP8LColorCacheInsert(&hashers, argb[i + k]); - } - } - // Add to the hash_chain (but cannot add the last pixel). - if (offset >= 3 && offset != xsize) { - const int last = (len < pix_count - 1 - i) ? len : pix_count - 1 - i; - for (k = 2; k < last - 8; k += 2) { - HashChainInsert(hash_chain, &argb[i + k], i + k); - } - for (; k < last; ++k) { - HashChainInsert(hash_chain, &argb[i + k], i + k); - } - } - i += len; - } else { - AddSingleLiteral(argb[i], use_color_cache, &hashers, refs); - HashChainInsert(hash_chain, &argb[i], i); - ++i; - --min_matches; - if (min_matches <= 0) { - AddSingleLiteral(argb[i], use_color_cache, &hashers, refs); - HashChainInsert(hash_chain, &argb[i], i); - ++i; - } - } - } - while (i < pix_count) { - // Handle the last pixel(s). - AddSingleLiteral(argb[i], use_color_cache, &hashers, refs); - ++i; - } - - ok = !refs->error_; - Error: - if (cc_init) VP8LColorCacheClear(&hashers); - return ok; -} - -// ----------------------------------------------------------------------------- - -typedef struct { - double alpha_[VALUES_IN_BYTE]; - double red_[VALUES_IN_BYTE]; - double blue_[VALUES_IN_BYTE]; - double distance_[NUM_DISTANCE_CODES]; - double* literal_; -} CostModel; - -static int BackwardReferencesTraceBackwards( - int xsize, int ysize, const uint32_t* const argb, int quality, - int cache_bits, VP8LHashChain* const hash_chain, - VP8LBackwardRefs* const refs); - -static void ConvertPopulationCountTableToBitEstimates( - int num_symbols, const uint32_t population_counts[], double output[]) { - uint32_t sum = 0; - int nonzeros = 0; - int i; - for (i = 0; i < num_symbols; ++i) { - sum += population_counts[i]; - if (population_counts[i] > 0) { - ++nonzeros; - } - } - if (nonzeros <= 1) { - memset(output, 0, num_symbols * sizeof(*output)); - } else { - const double logsum = VP8LFastLog2(sum); - for (i = 0; i < num_symbols; ++i) { - output[i] = logsum - VP8LFastLog2(population_counts[i]); - } - } -} - -static int CostModelBuild(CostModel* const m, int cache_bits, - VP8LBackwardRefs* const refs) { - int ok = 0; - VP8LHistogram* const histo = VP8LAllocateHistogram(cache_bits); - if (histo == NULL) goto Error; - - VP8LHistogramCreate(histo, refs, cache_bits); - - ConvertPopulationCountTableToBitEstimates( - VP8LHistogramNumCodes(histo->palette_code_bits_), - histo->literal_, m->literal_); - ConvertPopulationCountTableToBitEstimates( - VALUES_IN_BYTE, histo->red_, m->red_); - ConvertPopulationCountTableToBitEstimates( - VALUES_IN_BYTE, histo->blue_, m->blue_); - ConvertPopulationCountTableToBitEstimates( - VALUES_IN_BYTE, histo->alpha_, m->alpha_); - ConvertPopulationCountTableToBitEstimates( - NUM_DISTANCE_CODES, histo->distance_, m->distance_); - ok = 1; - - Error: - VP8LFreeHistogram(histo); - return ok; -} - -static WEBP_INLINE double GetLiteralCost(const CostModel* const m, uint32_t v) { - return m->alpha_[v >> 24] + - m->red_[(v >> 16) & 0xff] + - m->literal_[(v >> 8) & 0xff] + - m->blue_[v & 0xff]; -} - -static WEBP_INLINE double GetCacheCost(const CostModel* const m, uint32_t idx) { - const int literal_idx = VALUES_IN_BYTE + NUM_LENGTH_CODES + idx; - return m->literal_[literal_idx]; -} - -static WEBP_INLINE double GetLengthCost(const CostModel* const m, - uint32_t length) { - int code, extra_bits; - VP8LPrefixEncodeBits(length, &code, &extra_bits); - return m->literal_[VALUES_IN_BYTE + code] + extra_bits; -} - -static WEBP_INLINE double GetDistanceCost(const CostModel* const m, - uint32_t distance) { - int code, extra_bits; - VP8LPrefixEncodeBits(distance, &code, &extra_bits); - return m->distance_[code] + extra_bits; -} - -static void AddSingleLiteralWithCostModel( - const uint32_t* const argb, VP8LHashChain* const hash_chain, - VP8LColorCache* const hashers, const CostModel* const cost_model, int idx, - int is_last, int use_color_cache, double prev_cost, float* const cost, - uint16_t* const dist_array) { - double cost_val = prev_cost; - const uint32_t color = argb[0]; - if (!is_last) { - HashChainInsert(hash_chain, argb, idx); - } - if (use_color_cache && VP8LColorCacheContains(hashers, color)) { - const double mul0 = 0.68; - const int ix = VP8LColorCacheGetIndex(hashers, color); - cost_val += GetCacheCost(cost_model, ix) * mul0; - } else { - const double mul1 = 0.82; - if (use_color_cache) VP8LColorCacheInsert(hashers, color); - cost_val += GetLiteralCost(cost_model, color) * mul1; - } - if (cost[idx] > cost_val) { - cost[idx] = (float)cost_val; - dist_array[idx] = 1; // only one is inserted. - } -} - -static int BackwardReferencesHashChainDistanceOnly( - int xsize, int ysize, const uint32_t* const argb, - int quality, int cache_bits, VP8LHashChain* const hash_chain, - VP8LBackwardRefs* const refs, uint16_t* const dist_array) { - int i; - int ok = 0; - int cc_init = 0; - const int pix_count = xsize * ysize; - const int use_color_cache = (cache_bits > 0); - float* const cost = - (float*)WebPSafeMalloc(pix_count, sizeof(*cost)); - const size_t literal_array_size = sizeof(double) * - (NUM_LITERAL_CODES + NUM_LENGTH_CODES + - ((cache_bits > 0) ? (1 << cache_bits) : 0)); - const size_t cost_model_size = sizeof(CostModel) + literal_array_size; - CostModel* const cost_model = - (CostModel*)WebPSafeMalloc(1ULL, cost_model_size); - VP8LColorCache hashers; - const int skip_length = 32 + quality; - const int skip_min_distance_code = 2; - int iter_max = GetMaxItersForQuality(quality, 0); - const int window_size = GetWindowSizeForHashChain(quality, xsize); - - if (cost == NULL || cost_model == NULL) goto Error; - - cost_model->literal_ = (double*)(cost_model + 1); - if (use_color_cache) { - cc_init = VP8LColorCacheInit(&hashers, cache_bits); - if (!cc_init) goto Error; - } - - if (!CostModelBuild(cost_model, cache_bits, refs)) { - goto Error; - } - - for (i = 0; i < pix_count; ++i) cost[i] = 1e38f; - - // We loop one pixel at a time, but store all currently best points to - // non-processed locations from this point. - dist_array[0] = 0; - HashChainReset(hash_chain); - // Add first pixel as literal. - AddSingleLiteralWithCostModel(argb + 0, hash_chain, &hashers, cost_model, 0, - 0, use_color_cache, 0.0, cost, dist_array); - for (i = 1; i < pix_count - 1; ++i) { - int offset = 0; - int len = 0; - double prev_cost = cost[i - 1]; - const int max_len = MaxFindCopyLength(pix_count - i); - HashChainFindCopy(hash_chain, i, argb, max_len, window_size, - iter_max, &offset, &len); - if (len >= MIN_LENGTH) { - const int code = DistanceToPlaneCode(xsize, offset); - const double distance_cost = - prev_cost + GetDistanceCost(cost_model, code); - int k; - for (k = 1; k < len; ++k) { - const double cost_val = distance_cost + GetLengthCost(cost_model, k); - if (cost[i + k] > cost_val) { - cost[i + k] = (float)cost_val; - dist_array[i + k] = k + 1; - } - } - // This if is for speedup only. It roughly doubles the speed, and - // makes compression worse by .1 %. - if (len >= skip_length && code <= skip_min_distance_code) { - // Long copy for short distances, let's skip the middle - // lookups for better copies. - // 1) insert the hashes. - if (use_color_cache) { - for (k = 0; k < len; ++k) { - VP8LColorCacheInsert(&hashers, argb[i + k]); - } - } - // 2) Add to the hash_chain (but cannot add the last pixel) - { - const int last = (len + i < pix_count - 1) ? len + i - : pix_count - 1; - for (k = i; k < last; ++k) { - HashChainInsert(hash_chain, &argb[k], k); - } - } - // 3) jump. - i += len - 1; // for loop does ++i, thus -1 here. - goto next_symbol; - } - if (len != MIN_LENGTH) { - int code_min_length; - double cost_total; - HashChainFindOffset(hash_chain, i, argb, MIN_LENGTH, window_size, - &offset); - code_min_length = DistanceToPlaneCode(xsize, offset); - cost_total = prev_cost + - GetDistanceCost(cost_model, code_min_length) + - GetLengthCost(cost_model, 1); - if (cost[i + 1] > cost_total) { - cost[i + 1] = (float)cost_total; - dist_array[i + 1] = 2; - } - } - } - AddSingleLiteralWithCostModel(argb + i, hash_chain, &hashers, cost_model, i, - 0, use_color_cache, prev_cost, cost, - dist_array); - next_symbol: ; - } - // Handle the last pixel. - if (i == (pix_count - 1)) { - AddSingleLiteralWithCostModel(argb + i, hash_chain, &hashers, cost_model, i, - 1, use_color_cache, cost[pix_count - 2], cost, - dist_array); - } - ok = !refs->error_; - Error: - if (cc_init) VP8LColorCacheClear(&hashers); - WebPSafeFree(cost_model); - WebPSafeFree(cost); - return ok; -} - -// We pack the path at the end of *dist_array and return -// a pointer to this part of the array. Example: -// dist_array = [1x2xx3x2] => packed [1x2x1232], chosen_path = [1232] -static void TraceBackwards(uint16_t* const dist_array, - int dist_array_size, - uint16_t** const chosen_path, - int* const chosen_path_size) { - uint16_t* path = dist_array + dist_array_size; - uint16_t* cur = dist_array + dist_array_size - 1; - while (cur >= dist_array) { - const int k = *cur; - --path; - *path = k; - cur -= k; - } - *chosen_path = path; - *chosen_path_size = (int)(dist_array + dist_array_size - path); -} - -static int BackwardReferencesHashChainFollowChosenPath( - int xsize, int ysize, const uint32_t* const argb, - int quality, int cache_bits, - const uint16_t* const chosen_path, int chosen_path_size, - VP8LHashChain* const hash_chain, - VP8LBackwardRefs* const refs) { - const int pix_count = xsize * ysize; - const int use_color_cache = (cache_bits > 0); - int ix; - int i = 0; - int ok = 0; - int cc_init = 0; - const int window_size = GetWindowSizeForHashChain(quality, xsize); - VP8LColorCache hashers; - - if (use_color_cache) { - cc_init = VP8LColorCacheInit(&hashers, cache_bits); - if (!cc_init) goto Error; - } - - ClearBackwardRefs(refs); - HashChainReset(hash_chain); - for (ix = 0; ix < chosen_path_size; ++ix) { - int offset = 0; - const int len = chosen_path[ix]; - if (len != 1) { - int k; - HashChainFindOffset(hash_chain, i, argb, len, window_size, &offset); - BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len)); - if (use_color_cache) { - for (k = 0; k < len; ++k) { - VP8LColorCacheInsert(&hashers, argb[i + k]); - } - } - { - const int last = (len < pix_count - 1 - i) ? len : pix_count - 1 - i; - for (k = 0; k < last; ++k) { - HashChainInsert(hash_chain, &argb[i + k], i + k); - } - } - i += len; - } else { - PixOrCopy v; - if (use_color_cache && VP8LColorCacheContains(&hashers, argb[i])) { - // push pixel as a color cache index - const int idx = VP8LColorCacheGetIndex(&hashers, argb[i]); - v = PixOrCopyCreateCacheIdx(idx); - } else { - if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]); - v = PixOrCopyCreateLiteral(argb[i]); - } - BackwardRefsCursorAdd(refs, v); - if (i + 1 < pix_count) { - HashChainInsert(hash_chain, &argb[i], i); - } - ++i; - } - } - ok = !refs->error_; - Error: - if (cc_init) VP8LColorCacheClear(&hashers); - return ok; -} - -// Returns 1 on success. -static int BackwardReferencesTraceBackwards(int xsize, int ysize, - const uint32_t* const argb, - int quality, int cache_bits, - VP8LHashChain* const hash_chain, - VP8LBackwardRefs* const refs) { - int ok = 0; - const int dist_array_size = xsize * ysize; - uint16_t* chosen_path = NULL; - int chosen_path_size = 0; - uint16_t* dist_array = - (uint16_t*)WebPSafeMalloc(dist_array_size, sizeof(*dist_array)); - - if (dist_array == NULL) goto Error; - - if (!BackwardReferencesHashChainDistanceOnly( - xsize, ysize, argb, quality, cache_bits, hash_chain, - refs, dist_array)) { - goto Error; - } - TraceBackwards(dist_array, dist_array_size, &chosen_path, &chosen_path_size); - if (!BackwardReferencesHashChainFollowChosenPath( - xsize, ysize, argb, quality, cache_bits, chosen_path, chosen_path_size, - hash_chain, refs)) { - goto Error; - } - ok = 1; - Error: - WebPSafeFree(dist_array); - return ok; -} - -static void BackwardReferences2DLocality(int xsize, - const VP8LBackwardRefs* const refs) { - VP8LRefsCursor c = VP8LRefsCursorInit(refs); - while (VP8LRefsCursorOk(&c)) { - if (PixOrCopyIsCopy(c.cur_pos)) { - const int dist = c.cur_pos->argb_or_distance; - const int transformed_dist = DistanceToPlaneCode(xsize, dist); - c.cur_pos->argb_or_distance = transformed_dist; - } - VP8LRefsCursorNext(&c); - } -} - -// Returns entropy for the given cache bits. -static double ComputeCacheEntropy(const uint32_t* argb, - const VP8LBackwardRefs* const refs, - int cache_bits) { - const int use_color_cache = (cache_bits > 0); - int cc_init = 0; - double entropy = MAX_ENTROPY; - const double kSmallPenaltyForLargeCache = 4.0; - VP8LColorCache hashers; - VP8LRefsCursor c = VP8LRefsCursorInit(refs); - VP8LHistogram* histo = VP8LAllocateHistogram(cache_bits); - if (histo == NULL) goto Error; - - if (use_color_cache) { - cc_init = VP8LColorCacheInit(&hashers, cache_bits); - if (!cc_init) goto Error; - } - if (!use_color_cache) { - while (VP8LRefsCursorOk(&c)) { - VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos); - VP8LRefsCursorNext(&c); - } - } else { - while (VP8LRefsCursorOk(&c)) { - const PixOrCopy* const v = c.cur_pos; - if (PixOrCopyIsLiteral(v)) { - const uint32_t pix = *argb++; - const uint32_t key = VP8LColorCacheGetIndex(&hashers, pix); - if (VP8LColorCacheLookup(&hashers, key) == pix) { - ++histo->literal_[NUM_LITERAL_CODES + NUM_LENGTH_CODES + key]; - } else { - VP8LColorCacheSet(&hashers, key, pix); - ++histo->blue_[pix & 0xff]; - ++histo->literal_[(pix >> 8) & 0xff]; - ++histo->red_[(pix >> 16) & 0xff]; - ++histo->alpha_[pix >> 24]; - } - } else { - int len = PixOrCopyLength(v); - int code, extra_bits; - VP8LPrefixEncodeBits(len, &code, &extra_bits); - ++histo->literal_[NUM_LITERAL_CODES + code]; - VP8LPrefixEncodeBits(PixOrCopyDistance(v), &code, &extra_bits); - ++histo->distance_[code]; - do { - VP8LColorCacheInsert(&hashers, *argb++); - } while(--len != 0); - } - VP8LRefsCursorNext(&c); - } - } - entropy = VP8LHistogramEstimateBits(histo) + - kSmallPenaltyForLargeCache * cache_bits; - Error: - if (cc_init) VP8LColorCacheClear(&hashers); - VP8LFreeHistogram(histo); - return entropy; -} - -// Evaluate optimal cache bits for the local color cache. -// The input *best_cache_bits sets the maximum cache bits to use (passing 0 -// implies disabling the local color cache). The local color cache is also -// disabled for the lower (<= 25) quality. -// Returns 0 in case of memory error. -static int CalculateBestCacheSize(const uint32_t* const argb, - int xsize, int ysize, int quality, - VP8LHashChain* const hash_chain, - VP8LBackwardRefs* const refs, - int* const lz77_computed, - int* const best_cache_bits) { - int eval_low = 1; - int eval_high = 1; - double entropy_low = MAX_ENTROPY; - double entropy_high = MAX_ENTROPY; - const double cost_mul = 5e-4; - int cache_bits_low = 0; - int cache_bits_high = (quality <= 25) ? 0 : *best_cache_bits; - - assert(cache_bits_high <= MAX_COLOR_CACHE_BITS); - - *lz77_computed = 0; - if (cache_bits_high == 0) { - *best_cache_bits = 0; - // Local color cache is disabled. - return 1; - } - if (!BackwardReferencesLz77(xsize, ysize, argb, cache_bits_low, quality, 0, - hash_chain, refs)) { - return 0; - } - // Do a binary search to find the optimal entropy for cache_bits. - while (eval_low || eval_high) { - if (eval_low) { - entropy_low = ComputeCacheEntropy(argb, refs, cache_bits_low); - entropy_low += entropy_low * cache_bits_low * cost_mul; - eval_low = 0; - } - if (eval_high) { - entropy_high = ComputeCacheEntropy(argb, refs, cache_bits_high); - entropy_high += entropy_high * cache_bits_high * cost_mul; - eval_high = 0; - } - if (entropy_high < entropy_low) { - const int prev_cache_bits_low = cache_bits_low; - *best_cache_bits = cache_bits_high; - cache_bits_low = (cache_bits_low + cache_bits_high) / 2; - if (cache_bits_low != prev_cache_bits_low) eval_low = 1; - } else { - *best_cache_bits = cache_bits_low; - cache_bits_high = (cache_bits_low + cache_bits_high) / 2; - if (cache_bits_high != cache_bits_low) eval_high = 1; - } - } - *lz77_computed = 1; - return 1; -} - -// Update (in-place) backward references for specified cache_bits. -static int BackwardRefsWithLocalCache(const uint32_t* const argb, - int cache_bits, - VP8LBackwardRefs* const refs) { - int pixel_index = 0; - VP8LColorCache hashers; - VP8LRefsCursor c = VP8LRefsCursorInit(refs); - if (!VP8LColorCacheInit(&hashers, cache_bits)) return 0; - - while (VP8LRefsCursorOk(&c)) { - PixOrCopy* const v = c.cur_pos; - if (PixOrCopyIsLiteral(v)) { - const uint32_t argb_literal = v->argb_or_distance; - if (VP8LColorCacheContains(&hashers, argb_literal)) { - const int ix = VP8LColorCacheGetIndex(&hashers, argb_literal); - *v = PixOrCopyCreateCacheIdx(ix); - } else { - VP8LColorCacheInsert(&hashers, argb_literal); - } - ++pixel_index; - } else { - // refs was created without local cache, so it can not have cache indexes. - int k; - assert(PixOrCopyIsCopy(v)); - for (k = 0; k < v->len; ++k) { - VP8LColorCacheInsert(&hashers, argb[pixel_index++]); - } - } - VP8LRefsCursorNext(&c); - } - VP8LColorCacheClear(&hashers); - return 1; -} - -static VP8LBackwardRefs* GetBackwardReferencesLowEffort( - int width, int height, const uint32_t* const argb, int quality, - int* const cache_bits, VP8LHashChain* const hash_chain, - VP8LBackwardRefs refs_array[2]) { - VP8LBackwardRefs* refs_lz77 = &refs_array[0]; - *cache_bits = 0; - if (!BackwardReferencesLz77(width, height, argb, 0, quality, - 1 /* Low effort. */, hash_chain, refs_lz77)) { - return NULL; - } - BackwardReferences2DLocality(width, refs_lz77); - return refs_lz77; -} - -static VP8LBackwardRefs* GetBackwardReferences( - int width, int height, const uint32_t* const argb, int quality, - int* const cache_bits, VP8LHashChain* const hash_chain, - VP8LBackwardRefs refs_array[2]) { - int lz77_is_useful; - int lz77_computed; - double bit_cost_lz77, bit_cost_rle; - VP8LBackwardRefs* best = NULL; - VP8LBackwardRefs* refs_lz77 = &refs_array[0]; - VP8LBackwardRefs* refs_rle = &refs_array[1]; - VP8LHistogram* histo = NULL; - - if (!CalculateBestCacheSize(argb, width, height, quality, hash_chain, - refs_lz77, &lz77_computed, cache_bits)) { - goto Error; - } - - if (lz77_computed) { - // Transform refs_lz77 for the optimized cache_bits. - if (*cache_bits > 0) { - if (!BackwardRefsWithLocalCache(argb, *cache_bits, refs_lz77)) { - goto Error; - } - } - } else { - if (!BackwardReferencesLz77(width, height, argb, *cache_bits, quality, - 0 /* Low effort. */, hash_chain, refs_lz77)) { - goto Error; - } - } - - if (!BackwardReferencesRle(width, height, argb, *cache_bits, refs_rle)) { - goto Error; - } - - histo = VP8LAllocateHistogram(*cache_bits); - if (histo == NULL) goto Error; - - { - // Evaluate LZ77 coding. - VP8LHistogramCreate(histo, refs_lz77, *cache_bits); - bit_cost_lz77 = VP8LHistogramEstimateBits(histo); - // Evaluate RLE coding. - VP8LHistogramCreate(histo, refs_rle, *cache_bits); - bit_cost_rle = VP8LHistogramEstimateBits(histo); - // Decide if LZ77 is useful. - lz77_is_useful = (bit_cost_lz77 < bit_cost_rle); - } - - // Choose appropriate backward reference. - if (lz77_is_useful) { - // TraceBackwards is costly. Don't execute it at lower quality. - const int try_lz77_trace_backwards = (quality >= 25); - best = refs_lz77; // default guess: lz77 is better - if (try_lz77_trace_backwards) { - VP8LBackwardRefs* const refs_trace = refs_rle; - if (!VP8LBackwardRefsCopy(refs_lz77, refs_trace)) { - best = NULL; - goto Error; - } - if (BackwardReferencesTraceBackwards(width, height, argb, quality, - *cache_bits, hash_chain, - refs_trace)) { - double bit_cost_trace; - // Evaluate LZ77 coding. - VP8LHistogramCreate(histo, refs_trace, *cache_bits); - bit_cost_trace = VP8LHistogramEstimateBits(histo); - if (bit_cost_trace < bit_cost_lz77) { - best = refs_trace; - } - } - } - } else { - best = refs_rle; - } - - BackwardReferences2DLocality(width, best); - - Error: - VP8LFreeHistogram(histo); - return best; -} - -VP8LBackwardRefs* VP8LGetBackwardReferences( - int width, int height, const uint32_t* const argb, int quality, - int low_effort, int* const cache_bits, VP8LHashChain* const hash_chain, - VP8LBackwardRefs refs_array[2]) { - if (low_effort) { - return GetBackwardReferencesLowEffort(width, height, argb, quality, - cache_bits, hash_chain, refs_array); - } else { - return GetBackwardReferences(width, height, argb, quality, cache_bits, - hash_chain, refs_array); - } -} diff --git a/Example-Mac/Pods/libwebp/src/enc/backward_references.h b/Example-Mac/Pods/libwebp/src/enc/backward_references.h deleted file mode 100644 index daa084d8..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/backward_references.h +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Jyrki Alakuijala (jyrki@google.com) -// - -#ifndef WEBP_ENC_BACKWARD_REFERENCES_H_ -#define WEBP_ENC_BACKWARD_REFERENCES_H_ - -#include -#include -#include "../webp/types.h" -#include "../webp/format_constants.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// The maximum allowed limit is 11. -#define MAX_COLOR_CACHE_BITS 10 - -// ----------------------------------------------------------------------------- -// PixOrCopy - -enum Mode { - kLiteral, - kCacheIdx, - kCopy, - kNone -}; - -typedef struct { - // mode as uint8_t to make the memory layout to be exactly 8 bytes. - uint8_t mode; - uint16_t len; - uint32_t argb_or_distance; -} PixOrCopy; - -static WEBP_INLINE PixOrCopy PixOrCopyCreateCopy(uint32_t distance, - uint16_t len) { - PixOrCopy retval; - retval.mode = kCopy; - retval.argb_or_distance = distance; - retval.len = len; - return retval; -} - -static WEBP_INLINE PixOrCopy PixOrCopyCreateCacheIdx(int idx) { - PixOrCopy retval; - assert(idx >= 0); - assert(idx < (1 << MAX_COLOR_CACHE_BITS)); - retval.mode = kCacheIdx; - retval.argb_or_distance = idx; - retval.len = 1; - return retval; -} - -static WEBP_INLINE PixOrCopy PixOrCopyCreateLiteral(uint32_t argb) { - PixOrCopy retval; - retval.mode = kLiteral; - retval.argb_or_distance = argb; - retval.len = 1; - return retval; -} - -static WEBP_INLINE int PixOrCopyIsLiteral(const PixOrCopy* const p) { - return (p->mode == kLiteral); -} - -static WEBP_INLINE int PixOrCopyIsCacheIdx(const PixOrCopy* const p) { - return (p->mode == kCacheIdx); -} - -static WEBP_INLINE int PixOrCopyIsCopy(const PixOrCopy* const p) { - return (p->mode == kCopy); -} - -static WEBP_INLINE uint32_t PixOrCopyLiteral(const PixOrCopy* const p, - int component) { - assert(p->mode == kLiteral); - return (p->argb_or_distance >> (component * 8)) & 0xff; -} - -static WEBP_INLINE uint32_t PixOrCopyLength(const PixOrCopy* const p) { - return p->len; -} - -static WEBP_INLINE uint32_t PixOrCopyArgb(const PixOrCopy* const p) { - assert(p->mode == kLiteral); - return p->argb_or_distance; -} - -static WEBP_INLINE uint32_t PixOrCopyCacheIdx(const PixOrCopy* const p) { - assert(p->mode == kCacheIdx); - assert(p->argb_or_distance < (1U << MAX_COLOR_CACHE_BITS)); - return p->argb_or_distance; -} - -static WEBP_INLINE uint32_t PixOrCopyDistance(const PixOrCopy* const p) { - assert(p->mode == kCopy); - return p->argb_or_distance; -} - -// ----------------------------------------------------------------------------- -// VP8LHashChain - -#define HASH_BITS 18 -#define HASH_SIZE (1 << HASH_BITS) - -typedef struct VP8LHashChain VP8LHashChain; -struct VP8LHashChain { - // Stores the most recently added position with the given hash value. - int32_t hash_to_first_index_[HASH_SIZE]; - // chain_[pos] stores the previous position with the same hash value - // for every pixel in the image. - int32_t* chain_; - // This is the maximum size of the hash_chain that can be constructed. - // Typically this is the pixel count (width x height) for a given image. - int size_; -}; - -// Must be called first, to set size. -int VP8LHashChainInit(VP8LHashChain* const p, int size); -void VP8LHashChainClear(VP8LHashChain* const p); // release memory - -// ----------------------------------------------------------------------------- -// VP8LBackwardRefs (block-based backward-references storage) - -// maximum number of reference blocks the image will be segmented into -#define MAX_REFS_BLOCK_PER_IMAGE 16 - -typedef struct PixOrCopyBlock PixOrCopyBlock; // forward declaration -typedef struct VP8LBackwardRefs VP8LBackwardRefs; - -// Container for blocks chain -struct VP8LBackwardRefs { - int block_size_; // common block-size - int error_; // set to true if some memory error occurred - PixOrCopyBlock* refs_; // list of currently used blocks - PixOrCopyBlock** tail_; // for list recycling - PixOrCopyBlock* free_blocks_; // free-list - PixOrCopyBlock* last_block_; // used for adding new refs (internal) -}; - -// Initialize the object. 'block_size' is the common block size to store -// references (typically, width * height / MAX_REFS_BLOCK_PER_IMAGE). -void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size); -// Release memory for backward references. -void VP8LBackwardRefsClear(VP8LBackwardRefs* const refs); -// Copies the 'src' backward refs to the 'dst'. Returns 0 in case of error. -int VP8LBackwardRefsCopy(const VP8LBackwardRefs* const src, - VP8LBackwardRefs* const dst); - -// Cursor for iterating on references content -typedef struct { - // public: - PixOrCopy* cur_pos; // current position - // private: - PixOrCopyBlock* cur_block_; // current block in the refs list - const PixOrCopy* last_pos_; // sentinel for switching to next block -} VP8LRefsCursor; - -// Returns a cursor positioned at the beginning of the references list. -VP8LRefsCursor VP8LRefsCursorInit(const VP8LBackwardRefs* const refs); -// Returns true if cursor is pointing at a valid position. -static WEBP_INLINE int VP8LRefsCursorOk(const VP8LRefsCursor* const c) { - return (c->cur_pos != NULL); -} -// Move to next block of references. Internal, not to be called directly. -void VP8LRefsCursorNextBlock(VP8LRefsCursor* const c); -// Move to next position, or NULL. Should not be called if !VP8LRefsCursorOk(). -static WEBP_INLINE void VP8LRefsCursorNext(VP8LRefsCursor* const c) { - assert(c != NULL); - assert(VP8LRefsCursorOk(c)); - if (++c->cur_pos == c->last_pos_) VP8LRefsCursorNextBlock(c); -} - -// ----------------------------------------------------------------------------- -// Main entry points - -// Evaluates best possible backward references for specified quality. -// The input cache_bits to 'VP8LGetBackwardReferences' sets the maximum cache -// bits to use (passing 0 implies disabling the local color cache). -// The optimal cache bits is evaluated and set for the *cache_bits parameter. -// The return value is the pointer to the best of the two backward refs viz, -// refs[0] or refs[1]. -VP8LBackwardRefs* VP8LGetBackwardReferences( - int width, int height, const uint32_t* const argb, int quality, - int low_effort, int* const cache_bits, VP8LHashChain* const hash_chain, - VP8LBackwardRefs refs[2]); - -#ifdef __cplusplus -} -#endif - -#endif // WEBP_ENC_BACKWARD_REFERENCES_H_ diff --git a/Example-Mac/Pods/libwebp/src/enc/config.c b/Example-Mac/Pods/libwebp/src/enc/config.c deleted file mode 100644 index f9f7961d..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/config.c +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Coding tools configuration -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "../webp/encode.h" - -//------------------------------------------------------------------------------ -// WebPConfig -//------------------------------------------------------------------------------ - -int WebPConfigInitInternal(WebPConfig* config, - WebPPreset preset, float quality, int version) { - if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_ENCODER_ABI_VERSION)) { - return 0; // caller/system version mismatch! - } - if (config == NULL) return 0; - - config->quality = quality; - config->target_size = 0; - config->target_PSNR = 0.; - config->method = 4; - config->sns_strength = 50; - config->filter_strength = 60; // mid-filtering - config->filter_sharpness = 0; - config->filter_type = 1; // default: strong (so U/V is filtered too) - config->partitions = 0; - config->segments = 4; - config->pass = 1; - config->show_compressed = 0; - config->preprocessing = 0; - config->autofilter = 0; - config->partition_limit = 0; - config->alpha_compression = 1; - config->alpha_filtering = 1; - config->alpha_quality = 100; - config->lossless = 0; - config->exact = 0; - config->image_hint = WEBP_HINT_DEFAULT; - config->emulate_jpeg_size = 0; - config->thread_level = 0; - config->low_memory = 0; - config->near_lossless = 100; -#ifdef WEBP_EXPERIMENTAL_FEATURES - config->delta_palettization = 0; -#endif // WEBP_EXPERIMENTAL_FEATURES - - // TODO(skal): tune. - switch (preset) { - case WEBP_PRESET_PICTURE: - config->sns_strength = 80; - config->filter_sharpness = 4; - config->filter_strength = 35; - config->preprocessing &= ~2; // no dithering - break; - case WEBP_PRESET_PHOTO: - config->sns_strength = 80; - config->filter_sharpness = 3; - config->filter_strength = 30; - config->preprocessing |= 2; - break; - case WEBP_PRESET_DRAWING: - config->sns_strength = 25; - config->filter_sharpness = 6; - config->filter_strength = 10; - break; - case WEBP_PRESET_ICON: - config->sns_strength = 0; - config->filter_strength = 0; // disable filtering to retain sharpness - config->preprocessing &= ~2; // no dithering - break; - case WEBP_PRESET_TEXT: - config->sns_strength = 0; - config->filter_strength = 0; // disable filtering to retain sharpness - config->preprocessing &= ~2; // no dithering - config->segments = 2; - break; - case WEBP_PRESET_DEFAULT: - default: - break; - } - return WebPValidateConfig(config); -} - -int WebPValidateConfig(const WebPConfig* config) { - if (config == NULL) return 0; - if (config->quality < 0 || config->quality > 100) - return 0; - if (config->target_size < 0) - return 0; - if (config->target_PSNR < 0) - return 0; - if (config->method < 0 || config->method > 6) - return 0; - if (config->segments < 1 || config->segments > 4) - return 0; - if (config->sns_strength < 0 || config->sns_strength > 100) - return 0; - if (config->filter_strength < 0 || config->filter_strength > 100) - return 0; - if (config->filter_sharpness < 0 || config->filter_sharpness > 7) - return 0; - if (config->filter_type < 0 || config->filter_type > 1) - return 0; - if (config->autofilter < 0 || config->autofilter > 1) - return 0; - if (config->pass < 1 || config->pass > 10) - return 0; - if (config->show_compressed < 0 || config->show_compressed > 1) - return 0; - if (config->preprocessing < 0 || config->preprocessing > 7) - return 0; - if (config->partitions < 0 || config->partitions > 3) - return 0; - if (config->partition_limit < 0 || config->partition_limit > 100) - return 0; - if (config->alpha_compression < 0) - return 0; - if (config->alpha_filtering < 0) - return 0; - if (config->alpha_quality < 0 || config->alpha_quality > 100) - return 0; - if (config->lossless < 0 || config->lossless > 1) - return 0; - if (config->near_lossless < 0 || config->near_lossless > 100) - return 0; - if (config->image_hint >= WEBP_HINT_LAST) - return 0; - if (config->emulate_jpeg_size < 0 || config->emulate_jpeg_size > 1) - return 0; - if (config->thread_level < 0 || config->thread_level > 1) - return 0; - if (config->low_memory < 0 || config->low_memory > 1) - return 0; - if (config->exact < 0 || config->exact > 1) - return 0; -#ifdef WEBP_EXPERIMENTAL_FEATURES - if (config->delta_palettization < 0 || config->delta_palettization > 1) - return 0; -#endif // WEBP_EXPERIMENTAL_FEATURES - return 1; -} - -//------------------------------------------------------------------------------ - -#define MAX_LEVEL 9 - -// Mapping between -z level and -m / -q parameter settings. -static const struct { - uint8_t method_; - uint8_t quality_; -} kLosslessPresets[MAX_LEVEL + 1] = { - { 0, 0 }, { 1, 20 }, { 2, 25 }, { 3, 30 }, { 3, 50 }, - { 4, 50 }, { 4, 75 }, { 4, 90 }, { 5, 90 }, { 6, 100 } -}; - -int WebPConfigLosslessPreset(WebPConfig* config, int level) { - if (config == NULL || level < 0 || level > MAX_LEVEL) return 0; - config->lossless = 1; - config->method = kLosslessPresets[level].method_; - config->quality = kLosslessPresets[level].quality_; - return 1; -} - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/enc/cost.c b/Example-Mac/Pods/libwebp/src/enc/cost.c deleted file mode 100644 index ae7fe013..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/cost.c +++ /dev/null @@ -1,354 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Cost tables for level and modes -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./cost.h" - -//------------------------------------------------------------------------------ -// Level cost tables - -// For each given level, the following table gives the pattern of contexts to -// use for coding it (in [][0]) as well as the bit value to use for each -// context (in [][1]). -const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2] = { - {0x001, 0x000}, {0x007, 0x001}, {0x00f, 0x005}, - {0x00f, 0x00d}, {0x033, 0x003}, {0x033, 0x003}, {0x033, 0x023}, - {0x033, 0x023}, {0x033, 0x023}, {0x033, 0x023}, {0x0d3, 0x013}, - {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x013}, - {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x093}, - {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, - {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, - {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, - {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x153, 0x053}, - {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, - {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, - {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, - {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, - {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, - {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, - {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, - {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x153} -}; - -static int VariableLevelCost(int level, const uint8_t probas[NUM_PROBAS]) { - int pattern = VP8LevelCodes[level - 1][0]; - int bits = VP8LevelCodes[level - 1][1]; - int cost = 0; - int i; - for (i = 2; pattern; ++i) { - if (pattern & 1) { - cost += VP8BitCost(bits & 1, probas[i]); - } - bits >>= 1; - pattern >>= 1; - } - return cost; -} - -//------------------------------------------------------------------------------ -// Pre-calc level costs once for all - -void VP8CalculateLevelCosts(VP8EncProba* const proba) { - int ctype, band, ctx; - - if (!proba->dirty_) return; // nothing to do. - - for (ctype = 0; ctype < NUM_TYPES; ++ctype) { - int n; - for (band = 0; band < NUM_BANDS; ++band) { - for (ctx = 0; ctx < NUM_CTX; ++ctx) { - const uint8_t* const p = proba->coeffs_[ctype][band][ctx]; - uint16_t* const table = proba->level_cost_[ctype][band][ctx]; - const int cost0 = (ctx > 0) ? VP8BitCost(1, p[0]) : 0; - const int cost_base = VP8BitCost(1, p[1]) + cost0; - int v; - table[0] = VP8BitCost(0, p[1]) + cost0; - for (v = 1; v <= MAX_VARIABLE_LEVEL; ++v) { - table[v] = cost_base + VariableLevelCost(v, p); - } - // Starting at level 67 and up, the variable part of the cost is - // actually constant. - } - } - for (n = 0; n < 16; ++n) { // replicate bands. We don't need to sentinel. - for (ctx = 0; ctx < NUM_CTX; ++ctx) { - proba->remapped_costs_[ctype][n][ctx] = - proba->level_cost_[ctype][VP8EncBands[n]][ctx]; - } - } - } - proba->dirty_ = 0; -} - -//------------------------------------------------------------------------------ -// Mode cost tables. - -// These are the fixed probabilities (in the coding trees) turned into bit-cost -// by calling VP8BitCost(). -const uint16_t VP8FixedCostsUV[4] = { 302, 984, 439, 642 }; -// note: these values include the fixed VP8BitCost(1, 145) mode selection cost. -const uint16_t VP8FixedCostsI16[4] = { 663, 919, 872, 919 }; -const uint16_t VP8FixedCostsI4[NUM_BMODES][NUM_BMODES][NUM_BMODES] = { - { { 40, 1151, 1723, 1874, 2103, 2019, 1628, 1777, 2226, 2137 }, - { 192, 469, 1296, 1308, 1849, 1794, 1781, 1703, 1713, 1522 }, - { 142, 910, 762, 1684, 1849, 1576, 1460, 1305, 1801, 1657 }, - { 559, 641, 1370, 421, 1182, 1569, 1612, 1725, 863, 1007 }, - { 299, 1059, 1256, 1108, 636, 1068, 1581, 1883, 869, 1142 }, - { 277, 1111, 707, 1362, 1089, 672, 1603, 1541, 1545, 1291 }, - { 214, 781, 1609, 1303, 1632, 2229, 726, 1560, 1713, 918 }, - { 152, 1037, 1046, 1759, 1983, 2174, 1358, 742, 1740, 1390 }, - { 512, 1046, 1420, 753, 752, 1297, 1486, 1613, 460, 1207 }, - { 424, 827, 1362, 719, 1462, 1202, 1199, 1476, 1199, 538 } }, - { { 240, 402, 1134, 1491, 1659, 1505, 1517, 1555, 1979, 2099 }, - { 467, 242, 960, 1232, 1714, 1620, 1834, 1570, 1676, 1391 }, - { 500, 455, 463, 1507, 1699, 1282, 1564, 982, 2114, 2114 }, - { 672, 643, 1372, 331, 1589, 1667, 1453, 1938, 996, 876 }, - { 458, 783, 1037, 911, 738, 968, 1165, 1518, 859, 1033 }, - { 504, 815, 504, 1139, 1219, 719, 1506, 1085, 1268, 1268 }, - { 333, 630, 1445, 1239, 1883, 3672, 799, 1548, 1865, 598 }, - { 399, 644, 746, 1342, 1856, 1350, 1493, 613, 1855, 1015 }, - { 622, 749, 1205, 608, 1066, 1408, 1290, 1406, 546, 971 }, - { 500, 753, 1041, 668, 1230, 1617, 1297, 1425, 1383, 523 } }, - { { 394, 553, 523, 1502, 1536, 981, 1608, 1142, 1666, 2181 }, - { 655, 430, 375, 1411, 1861, 1220, 1677, 1135, 1978, 1553 }, - { 690, 640, 245, 1954, 2070, 1194, 1528, 982, 1972, 2232 }, - { 559, 834, 741, 867, 1131, 980, 1225, 852, 1092, 784 }, - { 690, 875, 516, 959, 673, 894, 1056, 1190, 1528, 1126 }, - { 740, 951, 384, 1277, 1177, 492, 1579, 1155, 1846, 1513 }, - { 323, 775, 1062, 1776, 3062, 1274, 813, 1188, 1372, 655 }, - { 488, 971, 484, 1767, 1515, 1775, 1115, 503, 1539, 1461 }, - { 740, 1006, 998, 709, 851, 1230, 1337, 788, 741, 721 }, - { 522, 1073, 573, 1045, 1346, 887, 1046, 1146, 1203, 697 } }, - { { 105, 864, 1442, 1009, 1934, 1840, 1519, 1920, 1673, 1579 }, - { 534, 305, 1193, 683, 1388, 2164, 1802, 1894, 1264, 1170 }, - { 305, 518, 877, 1108, 1426, 3215, 1425, 1064, 1320, 1242 }, - { 683, 732, 1927, 257, 1493, 2048, 1858, 1552, 1055, 947 }, - { 394, 814, 1024, 660, 959, 1556, 1282, 1289, 893, 1047 }, - { 528, 615, 996, 940, 1201, 635, 1094, 2515, 803, 1358 }, - { 347, 614, 1609, 1187, 3133, 1345, 1007, 1339, 1017, 667 }, - { 218, 740, 878, 1605, 3650, 3650, 1345, 758, 1357, 1617 }, - { 672, 750, 1541, 558, 1257, 1599, 1870, 2135, 402, 1087 }, - { 592, 684, 1161, 430, 1092, 1497, 1475, 1489, 1095, 822 } }, - { { 228, 1056, 1059, 1368, 752, 982, 1512, 1518, 987, 1782 }, - { 494, 514, 818, 942, 965, 892, 1610, 1356, 1048, 1363 }, - { 512, 648, 591, 1042, 761, 991, 1196, 1454, 1309, 1463 }, - { 683, 749, 1043, 676, 841, 1396, 1133, 1138, 654, 939 }, - { 622, 1101, 1126, 994, 361, 1077, 1203, 1318, 877, 1219 }, - { 631, 1068, 857, 1650, 651, 477, 1650, 1419, 828, 1170 }, - { 555, 727, 1068, 1335, 3127, 1339, 820, 1331, 1077, 429 }, - { 504, 879, 624, 1398, 889, 889, 1392, 808, 891, 1406 }, - { 683, 1602, 1289, 977, 578, 983, 1280, 1708, 406, 1122 }, - { 399, 865, 1433, 1070, 1072, 764, 968, 1477, 1223, 678 } }, - { { 333, 760, 935, 1638, 1010, 529, 1646, 1410, 1472, 2219 }, - { 512, 494, 750, 1160, 1215, 610, 1870, 1868, 1628, 1169 }, - { 572, 646, 492, 1934, 1208, 603, 1580, 1099, 1398, 1995 }, - { 786, 789, 942, 581, 1018, 951, 1599, 1207, 731, 768 }, - { 690, 1015, 672, 1078, 582, 504, 1693, 1438, 1108, 2897 }, - { 768, 1267, 571, 2005, 1243, 244, 2881, 1380, 1786, 1453 }, - { 452, 899, 1293, 903, 1311, 3100, 465, 1311, 1319, 813 }, - { 394, 927, 942, 1103, 1358, 1104, 946, 593, 1363, 1109 }, - { 559, 1005, 1007, 1016, 658, 1173, 1021, 1164, 623, 1028 }, - { 564, 796, 632, 1005, 1014, 863, 2316, 1268, 938, 764 } }, - { { 266, 606, 1098, 1228, 1497, 1243, 948, 1030, 1734, 1461 }, - { 366, 585, 901, 1060, 1407, 1247, 876, 1134, 1620, 1054 }, - { 452, 565, 542, 1729, 1479, 1479, 1016, 886, 2938, 1150 }, - { 555, 1088, 1533, 950, 1354, 895, 834, 1019, 1021, 496 }, - { 704, 815, 1193, 971, 973, 640, 1217, 2214, 832, 578 }, - { 672, 1245, 579, 871, 875, 774, 872, 1273, 1027, 949 }, - { 296, 1134, 2050, 1784, 1636, 3425, 442, 1550, 2076, 722 }, - { 342, 982, 1259, 1846, 1848, 1848, 622, 568, 1847, 1052 }, - { 555, 1064, 1304, 828, 746, 1343, 1075, 1329, 1078, 494 }, - { 288, 1167, 1285, 1174, 1639, 1639, 833, 2254, 1304, 509 } }, - { { 342, 719, 767, 1866, 1757, 1270, 1246, 550, 1746, 2151 }, - { 483, 653, 694, 1509, 1459, 1410, 1218, 507, 1914, 1266 }, - { 488, 757, 447, 2979, 1813, 1268, 1654, 539, 1849, 2109 }, - { 522, 1097, 1085, 851, 1365, 1111, 851, 901, 961, 605 }, - { 709, 716, 841, 728, 736, 945, 941, 862, 2845, 1057 }, - { 512, 1323, 500, 1336, 1083, 681, 1342, 717, 1604, 1350 }, - { 452, 1155, 1372, 1900, 1501, 3290, 311, 944, 1919, 922 }, - { 403, 1520, 977, 2132, 1733, 3522, 1076, 276, 3335, 1547 }, - { 559, 1374, 1101, 615, 673, 2462, 974, 795, 984, 984 }, - { 547, 1122, 1062, 812, 1410, 951, 1140, 622, 1268, 651 } }, - { { 165, 982, 1235, 938, 1334, 1366, 1659, 1578, 964, 1612 }, - { 592, 422, 925, 847, 1139, 1112, 1387, 2036, 861, 1041 }, - { 403, 837, 732, 770, 941, 1658, 1250, 809, 1407, 1407 }, - { 896, 874, 1071, 381, 1568, 1722, 1437, 2192, 480, 1035 }, - { 640, 1098, 1012, 1032, 684, 1382, 1581, 2106, 416, 865 }, - { 559, 1005, 819, 914, 710, 770, 1418, 920, 838, 1435 }, - { 415, 1258, 1245, 870, 1278, 3067, 770, 1021, 1287, 522 }, - { 406, 990, 601, 1009, 1265, 1265, 1267, 759, 1017, 1277 }, - { 968, 1182, 1329, 788, 1032, 1292, 1705, 1714, 203, 1403 }, - { 732, 877, 1279, 471, 901, 1161, 1545, 1294, 755, 755 } }, - { { 111, 931, 1378, 1185, 1933, 1648, 1148, 1714, 1873, 1307 }, - { 406, 414, 1030, 1023, 1910, 1404, 1313, 1647, 1509, 793 }, - { 342, 640, 575, 1088, 1241, 1349, 1161, 1350, 1756, 1502 }, - { 559, 766, 1185, 357, 1682, 1428, 1329, 1897, 1219, 802 }, - { 473, 909, 1164, 771, 719, 2508, 1427, 1432, 722, 782 }, - { 342, 892, 785, 1145, 1150, 794, 1296, 1550, 973, 1057 }, - { 208, 1036, 1326, 1343, 1606, 3395, 815, 1455, 1618, 712 }, - { 228, 928, 890, 1046, 3499, 1711, 994, 829, 1720, 1318 }, - { 768, 724, 1058, 636, 991, 1075, 1319, 1324, 616, 825 }, - { 305, 1167, 1358, 899, 1587, 1587, 987, 1988, 1332, 501 } } -}; - -//------------------------------------------------------------------------------ -// helper functions for residuals struct VP8Residual. - -void VP8InitResidual(int first, int coeff_type, - VP8Encoder* const enc, VP8Residual* const res) { - res->coeff_type = coeff_type; - res->prob = enc->proba_.coeffs_[coeff_type]; - res->stats = enc->proba_.stats_[coeff_type]; - res->costs = enc->proba_.remapped_costs_[coeff_type]; - res->first = first; -} - -//------------------------------------------------------------------------------ -// Mode costs - -int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]) { - const int x = (it->i4_ & 3), y = (it->i4_ >> 2); - VP8Residual res; - VP8Encoder* const enc = it->enc_; - int R = 0; - int ctx; - - VP8InitResidual(0, 3, enc, &res); - ctx = it->top_nz_[x] + it->left_nz_[y]; - VP8SetResidualCoeffs(levels, &res); - R += VP8GetResidualCost(ctx, &res); - return R; -} - -int VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd) { - VP8Residual res; - VP8Encoder* const enc = it->enc_; - int x, y; - int R = 0; - - VP8IteratorNzToBytes(it); // re-import the non-zero context - - // DC - VP8InitResidual(0, 1, enc, &res); - VP8SetResidualCoeffs(rd->y_dc_levels, &res); - R += VP8GetResidualCost(it->top_nz_[8] + it->left_nz_[8], &res); - - // AC - VP8InitResidual(1, 0, enc, &res); - for (y = 0; y < 4; ++y) { - for (x = 0; x < 4; ++x) { - const int ctx = it->top_nz_[x] + it->left_nz_[y]; - VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); - R += VP8GetResidualCost(ctx, &res); - it->top_nz_[x] = it->left_nz_[y] = (res.last >= 0); - } - } - return R; -} - -int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd) { - VP8Residual res; - VP8Encoder* const enc = it->enc_; - int ch, x, y; - int R = 0; - - VP8IteratorNzToBytes(it); // re-import the non-zero context - - VP8InitResidual(0, 2, enc, &res); - for (ch = 0; ch <= 2; ch += 2) { - for (y = 0; y < 2; ++y) { - for (x = 0; x < 2; ++x) { - const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; - VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); - R += VP8GetResidualCost(ctx, &res); - it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = (res.last >= 0); - } - } - } - return R; -} - - -//------------------------------------------------------------------------------ -// Recording of token probabilities. - -// Record proba context used -static int Record(int bit, proba_t* const stats) { - proba_t p = *stats; - if (p >= 0xffff0000u) { // an overflow is inbound. - p = ((p + 1u) >> 1) & 0x7fff7fffu; // -> divide the stats by 2. - } - // record bit count (lower 16 bits) and increment total count (upper 16 bits). - p += 0x00010000u + bit; - *stats = p; - return bit; -} - -// We keep the table-free variant around for reference, in case. -#define USE_LEVEL_CODE_TABLE - -// Simulate block coding, but only record statistics. -// Note: no need to record the fixed probas. -int VP8RecordCoeffs(int ctx, const VP8Residual* const res) { - int n = res->first; - // should be stats[VP8EncBands[n]], but it's equivalent for n=0 or 1 - proba_t* s = res->stats[n][ctx]; - if (res->last < 0) { - Record(0, s + 0); - return 0; - } - while (n <= res->last) { - int v; - Record(1, s + 0); // order of record doesn't matter - while ((v = res->coeffs[n++]) == 0) { - Record(0, s + 1); - s = res->stats[VP8EncBands[n]][0]; - } - Record(1, s + 1); - if (!Record(2u < (unsigned int)(v + 1), s + 2)) { // v = -1 or 1 - s = res->stats[VP8EncBands[n]][1]; - } else { - v = abs(v); -#if !defined(USE_LEVEL_CODE_TABLE) - if (!Record(v > 4, s + 3)) { - if (Record(v != 2, s + 4)) - Record(v == 4, s + 5); - } else if (!Record(v > 10, s + 6)) { - Record(v > 6, s + 7); - } else if (!Record((v >= 3 + (8 << 2)), s + 8)) { - Record((v >= 3 + (8 << 1)), s + 9); - } else { - Record((v >= 3 + (8 << 3)), s + 10); - } -#else - if (v > MAX_VARIABLE_LEVEL) { - v = MAX_VARIABLE_LEVEL; - } - - { - const int bits = VP8LevelCodes[v - 1][1]; - int pattern = VP8LevelCodes[v - 1][0]; - int i; - for (i = 0; (pattern >>= 1) != 0; ++i) { - const int mask = 2 << i; - if (pattern & 1) Record(!!(bits & mask), s + 3 + i); - } - } -#endif - s = res->stats[VP8EncBands[n]][2]; - } - } - if (n < 16) Record(0, s + 0); - return 1; -} - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/enc/cost.h b/Example-Mac/Pods/libwebp/src/enc/cost.h deleted file mode 100644 index 20960d6d..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/cost.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Cost tables for level and modes. -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_ENC_COST_H_ -#define WEBP_ENC_COST_H_ - -#include -#include -#include "./vp8enci.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// On-the-fly info about the current set of residuals. Handy to avoid -// passing zillions of params. -typedef struct VP8Residual VP8Residual; -struct VP8Residual { - int first; - int last; - const int16_t* coeffs; - - int coeff_type; - ProbaArray* prob; - StatsArray* stats; - CostArrayPtr costs; -}; - -void VP8InitResidual(int first, int coeff_type, - VP8Encoder* const enc, VP8Residual* const res); - -int VP8RecordCoeffs(int ctx, const VP8Residual* const res); - -// Cost of coding one event with probability 'proba'. -static WEBP_INLINE int VP8BitCost(int bit, uint8_t proba) { - return !bit ? VP8EntropyCost[proba] : VP8EntropyCost[255 - proba]; -} - -// Level cost calculations -extern const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2]; -void VP8CalculateLevelCosts(VP8EncProba* const proba); -static WEBP_INLINE int VP8LevelCost(const uint16_t* const table, int level) { - return VP8LevelFixedCosts[level] - + table[(level > MAX_VARIABLE_LEVEL) ? MAX_VARIABLE_LEVEL : level]; -} - -// Mode costs -extern const uint16_t VP8FixedCostsUV[4]; -extern const uint16_t VP8FixedCostsI16[4]; -extern const uint16_t VP8FixedCostsI4[NUM_BMODES][NUM_BMODES][NUM_BMODES]; - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_ENC_COST_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/enc/delta_palettization.c b/Example-Mac/Pods/libwebp/src/enc/delta_palettization.c deleted file mode 100644 index 062e588d..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/delta_palettization.c +++ /dev/null @@ -1,455 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Mislav Bradac (mislavm@google.com) -// - -#include "./delta_palettization.h" - -#ifdef WEBP_EXPERIMENTAL_FEATURES -#include "../webp/types.h" -#include "../dsp/lossless.h" - -#define MK_COL(r, g, b) (((r) << 16) + ((g) << 8) + (b)) - -// Format allows palette up to 256 entries, but more palette entries produce -// bigger entropy. In the future it will probably be useful to add more entries -// that are far from the origin of the palette or choose remaining entries -// dynamically. -#define DELTA_PALETTE_SIZE 226 - -// Palette used for delta_palettization. Entries are roughly sorted by distance -// of their signed equivalents from the origin. -static const uint32_t kDeltaPalette[DELTA_PALETTE_SIZE] = { - MK_COL(0u, 0u, 0u), - MK_COL(255u, 255u, 255u), - MK_COL(1u, 1u, 1u), - MK_COL(254u, 254u, 254u), - MK_COL(2u, 2u, 2u), - MK_COL(4u, 4u, 4u), - MK_COL(252u, 252u, 252u), - MK_COL(250u, 0u, 0u), - MK_COL(0u, 250u, 0u), - MK_COL(0u, 0u, 250u), - MK_COL(6u, 0u, 0u), - MK_COL(0u, 6u, 0u), - MK_COL(0u, 0u, 6u), - MK_COL(0u, 0u, 248u), - MK_COL(0u, 0u, 8u), - MK_COL(0u, 248u, 0u), - MK_COL(0u, 248u, 248u), - MK_COL(0u, 248u, 8u), - MK_COL(0u, 8u, 0u), - MK_COL(0u, 8u, 248u), - MK_COL(0u, 8u, 8u), - MK_COL(8u, 8u, 8u), - MK_COL(248u, 0u, 0u), - MK_COL(248u, 0u, 248u), - MK_COL(248u, 0u, 8u), - MK_COL(248u, 248u, 0u), - MK_COL(248u, 8u, 0u), - MK_COL(8u, 0u, 0u), - MK_COL(8u, 0u, 248u), - MK_COL(8u, 0u, 8u), - MK_COL(8u, 248u, 0u), - MK_COL(8u, 8u, 0u), - MK_COL(23u, 23u, 23u), - MK_COL(13u, 13u, 13u), - MK_COL(232u, 232u, 232u), - MK_COL(244u, 244u, 244u), - MK_COL(245u, 245u, 250u), - MK_COL(50u, 50u, 50u), - MK_COL(204u, 204u, 204u), - MK_COL(236u, 236u, 236u), - MK_COL(16u, 16u, 16u), - MK_COL(240u, 16u, 16u), - MK_COL(16u, 240u, 16u), - MK_COL(240u, 240u, 16u), - MK_COL(16u, 16u, 240u), - MK_COL(240u, 16u, 240u), - MK_COL(16u, 240u, 240u), - MK_COL(240u, 240u, 240u), - MK_COL(0u, 0u, 232u), - MK_COL(0u, 232u, 0u), - MK_COL(232u, 0u, 0u), - MK_COL(0u, 0u, 24u), - MK_COL(0u, 24u, 0u), - MK_COL(24u, 0u, 0u), - MK_COL(32u, 32u, 32u), - MK_COL(224u, 32u, 32u), - MK_COL(32u, 224u, 32u), - MK_COL(224u, 224u, 32u), - MK_COL(32u, 32u, 224u), - MK_COL(224u, 32u, 224u), - MK_COL(32u, 224u, 224u), - MK_COL(224u, 224u, 224u), - MK_COL(0u, 0u, 176u), - MK_COL(0u, 0u, 80u), - MK_COL(0u, 176u, 0u), - MK_COL(0u, 176u, 176u), - MK_COL(0u, 176u, 80u), - MK_COL(0u, 80u, 0u), - MK_COL(0u, 80u, 176u), - MK_COL(0u, 80u, 80u), - MK_COL(176u, 0u, 0u), - MK_COL(176u, 0u, 176u), - MK_COL(176u, 0u, 80u), - MK_COL(176u, 176u, 0u), - MK_COL(176u, 80u, 0u), - MK_COL(80u, 0u, 0u), - MK_COL(80u, 0u, 176u), - MK_COL(80u, 0u, 80u), - MK_COL(80u, 176u, 0u), - MK_COL(80u, 80u, 0u), - MK_COL(0u, 0u, 152u), - MK_COL(0u, 0u, 104u), - MK_COL(0u, 152u, 0u), - MK_COL(0u, 152u, 152u), - MK_COL(0u, 152u, 104u), - MK_COL(0u, 104u, 0u), - MK_COL(0u, 104u, 152u), - MK_COL(0u, 104u, 104u), - MK_COL(152u, 0u, 0u), - MK_COL(152u, 0u, 152u), - MK_COL(152u, 0u, 104u), - MK_COL(152u, 152u, 0u), - MK_COL(152u, 104u, 0u), - MK_COL(104u, 0u, 0u), - MK_COL(104u, 0u, 152u), - MK_COL(104u, 0u, 104u), - MK_COL(104u, 152u, 0u), - MK_COL(104u, 104u, 0u), - MK_COL(216u, 216u, 216u), - MK_COL(216u, 216u, 40u), - MK_COL(216u, 216u, 176u), - MK_COL(216u, 216u, 80u), - MK_COL(216u, 40u, 216u), - MK_COL(216u, 40u, 40u), - MK_COL(216u, 40u, 176u), - MK_COL(216u, 40u, 80u), - MK_COL(216u, 176u, 216u), - MK_COL(216u, 176u, 40u), - MK_COL(216u, 176u, 176u), - MK_COL(216u, 176u, 80u), - MK_COL(216u, 80u, 216u), - MK_COL(216u, 80u, 40u), - MK_COL(216u, 80u, 176u), - MK_COL(216u, 80u, 80u), - MK_COL(40u, 216u, 216u), - MK_COL(40u, 216u, 40u), - MK_COL(40u, 216u, 176u), - MK_COL(40u, 216u, 80u), - MK_COL(40u, 40u, 216u), - MK_COL(40u, 40u, 40u), - MK_COL(40u, 40u, 176u), - MK_COL(40u, 40u, 80u), - MK_COL(40u, 176u, 216u), - MK_COL(40u, 176u, 40u), - MK_COL(40u, 176u, 176u), - MK_COL(40u, 176u, 80u), - MK_COL(40u, 80u, 216u), - MK_COL(40u, 80u, 40u), - MK_COL(40u, 80u, 176u), - MK_COL(40u, 80u, 80u), - MK_COL(80u, 216u, 216u), - MK_COL(80u, 216u, 40u), - MK_COL(80u, 216u, 176u), - MK_COL(80u, 216u, 80u), - MK_COL(80u, 40u, 216u), - MK_COL(80u, 40u, 40u), - MK_COL(80u, 40u, 176u), - MK_COL(80u, 40u, 80u), - MK_COL(80u, 176u, 216u), - MK_COL(80u, 176u, 40u), - MK_COL(80u, 176u, 176u), - MK_COL(80u, 176u, 80u), - MK_COL(80u, 80u, 216u), - MK_COL(80u, 80u, 40u), - MK_COL(80u, 80u, 176u), - MK_COL(80u, 80u, 80u), - MK_COL(0u, 0u, 192u), - MK_COL(0u, 0u, 64u), - MK_COL(0u, 0u, 128u), - MK_COL(0u, 192u, 0u), - MK_COL(0u, 192u, 192u), - MK_COL(0u, 192u, 64u), - MK_COL(0u, 192u, 128u), - MK_COL(0u, 64u, 0u), - MK_COL(0u, 64u, 192u), - MK_COL(0u, 64u, 64u), - MK_COL(0u, 64u, 128u), - MK_COL(0u, 128u, 0u), - MK_COL(0u, 128u, 192u), - MK_COL(0u, 128u, 64u), - MK_COL(0u, 128u, 128u), - MK_COL(176u, 216u, 216u), - MK_COL(176u, 216u, 40u), - MK_COL(176u, 216u, 176u), - MK_COL(176u, 216u, 80u), - MK_COL(176u, 40u, 216u), - MK_COL(176u, 40u, 40u), - MK_COL(176u, 40u, 176u), - MK_COL(176u, 40u, 80u), - MK_COL(176u, 176u, 216u), - MK_COL(176u, 176u, 40u), - MK_COL(176u, 176u, 176u), - MK_COL(176u, 176u, 80u), - MK_COL(176u, 80u, 216u), - MK_COL(176u, 80u, 40u), - MK_COL(176u, 80u, 176u), - MK_COL(176u, 80u, 80u), - MK_COL(192u, 0u, 0u), - MK_COL(192u, 0u, 192u), - MK_COL(192u, 0u, 64u), - MK_COL(192u, 0u, 128u), - MK_COL(192u, 192u, 0u), - MK_COL(192u, 192u, 192u), - MK_COL(192u, 192u, 64u), - MK_COL(192u, 192u, 128u), - MK_COL(192u, 64u, 0u), - MK_COL(192u, 64u, 192u), - MK_COL(192u, 64u, 64u), - MK_COL(192u, 64u, 128u), - MK_COL(192u, 128u, 0u), - MK_COL(192u, 128u, 192u), - MK_COL(192u, 128u, 64u), - MK_COL(192u, 128u, 128u), - MK_COL(64u, 0u, 0u), - MK_COL(64u, 0u, 192u), - MK_COL(64u, 0u, 64u), - MK_COL(64u, 0u, 128u), - MK_COL(64u, 192u, 0u), - MK_COL(64u, 192u, 192u), - MK_COL(64u, 192u, 64u), - MK_COL(64u, 192u, 128u), - MK_COL(64u, 64u, 0u), - MK_COL(64u, 64u, 192u), - MK_COL(64u, 64u, 64u), - MK_COL(64u, 64u, 128u), - MK_COL(64u, 128u, 0u), - MK_COL(64u, 128u, 192u), - MK_COL(64u, 128u, 64u), - MK_COL(64u, 128u, 128u), - MK_COL(128u, 0u, 0u), - MK_COL(128u, 0u, 192u), - MK_COL(128u, 0u, 64u), - MK_COL(128u, 0u, 128u), - MK_COL(128u, 192u, 0u), - MK_COL(128u, 192u, 192u), - MK_COL(128u, 192u, 64u), - MK_COL(128u, 192u, 128u), - MK_COL(128u, 64u, 0u), - MK_COL(128u, 64u, 192u), - MK_COL(128u, 64u, 64u), - MK_COL(128u, 64u, 128u), - MK_COL(128u, 128u, 0u), - MK_COL(128u, 128u, 192u), - MK_COL(128u, 128u, 64u), - MK_COL(128u, 128u, 128u), -}; - -#undef MK_COL - -//------------------------------------------------------------------------------ -// TODO(skal): move the functions to dsp/lossless.c when the correct -// granularity is found. For now, we'll just copy-paste some useful bits -// here instead. - -// In-place sum of each component with mod 256. -static WEBP_INLINE void AddPixelsEq(uint32_t* a, uint32_t b) { - const uint32_t alpha_and_green = (*a & 0xff00ff00u) + (b & 0xff00ff00u); - const uint32_t red_and_blue = (*a & 0x00ff00ffu) + (b & 0x00ff00ffu); - *a = (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu); -} - -static WEBP_INLINE uint32_t Clip255(uint32_t a) { - if (a < 256) { - return a; - } - // return 0, when a is a negative integer. - // return 255, when a is positive. - return ~a >> 24; -} - -// Delta palettization functions. -static WEBP_INLINE int Square(int x) { - return x * x; -} - -static WEBP_INLINE uint32_t Intensity(uint32_t a) { - return - 30 * ((a >> 16) & 0xff) + - 59 * ((a >> 8) & 0xff) + - 11 * ((a >> 0) & 0xff); -} - -static uint32_t CalcDist(uint32_t predicted_value, uint32_t actual_value, - uint32_t palette_entry) { - int i; - uint32_t distance = 0; - AddPixelsEq(&predicted_value, palette_entry); - for (i = 0; i < 32; i += 8) { - const int32_t av = (actual_value >> i) & 0xff; - const int32_t pv = (predicted_value >> i) & 0xff; - distance += Square(pv - av); - } - // We sum square of intensity difference with factor 10, but because Intensity - // returns 100 times real intensity we need to multiply differences of colors - // by 1000. - distance *= 1000u; - distance += Square(Intensity(predicted_value) - - Intensity(actual_value)); - return distance; -} - -static uint32_t Predict(int x, int y, uint32_t* image) { - const uint32_t t = (y == 0) ? ARGB_BLACK : image[x]; - const uint32_t l = (x == 0) ? ARGB_BLACK : image[x - 1]; - const uint32_t p = - (((((t >> 24) & 0xff) + ((l >> 24) & 0xff)) / 2) << 24) + - (((((t >> 16) & 0xff) + ((l >> 16) & 0xff)) / 2) << 16) + - (((((t >> 8) & 0xff) + ((l >> 8) & 0xff)) / 2) << 8) + - (((((t >> 0) & 0xff) + ((l >> 0) & 0xff)) / 2) << 0); - if (x == 0 && y == 0) return ARGB_BLACK; - if (x == 0) return t; - if (y == 0) return l; - return p; -} - -static WEBP_INLINE int AddSubtractComponentFullWithCoefficient( - int a, int b, int c) { - return Clip255(a + ((b - c) >> 2)); -} - -static WEBP_INLINE uint32_t ClampedAddSubtractFullWithCoefficient( - uint32_t c0, uint32_t c1, uint32_t c2) { - const int a = AddSubtractComponentFullWithCoefficient( - c0 >> 24, c1 >> 24, c2 >> 24); - const int r = AddSubtractComponentFullWithCoefficient((c0 >> 16) & 0xff, - (c1 >> 16) & 0xff, - (c2 >> 16) & 0xff); - const int g = AddSubtractComponentFullWithCoefficient((c0 >> 8) & 0xff, - (c1 >> 8) & 0xff, - (c2 >> 8) & 0xff); - const int b = AddSubtractComponentFullWithCoefficient( - c0 & 0xff, c1 & 0xff, c2 & 0xff); - return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b; -} - -//------------------------------------------------------------------------------ - -// Find palette entry with minimum error from difference of actual pixel value -// and predicted pixel value. Propagate error of pixel to its top and left pixel -// in src array. Write predicted_value + palette_entry to new_image. Return -// index of best palette entry. -static int FindBestPaletteEntry(uint32_t src, uint32_t predicted_value, - const uint32_t palette[], int palette_size) { - int i; - int idx = 0; - uint32_t best_distance = CalcDist(predicted_value, src, palette[0]); - for (i = 1; i < palette_size; ++i) { - const uint32_t distance = CalcDist(predicted_value, src, palette[i]); - if (distance < best_distance) { - best_distance = distance; - idx = i; - } - } - return idx; -} - -static void ApplyBestPaletteEntry(int x, int y, - uint32_t new_value, uint32_t palette_value, - uint32_t* src, int src_stride, - uint32_t* new_image) { - AddPixelsEq(&new_value, palette_value); - if (x > 0) { - src[x - 1] = ClampedAddSubtractFullWithCoefficient(src[x - 1], - new_value, src[x]); - } - if (y > 0) { - src[x - src_stride] = - ClampedAddSubtractFullWithCoefficient(src[x - src_stride], - new_value, src[x]); - } - new_image[x] = new_value; -} - -//------------------------------------------------------------------------------ -// Main entry point - -static WebPEncodingError ApplyDeltaPalette(uint32_t* src, uint32_t* dst, - uint32_t src_stride, - uint32_t dst_stride, - const uint32_t* palette, - int palette_size, - int width, int height, - int num_passes) { - int x, y; - WebPEncodingError err = VP8_ENC_OK; - uint32_t* new_image = (uint32_t*)WebPSafeMalloc(width, sizeof(*new_image)); - uint8_t* const tmp_row = (uint8_t*)WebPSafeMalloc(width, sizeof(*tmp_row)); - if (new_image == NULL || tmp_row == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - while (num_passes--) { - uint32_t* cur_src = src; - uint32_t* cur_dst = dst; - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - const uint32_t predicted_value = Predict(x, y, new_image); - tmp_row[x] = FindBestPaletteEntry(cur_src[x], predicted_value, - palette, palette_size); - ApplyBestPaletteEntry(x, y, predicted_value, palette[tmp_row[x]], - cur_src, src_stride, new_image); - } - for (x = 0; x < width; ++x) { - cur_dst[x] = palette[tmp_row[x]]; - } - cur_src += src_stride; - cur_dst += dst_stride; - } - } - Error: - WebPSafeFree(new_image); - WebPSafeFree(tmp_row); - return err; -} - -// replaces enc->argb_ by a palettizable approximation of it, -// and generates optimal enc->palette_[] -WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc) { - const WebPPicture* const pic = enc->pic_; - uint32_t* src = pic->argb; - uint32_t* dst = enc->argb_; - const int width = pic->width; - const int height = pic->height; - - WebPEncodingError err = VP8_ENC_OK; - memcpy(enc->palette_, kDeltaPalette, sizeof(kDeltaPalette)); - enc->palette_[DELTA_PALETTE_SIZE - 1] = src[0] - 0xff000000u; - enc->palette_size_ = DELTA_PALETTE_SIZE; - err = ApplyDeltaPalette(src, dst, pic->argb_stride, enc->current_width_, - enc->palette_, enc->palette_size_, - width, height, 2); - if (err != VP8_ENC_OK) goto Error; - - Error: - return err; -} - -#else // !WEBP_EXPERIMENTAL_FEATURES - -WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc) { - (void)enc; - return VP8_ENC_ERROR_INVALID_CONFIGURATION; -} - -#endif // WEBP_EXPERIMENTAL_FEATURES diff --git a/Example-Mac/Pods/libwebp/src/enc/delta_palettization.h b/Example-Mac/Pods/libwebp/src/enc/delta_palettization.h deleted file mode 100644 index e41c0c5a..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/delta_palettization.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Mislav Bradac (mislavm@google.com) -// - -#ifndef WEBP_ENC_DELTA_PALETTIZATION_H_ -#define WEBP_ENC_DELTA_PALETTIZATION_H_ - -#include "../webp/encode.h" -#include "../enc/vp8li.h" - -// Replaces enc->argb_[] input by a palettizable approximation of it, -// and generates optimal enc->palette_[]. -// This function can revert enc->use_palette_ / enc->use_predict_ flag -// if delta-palettization is not producing expected saving. -WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc); - -#endif // WEBP_ENC_DELTA_PALETTIZATION_H_ diff --git a/Example-Mac/Pods/libwebp/src/enc/filter.c b/Example-Mac/Pods/libwebp/src/enc/filter.c deleted file mode 100644 index 41813cff..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/filter.c +++ /dev/null @@ -1,299 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Selecting filter level -// -// Author: somnath@google.com (Somnath Banerjee) - -#include -#include "./vp8enci.h" -#include "../dsp/dsp.h" - -// This table gives, for a given sharpness, the filtering strength to be -// used (at least) in order to filter a given edge step delta. -// This is constructed by brute force inspection: for all delta, we iterate -// over all possible filtering strength / thresh until needs_filter() returns -// true. -#define MAX_DELTA_SIZE 64 -static const uint8_t kLevelsFromDelta[8][MAX_DELTA_SIZE] = { - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 }, - { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 17, 18, - 20, 21, 23, 24, 26, 27, 29, 30, 32, 33, 35, 36, 38, 39, 41, 42, - 44, 45, 47, 48, 50, 51, 53, 54, 56, 57, 59, 60, 62, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, - { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 14, 16, 17, 19, - 20, 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, 37, 38, 40, 41, 43, - 44, 46, 47, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, - { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 18, 19, - 21, 22, 24, 25, 27, 28, 30, 31, 33, 34, 36, 37, 39, 40, 42, 43, - 45, 46, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, - { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 14, 15, 17, 18, 20, - 21, 23, 24, 26, 27, 29, 30, 32, 33, 35, 36, 38, 39, 41, 42, 44, - 45, 47, 48, 50, 51, 53, 54, 56, 57, 59, 60, 62, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, - { 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 17, 19, 20, - 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, 37, 38, 40, 41, 43, 44, - 46, 47, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, - { 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 18, 19, 21, - 22, 24, 25, 27, 28, 30, 31, 33, 34, 36, 37, 39, 40, 42, 43, 45, - 46, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, - { 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 14, 15, 17, 18, 20, 21, - 23, 24, 26, 27, 29, 30, 32, 33, 35, 36, 38, 39, 41, 42, 44, 45, - 47, 48, 50, 51, 53, 54, 56, 57, 59, 60, 62, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 } -}; - -int VP8FilterStrengthFromDelta(int sharpness, int delta) { - const int pos = (delta < MAX_DELTA_SIZE) ? delta : MAX_DELTA_SIZE - 1; - assert(sharpness >= 0 && sharpness <= 7); - return kLevelsFromDelta[sharpness][pos]; -} - -//------------------------------------------------------------------------------ -// Paragraph 15.4: compute the inner-edge filtering strength - -static int GetILevel(int sharpness, int level) { - if (sharpness > 0) { - if (sharpness > 4) { - level >>= 2; - } else { - level >>= 1; - } - if (level > 9 - sharpness) { - level = 9 - sharpness; - } - } - if (level < 1) level = 1; - return level; -} - -static void DoFilter(const VP8EncIterator* const it, int level) { - const VP8Encoder* const enc = it->enc_; - const int ilevel = GetILevel(enc->config_->filter_sharpness, level); - const int limit = 2 * level + ilevel; - - uint8_t* const y_dst = it->yuv_out2_ + Y_OFF_ENC; - uint8_t* const u_dst = it->yuv_out2_ + U_OFF_ENC; - uint8_t* const v_dst = it->yuv_out2_ + V_OFF_ENC; - - // copy current block to yuv_out2_ - memcpy(y_dst, it->yuv_out_, YUV_SIZE_ENC * sizeof(uint8_t)); - - if (enc->filter_hdr_.simple_ == 1) { // simple - VP8SimpleHFilter16i(y_dst, BPS, limit); - VP8SimpleVFilter16i(y_dst, BPS, limit); - } else { // complex - const int hev_thresh = (level >= 40) ? 2 : (level >= 15) ? 1 : 0; - VP8HFilter16i(y_dst, BPS, limit, ilevel, hev_thresh); - VP8HFilter8i(u_dst, v_dst, BPS, limit, ilevel, hev_thresh); - VP8VFilter16i(y_dst, BPS, limit, ilevel, hev_thresh); - VP8VFilter8i(u_dst, v_dst, BPS, limit, ilevel, hev_thresh); - } -} - -//------------------------------------------------------------------------------ -// SSIM metric - -enum { KERNEL = 3 }; -static const double kMinValue = 1.e-10; // minimal threshold - -void VP8SSIMAddStats(const DistoStats* const src, DistoStats* const dst) { - dst->w += src->w; - dst->xm += src->xm; - dst->ym += src->ym; - dst->xxm += src->xxm; - dst->xym += src->xym; - dst->yym += src->yym; -} - -static void VP8SSIMAccumulate(const uint8_t* src1, int stride1, - const uint8_t* src2, int stride2, - int xo, int yo, int W, int H, - DistoStats* const stats) { - const int ymin = (yo - KERNEL < 0) ? 0 : yo - KERNEL; - const int ymax = (yo + KERNEL > H - 1) ? H - 1 : yo + KERNEL; - const int xmin = (xo - KERNEL < 0) ? 0 : xo - KERNEL; - const int xmax = (xo + KERNEL > W - 1) ? W - 1 : xo + KERNEL; - int x, y; - src1 += ymin * stride1; - src2 += ymin * stride2; - for (y = ymin; y <= ymax; ++y, src1 += stride1, src2 += stride2) { - for (x = xmin; x <= xmax; ++x) { - const int s1 = src1[x]; - const int s2 = src2[x]; - stats->w += 1; - stats->xm += s1; - stats->ym += s2; - stats->xxm += s1 * s1; - stats->xym += s1 * s2; - stats->yym += s2 * s2; - } - } -} - -double VP8SSIMGet(const DistoStats* const stats) { - const double xmxm = stats->xm * stats->xm; - const double ymym = stats->ym * stats->ym; - const double xmym = stats->xm * stats->ym; - const double w2 = stats->w * stats->w; - double sxx = stats->xxm * stats->w - xmxm; - double syy = stats->yym * stats->w - ymym; - double sxy = stats->xym * stats->w - xmym; - double C1, C2; - double fnum; - double fden; - // small errors are possible, due to rounding. Clamp to zero. - if (sxx < 0.) sxx = 0.; - if (syy < 0.) syy = 0.; - C1 = 6.5025 * w2; - C2 = 58.5225 * w2; - fnum = (2 * xmym + C1) * (2 * sxy + C2); - fden = (xmxm + ymym + C1) * (sxx + syy + C2); - return (fden != 0.) ? fnum / fden : kMinValue; -} - -double VP8SSIMGetSquaredError(const DistoStats* const s) { - if (s->w > 0.) { - const double iw2 = 1. / (s->w * s->w); - const double sxx = s->xxm * s->w - s->xm * s->xm; - const double syy = s->yym * s->w - s->ym * s->ym; - const double sxy = s->xym * s->w - s->xm * s->ym; - const double SSE = iw2 * (sxx + syy - 2. * sxy); - if (SSE > kMinValue) return SSE; - } - return kMinValue; -} - -void VP8SSIMAccumulatePlane(const uint8_t* src1, int stride1, - const uint8_t* src2, int stride2, - int W, int H, DistoStats* const stats) { - int x, y; - for (y = 0; y < H; ++y) { - for (x = 0; x < W; ++x) { - VP8SSIMAccumulate(src1, stride1, src2, stride2, x, y, W, H, stats); - } - } -} - -static double GetMBSSIM(const uint8_t* yuv1, const uint8_t* yuv2) { - int x, y; - DistoStats s = { .0, .0, .0, .0, .0, .0 }; - - // compute SSIM in a 10 x 10 window - for (x = 3; x < 13; x++) { - for (y = 3; y < 13; y++) { - VP8SSIMAccumulate(yuv1 + Y_OFF_ENC, BPS, yuv2 + Y_OFF_ENC, BPS, - x, y, 16, 16, &s); - } - } - for (x = 1; x < 7; x++) { - for (y = 1; y < 7; y++) { - VP8SSIMAccumulate(yuv1 + U_OFF_ENC, BPS, yuv2 + U_OFF_ENC, BPS, - x, y, 8, 8, &s); - VP8SSIMAccumulate(yuv1 + V_OFF_ENC, BPS, yuv2 + V_OFF_ENC, BPS, - x, y, 8, 8, &s); - } - } - return VP8SSIMGet(&s); -} - -//------------------------------------------------------------------------------ -// Exposed APIs: Encoder should call the following 3 functions to adjust -// loop filter strength - -void VP8InitFilter(VP8EncIterator* const it) { - if (it->lf_stats_ != NULL) { - int s, i; - for (s = 0; s < NUM_MB_SEGMENTS; s++) { - for (i = 0; i < MAX_LF_LEVELS; i++) { - (*it->lf_stats_)[s][i] = 0; - } - } - } -} - -void VP8StoreFilterStats(VP8EncIterator* const it) { - int d; - VP8Encoder* const enc = it->enc_; - const int s = it->mb_->segment_; - const int level0 = enc->dqm_[s].fstrength_; - - // explore +/-quant range of values around level0 - const int delta_min = -enc->dqm_[s].quant_; - const int delta_max = enc->dqm_[s].quant_; - const int step_size = (delta_max - delta_min >= 4) ? 4 : 1; - - if (it->lf_stats_ == NULL) return; - - // NOTE: Currently we are applying filter only across the sublock edges - // There are two reasons for that. - // 1. Applying filter on macro block edges will change the pixels in - // the left and top macro blocks. That will be hard to restore - // 2. Macro Blocks on the bottom and right are not yet compressed. So we - // cannot apply filter on the right and bottom macro block edges. - if (it->mb_->type_ == 1 && it->mb_->skip_) return; - - // Always try filter level zero - (*it->lf_stats_)[s][0] += GetMBSSIM(it->yuv_in_, it->yuv_out_); - - for (d = delta_min; d <= delta_max; d += step_size) { - const int level = level0 + d; - if (level <= 0 || level >= MAX_LF_LEVELS) { - continue; - } - DoFilter(it, level); - (*it->lf_stats_)[s][level] += GetMBSSIM(it->yuv_in_, it->yuv_out2_); - } -} - -void VP8AdjustFilterStrength(VP8EncIterator* const it) { - VP8Encoder* const enc = it->enc_; - if (it->lf_stats_ != NULL) { - int s; - for (s = 0; s < NUM_MB_SEGMENTS; s++) { - int i, best_level = 0; - // Improvement over filter level 0 should be at least 1e-5 (relatively) - double best_v = 1.00001 * (*it->lf_stats_)[s][0]; - for (i = 1; i < MAX_LF_LEVELS; i++) { - const double v = (*it->lf_stats_)[s][i]; - if (v > best_v) { - best_v = v; - best_level = i; - } - } - enc->dqm_[s].fstrength_ = best_level; - } - } else if (enc->config_->filter_strength > 0) { - int max_level = 0; - int s; - for (s = 0; s < NUM_MB_SEGMENTS; s++) { - VP8SegmentInfo* const dqm = &enc->dqm_[s]; - // this '>> 3' accounts for some inverse WHT scaling - const int delta = (dqm->max_edge_ * dqm->y2_.q_[1]) >> 3; - const int level = - VP8FilterStrengthFromDelta(enc->filter_hdr_.sharpness_, delta); - if (level > dqm->fstrength_) { - dqm->fstrength_ = level; - } - if (max_level < dqm->fstrength_) { - max_level = dqm->fstrength_; - } - } - enc->filter_hdr_.level_ = max_level; - } -} - -// ----------------------------------------------------------------------------- diff --git a/Example-Mac/Pods/libwebp/src/enc/frame.c b/Example-Mac/Pods/libwebp/src/enc/frame.c deleted file mode 100644 index 5b7a40b9..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/frame.c +++ /dev/null @@ -1,850 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// frame coding and analysis -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include - -#include "./cost.h" -#include "./vp8enci.h" -#include "../dsp/dsp.h" -#include "../webp/format_constants.h" // RIFF constants - -#define SEGMENT_VISU 0 -#define DEBUG_SEARCH 0 // useful to track search convergence - -//------------------------------------------------------------------------------ -// multi-pass convergence - -#define HEADER_SIZE_ESTIMATE (RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + \ - VP8_FRAME_HEADER_SIZE) -#define DQ_LIMIT 0.4 // convergence is considered reached if dq < DQ_LIMIT -// we allow 2k of extra head-room in PARTITION0 limit. -#define PARTITION0_SIZE_LIMIT ((VP8_MAX_PARTITION0_SIZE - 2048ULL) << 11) - -typedef struct { // struct for organizing convergence in either size or PSNR - int is_first; - float dq; - float q, last_q; - double value, last_value; // PSNR or size - double target; - int do_size_search; -} PassStats; - -static int InitPassStats(const VP8Encoder* const enc, PassStats* const s) { - const uint64_t target_size = (uint64_t)enc->config_->target_size; - const int do_size_search = (target_size != 0); - const float target_PSNR = enc->config_->target_PSNR; - - s->is_first = 1; - s->dq = 10.f; - s->q = s->last_q = enc->config_->quality; - s->target = do_size_search ? (double)target_size - : (target_PSNR > 0.) ? target_PSNR - : 40.; // default, just in case - s->value = s->last_value = 0.; - s->do_size_search = do_size_search; - return do_size_search; -} - -static float Clamp(float v, float min, float max) { - return (v < min) ? min : (v > max) ? max : v; -} - -static float ComputeNextQ(PassStats* const s) { - float dq; - if (s->is_first) { - dq = (s->value > s->target) ? -s->dq : s->dq; - s->is_first = 0; - } else if (s->value != s->last_value) { - const double slope = (s->target - s->value) / (s->last_value - s->value); - dq = (float)(slope * (s->last_q - s->q)); - } else { - dq = 0.; // we're done?! - } - // Limit variable to avoid large swings. - s->dq = Clamp(dq, -30.f, 30.f); - s->last_q = s->q; - s->last_value = s->value; - s->q = Clamp(s->q + s->dq, 0.f, 100.f); - return s->q; -} - -//------------------------------------------------------------------------------ -// Tables for level coding - -const uint8_t VP8Cat3[] = { 173, 148, 140 }; -const uint8_t VP8Cat4[] = { 176, 155, 140, 135 }; -const uint8_t VP8Cat5[] = { 180, 157, 141, 134, 130 }; -const uint8_t VP8Cat6[] = - { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129 }; - -//------------------------------------------------------------------------------ -// Reset the statistics about: number of skips, token proba, level cost,... - -static void ResetStats(VP8Encoder* const enc) { - VP8EncProba* const proba = &enc->proba_; - VP8CalculateLevelCosts(proba); - proba->nb_skip_ = 0; -} - -//------------------------------------------------------------------------------ -// Skip decision probability - -#define SKIP_PROBA_THRESHOLD 250 // value below which using skip_proba is OK. - -static int CalcSkipProba(uint64_t nb, uint64_t total) { - return (int)(total ? (total - nb) * 255 / total : 255); -} - -// Returns the bit-cost for coding the skip probability. -static int FinalizeSkipProba(VP8Encoder* const enc) { - VP8EncProba* const proba = &enc->proba_; - const int nb_mbs = enc->mb_w_ * enc->mb_h_; - const int nb_events = proba->nb_skip_; - int size; - proba->skip_proba_ = CalcSkipProba(nb_events, nb_mbs); - proba->use_skip_proba_ = (proba->skip_proba_ < SKIP_PROBA_THRESHOLD); - size = 256; // 'use_skip_proba' bit - if (proba->use_skip_proba_) { - size += nb_events * VP8BitCost(1, proba->skip_proba_) - + (nb_mbs - nb_events) * VP8BitCost(0, proba->skip_proba_); - size += 8 * 256; // cost of signaling the skip_proba_ itself. - } - return size; -} - -// Collect statistics and deduce probabilities for next coding pass. -// Return the total bit-cost for coding the probability updates. -static int CalcTokenProba(int nb, int total) { - assert(nb <= total); - return nb ? (255 - nb * 255 / total) : 255; -} - -// Cost of coding 'nb' 1's and 'total-nb' 0's using 'proba' probability. -static int BranchCost(int nb, int total, int proba) { - return nb * VP8BitCost(1, proba) + (total - nb) * VP8BitCost(0, proba); -} - -static void ResetTokenStats(VP8Encoder* const enc) { - VP8EncProba* const proba = &enc->proba_; - memset(proba->stats_, 0, sizeof(proba->stats_)); -} - -static int FinalizeTokenProbas(VP8EncProba* const proba) { - int has_changed = 0; - int size = 0; - int t, b, c, p; - for (t = 0; t < NUM_TYPES; ++t) { - for (b = 0; b < NUM_BANDS; ++b) { - for (c = 0; c < NUM_CTX; ++c) { - for (p = 0; p < NUM_PROBAS; ++p) { - const proba_t stats = proba->stats_[t][b][c][p]; - const int nb = (stats >> 0) & 0xffff; - const int total = (stats >> 16) & 0xffff; - const int update_proba = VP8CoeffsUpdateProba[t][b][c][p]; - const int old_p = VP8CoeffsProba0[t][b][c][p]; - const int new_p = CalcTokenProba(nb, total); - const int old_cost = BranchCost(nb, total, old_p) - + VP8BitCost(0, update_proba); - const int new_cost = BranchCost(nb, total, new_p) - + VP8BitCost(1, update_proba) - + 8 * 256; - const int use_new_p = (old_cost > new_cost); - size += VP8BitCost(use_new_p, update_proba); - if (use_new_p) { // only use proba that seem meaningful enough. - proba->coeffs_[t][b][c][p] = new_p; - has_changed |= (new_p != old_p); - size += 8 * 256; - } else { - proba->coeffs_[t][b][c][p] = old_p; - } - } - } - } - } - proba->dirty_ = has_changed; - return size; -} - -//------------------------------------------------------------------------------ -// Finalize Segment probability based on the coding tree - -static int GetProba(int a, int b) { - const int total = a + b; - return (total == 0) ? 255 // that's the default probability. - : (255 * a + total / 2) / total; // rounded proba -} - -static void SetSegmentProbas(VP8Encoder* const enc) { - int p[NUM_MB_SEGMENTS] = { 0 }; - int n; - - for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { - const VP8MBInfo* const mb = &enc->mb_info_[n]; - p[mb->segment_]++; - } - if (enc->pic_->stats != NULL) { - for (n = 0; n < NUM_MB_SEGMENTS; ++n) { - enc->pic_->stats->segment_size[n] = p[n]; - } - } - if (enc->segment_hdr_.num_segments_ > 1) { - uint8_t* const probas = enc->proba_.segments_; - probas[0] = GetProba(p[0] + p[1], p[2] + p[3]); - probas[1] = GetProba(p[0], p[1]); - probas[2] = GetProba(p[2], p[3]); - - enc->segment_hdr_.update_map_ = - (probas[0] != 255) || (probas[1] != 255) || (probas[2] != 255); - enc->segment_hdr_.size_ = - p[0] * (VP8BitCost(0, probas[0]) + VP8BitCost(0, probas[1])) + - p[1] * (VP8BitCost(0, probas[0]) + VP8BitCost(1, probas[1])) + - p[2] * (VP8BitCost(1, probas[0]) + VP8BitCost(0, probas[2])) + - p[3] * (VP8BitCost(1, probas[0]) + VP8BitCost(1, probas[2])); - } else { - enc->segment_hdr_.update_map_ = 0; - enc->segment_hdr_.size_ = 0; - } -} - -//------------------------------------------------------------------------------ -// Coefficient coding - -static int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) { - int n = res->first; - // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 - const uint8_t* p = res->prob[n][ctx]; - if (!VP8PutBit(bw, res->last >= 0, p[0])) { - return 0; - } - - while (n < 16) { - const int c = res->coeffs[n++]; - const int sign = c < 0; - int v = sign ? -c : c; - if (!VP8PutBit(bw, v != 0, p[1])) { - p = res->prob[VP8EncBands[n]][0]; - continue; - } - if (!VP8PutBit(bw, v > 1, p[2])) { - p = res->prob[VP8EncBands[n]][1]; - } else { - if (!VP8PutBit(bw, v > 4, p[3])) { - if (VP8PutBit(bw, v != 2, p[4])) - VP8PutBit(bw, v == 4, p[5]); - } else if (!VP8PutBit(bw, v > 10, p[6])) { - if (!VP8PutBit(bw, v > 6, p[7])) { - VP8PutBit(bw, v == 6, 159); - } else { - VP8PutBit(bw, v >= 9, 165); - VP8PutBit(bw, !(v & 1), 145); - } - } else { - int mask; - const uint8_t* tab; - if (v < 3 + (8 << 1)) { // VP8Cat3 (3b) - VP8PutBit(bw, 0, p[8]); - VP8PutBit(bw, 0, p[9]); - v -= 3 + (8 << 0); - mask = 1 << 2; - tab = VP8Cat3; - } else if (v < 3 + (8 << 2)) { // VP8Cat4 (4b) - VP8PutBit(bw, 0, p[8]); - VP8PutBit(bw, 1, p[9]); - v -= 3 + (8 << 1); - mask = 1 << 3; - tab = VP8Cat4; - } else if (v < 3 + (8 << 3)) { // VP8Cat5 (5b) - VP8PutBit(bw, 1, p[8]); - VP8PutBit(bw, 0, p[10]); - v -= 3 + (8 << 2); - mask = 1 << 4; - tab = VP8Cat5; - } else { // VP8Cat6 (11b) - VP8PutBit(bw, 1, p[8]); - VP8PutBit(bw, 1, p[10]); - v -= 3 + (8 << 3); - mask = 1 << 10; - tab = VP8Cat6; - } - while (mask) { - VP8PutBit(bw, !!(v & mask), *tab++); - mask >>= 1; - } - } - p = res->prob[VP8EncBands[n]][2]; - } - VP8PutBitUniform(bw, sign); - if (n == 16 || !VP8PutBit(bw, n <= res->last, p[0])) { - return 1; // EOB - } - } - return 1; -} - -static void CodeResiduals(VP8BitWriter* const bw, VP8EncIterator* const it, - const VP8ModeScore* const rd) { - int x, y, ch; - VP8Residual res; - uint64_t pos1, pos2, pos3; - const int i16 = (it->mb_->type_ == 1); - const int segment = it->mb_->segment_; - VP8Encoder* const enc = it->enc_; - - VP8IteratorNzToBytes(it); - - pos1 = VP8BitWriterPos(bw); - if (i16) { - VP8InitResidual(0, 1, enc, &res); - VP8SetResidualCoeffs(rd->y_dc_levels, &res); - it->top_nz_[8] = it->left_nz_[8] = - PutCoeffs(bw, it->top_nz_[8] + it->left_nz_[8], &res); - VP8InitResidual(1, 0, enc, &res); - } else { - VP8InitResidual(0, 3, enc, &res); - } - - // luma-AC - for (y = 0; y < 4; ++y) { - for (x = 0; x < 4; ++x) { - const int ctx = it->top_nz_[x] + it->left_nz_[y]; - VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); - it->top_nz_[x] = it->left_nz_[y] = PutCoeffs(bw, ctx, &res); - } - } - pos2 = VP8BitWriterPos(bw); - - // U/V - VP8InitResidual(0, 2, enc, &res); - for (ch = 0; ch <= 2; ch += 2) { - for (y = 0; y < 2; ++y) { - for (x = 0; x < 2; ++x) { - const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; - VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); - it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = - PutCoeffs(bw, ctx, &res); - } - } - } - pos3 = VP8BitWriterPos(bw); - it->luma_bits_ = pos2 - pos1; - it->uv_bits_ = pos3 - pos2; - it->bit_count_[segment][i16] += it->luma_bits_; - it->bit_count_[segment][2] += it->uv_bits_; - VP8IteratorBytesToNz(it); -} - -// Same as CodeResiduals, but doesn't actually write anything. -// Instead, it just records the event distribution. -static void RecordResiduals(VP8EncIterator* const it, - const VP8ModeScore* const rd) { - int x, y, ch; - VP8Residual res; - VP8Encoder* const enc = it->enc_; - - VP8IteratorNzToBytes(it); - - if (it->mb_->type_ == 1) { // i16x16 - VP8InitResidual(0, 1, enc, &res); - VP8SetResidualCoeffs(rd->y_dc_levels, &res); - it->top_nz_[8] = it->left_nz_[8] = - VP8RecordCoeffs(it->top_nz_[8] + it->left_nz_[8], &res); - VP8InitResidual(1, 0, enc, &res); - } else { - VP8InitResidual(0, 3, enc, &res); - } - - // luma-AC - for (y = 0; y < 4; ++y) { - for (x = 0; x < 4; ++x) { - const int ctx = it->top_nz_[x] + it->left_nz_[y]; - VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); - it->top_nz_[x] = it->left_nz_[y] = VP8RecordCoeffs(ctx, &res); - } - } - - // U/V - VP8InitResidual(0, 2, enc, &res); - for (ch = 0; ch <= 2; ch += 2) { - for (y = 0; y < 2; ++y) { - for (x = 0; x < 2; ++x) { - const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; - VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); - it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = - VP8RecordCoeffs(ctx, &res); - } - } - } - - VP8IteratorBytesToNz(it); -} - -//------------------------------------------------------------------------------ -// Token buffer - -#if !defined(DISABLE_TOKEN_BUFFER) - -static int RecordTokens(VP8EncIterator* const it, const VP8ModeScore* const rd, - VP8TBuffer* const tokens) { - int x, y, ch; - VP8Residual res; - VP8Encoder* const enc = it->enc_; - - VP8IteratorNzToBytes(it); - if (it->mb_->type_ == 1) { // i16x16 - const int ctx = it->top_nz_[8] + it->left_nz_[8]; - VP8InitResidual(0, 1, enc, &res); - VP8SetResidualCoeffs(rd->y_dc_levels, &res); - it->top_nz_[8] = it->left_nz_[8] = - VP8RecordCoeffTokens(ctx, 1, - res.first, res.last, res.coeffs, tokens); - VP8RecordCoeffs(ctx, &res); - VP8InitResidual(1, 0, enc, &res); - } else { - VP8InitResidual(0, 3, enc, &res); - } - - // luma-AC - for (y = 0; y < 4; ++y) { - for (x = 0; x < 4; ++x) { - const int ctx = it->top_nz_[x] + it->left_nz_[y]; - VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); - it->top_nz_[x] = it->left_nz_[y] = - VP8RecordCoeffTokens(ctx, res.coeff_type, - res.first, res.last, res.coeffs, tokens); - VP8RecordCoeffs(ctx, &res); - } - } - - // U/V - VP8InitResidual(0, 2, enc, &res); - for (ch = 0; ch <= 2; ch += 2) { - for (y = 0; y < 2; ++y) { - for (x = 0; x < 2; ++x) { - const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; - VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); - it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = - VP8RecordCoeffTokens(ctx, 2, - res.first, res.last, res.coeffs, tokens); - VP8RecordCoeffs(ctx, &res); - } - } - } - VP8IteratorBytesToNz(it); - return !tokens->error_; -} - -#endif // !DISABLE_TOKEN_BUFFER - -//------------------------------------------------------------------------------ -// ExtraInfo map / Debug function - -#if SEGMENT_VISU -static void SetBlock(uint8_t* p, int value, int size) { - int y; - for (y = 0; y < size; ++y) { - memset(p, value, size); - p += BPS; - } -} -#endif - -static void ResetSSE(VP8Encoder* const enc) { - enc->sse_[0] = 0; - enc->sse_[1] = 0; - enc->sse_[2] = 0; - // Note: enc->sse_[3] is managed by alpha.c - enc->sse_count_ = 0; -} - -static void StoreSSE(const VP8EncIterator* const it) { - VP8Encoder* const enc = it->enc_; - const uint8_t* const in = it->yuv_in_; - const uint8_t* const out = it->yuv_out_; - // Note: not totally accurate at boundary. And doesn't include in-loop filter. - enc->sse_[0] += VP8SSE16x16(in + Y_OFF_ENC, out + Y_OFF_ENC); - enc->sse_[1] += VP8SSE8x8(in + U_OFF_ENC, out + U_OFF_ENC); - enc->sse_[2] += VP8SSE8x8(in + V_OFF_ENC, out + V_OFF_ENC); - enc->sse_count_ += 16 * 16; -} - -static void StoreSideInfo(const VP8EncIterator* const it) { - VP8Encoder* const enc = it->enc_; - const VP8MBInfo* const mb = it->mb_; - WebPPicture* const pic = enc->pic_; - - if (pic->stats != NULL) { - StoreSSE(it); - enc->block_count_[0] += (mb->type_ == 0); - enc->block_count_[1] += (mb->type_ == 1); - enc->block_count_[2] += (mb->skip_ != 0); - } - - if (pic->extra_info != NULL) { - uint8_t* const info = &pic->extra_info[it->x_ + it->y_ * enc->mb_w_]; - switch (pic->extra_info_type) { - case 1: *info = mb->type_; break; - case 2: *info = mb->segment_; break; - case 3: *info = enc->dqm_[mb->segment_].quant_; break; - case 4: *info = (mb->type_ == 1) ? it->preds_[0] : 0xff; break; - case 5: *info = mb->uv_mode_; break; - case 6: { - const int b = (int)((it->luma_bits_ + it->uv_bits_ + 7) >> 3); - *info = (b > 255) ? 255 : b; break; - } - case 7: *info = mb->alpha_; break; - default: *info = 0; break; - } - } -#if SEGMENT_VISU // visualize segments and prediction modes - SetBlock(it->yuv_out_ + Y_OFF_ENC, mb->segment_ * 64, 16); - SetBlock(it->yuv_out_ + U_OFF_ENC, it->preds_[0] * 64, 8); - SetBlock(it->yuv_out_ + V_OFF_ENC, mb->uv_mode_ * 64, 8); -#endif -} - -static double GetPSNR(uint64_t mse, uint64_t size) { - return (mse > 0 && size > 0) ? 10. * log10(255. * 255. * size / mse) : 99; -} - -//------------------------------------------------------------------------------ -// StatLoop(): only collect statistics (number of skips, token usage, ...). -// This is used for deciding optimal probabilities. It also modifies the -// quantizer value if some target (size, PSNR) was specified. - -static void SetLoopParams(VP8Encoder* const enc, float q) { - // Make sure the quality parameter is inside valid bounds - q = Clamp(q, 0.f, 100.f); - - VP8SetSegmentParams(enc, q); // setup segment quantizations and filters - SetSegmentProbas(enc); // compute segment probabilities - - ResetStats(enc); - ResetSSE(enc); -} - -static uint64_t OneStatPass(VP8Encoder* const enc, VP8RDLevel rd_opt, - int nb_mbs, int percent_delta, - PassStats* const s) { - VP8EncIterator it; - uint64_t size = 0; - uint64_t size_p0 = 0; - uint64_t distortion = 0; - const uint64_t pixel_count = nb_mbs * 384; - - VP8IteratorInit(enc, &it); - SetLoopParams(enc, s->q); - do { - VP8ModeScore info; - VP8IteratorImport(&it, NULL); - if (VP8Decimate(&it, &info, rd_opt)) { - // Just record the number of skips and act like skip_proba is not used. - enc->proba_.nb_skip_++; - } - RecordResiduals(&it, &info); - size += info.R + info.H; - size_p0 += info.H; - distortion += info.D; - if (percent_delta && !VP8IteratorProgress(&it, percent_delta)) - return 0; - VP8IteratorSaveBoundary(&it); - } while (VP8IteratorNext(&it) && --nb_mbs > 0); - - size_p0 += enc->segment_hdr_.size_; - if (s->do_size_search) { - size += FinalizeSkipProba(enc); - size += FinalizeTokenProbas(&enc->proba_); - size = ((size + size_p0 + 1024) >> 11) + HEADER_SIZE_ESTIMATE; - s->value = (double)size; - } else { - s->value = GetPSNR(distortion, pixel_count); - } - return size_p0; -} - -static int StatLoop(VP8Encoder* const enc) { - const int method = enc->method_; - const int do_search = enc->do_search_; - const int fast_probe = ((method == 0 || method == 3) && !do_search); - int num_pass_left = enc->config_->pass; - const int task_percent = 20; - const int percent_per_pass = - (task_percent + num_pass_left / 2) / num_pass_left; - const int final_percent = enc->percent_ + task_percent; - const VP8RDLevel rd_opt = - (method >= 3 || do_search) ? RD_OPT_BASIC : RD_OPT_NONE; - int nb_mbs = enc->mb_w_ * enc->mb_h_; - PassStats stats; - - InitPassStats(enc, &stats); - ResetTokenStats(enc); - - // Fast mode: quick analysis pass over few mbs. Better than nothing. - if (fast_probe) { - if (method == 3) { // we need more stats for method 3 to be reliable. - nb_mbs = (nb_mbs > 200) ? nb_mbs >> 1 : 100; - } else { - nb_mbs = (nb_mbs > 200) ? nb_mbs >> 2 : 50; - } - } - - while (num_pass_left-- > 0) { - const int is_last_pass = (fabs(stats.dq) <= DQ_LIMIT) || - (num_pass_left == 0) || - (enc->max_i4_header_bits_ == 0); - const uint64_t size_p0 = - OneStatPass(enc, rd_opt, nb_mbs, percent_per_pass, &stats); - if (size_p0 == 0) return 0; -#if (DEBUG_SEARCH > 0) - printf("#%d value:%.1lf -> %.1lf q:%.2f -> %.2f\n", - num_pass_left, stats.last_value, stats.value, stats.last_q, stats.q); -#endif - if (enc->max_i4_header_bits_ > 0 && size_p0 > PARTITION0_SIZE_LIMIT) { - ++num_pass_left; - enc->max_i4_header_bits_ >>= 1; // strengthen header bit limitation... - continue; // ...and start over - } - if (is_last_pass) { - break; - } - // If no target size: just do several pass without changing 'q' - if (do_search) { - ComputeNextQ(&stats); - if (fabs(stats.dq) <= DQ_LIMIT) break; - } - } - if (!do_search || !stats.do_size_search) { - // Need to finalize probas now, since it wasn't done during the search. - FinalizeSkipProba(enc); - FinalizeTokenProbas(&enc->proba_); - } - VP8CalculateLevelCosts(&enc->proba_); // finalize costs - return WebPReportProgress(enc->pic_, final_percent, &enc->percent_); -} - -//------------------------------------------------------------------------------ -// Main loops -// - -static const int kAverageBytesPerMB[8] = { 50, 24, 16, 9, 7, 5, 3, 2 }; - -static int PreLoopInitialize(VP8Encoder* const enc) { - int p; - int ok = 1; - const int average_bytes_per_MB = kAverageBytesPerMB[enc->base_quant_ >> 4]; - const int bytes_per_parts = - enc->mb_w_ * enc->mb_h_ * average_bytes_per_MB / enc->num_parts_; - // Initialize the bit-writers - for (p = 0; ok && p < enc->num_parts_; ++p) { - ok = VP8BitWriterInit(enc->parts_ + p, bytes_per_parts); - } - if (!ok) { - VP8EncFreeBitWriters(enc); // malloc error occurred - WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); - } - return ok; -} - -static int PostLoopFinalize(VP8EncIterator* const it, int ok) { - VP8Encoder* const enc = it->enc_; - if (ok) { // Finalize the partitions, check for extra errors. - int p; - for (p = 0; p < enc->num_parts_; ++p) { - VP8BitWriterFinish(enc->parts_ + p); - ok &= !enc->parts_[p].error_; - } - } - - if (ok) { // All good. Finish up. - if (enc->pic_->stats != NULL) { // finalize byte counters... - int i, s; - for (i = 0; i <= 2; ++i) { - for (s = 0; s < NUM_MB_SEGMENTS; ++s) { - enc->residual_bytes_[i][s] = (int)((it->bit_count_[s][i] + 7) >> 3); - } - } - } - VP8AdjustFilterStrength(it); // ...and store filter stats. - } else { - // Something bad happened -> need to do some memory cleanup. - VP8EncFreeBitWriters(enc); - } - return ok; -} - -//------------------------------------------------------------------------------ -// VP8EncLoop(): does the final bitstream coding. - -static void ResetAfterSkip(VP8EncIterator* const it) { - if (it->mb_->type_ == 1) { - *it->nz_ = 0; // reset all predictors - it->left_nz_[8] = 0; - } else { - *it->nz_ &= (1 << 24); // preserve the dc_nz bit - } -} - -int VP8EncLoop(VP8Encoder* const enc) { - VP8EncIterator it; - int ok = PreLoopInitialize(enc); - if (!ok) return 0; - - StatLoop(enc); // stats-collection loop - - VP8IteratorInit(enc, &it); - VP8InitFilter(&it); - do { - VP8ModeScore info; - const int dont_use_skip = !enc->proba_.use_skip_proba_; - const VP8RDLevel rd_opt = enc->rd_opt_level_; - - VP8IteratorImport(&it, NULL); - // Warning! order is important: first call VP8Decimate() and - // *then* decide how to code the skip decision if there's one. - if (!VP8Decimate(&it, &info, rd_opt) || dont_use_skip) { - CodeResiduals(it.bw_, &it, &info); - } else { // reset predictors after a skip - ResetAfterSkip(&it); - } - StoreSideInfo(&it); - VP8StoreFilterStats(&it); - VP8IteratorExport(&it); - ok = VP8IteratorProgress(&it, 20); - VP8IteratorSaveBoundary(&it); - } while (ok && VP8IteratorNext(&it)); - - return PostLoopFinalize(&it, ok); -} - -//------------------------------------------------------------------------------ -// Single pass using Token Buffer. - -#if !defined(DISABLE_TOKEN_BUFFER) - -#define MIN_COUNT 96 // minimum number of macroblocks before updating stats - -int VP8EncTokenLoop(VP8Encoder* const enc) { - // Roughly refresh the proba eight times per pass - int max_count = (enc->mb_w_ * enc->mb_h_) >> 3; - int num_pass_left = enc->config_->pass; - const int do_search = enc->do_search_; - VP8EncIterator it; - VP8EncProba* const proba = &enc->proba_; - const VP8RDLevel rd_opt = enc->rd_opt_level_; - const uint64_t pixel_count = enc->mb_w_ * enc->mb_h_ * 384; - PassStats stats; - int ok; - - InitPassStats(enc, &stats); - ok = PreLoopInitialize(enc); - if (!ok) return 0; - - if (max_count < MIN_COUNT) max_count = MIN_COUNT; - - assert(enc->num_parts_ == 1); - assert(enc->use_tokens_); - assert(proba->use_skip_proba_ == 0); - assert(rd_opt >= RD_OPT_BASIC); // otherwise, token-buffer won't be useful - assert(num_pass_left > 0); - - while (ok && num_pass_left-- > 0) { - const int is_last_pass = (fabs(stats.dq) <= DQ_LIMIT) || - (num_pass_left == 0) || - (enc->max_i4_header_bits_ == 0); - uint64_t size_p0 = 0; - uint64_t distortion = 0; - int cnt = max_count; - VP8IteratorInit(enc, &it); - SetLoopParams(enc, stats.q); - if (is_last_pass) { - ResetTokenStats(enc); - VP8InitFilter(&it); // don't collect stats until last pass (too costly) - } - VP8TBufferClear(&enc->tokens_); - do { - VP8ModeScore info; - VP8IteratorImport(&it, NULL); - if (--cnt < 0) { - FinalizeTokenProbas(proba); - VP8CalculateLevelCosts(proba); // refresh cost tables for rd-opt - cnt = max_count; - } - VP8Decimate(&it, &info, rd_opt); - ok = RecordTokens(&it, &info, &enc->tokens_); - if (!ok) { - WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); - break; - } - size_p0 += info.H; - distortion += info.D; - if (is_last_pass) { - StoreSideInfo(&it); - VP8StoreFilterStats(&it); - VP8IteratorExport(&it); - ok = VP8IteratorProgress(&it, 20); - } - VP8IteratorSaveBoundary(&it); - } while (ok && VP8IteratorNext(&it)); - if (!ok) break; - - size_p0 += enc->segment_hdr_.size_; - if (stats.do_size_search) { - uint64_t size = FinalizeTokenProbas(&enc->proba_); - size += VP8EstimateTokenSize(&enc->tokens_, - (const uint8_t*)proba->coeffs_); - size = (size + size_p0 + 1024) >> 11; // -> size in bytes - size += HEADER_SIZE_ESTIMATE; - stats.value = (double)size; - } else { // compute and store PSNR - stats.value = GetPSNR(distortion, pixel_count); - } - -#if (DEBUG_SEARCH > 0) - printf("#%2d metric:%.1lf -> %.1lf last_q=%.2lf q=%.2lf dq=%.2lf\n", - num_pass_left, stats.last_value, stats.value, - stats.last_q, stats.q, stats.dq); -#endif - if (size_p0 > PARTITION0_SIZE_LIMIT) { - ++num_pass_left; - enc->max_i4_header_bits_ >>= 1; // strengthen header bit limitation... - continue; // ...and start over - } - if (is_last_pass) { - break; // done - } - if (do_search) { - ComputeNextQ(&stats); // Adjust q - } - } - if (ok) { - if (!stats.do_size_search) { - FinalizeTokenProbas(&enc->proba_); - } - ok = VP8EmitTokens(&enc->tokens_, enc->parts_ + 0, - (const uint8_t*)proba->coeffs_, 1); - } - ok = ok && WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_); - return PostLoopFinalize(&it, ok); -} - -#else - -int VP8EncTokenLoop(VP8Encoder* const enc) { - (void)enc; - return 0; // we shouldn't be here. -} - -#endif // DISABLE_TOKEN_BUFFER - -//------------------------------------------------------------------------------ - diff --git a/Example-Mac/Pods/libwebp/src/enc/histogram.c b/Example-Mac/Pods/libwebp/src/enc/histogram.c deleted file mode 100644 index 869882de..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/histogram.c +++ /dev/null @@ -1,942 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Jyrki Alakuijala (jyrki@google.com) -// -#ifdef HAVE_CONFIG_H -#include "../webp/config.h" -#endif - -#include - -#include "./backward_references.h" -#include "./histogram.h" -#include "../dsp/lossless.h" -#include "../utils/utils.h" - -#define MAX_COST 1.e38 - -// Number of partitions for the three dominant (literal, red and blue) symbol -// costs. -#define NUM_PARTITIONS 4 -// The size of the bin-hash corresponding to the three dominant costs. -#define BIN_SIZE (NUM_PARTITIONS * NUM_PARTITIONS * NUM_PARTITIONS) -// Maximum number of histograms allowed in greedy combining algorithm. -#define MAX_HISTO_GREEDY 100 - -static void HistogramClear(VP8LHistogram* const p) { - uint32_t* const literal = p->literal_; - const int cache_bits = p->palette_code_bits_; - const int histo_size = VP8LGetHistogramSize(cache_bits); - memset(p, 0, histo_size); - p->palette_code_bits_ = cache_bits; - p->literal_ = literal; -} - -// Swap two histogram pointers. -static void HistogramSwap(VP8LHistogram** const A, VP8LHistogram** const B) { - VP8LHistogram* const tmp = *A; - *A = *B; - *B = tmp; -} - -static void HistogramCopy(const VP8LHistogram* const src, - VP8LHistogram* const dst) { - uint32_t* const dst_literal = dst->literal_; - const int dst_cache_bits = dst->palette_code_bits_; - const int histo_size = VP8LGetHistogramSize(dst_cache_bits); - assert(src->palette_code_bits_ == dst_cache_bits); - memcpy(dst, src, histo_size); - dst->literal_ = dst_literal; -} - -int VP8LGetHistogramSize(int cache_bits) { - const int literal_size = VP8LHistogramNumCodes(cache_bits); - const size_t total_size = sizeof(VP8LHistogram) + sizeof(int) * literal_size; - assert(total_size <= (size_t)0x7fffffff); - return (int)total_size; -} - -void VP8LFreeHistogram(VP8LHistogram* const histo) { - WebPSafeFree(histo); -} - -void VP8LFreeHistogramSet(VP8LHistogramSet* const histo) { - WebPSafeFree(histo); -} - -void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs, - VP8LHistogram* const histo) { - VP8LRefsCursor c = VP8LRefsCursorInit(refs); - while (VP8LRefsCursorOk(&c)) { - VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos); - VP8LRefsCursorNext(&c); - } -} - -void VP8LHistogramCreate(VP8LHistogram* const p, - const VP8LBackwardRefs* const refs, - int palette_code_bits) { - if (palette_code_bits >= 0) { - p->palette_code_bits_ = palette_code_bits; - } - HistogramClear(p); - VP8LHistogramStoreRefs(refs, p); -} - -void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits) { - p->palette_code_bits_ = palette_code_bits; - HistogramClear(p); -} - -VP8LHistogram* VP8LAllocateHistogram(int cache_bits) { - VP8LHistogram* histo = NULL; - const int total_size = VP8LGetHistogramSize(cache_bits); - uint8_t* const memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory)); - if (memory == NULL) return NULL; - histo = (VP8LHistogram*)memory; - // literal_ won't necessary be aligned. - histo->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram)); - VP8LHistogramInit(histo, cache_bits); - return histo; -} - -VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits) { - int i; - VP8LHistogramSet* set; - const int histo_size = VP8LGetHistogramSize(cache_bits); - const size_t total_size = - sizeof(*set) + size * (sizeof(*set->histograms) + - histo_size + WEBP_ALIGN_CST); - uint8_t* memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory)); - if (memory == NULL) return NULL; - - set = (VP8LHistogramSet*)memory; - memory += sizeof(*set); - set->histograms = (VP8LHistogram**)memory; - memory += size * sizeof(*set->histograms); - set->max_size = size; - set->size = size; - for (i = 0; i < size; ++i) { - memory = (uint8_t*)WEBP_ALIGN(memory); - set->histograms[i] = (VP8LHistogram*)memory; - // literal_ won't necessary be aligned. - set->histograms[i]->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram)); - VP8LHistogramInit(set->histograms[i], cache_bits); - memory += histo_size; - } - return set; -} - -// ----------------------------------------------------------------------------- - -void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo, - const PixOrCopy* const v) { - if (PixOrCopyIsLiteral(v)) { - ++histo->alpha_[PixOrCopyLiteral(v, 3)]; - ++histo->red_[PixOrCopyLiteral(v, 2)]; - ++histo->literal_[PixOrCopyLiteral(v, 1)]; - ++histo->blue_[PixOrCopyLiteral(v, 0)]; - } else if (PixOrCopyIsCacheIdx(v)) { - const int literal_ix = - NUM_LITERAL_CODES + NUM_LENGTH_CODES + PixOrCopyCacheIdx(v); - ++histo->literal_[literal_ix]; - } else { - int code, extra_bits; - VP8LPrefixEncodeBits(PixOrCopyLength(v), &code, &extra_bits); - ++histo->literal_[NUM_LITERAL_CODES + code]; - VP8LPrefixEncodeBits(PixOrCopyDistance(v), &code, &extra_bits); - ++histo->distance_[code]; - } -} - -// ----------------------------------------------------------------------------- -// Entropy-related functions. - -static WEBP_INLINE double BitsEntropyRefine(const VP8LBitEntropy* entropy) { - double mix; - if (entropy->nonzeros < 5) { - if (entropy->nonzeros <= 1) { - return 0; - } - // Two symbols, they will be 0 and 1 in a Huffman code. - // Let's mix in a bit of entropy to favor good clustering when - // distributions of these are combined. - if (entropy->nonzeros == 2) { - return 0.99 * entropy->sum + 0.01 * entropy->entropy; - } - // No matter what the entropy says, we cannot be better than min_limit - // with Huffman coding. I am mixing a bit of entropy into the - // min_limit since it produces much better (~0.5 %) compression results - // perhaps because of better entropy clustering. - if (entropy->nonzeros == 3) { - mix = 0.95; - } else { - mix = 0.7; // nonzeros == 4. - } - } else { - mix = 0.627; - } - - { - double min_limit = 2 * entropy->sum - entropy->max_val; - min_limit = mix * min_limit + (1.0 - mix) * entropy->entropy; - return (entropy->entropy < min_limit) ? min_limit : entropy->entropy; - } -} - -double VP8LBitsEntropy(const uint32_t* const array, int n, - uint32_t* const trivial_symbol) { - VP8LBitEntropy entropy; - VP8LBitsEntropyUnrefined(array, n, &entropy); - if (trivial_symbol != NULL) { - *trivial_symbol = - (entropy.nonzeros == 1) ? entropy.nonzero_code : VP8L_NON_TRIVIAL_SYM; - } - - return BitsEntropyRefine(&entropy); -} - -static double InitialHuffmanCost(void) { - // Small bias because Huffman code length is typically not stored in - // full length. - static const int kHuffmanCodeOfHuffmanCodeSize = CODE_LENGTH_CODES * 3; - static const double kSmallBias = 9.1; - return kHuffmanCodeOfHuffmanCodeSize - kSmallBias; -} - -// Finalize the Huffman cost based on streak numbers and length type (<3 or >=3) -static double FinalHuffmanCost(const VP8LStreaks* const stats) { - double retval = InitialHuffmanCost(); - retval += stats->counts[0] * 1.5625 + 0.234375 * stats->streaks[0][1]; - retval += stats->counts[1] * 2.578125 + 0.703125 * stats->streaks[1][1]; - retval += 1.796875 * stats->streaks[0][0]; - retval += 3.28125 * stats->streaks[1][0]; - return retval; -} - -// Get the symbol entropy for the distribution 'population'. -// Set 'trivial_sym', if there's only one symbol present in the distribution. -static double PopulationCost(const uint32_t* const population, int length, - uint32_t* const trivial_sym) { - VP8LBitEntropy bit_entropy; - VP8LStreaks stats; - VP8LGetEntropyUnrefined(population, length, &bit_entropy, &stats); - if (trivial_sym != NULL) { - *trivial_sym = (bit_entropy.nonzeros == 1) ? bit_entropy.nonzero_code - : VP8L_NON_TRIVIAL_SYM; - } - - return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats); -} - -static WEBP_INLINE double GetCombinedEntropy(const uint32_t* const X, - const uint32_t* const Y, - int length) { - VP8LBitEntropy bit_entropy; - VP8LStreaks stats; - VP8LGetCombinedEntropyUnrefined(X, Y, length, &bit_entropy, &stats); - - return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats); -} - -// Estimates the Entropy + Huffman + other block overhead size cost. -double VP8LHistogramEstimateBits(const VP8LHistogram* const p) { - return - PopulationCost( - p->literal_, VP8LHistogramNumCodes(p->palette_code_bits_), NULL) - + PopulationCost(p->red_, NUM_LITERAL_CODES, NULL) - + PopulationCost(p->blue_, NUM_LITERAL_CODES, NULL) - + PopulationCost(p->alpha_, NUM_LITERAL_CODES, NULL) - + PopulationCost(p->distance_, NUM_DISTANCE_CODES, NULL) - + VP8LExtraCost(p->literal_ + NUM_LITERAL_CODES, NUM_LENGTH_CODES) - + VP8LExtraCost(p->distance_, NUM_DISTANCE_CODES); -} - -// ----------------------------------------------------------------------------- -// Various histogram combine/cost-eval functions - -static int GetCombinedHistogramEntropy(const VP8LHistogram* const a, - const VP8LHistogram* const b, - double cost_threshold, - double* cost) { - const int palette_code_bits = a->palette_code_bits_; - assert(a->palette_code_bits_ == b->palette_code_bits_); - *cost += GetCombinedEntropy(a->literal_, b->literal_, - VP8LHistogramNumCodes(palette_code_bits)); - *cost += VP8LExtraCostCombined(a->literal_ + NUM_LITERAL_CODES, - b->literal_ + NUM_LITERAL_CODES, - NUM_LENGTH_CODES); - if (*cost > cost_threshold) return 0; - - *cost += GetCombinedEntropy(a->red_, b->red_, NUM_LITERAL_CODES); - if (*cost > cost_threshold) return 0; - - *cost += GetCombinedEntropy(a->blue_, b->blue_, NUM_LITERAL_CODES); - if (*cost > cost_threshold) return 0; - - *cost += GetCombinedEntropy(a->alpha_, b->alpha_, NUM_LITERAL_CODES); - if (*cost > cost_threshold) return 0; - - *cost += GetCombinedEntropy(a->distance_, b->distance_, NUM_DISTANCE_CODES); - *cost += - VP8LExtraCostCombined(a->distance_, b->distance_, NUM_DISTANCE_CODES); - if (*cost > cost_threshold) return 0; - - return 1; -} - -// Performs out = a + b, computing the cost C(a+b) - C(a) - C(b) while comparing -// to the threshold value 'cost_threshold'. The score returned is -// Score = C(a+b) - C(a) - C(b), where C(a) + C(b) is known and fixed. -// Since the previous score passed is 'cost_threshold', we only need to compare -// the partial cost against 'cost_threshold + C(a) + C(b)' to possibly bail-out -// early. -static double HistogramAddEval(const VP8LHistogram* const a, - const VP8LHistogram* const b, - VP8LHistogram* const out, - double cost_threshold) { - double cost = 0; - const double sum_cost = a->bit_cost_ + b->bit_cost_; - cost_threshold += sum_cost; - - if (GetCombinedHistogramEntropy(a, b, cost_threshold, &cost)) { - VP8LHistogramAdd(a, b, out); - out->bit_cost_ = cost; - out->palette_code_bits_ = a->palette_code_bits_; - out->trivial_symbol_ = (a->trivial_symbol_ == b->trivial_symbol_) ? - a->trivial_symbol_ : VP8L_NON_TRIVIAL_SYM; - } - - return cost - sum_cost; -} - -// Same as HistogramAddEval(), except that the resulting histogram -// is not stored. Only the cost C(a+b) - C(a) is evaluated. We omit -// the term C(b) which is constant over all the evaluations. -static double HistogramAddThresh(const VP8LHistogram* const a, - const VP8LHistogram* const b, - double cost_threshold) { - double cost = -a->bit_cost_; - GetCombinedHistogramEntropy(a, b, cost_threshold, &cost); - return cost; -} - -// ----------------------------------------------------------------------------- - -// The structure to keep track of cost range for the three dominant entropy -// symbols. -// TODO(skal): Evaluate if float can be used here instead of double for -// representing the entropy costs. -typedef struct { - double literal_max_; - double literal_min_; - double red_max_; - double red_min_; - double blue_max_; - double blue_min_; -} DominantCostRange; - -static void DominantCostRangeInit(DominantCostRange* const c) { - c->literal_max_ = 0.; - c->literal_min_ = MAX_COST; - c->red_max_ = 0.; - c->red_min_ = MAX_COST; - c->blue_max_ = 0.; - c->blue_min_ = MAX_COST; -} - -static void UpdateDominantCostRange( - const VP8LHistogram* const h, DominantCostRange* const c) { - if (c->literal_max_ < h->literal_cost_) c->literal_max_ = h->literal_cost_; - if (c->literal_min_ > h->literal_cost_) c->literal_min_ = h->literal_cost_; - if (c->red_max_ < h->red_cost_) c->red_max_ = h->red_cost_; - if (c->red_min_ > h->red_cost_) c->red_min_ = h->red_cost_; - if (c->blue_max_ < h->blue_cost_) c->blue_max_ = h->blue_cost_; - if (c->blue_min_ > h->blue_cost_) c->blue_min_ = h->blue_cost_; -} - -static void UpdateHistogramCost(VP8LHistogram* const h) { - uint32_t alpha_sym, red_sym, blue_sym; - const double alpha_cost = - PopulationCost(h->alpha_, NUM_LITERAL_CODES, &alpha_sym); - const double distance_cost = - PopulationCost(h->distance_, NUM_DISTANCE_CODES, NULL) + - VP8LExtraCost(h->distance_, NUM_DISTANCE_CODES); - const int num_codes = VP8LHistogramNumCodes(h->palette_code_bits_); - h->literal_cost_ = PopulationCost(h->literal_, num_codes, NULL) + - VP8LExtraCost(h->literal_ + NUM_LITERAL_CODES, - NUM_LENGTH_CODES); - h->red_cost_ = PopulationCost(h->red_, NUM_LITERAL_CODES, &red_sym); - h->blue_cost_ = PopulationCost(h->blue_, NUM_LITERAL_CODES, &blue_sym); - h->bit_cost_ = h->literal_cost_ + h->red_cost_ + h->blue_cost_ + - alpha_cost + distance_cost; - if ((alpha_sym | red_sym | blue_sym) == VP8L_NON_TRIVIAL_SYM) { - h->trivial_symbol_ = VP8L_NON_TRIVIAL_SYM; - } else { - h->trivial_symbol_ = - ((uint32_t)alpha_sym << 24) | (red_sym << 16) | (blue_sym << 0); - } -} - -static int GetBinIdForEntropy(double min, double max, double val) { - const double range = max - min + 1e-6; - const double delta = val - min; - return (int)(NUM_PARTITIONS * delta / range); -} - -static int GetHistoBinIndexLowEffort( - const VP8LHistogram* const h, const DominantCostRange* const c) { - const int bin_id = GetBinIdForEntropy(c->literal_min_, c->literal_max_, - h->literal_cost_); - assert(bin_id < NUM_PARTITIONS); - return bin_id; -} - -static int GetHistoBinIndex( - const VP8LHistogram* const h, const DominantCostRange* const c) { - const int bin_id = - GetBinIdForEntropy(c->blue_min_, c->blue_max_, h->blue_cost_) + - NUM_PARTITIONS * GetBinIdForEntropy(c->red_min_, c->red_max_, - h->red_cost_) + - NUM_PARTITIONS * NUM_PARTITIONS * GetBinIdForEntropy(c->literal_min_, - c->literal_max_, - h->literal_cost_); - assert(bin_id < BIN_SIZE); - return bin_id; -} - -// Construct the histograms from backward references. -static void HistogramBuild( - int xsize, int histo_bits, const VP8LBackwardRefs* const backward_refs, - VP8LHistogramSet* const image_histo) { - int x = 0, y = 0; - const int histo_xsize = VP8LSubSampleSize(xsize, histo_bits); - VP8LHistogram** const histograms = image_histo->histograms; - VP8LRefsCursor c = VP8LRefsCursorInit(backward_refs); - assert(histo_bits > 0); - while (VP8LRefsCursorOk(&c)) { - const PixOrCopy* const v = c.cur_pos; - const int ix = (y >> histo_bits) * histo_xsize + (x >> histo_bits); - VP8LHistogramAddSinglePixOrCopy(histograms[ix], v); - x += PixOrCopyLength(v); - while (x >= xsize) { - x -= xsize; - ++y; - } - VP8LRefsCursorNext(&c); - } -} - -// Copies the histograms and computes its bit_cost. -static void HistogramCopyAndAnalyze( - VP8LHistogramSet* const orig_histo, VP8LHistogramSet* const image_histo) { - int i; - const int histo_size = orig_histo->size; - VP8LHistogram** const orig_histograms = orig_histo->histograms; - VP8LHistogram** const histograms = image_histo->histograms; - for (i = 0; i < histo_size; ++i) { - VP8LHistogram* const histo = orig_histograms[i]; - UpdateHistogramCost(histo); - // Copy histograms from orig_histo[] to image_histo[]. - HistogramCopy(histo, histograms[i]); - } -} - -// Partition histograms to different entropy bins for three dominant (literal, -// red and blue) symbol costs and compute the histogram aggregate bit_cost. -static void HistogramAnalyzeEntropyBin(VP8LHistogramSet* const image_histo, - int16_t* const bin_map, int low_effort) { - int i; - VP8LHistogram** const histograms = image_histo->histograms; - const int histo_size = image_histo->size; - const int bin_depth = histo_size + 1; - DominantCostRange cost_range; - DominantCostRangeInit(&cost_range); - - // Analyze the dominant (literal, red and blue) entropy costs. - for (i = 0; i < histo_size; ++i) { - VP8LHistogram* const histo = histograms[i]; - UpdateDominantCostRange(histo, &cost_range); - } - - // bin-hash histograms on three of the dominant (literal, red and blue) - // symbol costs. - for (i = 0; i < histo_size; ++i) { - int num_histos; - VP8LHistogram* const histo = histograms[i]; - const int16_t bin_id = low_effort ? - (int16_t)GetHistoBinIndexLowEffort(histo, &cost_range) : - (int16_t)GetHistoBinIndex(histo, &cost_range); - const int bin_offset = bin_id * bin_depth; - // bin_map[n][0] for every bin 'n' maintains the counter for the number of - // histograms in that bin. - // Get and increment the num_histos in that bin. - num_histos = ++bin_map[bin_offset]; - assert(bin_offset + num_histos < bin_depth * BIN_SIZE); - // Add histogram i'th index at num_histos (last) position in the bin_map. - bin_map[bin_offset + num_histos] = i; - } -} - -// Compact the histogram set by removing unused entries. -static void HistogramCompactBins(VP8LHistogramSet* const image_histo) { - VP8LHistogram** const histograms = image_histo->histograms; - int i, j; - - for (i = 0, j = 0; i < image_histo->size; ++i) { - if (histograms[i] != NULL && histograms[i]->bit_cost_ != 0.) { - if (j < i) { - histograms[j] = histograms[i]; - histograms[i] = NULL; - } - ++j; - } - } - image_histo->size = j; -} - -static VP8LHistogram* HistogramCombineEntropyBin( - VP8LHistogramSet* const image_histo, - VP8LHistogram* cur_combo, - int16_t* const bin_map, int bin_depth, int num_bins, - double combine_cost_factor, int low_effort) { - int bin_id; - VP8LHistogram** const histograms = image_histo->histograms; - - for (bin_id = 0; bin_id < num_bins; ++bin_id) { - const int bin_offset = bin_id * bin_depth; - const int num_histos = bin_map[bin_offset]; - const int idx1 = bin_map[bin_offset + 1]; - int num_combine_failures = 0; - int n; - for (n = 2; n <= num_histos; ++n) { - const int idx2 = bin_map[bin_offset + n]; - if (low_effort) { - // Merge all histograms with the same bin index, irrespective of cost of - // the merged histograms. - VP8LHistogramAdd(histograms[idx1], histograms[idx2], histograms[idx1]); - histograms[idx2]->bit_cost_ = 0.; - } else { - const double bit_cost_idx2 = histograms[idx2]->bit_cost_; - if (bit_cost_idx2 > 0.) { - const double bit_cost_thresh = -bit_cost_idx2 * combine_cost_factor; - const double curr_cost_diff = - HistogramAddEval(histograms[idx1], histograms[idx2], - cur_combo, bit_cost_thresh); - if (curr_cost_diff < bit_cost_thresh) { - // Try to merge two histograms only if the combo is a trivial one or - // the two candidate histograms are already non-trivial. - // For some images, 'try_combine' turns out to be false for a lot of - // histogram pairs. In that case, we fallback to combining - // histograms as usual to avoid increasing the header size. - const int try_combine = - (cur_combo->trivial_symbol_ != VP8L_NON_TRIVIAL_SYM) || - ((histograms[idx1]->trivial_symbol_ == VP8L_NON_TRIVIAL_SYM) && - (histograms[idx2]->trivial_symbol_ == VP8L_NON_TRIVIAL_SYM)); - const int max_combine_failures = 32; - if (try_combine || (num_combine_failures >= max_combine_failures)) { - HistogramSwap(&cur_combo, &histograms[idx1]); - histograms[idx2]->bit_cost_ = 0.; - } else { - ++num_combine_failures; - } - } - } - } - } - if (low_effort) { - // Update the bit_cost for the merged histograms (per bin index). - UpdateHistogramCost(histograms[idx1]); - } - } - HistogramCompactBins(image_histo); - return cur_combo; -} - -static uint32_t MyRand(uint32_t *seed) { - *seed *= 16807U; - if (*seed == 0) { - *seed = 1; - } - return *seed; -} - -// ----------------------------------------------------------------------------- -// Histogram pairs priority queue - -// Pair of histograms. Negative idx1 value means that pair is out-of-date. -typedef struct { - int idx1; - int idx2; - double cost_diff; - double cost_combo; -} HistogramPair; - -typedef struct { - HistogramPair* queue; - int size; - int max_size; -} HistoQueue; - -static int HistoQueueInit(HistoQueue* const histo_queue, const int max_index) { - histo_queue->size = 0; - // max_index^2 for the queue size is safe. If you look at - // HistogramCombineGreedy, and imagine that UpdateQueueFront always pushes - // data to the queue, you insert at most: - // - max_index*(max_index-1)/2 (the first two for loops) - // - max_index - 1 in the last for loop at the first iteration of the while - // loop, max_index - 2 at the second iteration ... therefore - // max_index*(max_index-1)/2 overall too - histo_queue->max_size = max_index * max_index; - // We allocate max_size + 1 because the last element at index "size" is - // used as temporary data (and it could be up to max_size). - histo_queue->queue = WebPSafeMalloc(histo_queue->max_size + 1, - sizeof(*histo_queue->queue)); - return histo_queue->queue != NULL; -} - -static void HistoQueueClear(HistoQueue* const histo_queue) { - assert(histo_queue != NULL); - WebPSafeFree(histo_queue->queue); -} - -static void SwapHistogramPairs(HistogramPair *p1, - HistogramPair *p2) { - const HistogramPair tmp = *p1; - *p1 = *p2; - *p2 = tmp; -} - -// Given a valid priority queue in range [0, queue_size) this function checks -// whether histo_queue[queue_size] should be accepted and swaps it with the -// front if it is smaller. Otherwise, it leaves it as is. -static void UpdateQueueFront(HistoQueue* const histo_queue) { - if (histo_queue->queue[histo_queue->size].cost_diff >= 0) return; - - if (histo_queue->queue[histo_queue->size].cost_diff < - histo_queue->queue[0].cost_diff) { - SwapHistogramPairs(histo_queue->queue, - histo_queue->queue + histo_queue->size); - } - ++histo_queue->size; - - // We cannot add more elements than the capacity. - // The allocation adds an extra element to the official capacity so that - // histo_queue->queue[histo_queue->max_size] is read/written within bound. - assert(histo_queue->size <= histo_queue->max_size); -} - -// ----------------------------------------------------------------------------- - -static void PreparePair(VP8LHistogram** histograms, int idx1, int idx2, - HistogramPair* const pair, - VP8LHistogram* const histos) { - if (idx1 > idx2) { - const int tmp = idx2; - idx2 = idx1; - idx1 = tmp; - } - pair->idx1 = idx1; - pair->idx2 = idx2; - pair->cost_diff = - HistogramAddEval(histograms[idx1], histograms[idx2], histos, 0); - pair->cost_combo = histos->bit_cost_; -} - -// Combines histograms by continuously choosing the one with the highest cost -// reduction. -static int HistogramCombineGreedy(VP8LHistogramSet* const image_histo, - VP8LHistogram* const histos) { - int ok = 0; - int image_histo_size = image_histo->size; - int i, j; - VP8LHistogram** const histograms = image_histo->histograms; - // Indexes of remaining histograms. - int* const clusters = WebPSafeMalloc(image_histo_size, sizeof(*clusters)); - // Priority queue of histogram pairs. - HistoQueue histo_queue; - - if (!HistoQueueInit(&histo_queue, image_histo_size) || clusters == NULL) { - goto End; - } - - for (i = 0; i < image_histo_size; ++i) { - // Initialize clusters indexes. - clusters[i] = i; - for (j = i + 1; j < image_histo_size; ++j) { - // Initialize positions array. - PreparePair(histograms, i, j, &histo_queue.queue[histo_queue.size], - histos); - UpdateQueueFront(&histo_queue); - } - } - - while (image_histo_size > 1 && histo_queue.size > 0) { - HistogramPair* copy_to; - const int idx1 = histo_queue.queue[0].idx1; - const int idx2 = histo_queue.queue[0].idx2; - VP8LHistogramAdd(histograms[idx2], histograms[idx1], histograms[idx1]); - histograms[idx1]->bit_cost_ = histo_queue.queue[0].cost_combo; - // Remove merged histogram. - for (i = 0; i + 1 < image_histo_size; ++i) { - if (clusters[i] >= idx2) { - clusters[i] = clusters[i + 1]; - } - } - --image_histo_size; - - // Remove pairs intersecting the just combined best pair. This will - // therefore pop the head of the queue. - copy_to = histo_queue.queue; - for (i = 0; i < histo_queue.size; ++i) { - HistogramPair* const p = histo_queue.queue + i; - if (p->idx1 == idx1 || p->idx2 == idx1 || - p->idx1 == idx2 || p->idx2 == idx2) { - // Do not copy the invalid pair. - continue; - } - if (p->cost_diff < histo_queue.queue[0].cost_diff) { - // Replace the top of the queue if we found better. - SwapHistogramPairs(histo_queue.queue, p); - } - SwapHistogramPairs(copy_to, p); - ++copy_to; - } - histo_queue.size = (int)(copy_to - histo_queue.queue); - - // Push new pairs formed with combined histogram to the queue. - for (i = 0; i < image_histo_size; ++i) { - if (clusters[i] != idx1) { - PreparePair(histograms, idx1, clusters[i], - &histo_queue.queue[histo_queue.size], histos); - UpdateQueueFront(&histo_queue); - } - } - } - // Move remaining histograms to the beginning of the array. - for (i = 0; i < image_histo_size; ++i) { - if (i != clusters[i]) { // swap the two histograms - HistogramSwap(&histograms[i], &histograms[clusters[i]]); - } - } - - image_histo->size = image_histo_size; - ok = 1; - - End: - WebPSafeFree(clusters); - HistoQueueClear(&histo_queue); - return ok; -} - -static VP8LHistogram* HistogramCombineStochastic( - VP8LHistogramSet* const image_histo, - VP8LHistogram* tmp_histo, - VP8LHistogram* best_combo, - int quality, int min_cluster_size) { - int iter; - uint32_t seed = 0; - int tries_with_no_success = 0; - int image_histo_size = image_histo->size; - const int iter_mult = (quality < 25) ? 2 : 2 + (quality - 25) / 8; - const int outer_iters = image_histo_size * iter_mult; - const int num_pairs = image_histo_size / 2; - const int num_tries_no_success = outer_iters / 2; - VP8LHistogram** const histograms = image_histo->histograms; - - // Collapse similar histograms in 'image_histo'. - ++min_cluster_size; - for (iter = 0; - iter < outer_iters && image_histo_size >= min_cluster_size; - ++iter) { - double best_cost_diff = 0.; - int best_idx1 = -1, best_idx2 = 1; - int j; - const int num_tries = - (num_pairs < image_histo_size) ? num_pairs : image_histo_size; - seed += iter; - for (j = 0; j < num_tries; ++j) { - double curr_cost_diff; - // Choose two histograms at random and try to combine them. - const uint32_t idx1 = MyRand(&seed) % image_histo_size; - const uint32_t tmp = (j & 7) + 1; - const uint32_t diff = - (tmp < 3) ? tmp : MyRand(&seed) % (image_histo_size - 1); - const uint32_t idx2 = (idx1 + diff + 1) % image_histo_size; - if (idx1 == idx2) { - continue; - } - - // Calculate cost reduction on combining. - curr_cost_diff = HistogramAddEval(histograms[idx1], histograms[idx2], - tmp_histo, best_cost_diff); - if (curr_cost_diff < best_cost_diff) { // found a better pair? - HistogramSwap(&best_combo, &tmp_histo); - best_cost_diff = curr_cost_diff; - best_idx1 = idx1; - best_idx2 = idx2; - } - } - - if (best_idx1 >= 0) { - HistogramSwap(&best_combo, &histograms[best_idx1]); - // swap best_idx2 slot with last one (which is now unused) - --image_histo_size; - if (best_idx2 != image_histo_size) { - HistogramSwap(&histograms[image_histo_size], &histograms[best_idx2]); - histograms[image_histo_size] = NULL; - } - tries_with_no_success = 0; - } - if (++tries_with_no_success >= num_tries_no_success) { - break; - } - } - image_histo->size = image_histo_size; - return best_combo; -} - -// ----------------------------------------------------------------------------- -// Histogram refinement - -// Find the best 'out' histogram for each of the 'in' histograms. -// Note: we assume that out[]->bit_cost_ is already up-to-date. -static void HistogramRemap(const VP8LHistogramSet* const orig_histo, - const VP8LHistogramSet* const image_histo, - uint16_t* const symbols) { - int i; - VP8LHistogram** const orig_histograms = orig_histo->histograms; - VP8LHistogram** const histograms = image_histo->histograms; - const int orig_histo_size = orig_histo->size; - const int image_histo_size = image_histo->size; - if (image_histo_size > 1) { - for (i = 0; i < orig_histo_size; ++i) { - int best_out = 0; - double best_bits = - HistogramAddThresh(histograms[0], orig_histograms[i], MAX_COST); - int k; - for (k = 1; k < image_histo_size; ++k) { - const double cur_bits = - HistogramAddThresh(histograms[k], orig_histograms[i], best_bits); - if (cur_bits < best_bits) { - best_bits = cur_bits; - best_out = k; - } - } - symbols[i] = best_out; - } - } else { - assert(image_histo_size == 1); - for (i = 0; i < orig_histo_size; ++i) { - symbols[i] = 0; - } - } - - // Recompute each out based on raw and symbols. - for (i = 0; i < image_histo_size; ++i) { - HistogramClear(histograms[i]); - } - - for (i = 0; i < orig_histo_size; ++i) { - const int idx = symbols[i]; - VP8LHistogramAdd(orig_histograms[i], histograms[idx], histograms[idx]); - } -} - -static double GetCombineCostFactor(int histo_size, int quality) { - double combine_cost_factor = 0.16; - if (quality < 90) { - if (histo_size > 256) combine_cost_factor /= 2.; - if (histo_size > 512) combine_cost_factor /= 2.; - if (histo_size > 1024) combine_cost_factor /= 2.; - if (quality <= 50) combine_cost_factor /= 2.; - } - return combine_cost_factor; -} - -int VP8LGetHistoImageSymbols(int xsize, int ysize, - const VP8LBackwardRefs* const refs, - int quality, int low_effort, - int histo_bits, int cache_bits, - VP8LHistogramSet* const image_histo, - VP8LHistogramSet* const tmp_histos, - uint16_t* const histogram_symbols) { - int ok = 0; - const int histo_xsize = histo_bits ? VP8LSubSampleSize(xsize, histo_bits) : 1; - const int histo_ysize = histo_bits ? VP8LSubSampleSize(ysize, histo_bits) : 1; - const int image_histo_raw_size = histo_xsize * histo_ysize; - const int entropy_combine_num_bins = low_effort ? NUM_PARTITIONS : BIN_SIZE; - - // The bin_map for every bin follows following semantics: - // bin_map[n][0] = num_histo; // The number of histograms in that bin. - // bin_map[n][1] = index of first histogram in that bin; - // bin_map[n][num_histo] = index of last histogram in that bin; - // bin_map[n][num_histo + 1] ... bin_map[n][bin_depth - 1] = unused indices. - const int bin_depth = image_histo_raw_size + 1; - int16_t* bin_map = NULL; - VP8LHistogramSet* const orig_histo = - VP8LAllocateHistogramSet(image_histo_raw_size, cache_bits); - VP8LHistogram* cur_combo; - const int entropy_combine = - (orig_histo->size > entropy_combine_num_bins * 2) && (quality < 100); - - if (orig_histo == NULL) goto Error; - - // Don't attempt linear bin-partition heuristic for: - // histograms of small sizes, as bin_map will be very sparse and; - // Maximum quality (q==100), to preserve the compression gains at that level. - if (entropy_combine) { - const int bin_map_size = bin_depth * entropy_combine_num_bins; - bin_map = (int16_t*)WebPSafeCalloc(bin_map_size, sizeof(*bin_map)); - if (bin_map == NULL) goto Error; - } - - // Construct the histograms from backward references. - HistogramBuild(xsize, histo_bits, refs, orig_histo); - // Copies the histograms and computes its bit_cost. - HistogramCopyAndAnalyze(orig_histo, image_histo); - - cur_combo = tmp_histos->histograms[1]; // pick up working slot - if (entropy_combine) { - const double combine_cost_factor = - GetCombineCostFactor(image_histo_raw_size, quality); - HistogramAnalyzeEntropyBin(orig_histo, bin_map, low_effort); - // Collapse histograms with similar entropy. - cur_combo = HistogramCombineEntropyBin(image_histo, cur_combo, bin_map, - bin_depth, entropy_combine_num_bins, - combine_cost_factor, low_effort); - } - - // Don't combine the histograms using stochastic and greedy heuristics for - // low-effort compression mode. - if (!low_effort || !entropy_combine) { - const float x = quality / 100.f; - // cubic ramp between 1 and MAX_HISTO_GREEDY: - const int threshold_size = (int)(1 + (x * x * x) * (MAX_HISTO_GREEDY - 1)); - cur_combo = HistogramCombineStochastic(image_histo, - tmp_histos->histograms[0], - cur_combo, quality, threshold_size); - if ((image_histo->size <= threshold_size) && - !HistogramCombineGreedy(image_histo, cur_combo)) { - goto Error; - } - } - - // TODO(vikasa): Optimize HistogramRemap for low-effort compression mode also. - // Find the optimal map from original histograms to the final ones. - HistogramRemap(orig_histo, image_histo, histogram_symbols); - - ok = 1; - - Error: - WebPSafeFree(bin_map); - VP8LFreeHistogramSet(orig_histo); - return ok; -} diff --git a/Example-Mac/Pods/libwebp/src/enc/histogram.h b/Example-Mac/Pods/libwebp/src/enc/histogram.h deleted file mode 100644 index d303d1d5..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/histogram.h +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Jyrki Alakuijala (jyrki@google.com) -// -// Models the histograms of literal and distance codes. - -#ifndef WEBP_ENC_HISTOGRAM_H_ -#define WEBP_ENC_HISTOGRAM_H_ - -#include - -#include "./backward_references.h" -#include "../webp/format_constants.h" -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Not a trivial literal symbol. -#define VP8L_NON_TRIVIAL_SYM (0xffffffff) - -// A simple container for histograms of data. -typedef struct { - // literal_ contains green literal, palette-code and - // copy-length-prefix histogram - uint32_t* literal_; // Pointer to the allocated buffer for literal. - uint32_t red_[NUM_LITERAL_CODES]; - uint32_t blue_[NUM_LITERAL_CODES]; - uint32_t alpha_[NUM_LITERAL_CODES]; - // Backward reference prefix-code histogram. - uint32_t distance_[NUM_DISTANCE_CODES]; - int palette_code_bits_; - uint32_t trivial_symbol_; // True, if histograms for Red, Blue & Alpha - // literal symbols are single valued. - double bit_cost_; // cached value of bit cost. - double literal_cost_; // Cached values of dominant entropy costs: - double red_cost_; // literal, red & blue. - double blue_cost_; -} VP8LHistogram; - -// Collection of histograms with fixed capacity, allocated as one -// big memory chunk. Can be destroyed by calling WebPSafeFree(). -typedef struct { - int size; // number of slots currently in use - int max_size; // maximum capacity - VP8LHistogram** histograms; -} VP8LHistogramSet; - -// Create the histogram. -// -// The input data is the PixOrCopy data, which models the literals, stop -// codes and backward references (both distances and lengths). Also: if -// palette_code_bits is >= 0, initialize the histogram with this value. -void VP8LHistogramCreate(VP8LHistogram* const p, - const VP8LBackwardRefs* const refs, - int palette_code_bits); - -// Return the size of the histogram for a given palette_code_bits. -int VP8LGetHistogramSize(int palette_code_bits); - -// Set the palette_code_bits and reset the stats. -void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits); - -// Collect all the references into a histogram (without reset) -void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs, - VP8LHistogram* const histo); - -// Free the memory allocated for the histogram. -void VP8LFreeHistogram(VP8LHistogram* const histo); - -// Free the memory allocated for the histogram set. -void VP8LFreeHistogramSet(VP8LHistogramSet* const histo); - -// Allocate an array of pointer to histograms, allocated and initialized -// using 'cache_bits'. Return NULL in case of memory error. -VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits); - -// Allocate and initialize histogram object with specified 'cache_bits'. -// Returns NULL in case of memory error. -// Special case of VP8LAllocateHistogramSet, with size equals 1. -VP8LHistogram* VP8LAllocateHistogram(int cache_bits); - -// Accumulate a token 'v' into a histogram. -void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo, - const PixOrCopy* const v); - -static WEBP_INLINE int VP8LHistogramNumCodes(int palette_code_bits) { - return NUM_LITERAL_CODES + NUM_LENGTH_CODES + - ((palette_code_bits > 0) ? (1 << palette_code_bits) : 0); -} - -// Builds the histogram image. -int VP8LGetHistoImageSymbols(int xsize, int ysize, - const VP8LBackwardRefs* const refs, - int quality, int low_effort, - int histogram_bits, int cache_bits, - VP8LHistogramSet* const image_in, - VP8LHistogramSet* const tmp_histos, - uint16_t* const histogram_symbols); - -// Returns the entropy for the symbols in the input array. -// Also sets trivial_symbol to the code value, if the array has only one code -// value. Otherwise, set it to VP8L_NON_TRIVIAL_SYM. -double VP8LBitsEntropy(const uint32_t* const array, int n, - uint32_t* const trivial_symbol); - -// Estimate how many bits the combined entropy of literals and distance -// approximately maps to. -double VP8LHistogramEstimateBits(const VP8LHistogram* const p); - -#ifdef __cplusplus -} -#endif - -#endif // WEBP_ENC_HISTOGRAM_H_ diff --git a/Example-Mac/Pods/libwebp/src/enc/iterator.c b/Example-Mac/Pods/libwebp/src/enc/iterator.c deleted file mode 100644 index 99d960a5..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/iterator.c +++ /dev/null @@ -1,456 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// VP8Iterator: block iterator -// -// Author: Skal (pascal.massimino@gmail.com) - -#include - -#include "./vp8enci.h" - -//------------------------------------------------------------------------------ -// VP8Iterator -//------------------------------------------------------------------------------ - -static void InitLeft(VP8EncIterator* const it) { - it->y_left_[-1] = it->u_left_[-1] = it->v_left_[-1] = - (it->y_ > 0) ? 129 : 127; - memset(it->y_left_, 129, 16); - memset(it->u_left_, 129, 8); - memset(it->v_left_, 129, 8); - it->left_nz_[8] = 0; -} - -static void InitTop(VP8EncIterator* const it) { - const VP8Encoder* const enc = it->enc_; - const size_t top_size = enc->mb_w_ * 16; - memset(enc->y_top_, 127, 2 * top_size); - memset(enc->nz_, 0, enc->mb_w_ * sizeof(*enc->nz_)); -} - -void VP8IteratorSetRow(VP8EncIterator* const it, int y) { - VP8Encoder* const enc = it->enc_; - it->x_ = 0; - it->y_ = y; - it->bw_ = &enc->parts_[y & (enc->num_parts_ - 1)]; - it->preds_ = enc->preds_ + y * 4 * enc->preds_w_; - it->nz_ = enc->nz_; - it->mb_ = enc->mb_info_ + y * enc->mb_w_; - it->y_top_ = enc->y_top_; - it->uv_top_ = enc->uv_top_; - InitLeft(it); -} - -void VP8IteratorReset(VP8EncIterator* const it) { - VP8Encoder* const enc = it->enc_; - VP8IteratorSetRow(it, 0); - VP8IteratorSetCountDown(it, enc->mb_w_ * enc->mb_h_); // default - InitTop(it); - InitLeft(it); - memset(it->bit_count_, 0, sizeof(it->bit_count_)); - it->do_trellis_ = 0; -} - -void VP8IteratorSetCountDown(VP8EncIterator* const it, int count_down) { - it->count_down_ = it->count_down0_ = count_down; -} - -int VP8IteratorIsDone(const VP8EncIterator* const it) { - return (it->count_down_ <= 0); -} - -void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it) { - it->enc_ = enc; - it->y_stride_ = enc->pic_->y_stride; - it->uv_stride_ = enc->pic_->uv_stride; - it->yuv_in_ = (uint8_t*)WEBP_ALIGN(it->yuv_mem_); - it->yuv_out_ = it->yuv_in_ + YUV_SIZE_ENC; - it->yuv_out2_ = it->yuv_out_ + YUV_SIZE_ENC; - it->yuv_p_ = it->yuv_out2_ + YUV_SIZE_ENC; - it->lf_stats_ = enc->lf_stats_; - it->percent0_ = enc->percent_; - it->y_left_ = (uint8_t*)WEBP_ALIGN(it->yuv_left_mem_ + 1); - it->u_left_ = it->y_left_ + 16 + 16; - it->v_left_ = it->u_left_ + 16; - VP8IteratorReset(it); -} - -int VP8IteratorProgress(const VP8EncIterator* const it, int delta) { - VP8Encoder* const enc = it->enc_; - if (delta && enc->pic_->progress_hook != NULL) { - const int done = it->count_down0_ - it->count_down_; - const int percent = (it->count_down0_ <= 0) - ? it->percent0_ - : it->percent0_ + delta * done / it->count_down0_; - return WebPReportProgress(enc->pic_, percent, &enc->percent_); - } - return 1; -} - -//------------------------------------------------------------------------------ -// Import the source samples into the cache. Takes care of replicating -// boundary pixels if necessary. - -static WEBP_INLINE int MinSize(int a, int b) { return (a < b) ? a : b; } - -static void ImportBlock(const uint8_t* src, int src_stride, - uint8_t* dst, int w, int h, int size) { - int i; - for (i = 0; i < h; ++i) { - memcpy(dst, src, w); - if (w < size) { - memset(dst + w, dst[w - 1], size - w); - } - dst += BPS; - src += src_stride; - } - for (i = h; i < size; ++i) { - memcpy(dst, dst - BPS, size); - dst += BPS; - } -} - -static void ImportLine(const uint8_t* src, int src_stride, - uint8_t* dst, int len, int total_len) { - int i; - for (i = 0; i < len; ++i, src += src_stride) dst[i] = *src; - for (; i < total_len; ++i) dst[i] = dst[len - 1]; -} - -void VP8IteratorImport(VP8EncIterator* const it, uint8_t* tmp_32) { - const VP8Encoder* const enc = it->enc_; - const int x = it->x_, y = it->y_; - const WebPPicture* const pic = enc->pic_; - const uint8_t* const ysrc = pic->y + (y * pic->y_stride + x) * 16; - const uint8_t* const usrc = pic->u + (y * pic->uv_stride + x) * 8; - const uint8_t* const vsrc = pic->v + (y * pic->uv_stride + x) * 8; - const int w = MinSize(pic->width - x * 16, 16); - const int h = MinSize(pic->height - y * 16, 16); - const int uv_w = (w + 1) >> 1; - const int uv_h = (h + 1) >> 1; - - ImportBlock(ysrc, pic->y_stride, it->yuv_in_ + Y_OFF_ENC, w, h, 16); - ImportBlock(usrc, pic->uv_stride, it->yuv_in_ + U_OFF_ENC, uv_w, uv_h, 8); - ImportBlock(vsrc, pic->uv_stride, it->yuv_in_ + V_OFF_ENC, uv_w, uv_h, 8); - - if (tmp_32 == NULL) return; - - // Import source (uncompressed) samples into boundary. - if (x == 0) { - InitLeft(it); - } else { - if (y == 0) { - it->y_left_[-1] = it->u_left_[-1] = it->v_left_[-1] = 127; - } else { - it->y_left_[-1] = ysrc[- 1 - pic->y_stride]; - it->u_left_[-1] = usrc[- 1 - pic->uv_stride]; - it->v_left_[-1] = vsrc[- 1 - pic->uv_stride]; - } - ImportLine(ysrc - 1, pic->y_stride, it->y_left_, h, 16); - ImportLine(usrc - 1, pic->uv_stride, it->u_left_, uv_h, 8); - ImportLine(vsrc - 1, pic->uv_stride, it->v_left_, uv_h, 8); - } - - it->y_top_ = tmp_32 + 0; - it->uv_top_ = tmp_32 + 16; - if (y == 0) { - memset(tmp_32, 127, 32 * sizeof(*tmp_32)); - } else { - ImportLine(ysrc - pic->y_stride, 1, tmp_32, w, 16); - ImportLine(usrc - pic->uv_stride, 1, tmp_32 + 16, uv_w, 8); - ImportLine(vsrc - pic->uv_stride, 1, tmp_32 + 16 + 8, uv_w, 8); - } -} - -//------------------------------------------------------------------------------ -// Copy back the compressed samples into user space if requested. - -static void ExportBlock(const uint8_t* src, uint8_t* dst, int dst_stride, - int w, int h) { - while (h-- > 0) { - memcpy(dst, src, w); - dst += dst_stride; - src += BPS; - } -} - -void VP8IteratorExport(const VP8EncIterator* const it) { - const VP8Encoder* const enc = it->enc_; - if (enc->config_->show_compressed) { - const int x = it->x_, y = it->y_; - const uint8_t* const ysrc = it->yuv_out_ + Y_OFF_ENC; - const uint8_t* const usrc = it->yuv_out_ + U_OFF_ENC; - const uint8_t* const vsrc = it->yuv_out_ + V_OFF_ENC; - const WebPPicture* const pic = enc->pic_; - uint8_t* const ydst = pic->y + (y * pic->y_stride + x) * 16; - uint8_t* const udst = pic->u + (y * pic->uv_stride + x) * 8; - uint8_t* const vdst = pic->v + (y * pic->uv_stride + x) * 8; - int w = (pic->width - x * 16); - int h = (pic->height - y * 16); - - if (w > 16) w = 16; - if (h > 16) h = 16; - - // Luma plane - ExportBlock(ysrc, ydst, pic->y_stride, w, h); - - { // U/V planes - const int uv_w = (w + 1) >> 1; - const int uv_h = (h + 1) >> 1; - ExportBlock(usrc, udst, pic->uv_stride, uv_w, uv_h); - ExportBlock(vsrc, vdst, pic->uv_stride, uv_w, uv_h); - } - } -} - -//------------------------------------------------------------------------------ -// Non-zero contexts setup/teardown - -// Nz bits: -// 0 1 2 3 Y -// 4 5 6 7 -// 8 9 10 11 -// 12 13 14 15 -// 16 17 U -// 18 19 -// 20 21 V -// 22 23 -// 24 DC-intra16 - -// Convert packed context to byte array -#define BIT(nz, n) (!!((nz) & (1 << (n)))) - -void VP8IteratorNzToBytes(VP8EncIterator* const it) { - const int tnz = it->nz_[0], lnz = it->nz_[-1]; - int* const top_nz = it->top_nz_; - int* const left_nz = it->left_nz_; - - // Top-Y - top_nz[0] = BIT(tnz, 12); - top_nz[1] = BIT(tnz, 13); - top_nz[2] = BIT(tnz, 14); - top_nz[3] = BIT(tnz, 15); - // Top-U - top_nz[4] = BIT(tnz, 18); - top_nz[5] = BIT(tnz, 19); - // Top-V - top_nz[6] = BIT(tnz, 22); - top_nz[7] = BIT(tnz, 23); - // DC - top_nz[8] = BIT(tnz, 24); - - // left-Y - left_nz[0] = BIT(lnz, 3); - left_nz[1] = BIT(lnz, 7); - left_nz[2] = BIT(lnz, 11); - left_nz[3] = BIT(lnz, 15); - // left-U - left_nz[4] = BIT(lnz, 17); - left_nz[5] = BIT(lnz, 19); - // left-V - left_nz[6] = BIT(lnz, 21); - left_nz[7] = BIT(lnz, 23); - // left-DC is special, iterated separately -} - -void VP8IteratorBytesToNz(VP8EncIterator* const it) { - uint32_t nz = 0; - const int* const top_nz = it->top_nz_; - const int* const left_nz = it->left_nz_; - // top - nz |= (top_nz[0] << 12) | (top_nz[1] << 13); - nz |= (top_nz[2] << 14) | (top_nz[3] << 15); - nz |= (top_nz[4] << 18) | (top_nz[5] << 19); - nz |= (top_nz[6] << 22) | (top_nz[7] << 23); - nz |= (top_nz[8] << 24); // we propagate the _top_ bit, esp. for intra4 - // left - nz |= (left_nz[0] << 3) | (left_nz[1] << 7); - nz |= (left_nz[2] << 11); - nz |= (left_nz[4] << 17) | (left_nz[6] << 21); - - *it->nz_ = nz; -} - -#undef BIT - -//------------------------------------------------------------------------------ -// Advance to the next position, doing the bookkeeping. - -void VP8IteratorSaveBoundary(VP8EncIterator* const it) { - VP8Encoder* const enc = it->enc_; - const int x = it->x_, y = it->y_; - const uint8_t* const ysrc = it->yuv_out_ + Y_OFF_ENC; - const uint8_t* const uvsrc = it->yuv_out_ + U_OFF_ENC; - if (x < enc->mb_w_ - 1) { // left - int i; - for (i = 0; i < 16; ++i) { - it->y_left_[i] = ysrc[15 + i * BPS]; - } - for (i = 0; i < 8; ++i) { - it->u_left_[i] = uvsrc[7 + i * BPS]; - it->v_left_[i] = uvsrc[15 + i * BPS]; - } - // top-left (before 'top'!) - it->y_left_[-1] = it->y_top_[15]; - it->u_left_[-1] = it->uv_top_[0 + 7]; - it->v_left_[-1] = it->uv_top_[8 + 7]; - } - if (y < enc->mb_h_ - 1) { // top - memcpy(it->y_top_, ysrc + 15 * BPS, 16); - memcpy(it->uv_top_, uvsrc + 7 * BPS, 8 + 8); - } -} - -int VP8IteratorNext(VP8EncIterator* const it) { - it->preds_ += 4; - it->mb_ += 1; - it->nz_ += 1; - it->y_top_ += 16; - it->uv_top_ += 16; - it->x_ += 1; - if (it->x_ == it->enc_->mb_w_) { - VP8IteratorSetRow(it, ++it->y_); - } - return (0 < --it->count_down_); -} - -//------------------------------------------------------------------------------ -// Helper function to set mode properties - -void VP8SetIntra16Mode(const VP8EncIterator* const it, int mode) { - uint8_t* preds = it->preds_; - int y; - for (y = 0; y < 4; ++y) { - memset(preds, mode, 4); - preds += it->enc_->preds_w_; - } - it->mb_->type_ = 1; -} - -void VP8SetIntra4Mode(const VP8EncIterator* const it, const uint8_t* modes) { - uint8_t* preds = it->preds_; - int y; - for (y = 4; y > 0; --y) { - memcpy(preds, modes, 4 * sizeof(*modes)); - preds += it->enc_->preds_w_; - modes += 4; - } - it->mb_->type_ = 0; -} - -void VP8SetIntraUVMode(const VP8EncIterator* const it, int mode) { - it->mb_->uv_mode_ = mode; -} - -void VP8SetSkip(const VP8EncIterator* const it, int skip) { - it->mb_->skip_ = skip; -} - -void VP8SetSegment(const VP8EncIterator* const it, int segment) { - it->mb_->segment_ = segment; -} - -//------------------------------------------------------------------------------ -// Intra4x4 sub-blocks iteration -// -// We store and update the boundary samples into an array of 37 pixels. They -// are updated as we iterate and reconstructs each intra4x4 blocks in turn. -// The position of the samples has the following snake pattern: -// -// 16|17 18 19 20|21 22 23 24|25 26 27 28|29 30 31 32|33 34 35 36 <- Top-right -// --+-----------+-----------+-----------+-----------+ -// 15| 19| 23| 27| 31| -// 14| 18| 22| 26| 30| -// 13| 17| 21| 25| 29| -// 12|13 14 15 16|17 18 19 20|21 22 23 24|25 26 27 28| -// --+-----------+-----------+-----------+-----------+ -// 11| 15| 19| 23| 27| -// 10| 14| 18| 22| 26| -// 9| 13| 17| 21| 25| -// 8| 9 10 11 12|13 14 15 16|17 18 19 20|21 22 23 24| -// --+-----------+-----------+-----------+-----------+ -// 7| 11| 15| 19| 23| -// 6| 10| 14| 18| 22| -// 5| 9| 13| 17| 21| -// 4| 5 6 7 8| 9 10 11 12|13 14 15 16|17 18 19 20| -// --+-----------+-----------+-----------+-----------+ -// 3| 7| 11| 15| 19| -// 2| 6| 10| 14| 18| -// 1| 5| 9| 13| 17| -// 0| 1 2 3 4| 5 6 7 8| 9 10 11 12|13 14 15 16| -// --+-----------+-----------+-----------+-----------+ - -// Array to record the position of the top sample to pass to the prediction -// functions in dsp.c. -static const uint8_t VP8TopLeftI4[16] = { - 17, 21, 25, 29, - 13, 17, 21, 25, - 9, 13, 17, 21, - 5, 9, 13, 17 -}; - -void VP8IteratorStartI4(VP8EncIterator* const it) { - const VP8Encoder* const enc = it->enc_; - int i; - - it->i4_ = 0; // first 4x4 sub-block - it->i4_top_ = it->i4_boundary_ + VP8TopLeftI4[0]; - - // Import the boundary samples - for (i = 0; i < 17; ++i) { // left - it->i4_boundary_[i] = it->y_left_[15 - i]; - } - for (i = 0; i < 16; ++i) { // top - it->i4_boundary_[17 + i] = it->y_top_[i]; - } - // top-right samples have a special case on the far right of the picture - if (it->x_ < enc->mb_w_ - 1) { - for (i = 16; i < 16 + 4; ++i) { - it->i4_boundary_[17 + i] = it->y_top_[i]; - } - } else { // else, replicate the last valid pixel four times - for (i = 16; i < 16 + 4; ++i) { - it->i4_boundary_[17 + i] = it->i4_boundary_[17 + 15]; - } - } - VP8IteratorNzToBytes(it); // import the non-zero context -} - -int VP8IteratorRotateI4(VP8EncIterator* const it, - const uint8_t* const yuv_out) { - const uint8_t* const blk = yuv_out + VP8Scan[it->i4_]; - uint8_t* const top = it->i4_top_; - int i; - - // Update the cache with 7 fresh samples - for (i = 0; i <= 3; ++i) { - top[-4 + i] = blk[i + 3 * BPS]; // store future top samples - } - if ((it->i4_ & 3) != 3) { // if not on the right sub-blocks #3, #7, #11, #15 - for (i = 0; i <= 2; ++i) { // store future left samples - top[i] = blk[3 + (2 - i) * BPS]; - } - } else { // else replicate top-right samples, as says the specs. - for (i = 0; i <= 3; ++i) { - top[i] = top[i + 4]; - } - } - // move pointers to next sub-block - ++it->i4_; - if (it->i4_ == 16) { // we're done - return 0; - } - - it->i4_top_ = it->i4_boundary_ + VP8TopLeftI4[it->i4_]; - return 1; -} - -//------------------------------------------------------------------------------ - diff --git a/Example-Mac/Pods/libwebp/src/enc/near_lossless.c b/Example-Mac/Pods/libwebp/src/enc/near_lossless.c deleted file mode 100644 index 9bc0f0e7..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/near_lossless.c +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Near-lossless image preprocessing adjusts pixel values to help -// compressibility with a guarantee of maximum deviation between original and -// resulting pixel values. -// -// Author: Jyrki Alakuijala (jyrki@google.com) -// Converted to C by Aleksander Kramarz (akramarz@google.com) - -#include - -#include "../dsp/lossless.h" -#include "../utils/utils.h" -#include "./vp8enci.h" - -#define MIN_DIM_FOR_NEAR_LOSSLESS 64 -#define MAX_LIMIT_BITS 5 - -// Computes quantized pixel value and distance from original value. -static void GetValAndDistance(int a, int initial, int bits, - int* const val, int* const distance) { - const int mask = ~((1 << bits) - 1); - *val = (initial & mask) | (initial >> (8 - bits)); - *distance = 2 * abs(a - *val); -} - -// Clamps the value to range [0, 255]. -static int Clamp8b(int val) { - const int min_val = 0; - const int max_val = 0xff; - return (val < min_val) ? min_val : (val > max_val) ? max_val : val; -} - -// Quantizes values {a, a+(1<> 24, bits) << 24) | - (FindClosestDiscretized((a >> 16) & 0xff, bits) << 16) | - (FindClosestDiscretized((a >> 8) & 0xff, bits) << 8) | - (FindClosestDiscretized(a & 0xff, bits)); -} - -// Checks if distance between corresponding channel values of pixels a and b -// is within the given limit. -static int IsNear(uint32_t a, uint32_t b, int limit) { - int k; - for (k = 0; k < 4; ++k) { - const int delta = - (int)((a >> (k * 8)) & 0xff) - (int)((b >> (k * 8)) & 0xff); - if (delta >= limit || delta <= -limit) { - return 0; - } - } - return 1; -} - -static int IsSmooth(const uint32_t* const prev_row, - const uint32_t* const curr_row, - const uint32_t* const next_row, - int ix, int limit) { - // Check that all pixels in 4-connected neighborhood are smooth. - return (IsNear(curr_row[ix], curr_row[ix - 1], limit) && - IsNear(curr_row[ix], curr_row[ix + 1], limit) && - IsNear(curr_row[ix], prev_row[ix], limit) && - IsNear(curr_row[ix], next_row[ix], limit)); -} - -// Adjusts pixel values of image with given maximum error. -static void NearLossless(int xsize, int ysize, uint32_t* argb, - int limit_bits, uint32_t* copy_buffer) { - int x, y; - const int limit = 1 << limit_bits; - uint32_t* prev_row = copy_buffer; - uint32_t* curr_row = prev_row + xsize; - uint32_t* next_row = curr_row + xsize; - memcpy(copy_buffer, argb, xsize * 2 * sizeof(argb[0])); - - for (y = 1; y < ysize - 1; ++y) { - uint32_t* const curr_argb_row = argb + y * xsize; - uint32_t* const next_argb_row = curr_argb_row + xsize; - memcpy(next_row, next_argb_row, xsize * sizeof(argb[0])); - for (x = 1; x < xsize - 1; ++x) { - if (!IsSmooth(prev_row, curr_row, next_row, x, limit)) { - curr_argb_row[x] = ClosestDiscretizedArgb(curr_row[x], limit_bits); - } - } - { - // Three-way swap. - uint32_t* const temp = prev_row; - prev_row = curr_row; - curr_row = next_row; - next_row = temp; - } - } -} - -static int QualityToLimitBits(int quality) { - // quality mapping: - // 0..19 -> 5 - // 0..39 -> 4 - // 0..59 -> 3 - // 0..79 -> 2 - // 0..99 -> 1 - // 100 -> 0 - return MAX_LIMIT_BITS - quality / 20; -} - -int VP8ApplyNearLossless(int xsize, int ysize, uint32_t* argb, int quality) { - int i; - uint32_t* const copy_buffer = - (uint32_t*)WebPSafeMalloc(xsize * 3, sizeof(*copy_buffer)); - const int limit_bits = QualityToLimitBits(quality); - assert(argb != NULL); - assert(limit_bits >= 0); - assert(limit_bits <= MAX_LIMIT_BITS); - if (copy_buffer == NULL) { - return 0; - } - // For small icon images, don't attempt to apply near-lossless compression. - if (xsize < MIN_DIM_FOR_NEAR_LOSSLESS && ysize < MIN_DIM_FOR_NEAR_LOSSLESS) { - WebPSafeFree(copy_buffer); - return 1; - } - - for (i = limit_bits; i != 0; --i) { - NearLossless(xsize, ysize, argb, i, copy_buffer); - } - WebPSafeFree(copy_buffer); - return 1; -} diff --git a/Example-Mac/Pods/libwebp/src/enc/picture.c b/Example-Mac/Pods/libwebp/src/enc/picture.c deleted file mode 100644 index 26679a72..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/picture.c +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// WebPPicture class basis -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include - -#include "./vp8enci.h" -#include "../dsp/dsp.h" -#include "../utils/utils.h" - -//------------------------------------------------------------------------------ -// WebPPicture -//------------------------------------------------------------------------------ - -static int DummyWriter(const uint8_t* data, size_t data_size, - const WebPPicture* const picture) { - // The following are to prevent 'unused variable' error message. - (void)data; - (void)data_size; - (void)picture; - return 1; -} - -int WebPPictureInitInternal(WebPPicture* picture, int version) { - if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_ENCODER_ABI_VERSION)) { - return 0; // caller/system version mismatch! - } - if (picture != NULL) { - memset(picture, 0, sizeof(*picture)); - picture->writer = DummyWriter; - WebPEncodingSetError(picture, VP8_ENC_OK); - } - return 1; -} - -//------------------------------------------------------------------------------ - -static void WebPPictureResetBufferARGB(WebPPicture* const picture) { - picture->memory_argb_ = NULL; - picture->argb = NULL; - picture->argb_stride = 0; -} - -static void WebPPictureResetBufferYUVA(WebPPicture* const picture) { - picture->memory_ = NULL; - picture->y = picture->u = picture->v = picture->a = NULL; - picture->y_stride = picture->uv_stride = 0; - picture->a_stride = 0; -} - -void WebPPictureResetBuffers(WebPPicture* const picture) { - WebPPictureResetBufferARGB(picture); - WebPPictureResetBufferYUVA(picture); -} - -int WebPPictureAllocARGB(WebPPicture* const picture, int width, int height) { - void* memory; - const uint64_t argb_size = (uint64_t)width * height; - - assert(picture != NULL); - - WebPSafeFree(picture->memory_argb_); - WebPPictureResetBufferARGB(picture); - - if (width <= 0 || height <= 0) { - return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION); - } - // allocate a new buffer. - memory = WebPSafeMalloc(argb_size, sizeof(*picture->argb)); - if (memory == NULL) { - return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); - } - // TODO(skal): align plane to cache line? - picture->memory_argb_ = memory; - picture->argb = (uint32_t*)memory; - picture->argb_stride = width; - return 1; -} - -int WebPPictureAllocYUVA(WebPPicture* const picture, int width, int height) { - const WebPEncCSP uv_csp = picture->colorspace & WEBP_CSP_UV_MASK; - const int has_alpha = picture->colorspace & WEBP_CSP_ALPHA_BIT; - const int y_stride = width; - const int uv_width = (width + 1) >> 1; - const int uv_height = (height + 1) >> 1; - const int uv_stride = uv_width; - int a_width, a_stride; - uint64_t y_size, uv_size, a_size, total_size; - uint8_t* mem; - - assert(picture != NULL); - - WebPSafeFree(picture->memory_); - WebPPictureResetBufferYUVA(picture); - - if (uv_csp != WEBP_YUV420) { - return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION); - } - - // alpha - a_width = has_alpha ? width : 0; - a_stride = a_width; - y_size = (uint64_t)y_stride * height; - uv_size = (uint64_t)uv_stride * uv_height; - a_size = (uint64_t)a_stride * height; - - total_size = y_size + a_size + 2 * uv_size; - - // Security and validation checks - if (width <= 0 || height <= 0 || // luma/alpha param error - uv_width < 0 || uv_height < 0) { // u/v param error - return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION); - } - // allocate a new buffer. - mem = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*mem)); - if (mem == NULL) { - return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); - } - - // From now on, we're in the clear, we can no longer fail... - picture->memory_ = (void*)mem; - picture->y_stride = y_stride; - picture->uv_stride = uv_stride; - picture->a_stride = a_stride; - - // TODO(skal): we could align the y/u/v planes and adjust stride. - picture->y = mem; - mem += y_size; - - picture->u = mem; - mem += uv_size; - picture->v = mem; - mem += uv_size; - - if (a_size > 0) { - picture->a = mem; - mem += a_size; - } - (void)mem; // makes the static analyzer happy - return 1; -} - -int WebPPictureAlloc(WebPPicture* picture) { - if (picture != NULL) { - const int width = picture->width; - const int height = picture->height; - - WebPPictureFree(picture); // erase previous buffer - - if (!picture->use_argb) { - return WebPPictureAllocYUVA(picture, width, height); - } else { - return WebPPictureAllocARGB(picture, width, height); - } - } - return 1; -} - -void WebPPictureFree(WebPPicture* picture) { - if (picture != NULL) { - WebPSafeFree(picture->memory_); - WebPSafeFree(picture->memory_argb_); - WebPPictureResetBuffers(picture); - } -} - -//------------------------------------------------------------------------------ -// WebPMemoryWriter: Write-to-memory - -void WebPMemoryWriterInit(WebPMemoryWriter* writer) { - writer->mem = NULL; - writer->size = 0; - writer->max_size = 0; -} - -int WebPMemoryWrite(const uint8_t* data, size_t data_size, - const WebPPicture* picture) { - WebPMemoryWriter* const w = (WebPMemoryWriter*)picture->custom_ptr; - uint64_t next_size; - if (w == NULL) { - return 1; - } - next_size = (uint64_t)w->size + data_size; - if (next_size > w->max_size) { - uint8_t* new_mem; - uint64_t next_max_size = 2ULL * w->max_size; - if (next_max_size < next_size) next_max_size = next_size; - if (next_max_size < 8192ULL) next_max_size = 8192ULL; - new_mem = (uint8_t*)WebPSafeMalloc(next_max_size, 1); - if (new_mem == NULL) { - return 0; - } - if (w->size > 0) { - memcpy(new_mem, w->mem, w->size); - } - WebPSafeFree(w->mem); - w->mem = new_mem; - // down-cast is ok, thanks to WebPSafeMalloc - w->max_size = (size_t)next_max_size; - } - if (data_size > 0) { - memcpy(w->mem + w->size, data, data_size); - w->size += data_size; - } - return 1; -} - -void WebPMemoryWriterClear(WebPMemoryWriter* writer) { - if (writer != NULL) { - WebPSafeFree(writer->mem); - writer->mem = NULL; - writer->size = 0; - writer->max_size = 0; - } -} - -//------------------------------------------------------------------------------ -// Simplest high-level calls: - -typedef int (*Importer)(WebPPicture* const, const uint8_t* const, int); - -static size_t Encode(const uint8_t* rgba, int width, int height, int stride, - Importer import, float quality_factor, int lossless, - uint8_t** output) { - WebPPicture pic; - WebPConfig config; - WebPMemoryWriter wrt; - int ok; - - if (!WebPConfigPreset(&config, WEBP_PRESET_DEFAULT, quality_factor) || - !WebPPictureInit(&pic)) { - return 0; // shouldn't happen, except if system installation is broken - } - - config.lossless = !!lossless; - pic.use_argb = !!lossless; - pic.width = width; - pic.height = height; - pic.writer = WebPMemoryWrite; - pic.custom_ptr = &wrt; - WebPMemoryWriterInit(&wrt); - - ok = import(&pic, rgba, stride) && WebPEncode(&config, &pic); - WebPPictureFree(&pic); - if (!ok) { - WebPMemoryWriterClear(&wrt); - *output = NULL; - return 0; - } - *output = wrt.mem; - return wrt.size; -} - -#define ENCODE_FUNC(NAME, IMPORTER) \ -size_t NAME(const uint8_t* in, int w, int h, int bps, float q, \ - uint8_t** out) { \ - return Encode(in, w, h, bps, IMPORTER, q, 0, out); \ -} - -ENCODE_FUNC(WebPEncodeRGB, WebPPictureImportRGB) -ENCODE_FUNC(WebPEncodeBGR, WebPPictureImportBGR) -ENCODE_FUNC(WebPEncodeRGBA, WebPPictureImportRGBA) -ENCODE_FUNC(WebPEncodeBGRA, WebPPictureImportBGRA) - -#undef ENCODE_FUNC - -#define LOSSLESS_DEFAULT_QUALITY 70. -#define LOSSLESS_ENCODE_FUNC(NAME, IMPORTER) \ -size_t NAME(const uint8_t* in, int w, int h, int bps, uint8_t** out) { \ - return Encode(in, w, h, bps, IMPORTER, LOSSLESS_DEFAULT_QUALITY, 1, out); \ -} - -LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessRGB, WebPPictureImportRGB) -LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGR, WebPPictureImportBGR) -LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessRGBA, WebPPictureImportRGBA) -LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGRA, WebPPictureImportBGRA) - -#undef LOSSLESS_ENCODE_FUNC - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/enc/picture_csp.c b/Example-Mac/Pods/libwebp/src/enc/picture_csp.c deleted file mode 100644 index 0ef5f9ee..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/picture_csp.c +++ /dev/null @@ -1,1156 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// WebPPicture utils for colorspace conversion -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include -#include - -#include "./vp8enci.h" -#include "../utils/random.h" -#include "../utils/utils.h" -#include "../dsp/yuv.h" - -// Uncomment to disable gamma-compression during RGB->U/V averaging -#define USE_GAMMA_COMPRESSION - -// If defined, use table to compute x / alpha. -#define USE_INVERSE_ALPHA_TABLE - -static const union { - uint32_t argb; - uint8_t bytes[4]; -} test_endian = { 0xff000000u }; -#define ALPHA_IS_LAST (test_endian.bytes[3] == 0xff) - -//------------------------------------------------------------------------------ -// Detection of non-trivial transparency - -// Returns true if alpha[] has non-0xff values. -static int CheckNonOpaque(const uint8_t* alpha, int width, int height, - int x_step, int y_step) { - if (alpha == NULL) return 0; - while (height-- > 0) { - int x; - for (x = 0; x < width * x_step; x += x_step) { - if (alpha[x] != 0xff) return 1; // TODO(skal): check 4/8 bytes at a time. - } - alpha += y_step; - } - return 0; -} - -// Checking for the presence of non-opaque alpha. -int WebPPictureHasTransparency(const WebPPicture* picture) { - if (picture == NULL) return 0; - if (!picture->use_argb) { - return CheckNonOpaque(picture->a, picture->width, picture->height, - 1, picture->a_stride); - } else { - int x, y; - const uint32_t* argb = picture->argb; - if (argb == NULL) return 0; - for (y = 0; y < picture->height; ++y) { - for (x = 0; x < picture->width; ++x) { - if (argb[x] < 0xff000000u) return 1; // test any alpha values != 0xff - } - argb += picture->argb_stride; - } - } - return 0; -} - -//------------------------------------------------------------------------------ -// Code for gamma correction - -#if defined(USE_GAMMA_COMPRESSION) - -// gamma-compensates loss of resolution during chroma subsampling -#define kGamma 0.80 // for now we use a different gamma value than kGammaF -#define kGammaFix 12 // fixed-point precision for linear values -#define kGammaScale ((1 << kGammaFix) - 1) -#define kGammaTabFix 7 // fixed-point fractional bits precision -#define kGammaTabScale (1 << kGammaTabFix) -#define kGammaTabRounder (kGammaTabScale >> 1) -#define kGammaTabSize (1 << (kGammaFix - kGammaTabFix)) - -static int kLinearToGammaTab[kGammaTabSize + 1]; -static uint16_t kGammaToLinearTab[256]; -static volatile int kGammaTablesOk = 0; - -static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTables(void) { - if (!kGammaTablesOk) { - int v; - const double scale = (double)(1 << kGammaTabFix) / kGammaScale; - const double norm = 1. / 255.; - for (v = 0; v <= 255; ++v) { - kGammaToLinearTab[v] = - (uint16_t)(pow(norm * v, kGamma) * kGammaScale + .5); - } - for (v = 0; v <= kGammaTabSize; ++v) { - kLinearToGammaTab[v] = (int)(255. * pow(scale * v, 1. / kGamma) + .5); - } - kGammaTablesOk = 1; - } -} - -static WEBP_INLINE uint32_t GammaToLinear(uint8_t v) { - return kGammaToLinearTab[v]; -} - -static WEBP_INLINE int Interpolate(int v) { - const int tab_pos = v >> (kGammaTabFix + 2); // integer part - const int x = v & ((kGammaTabScale << 2) - 1); // fractional part - const int v0 = kLinearToGammaTab[tab_pos]; - const int v1 = kLinearToGammaTab[tab_pos + 1]; - const int y = v1 * x + v0 * ((kGammaTabScale << 2) - x); // interpolate - assert(tab_pos + 1 < kGammaTabSize + 1); - return y; -} - -// Convert a linear value 'v' to YUV_FIX+2 fixed-point precision -// U/V value, suitable for RGBToU/V calls. -static WEBP_INLINE int LinearToGamma(uint32_t base_value, int shift) { - const int y = Interpolate(base_value << shift); // final uplifted value - return (y + kGammaTabRounder) >> kGammaTabFix; // descale -} - -#else - -static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTables(void) {} -static WEBP_INLINE uint32_t GammaToLinear(uint8_t v) { return v; } -static WEBP_INLINE int LinearToGamma(uint32_t base_value, int shift) { - return (int)(base_value << shift); -} - -#endif // USE_GAMMA_COMPRESSION - -//------------------------------------------------------------------------------ -// RGB -> YUV conversion - -static int RGBToY(int r, int g, int b, VP8Random* const rg) { - return (rg == NULL) ? VP8RGBToY(r, g, b, YUV_HALF) - : VP8RGBToY(r, g, b, VP8RandomBits(rg, YUV_FIX)); -} - -static int RGBToU(int r, int g, int b, VP8Random* const rg) { - return (rg == NULL) ? VP8RGBToU(r, g, b, YUV_HALF << 2) - : VP8RGBToU(r, g, b, VP8RandomBits(rg, YUV_FIX + 2)); -} - -static int RGBToV(int r, int g, int b, VP8Random* const rg) { - return (rg == NULL) ? VP8RGBToV(r, g, b, YUV_HALF << 2) - : VP8RGBToV(r, g, b, VP8RandomBits(rg, YUV_FIX + 2)); -} - -//------------------------------------------------------------------------------ -// Smart RGB->YUV conversion - -static const int kNumIterations = 6; -static const int kMinDimensionIterativeConversion = 4; - -// We could use SFIX=0 and only uint8_t for fixed_y_t, but it produces some -// banding sometimes. Better use extra precision. -#define SFIX 2 // fixed-point precision of RGB and Y/W -typedef int16_t fixed_t; // signed type with extra SFIX precision for UV -typedef uint16_t fixed_y_t; // unsigned type with extra SFIX precision for W - -#define SHALF (1 << SFIX >> 1) -#define MAX_Y_T ((256 << SFIX) - 1) -#define SROUNDER (1 << (YUV_FIX + SFIX - 1)) - -#if defined(USE_GAMMA_COMPRESSION) - -// float variant of gamma-correction -// We use tables of different size and precision, along with a 'real-world' -// Gamma value close to ~2. -#define kGammaF 2.2 -static float kGammaToLinearTabF[MAX_Y_T + 1]; // size scales with Y_FIX -static float kLinearToGammaTabF[kGammaTabSize + 2]; -static volatile int kGammaTablesFOk = 0; - -static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTablesF(void) { - if (!kGammaTablesFOk) { - int v; - const double norm = 1. / MAX_Y_T; - const double scale = 1. / kGammaTabSize; - for (v = 0; v <= MAX_Y_T; ++v) { - kGammaToLinearTabF[v] = (float)pow(norm * v, kGammaF); - } - for (v = 0; v <= kGammaTabSize; ++v) { - kLinearToGammaTabF[v] = (float)(MAX_Y_T * pow(scale * v, 1. / kGammaF)); - } - // to prevent small rounding errors to cause read-overflow: - kLinearToGammaTabF[kGammaTabSize + 1] = kLinearToGammaTabF[kGammaTabSize]; - kGammaTablesFOk = 1; - } -} - -static WEBP_INLINE float GammaToLinearF(int v) { - return kGammaToLinearTabF[v]; -} - -static WEBP_INLINE int LinearToGammaF(float value) { - const float v = value * kGammaTabSize; - const int tab_pos = (int)v; - const float x = v - (float)tab_pos; // fractional part - const float v0 = kLinearToGammaTabF[tab_pos + 0]; - const float v1 = kLinearToGammaTabF[tab_pos + 1]; - const float y = v1 * x + v0 * (1.f - x); // interpolate - return (int)(y + .5); -} - -#else - -static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTablesF(void) {} -static WEBP_INLINE float GammaToLinearF(int v) { - const float norm = 1.f / MAX_Y_T; - return norm * v; -} -static WEBP_INLINE int LinearToGammaF(float value) { - return (int)(MAX_Y_T * value + .5); -} - -#endif // USE_GAMMA_COMPRESSION - -//------------------------------------------------------------------------------ - -static uint8_t clip_8b(fixed_t v) { - return (!(v & ~0xff)) ? (uint8_t)v : (v < 0) ? 0u : 255u; -} - -static fixed_y_t clip_y(int y) { - return (!(y & ~MAX_Y_T)) ? (fixed_y_t)y : (y < 0) ? 0 : MAX_Y_T; -} - -//------------------------------------------------------------------------------ - -static int RGBToGray(int r, int g, int b) { - const int luma = 19595 * r + 38470 * g + 7471 * b + YUV_HALF; - return (luma >> YUV_FIX); -} - -static float RGBToGrayF(float r, float g, float b) { - return 0.299f * r + 0.587f * g + 0.114f * b; -} - -static int ScaleDown(int a, int b, int c, int d) { - const float A = GammaToLinearF(a); - const float B = GammaToLinearF(b); - const float C = GammaToLinearF(c); - const float D = GammaToLinearF(d); - return LinearToGammaF(0.25f * (A + B + C + D)); -} - -static WEBP_INLINE void UpdateW(const fixed_y_t* src, fixed_y_t* dst, int len) { - while (len-- > 0) { - const float R = GammaToLinearF(src[0]); - const float G = GammaToLinearF(src[1]); - const float B = GammaToLinearF(src[2]); - const float Y = RGBToGrayF(R, G, B); - *dst++ = (fixed_y_t)LinearToGammaF(Y); - src += 3; - } -} - -static int UpdateChroma(const fixed_y_t* src1, - const fixed_y_t* src2, - fixed_t* dst, fixed_y_t* tmp, int len) { - int diff = 0; - while (len--> 0) { - const int r = ScaleDown(src1[0], src1[3], src2[0], src2[3]); - const int g = ScaleDown(src1[1], src1[4], src2[1], src2[4]); - const int b = ScaleDown(src1[2], src1[5], src2[2], src2[5]); - const int W = RGBToGray(r, g, b); - const int r_avg = (src1[0] + src1[3] + src2[0] + src2[3] + 2) >> 2; - const int g_avg = (src1[1] + src1[4] + src2[1] + src2[4] + 2) >> 2; - const int b_avg = (src1[2] + src1[5] + src2[2] + src2[5] + 2) >> 2; - dst[0] = (fixed_t)(r - W); - dst[1] = (fixed_t)(g - W); - dst[2] = (fixed_t)(b - W); - dst += 3; - src1 += 6; - src2 += 6; - if (tmp != NULL) { - tmp[0] = tmp[1] = clip_y(W); - tmp += 2; - } - diff += abs(RGBToGray(r_avg, g_avg, b_avg) - W); - } - return diff; -} - -//------------------------------------------------------------------------------ - -static WEBP_INLINE int Filter(const fixed_t* const A, const fixed_t* const B, - int rightwise) { - int v; - if (!rightwise) { - v = (A[0] * 9 + A[-3] * 3 + B[0] * 3 + B[-3]); - } else { - v = (A[0] * 9 + A[+3] * 3 + B[0] * 3 + B[+3]); - } - return (v + 8) >> 4; -} - -static WEBP_INLINE int Filter2(int A, int B) { return (A * 3 + B + 2) >> 2; } - -//------------------------------------------------------------------------------ - -static WEBP_INLINE fixed_y_t UpLift(uint8_t a) { // 8bit -> SFIX - return ((fixed_y_t)a << SFIX) | SHALF; -} - -static void ImportOneRow(const uint8_t* const r_ptr, - const uint8_t* const g_ptr, - const uint8_t* const b_ptr, - int step, - int pic_width, - fixed_y_t* const dst) { - int i; - for (i = 0; i < pic_width; ++i) { - const int off = i * step; - dst[3 * i + 0] = UpLift(r_ptr[off]); - dst[3 * i + 1] = UpLift(g_ptr[off]); - dst[3 * i + 2] = UpLift(b_ptr[off]); - } - if (pic_width & 1) { // replicate rightmost pixel - memcpy(dst + 3 * pic_width, dst + 3 * (pic_width - 1), 3 * sizeof(*dst)); - } -} - -static void InterpolateTwoRows(const fixed_y_t* const best_y, - const fixed_t* const prev_uv, - const fixed_t* const cur_uv, - const fixed_t* const next_uv, - int w, - fixed_y_t* const out1, - fixed_y_t* const out2) { - int i, k; - { // special boundary case for i==0 - const int W0 = best_y[0]; - const int W1 = best_y[w]; - for (k = 0; k <= 2; ++k) { - out1[k] = clip_y(Filter2(cur_uv[k], prev_uv[k]) + W0); - out2[k] = clip_y(Filter2(cur_uv[k], next_uv[k]) + W1); - } - } - for (i = 1; i < w - 1; ++i) { - const int W0 = best_y[i + 0]; - const int W1 = best_y[i + w]; - const int off = 3 * (i >> 1); - for (k = 0; k <= 2; ++k) { - const int tmp0 = Filter(cur_uv + off + k, prev_uv + off + k, i & 1); - const int tmp1 = Filter(cur_uv + off + k, next_uv + off + k, i & 1); - out1[3 * i + k] = clip_y(tmp0 + W0); - out2[3 * i + k] = clip_y(tmp1 + W1); - } - } - { // special boundary case for i == w - 1 - const int W0 = best_y[i + 0]; - const int W1 = best_y[i + w]; - const int off = 3 * (i >> 1); - for (k = 0; k <= 2; ++k) { - out1[3 * i + k] = clip_y(Filter2(cur_uv[off + k], prev_uv[off + k]) + W0); - out2[3 * i + k] = clip_y(Filter2(cur_uv[off + k], next_uv[off + k]) + W1); - } - } -} - -static WEBP_INLINE uint8_t ConvertRGBToY(int r, int g, int b) { - const int luma = 16839 * r + 33059 * g + 6420 * b + SROUNDER; - return clip_8b(16 + (luma >> (YUV_FIX + SFIX))); -} - -static WEBP_INLINE uint8_t ConvertRGBToU(int r, int g, int b) { - const int u = -9719 * r - 19081 * g + 28800 * b + SROUNDER; - return clip_8b(128 + (u >> (YUV_FIX + SFIX))); -} - -static WEBP_INLINE uint8_t ConvertRGBToV(int r, int g, int b) { - const int v = +28800 * r - 24116 * g - 4684 * b + SROUNDER; - return clip_8b(128 + (v >> (YUV_FIX + SFIX))); -} - -static int ConvertWRGBToYUV(const fixed_y_t* const best_y, - const fixed_t* const best_uv, - WebPPicture* const picture) { - int i, j; - const int w = (picture->width + 1) & ~1; - const int h = (picture->height + 1) & ~1; - const int uv_w = w >> 1; - const int uv_h = h >> 1; - for (j = 0; j < picture->height; ++j) { - for (i = 0; i < picture->width; ++i) { - const int off = 3 * ((i >> 1) + (j >> 1) * uv_w); - const int off2 = i + j * picture->y_stride; - const int W = best_y[i + j * w]; - const int r = best_uv[off + 0] + W; - const int g = best_uv[off + 1] + W; - const int b = best_uv[off + 2] + W; - picture->y[off2] = ConvertRGBToY(r, g, b); - } - } - for (j = 0; j < uv_h; ++j) { - uint8_t* const dst_u = picture->u + j * picture->uv_stride; - uint8_t* const dst_v = picture->v + j * picture->uv_stride; - for (i = 0; i < uv_w; ++i) { - const int off = 3 * (i + j * uv_w); - const int r = best_uv[off + 0]; - const int g = best_uv[off + 1]; - const int b = best_uv[off + 2]; - dst_u[i] = ConvertRGBToU(r, g, b); - dst_v[i] = ConvertRGBToV(r, g, b); - } - } - return 1; -} - -//------------------------------------------------------------------------------ -// Main function - -#define SAFE_ALLOC(W, H, T) ((T*)WebPSafeMalloc((W) * (H), sizeof(T))) - -static int PreprocessARGB(const uint8_t* const r_ptr, - const uint8_t* const g_ptr, - const uint8_t* const b_ptr, - int step, int rgb_stride, - WebPPicture* const picture) { - // we expand the right/bottom border if needed - const int w = (picture->width + 1) & ~1; - const int h = (picture->height + 1) & ~1; - const int uv_w = w >> 1; - const int uv_h = h >> 1; - int i, j, iter; - - // TODO(skal): allocate one big memory chunk. But for now, it's easier - // for valgrind debugging to have several chunks. - fixed_y_t* const tmp_buffer = SAFE_ALLOC(w * 3, 2, fixed_y_t); // scratch - fixed_y_t* const best_y = SAFE_ALLOC(w, h, fixed_y_t); - fixed_y_t* const target_y = SAFE_ALLOC(w, h, fixed_y_t); - fixed_y_t* const best_rgb_y = SAFE_ALLOC(w, 2, fixed_y_t); - fixed_t* const best_uv = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t); - fixed_t* const target_uv = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t); - fixed_t* const best_rgb_uv = SAFE_ALLOC(uv_w * 3, 1, fixed_t); - int ok; - int diff_sum = 0; - const int first_diff_threshold = (int)(2.5 * w * h); - const int min_improvement = 5; // stop if improvement is below this % - const int min_first_improvement = 80; - - if (best_y == NULL || best_uv == NULL || - target_y == NULL || target_uv == NULL || - best_rgb_y == NULL || best_rgb_uv == NULL || - tmp_buffer == NULL) { - ok = WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); - goto End; - } - assert(picture->width >= kMinDimensionIterativeConversion); - assert(picture->height >= kMinDimensionIterativeConversion); - - // Import RGB samples to W/RGB representation. - for (j = 0; j < picture->height; j += 2) { - const int is_last_row = (j == picture->height - 1); - fixed_y_t* const src1 = tmp_buffer; - fixed_y_t* const src2 = tmp_buffer + 3 * w; - const int off1 = j * rgb_stride; - const int off2 = off1 + rgb_stride; - const int uv_off = (j >> 1) * 3 * uv_w; - fixed_y_t* const dst_y = best_y + j * w; - - // prepare two rows of input - ImportOneRow(r_ptr + off1, g_ptr + off1, b_ptr + off1, - step, picture->width, src1); - if (!is_last_row) { - ImportOneRow(r_ptr + off2, g_ptr + off2, b_ptr + off2, - step, picture->width, src2); - } else { - memcpy(src2, src1, 3 * w * sizeof(*src2)); - } - UpdateW(src1, target_y + (j + 0) * w, w); - UpdateW(src2, target_y + (j + 1) * w, w); - diff_sum += UpdateChroma(src1, src2, target_uv + uv_off, dst_y, uv_w); - memcpy(best_uv + uv_off, target_uv + uv_off, 3 * uv_w * sizeof(*best_uv)); - memcpy(dst_y + w, dst_y, w * sizeof(*dst_y)); - } - - // Iterate and resolve clipping conflicts. - for (iter = 0; iter < kNumIterations; ++iter) { - int k; - const fixed_t* cur_uv = best_uv; - const fixed_t* prev_uv = best_uv; - const int old_diff_sum = diff_sum; - diff_sum = 0; - for (j = 0; j < h; j += 2) { - fixed_y_t* const src1 = tmp_buffer; - fixed_y_t* const src2 = tmp_buffer + 3 * w; - { - const fixed_t* const next_uv = cur_uv + ((j < h - 2) ? 3 * uv_w : 0); - InterpolateTwoRows(best_y + j * w, prev_uv, cur_uv, next_uv, - w, src1, src2); - prev_uv = cur_uv; - cur_uv = next_uv; - } - - UpdateW(src1, best_rgb_y + 0 * w, w); - UpdateW(src2, best_rgb_y + 1 * w, w); - diff_sum += UpdateChroma(src1, src2, best_rgb_uv, NULL, uv_w); - - // update two rows of Y and one row of RGB - for (i = 0; i < 2 * w; ++i) { - const int off = i + j * w; - const int diff_y = target_y[off] - best_rgb_y[i]; - const int new_y = (int)best_y[off] + diff_y; - best_y[off] = clip_y(new_y); - } - for (i = 0; i < uv_w; ++i) { - const int off = 3 * (i + (j >> 1) * uv_w); - int W; - for (k = 0; k <= 2; ++k) { - const int diff_uv = (int)target_uv[off + k] - best_rgb_uv[3 * i + k]; - best_uv[off + k] += diff_uv; - } - W = RGBToGray(best_uv[off + 0], best_uv[off + 1], best_uv[off + 2]); - for (k = 0; k <= 2; ++k) { - best_uv[off + k] -= W; - } - } - } - // test exit condition - if (diff_sum > 0) { - const int improvement = 100 * abs(diff_sum - old_diff_sum) / diff_sum; - // Check if first iteration gave good result already, without a large - // jump of improvement (otherwise it means we need to try few extra - // iterations, just to be sure). - if (iter == 0 && diff_sum < first_diff_threshold && - improvement < min_first_improvement) { - break; - } - // then, check if improvement is stalling. - if (improvement < min_improvement) { - break; - } - } else { - break; - } - } - - // final reconstruction - ok = ConvertWRGBToYUV(best_y, best_uv, picture); - - End: - WebPSafeFree(best_y); - WebPSafeFree(best_uv); - WebPSafeFree(target_y); - WebPSafeFree(target_uv); - WebPSafeFree(best_rgb_y); - WebPSafeFree(best_rgb_uv); - WebPSafeFree(tmp_buffer); - return ok; -} -#undef SAFE_ALLOC - -//------------------------------------------------------------------------------ -// "Fast" regular RGB->YUV - -#define SUM4(ptr, step) LinearToGamma( \ - GammaToLinear((ptr)[0]) + \ - GammaToLinear((ptr)[(step)]) + \ - GammaToLinear((ptr)[rgb_stride]) + \ - GammaToLinear((ptr)[rgb_stride + (step)]), 0) \ - -#define SUM2(ptr) \ - LinearToGamma(GammaToLinear((ptr)[0]) + GammaToLinear((ptr)[rgb_stride]), 1) - -#define SUM2ALPHA(ptr) ((ptr)[0] + (ptr)[rgb_stride]) -#define SUM4ALPHA(ptr) (SUM2ALPHA(ptr) + SUM2ALPHA((ptr) + 4)) - -#if defined(USE_INVERSE_ALPHA_TABLE) - -static const int kAlphaFix = 19; -// Following table is (1 << kAlphaFix) / a. The (v * kInvAlpha[a]) >> kAlphaFix -// formula is then equal to v / a in most (99.6%) cases. Note that this table -// and constant are adjusted very tightly to fit 32b arithmetic. -// In particular, they use the fact that the operands for 'v / a' are actually -// derived as v = (a0.p0 + a1.p1 + a2.p2 + a3.p3) and a = a0 + a1 + a2 + a3 -// with ai in [0..255] and pi in [0..1<> (kAlphaFix - 2)) - -#else - -#define DIVIDE_BY_ALPHA(sum, a) (4 * (sum) / (a)) - -#endif // USE_INVERSE_ALPHA_TABLE - -static WEBP_INLINE int LinearToGammaWeighted(const uint8_t* src, - const uint8_t* a_ptr, - uint32_t total_a, int step, - int rgb_stride) { - const uint32_t sum = - a_ptr[0] * GammaToLinear(src[0]) + - a_ptr[step] * GammaToLinear(src[step]) + - a_ptr[rgb_stride] * GammaToLinear(src[rgb_stride]) + - a_ptr[rgb_stride + step] * GammaToLinear(src[rgb_stride + step]); - assert(total_a > 0 && total_a <= 4 * 0xff); -#if defined(USE_INVERSE_ALPHA_TABLE) - assert((uint64_t)sum * kInvAlpha[total_a] < ((uint64_t)1 << 32)); -#endif - return LinearToGamma(DIVIDE_BY_ALPHA(sum, total_a), 0); -} - -static WEBP_INLINE void ConvertRowToY(const uint8_t* const r_ptr, - const uint8_t* const g_ptr, - const uint8_t* const b_ptr, - int step, - uint8_t* const dst_y, - int width, - VP8Random* const rg) { - int i, j; - for (i = 0, j = 0; i < width; i += 1, j += step) { - dst_y[i] = RGBToY(r_ptr[j], g_ptr[j], b_ptr[j], rg); - } -} - -static WEBP_INLINE void AccumulateRGBA(const uint8_t* const r_ptr, - const uint8_t* const g_ptr, - const uint8_t* const b_ptr, - const uint8_t* const a_ptr, - int rgb_stride, - uint16_t* dst, int width) { - int i, j; - // we loop over 2x2 blocks and produce one R/G/B/A value for each. - for (i = 0, j = 0; i < (width >> 1); i += 1, j += 2 * 4, dst += 4) { - const uint32_t a = SUM4ALPHA(a_ptr + j); - int r, g, b; - if (a == 4 * 0xff || a == 0) { - r = SUM4(r_ptr + j, 4); - g = SUM4(g_ptr + j, 4); - b = SUM4(b_ptr + j, 4); - } else { - r = LinearToGammaWeighted(r_ptr + j, a_ptr + j, a, 4, rgb_stride); - g = LinearToGammaWeighted(g_ptr + j, a_ptr + j, a, 4, rgb_stride); - b = LinearToGammaWeighted(b_ptr + j, a_ptr + j, a, 4, rgb_stride); - } - dst[0] = r; - dst[1] = g; - dst[2] = b; - dst[3] = a; - } - if (width & 1) { - const uint32_t a = 2u * SUM2ALPHA(a_ptr + j); - int r, g, b; - if (a == 4 * 0xff || a == 0) { - r = SUM2(r_ptr + j); - g = SUM2(g_ptr + j); - b = SUM2(b_ptr + j); - } else { - r = LinearToGammaWeighted(r_ptr + j, a_ptr + j, a, 0, rgb_stride); - g = LinearToGammaWeighted(g_ptr + j, a_ptr + j, a, 0, rgb_stride); - b = LinearToGammaWeighted(b_ptr + j, a_ptr + j, a, 0, rgb_stride); - } - dst[0] = r; - dst[1] = g; - dst[2] = b; - dst[3] = a; - } -} - -static WEBP_INLINE void AccumulateRGB(const uint8_t* const r_ptr, - const uint8_t* const g_ptr, - const uint8_t* const b_ptr, - int step, int rgb_stride, - uint16_t* dst, int width) { - int i, j; - for (i = 0, j = 0; i < (width >> 1); i += 1, j += 2 * step, dst += 4) { - dst[0] = SUM4(r_ptr + j, step); - dst[1] = SUM4(g_ptr + j, step); - dst[2] = SUM4(b_ptr + j, step); - } - if (width & 1) { - dst[0] = SUM2(r_ptr + j); - dst[1] = SUM2(g_ptr + j); - dst[2] = SUM2(b_ptr + j); - } -} - -static WEBP_INLINE void ConvertRowsToUV(const uint16_t* rgb, - uint8_t* const dst_u, - uint8_t* const dst_v, - int width, - VP8Random* const rg) { - int i; - for (i = 0; i < width; i += 1, rgb += 4) { - const int r = rgb[0], g = rgb[1], b = rgb[2]; - dst_u[i] = RGBToU(r, g, b, rg); - dst_v[i] = RGBToV(r, g, b, rg); - } -} - -static int ImportYUVAFromRGBA(const uint8_t* const r_ptr, - const uint8_t* const g_ptr, - const uint8_t* const b_ptr, - const uint8_t* const a_ptr, - int step, // bytes per pixel - int rgb_stride, // bytes per scanline - float dithering, - int use_iterative_conversion, - WebPPicture* const picture) { - int y; - const int width = picture->width; - const int height = picture->height; - const int has_alpha = CheckNonOpaque(a_ptr, width, height, step, rgb_stride); - const int is_rgb = (r_ptr < b_ptr); // otherwise it's bgr - - picture->colorspace = has_alpha ? WEBP_YUV420A : WEBP_YUV420; - picture->use_argb = 0; - - // disable smart conversion if source is too small (overkill). - if (width < kMinDimensionIterativeConversion || - height < kMinDimensionIterativeConversion) { - use_iterative_conversion = 0; - } - - if (!WebPPictureAllocYUVA(picture, width, height)) { - return 0; - } - if (has_alpha) { - WebPInitAlphaProcessing(); - assert(step == 4); -#if defined(USE_GAMMA_COMPRESSION) && defined(USE_INVERSE_ALPHA_TABLE) - assert(kAlphaFix + kGammaFix <= 31); -#endif - } - - if (use_iterative_conversion) { - InitGammaTablesF(); - if (!PreprocessARGB(r_ptr, g_ptr, b_ptr, step, rgb_stride, picture)) { - return 0; - } - if (has_alpha) { - WebPExtractAlpha(a_ptr, rgb_stride, width, height, - picture->a, picture->a_stride); - } - } else { - const int uv_width = (width + 1) >> 1; - int use_dsp = (step == 3); // use special function in this case - // temporary storage for accumulated R/G/B values during conversion to U/V - uint16_t* const tmp_rgb = - (uint16_t*)WebPSafeMalloc(4 * uv_width, sizeof(*tmp_rgb)); - uint8_t* dst_y = picture->y; - uint8_t* dst_u = picture->u; - uint8_t* dst_v = picture->v; - uint8_t* dst_a = picture->a; - - VP8Random base_rg; - VP8Random* rg = NULL; - if (dithering > 0.) { - VP8InitRandom(&base_rg, dithering); - rg = &base_rg; - use_dsp = 0; // can't use dsp in this case - } - WebPInitConvertARGBToYUV(); - InitGammaTables(); - - if (tmp_rgb == NULL) return 0; // malloc error - - // Downsample Y/U/V planes, two rows at a time - for (y = 0; y < (height >> 1); ++y) { - int rows_have_alpha = has_alpha; - const int off1 = (2 * y + 0) * rgb_stride; - const int off2 = (2 * y + 1) * rgb_stride; - if (use_dsp) { - if (is_rgb) { - WebPConvertRGB24ToY(r_ptr + off1, dst_y, width); - WebPConvertRGB24ToY(r_ptr + off2, dst_y + picture->y_stride, width); - } else { - WebPConvertBGR24ToY(b_ptr + off1, dst_y, width); - WebPConvertBGR24ToY(b_ptr + off2, dst_y + picture->y_stride, width); - } - } else { - ConvertRowToY(r_ptr + off1, g_ptr + off1, b_ptr + off1, step, - dst_y, width, rg); - ConvertRowToY(r_ptr + off2, g_ptr + off2, b_ptr + off2, step, - dst_y + picture->y_stride, width, rg); - } - dst_y += 2 * picture->y_stride; - if (has_alpha) { - rows_have_alpha &= !WebPExtractAlpha(a_ptr + off1, rgb_stride, - width, 2, - dst_a, picture->a_stride); - dst_a += 2 * picture->a_stride; - } - // Collect averaged R/G/B(/A) - if (!rows_have_alpha) { - AccumulateRGB(r_ptr + off1, g_ptr + off1, b_ptr + off1, - step, rgb_stride, tmp_rgb, width); - } else { - AccumulateRGBA(r_ptr + off1, g_ptr + off1, b_ptr + off1, a_ptr + off1, - rgb_stride, tmp_rgb, width); - } - // Convert to U/V - if (rg == NULL) { - WebPConvertRGBA32ToUV(tmp_rgb, dst_u, dst_v, uv_width); - } else { - ConvertRowsToUV(tmp_rgb, dst_u, dst_v, uv_width, rg); - } - dst_u += picture->uv_stride; - dst_v += picture->uv_stride; - } - if (height & 1) { // extra last row - const int off = 2 * y * rgb_stride; - int row_has_alpha = has_alpha; - if (use_dsp) { - if (r_ptr < b_ptr) { - WebPConvertRGB24ToY(r_ptr + off, dst_y, width); - } else { - WebPConvertBGR24ToY(b_ptr + off, dst_y, width); - } - } else { - ConvertRowToY(r_ptr + off, g_ptr + off, b_ptr + off, step, - dst_y, width, rg); - } - if (row_has_alpha) { - row_has_alpha &= !WebPExtractAlpha(a_ptr + off, 0, width, 1, dst_a, 0); - } - // Collect averaged R/G/B(/A) - if (!row_has_alpha) { - // Collect averaged R/G/B - AccumulateRGB(r_ptr + off, g_ptr + off, b_ptr + off, - step, /* rgb_stride = */ 0, tmp_rgb, width); - } else { - AccumulateRGBA(r_ptr + off, g_ptr + off, b_ptr + off, a_ptr + off, - /* rgb_stride = */ 0, tmp_rgb, width); - } - if (rg == NULL) { - WebPConvertRGBA32ToUV(tmp_rgb, dst_u, dst_v, uv_width); - } else { - ConvertRowsToUV(tmp_rgb, dst_u, dst_v, uv_width, rg); - } - } - WebPSafeFree(tmp_rgb); - } - return 1; -} - -#undef SUM4 -#undef SUM2 -#undef SUM4ALPHA -#undef SUM2ALPHA - -//------------------------------------------------------------------------------ -// call for ARGB->YUVA conversion - -static int PictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace, - float dithering, int use_iterative_conversion) { - if (picture == NULL) return 0; - if (picture->argb == NULL) { - return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER); - } else if ((colorspace & WEBP_CSP_UV_MASK) != WEBP_YUV420) { - return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION); - } else { - const uint8_t* const argb = (const uint8_t*)picture->argb; - const uint8_t* const r = ALPHA_IS_LAST ? argb + 2 : argb + 1; - const uint8_t* const g = ALPHA_IS_LAST ? argb + 1 : argb + 2; - const uint8_t* const b = ALPHA_IS_LAST ? argb + 0 : argb + 3; - const uint8_t* const a = ALPHA_IS_LAST ? argb + 3 : argb + 0; - - picture->colorspace = WEBP_YUV420; - return ImportYUVAFromRGBA(r, g, b, a, 4, 4 * picture->argb_stride, - dithering, use_iterative_conversion, picture); - } -} - -int WebPPictureARGBToYUVADithered(WebPPicture* picture, WebPEncCSP colorspace, - float dithering) { - return PictureARGBToYUVA(picture, colorspace, dithering, 0); -} - -int WebPPictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace) { - return PictureARGBToYUVA(picture, colorspace, 0.f, 0); -} - -int WebPPictureSmartARGBToYUVA(WebPPicture* picture) { - return PictureARGBToYUVA(picture, WEBP_YUV420, 0.f, 1); -} - -//------------------------------------------------------------------------------ -// call for YUVA -> ARGB conversion - -int WebPPictureYUVAToARGB(WebPPicture* picture) { - if (picture == NULL) return 0; - if (picture->y == NULL || picture->u == NULL || picture->v == NULL) { - return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER); - } - if ((picture->colorspace & WEBP_CSP_ALPHA_BIT) && picture->a == NULL) { - return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER); - } - if ((picture->colorspace & WEBP_CSP_UV_MASK) != WEBP_YUV420) { - return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION); - } - // Allocate a new argb buffer (discarding the previous one). - if (!WebPPictureAllocARGB(picture, picture->width, picture->height)) return 0; - picture->use_argb = 1; - - // Convert - { - int y; - const int width = picture->width; - const int height = picture->height; - const int argb_stride = 4 * picture->argb_stride; - uint8_t* dst = (uint8_t*)picture->argb; - const uint8_t *cur_u = picture->u, *cur_v = picture->v, *cur_y = picture->y; - WebPUpsampleLinePairFunc upsample = WebPGetLinePairConverter(ALPHA_IS_LAST); - - // First row, with replicated top samples. - upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width); - cur_y += picture->y_stride; - dst += argb_stride; - // Center rows. - for (y = 1; y + 1 < height; y += 2) { - const uint8_t* const top_u = cur_u; - const uint8_t* const top_v = cur_v; - cur_u += picture->uv_stride; - cur_v += picture->uv_stride; - upsample(cur_y, cur_y + picture->y_stride, top_u, top_v, cur_u, cur_v, - dst, dst + argb_stride, width); - cur_y += 2 * picture->y_stride; - dst += 2 * argb_stride; - } - // Last row (if needed), with replicated bottom samples. - if (height > 1 && !(height & 1)) { - upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width); - } - // Insert alpha values if needed, in replacement for the default 0xff ones. - if (picture->colorspace & WEBP_CSP_ALPHA_BIT) { - for (y = 0; y < height; ++y) { - uint32_t* const argb_dst = picture->argb + y * picture->argb_stride; - const uint8_t* const src = picture->a + y * picture->a_stride; - int x; - for (x = 0; x < width; ++x) { - argb_dst[x] = (argb_dst[x] & 0x00ffffffu) | ((uint32_t)src[x] << 24); - } - } - } - } - return 1; -} - -//------------------------------------------------------------------------------ -// automatic import / conversion - -static int Import(WebPPicture* const picture, - const uint8_t* const rgb, int rgb_stride, - int step, int swap_rb, int import_alpha) { - int y; - const uint8_t* const r_ptr = rgb + (swap_rb ? 2 : 0); - const uint8_t* const g_ptr = rgb + 1; - const uint8_t* const b_ptr = rgb + (swap_rb ? 0 : 2); - const uint8_t* const a_ptr = import_alpha ? rgb + 3 : NULL; - const int width = picture->width; - const int height = picture->height; - - if (!picture->use_argb) { - return ImportYUVAFromRGBA(r_ptr, g_ptr, b_ptr, a_ptr, step, rgb_stride, - 0.f /* no dithering */, 0, picture); - } - if (!WebPPictureAlloc(picture)) return 0; - - VP8EncDspARGBInit(); - - if (import_alpha) { - assert(step == 4); - for (y = 0; y < height; ++y) { - uint32_t* const dst = &picture->argb[y * picture->argb_stride]; - const int offset = y * rgb_stride; - VP8PackARGB(a_ptr + offset, r_ptr + offset, g_ptr + offset, - b_ptr + offset, width, dst); - } - } else { - assert(step >= 3); - for (y = 0; y < height; ++y) { - uint32_t* const dst = &picture->argb[y * picture->argb_stride]; - const int offset = y * rgb_stride; - VP8PackRGB(r_ptr + offset, g_ptr + offset, b_ptr + offset, - width, step, dst); - } - } - return 1; -} - -// Public API - -int WebPPictureImportRGB(WebPPicture* picture, - const uint8_t* rgb, int rgb_stride) { - return (picture != NULL) ? Import(picture, rgb, rgb_stride, 3, 0, 0) : 0; -} - -int WebPPictureImportBGR(WebPPicture* picture, - const uint8_t* rgb, int rgb_stride) { - return (picture != NULL) ? Import(picture, rgb, rgb_stride, 3, 1, 0) : 0; -} - -int WebPPictureImportRGBA(WebPPicture* picture, - const uint8_t* rgba, int rgba_stride) { - return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 0, 1) : 0; -} - -int WebPPictureImportBGRA(WebPPicture* picture, - const uint8_t* rgba, int rgba_stride) { - return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 1, 1) : 0; -} - -int WebPPictureImportRGBX(WebPPicture* picture, - const uint8_t* rgba, int rgba_stride) { - return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 0, 0) : 0; -} - -int WebPPictureImportBGRX(WebPPicture* picture, - const uint8_t* rgba, int rgba_stride) { - return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 1, 0) : 0; -} - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/enc/picture_psnr.c b/Example-Mac/Pods/libwebp/src/enc/picture_psnr.c deleted file mode 100644 index 40214efc..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/picture_psnr.c +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// WebPPicture tools for measuring distortion -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include - -#include "./vp8enci.h" -#include "../utils/utils.h" - -//------------------------------------------------------------------------------ -// local-min distortion -// -// For every pixel in the *reference* picture, we search for the local best -// match in the compressed image. This is not a symmetrical measure. - -#define RADIUS 2 // search radius. Shouldn't be too large. - -static void AccumulateLSIM(const uint8_t* src, int src_stride, - const uint8_t* ref, int ref_stride, - int w, int h, DistoStats* stats) { - int x, y; - double total_sse = 0.; - for (y = 0; y < h; ++y) { - const int y_0 = (y - RADIUS < 0) ? 0 : y - RADIUS; - const int y_1 = (y + RADIUS + 1 >= h) ? h : y + RADIUS + 1; - for (x = 0; x < w; ++x) { - const int x_0 = (x - RADIUS < 0) ? 0 : x - RADIUS; - const int x_1 = (x + RADIUS + 1 >= w) ? w : x + RADIUS + 1; - double best_sse = 255. * 255.; - const double value = (double)ref[y * ref_stride + x]; - int i, j; - for (j = y_0; j < y_1; ++j) { - const uint8_t* const s = src + j * src_stride; - for (i = x_0; i < x_1; ++i) { - const double diff = s[i] - value; - const double sse = diff * diff; - if (sse < best_sse) best_sse = sse; - } - } - total_sse += best_sse; - } - } - stats->w = w * h; - stats->xm = 0; - stats->ym = 0; - stats->xxm = total_sse; - stats->yym = 0; - stats->xxm = 0; -} -#undef RADIUS - -//------------------------------------------------------------------------------ -// Distortion - -// Max value returned in case of exact similarity. -static const double kMinDistortion_dB = 99.; -static float GetPSNR(const double v) { - return (float)((v > 0.) ? -4.3429448 * log(v / (255 * 255.)) - : kMinDistortion_dB); -} - -int WebPPictureDistortion(const WebPPicture* src, const WebPPicture* ref, - int type, float result[5]) { - DistoStats stats[5]; - int w, h; - - memset(stats, 0, sizeof(stats)); - - if (src == NULL || ref == NULL || - src->width != ref->width || src->height != ref->height || - src->use_argb != ref->use_argb || result == NULL) { - return 0; - } - w = src->width; - h = src->height; - - if (src->use_argb == 1) { - if (src->argb == NULL || ref->argb == NULL) { - return 0; - } else { - int i, j, c; - uint8_t* tmp1, *tmp2; - uint8_t* const tmp_plane = - (uint8_t*)WebPSafeMalloc(2ULL * w * h, sizeof(*tmp_plane)); - if (tmp_plane == NULL) return 0; - tmp1 = tmp_plane; - tmp2 = tmp_plane + w * h; - for (c = 0; c < 4; ++c) { - for (j = 0; j < h; ++j) { - for (i = 0; i < w; ++i) { - tmp1[j * w + i] = src->argb[i + j * src->argb_stride] >> (c * 8); - tmp2[j * w + i] = ref->argb[i + j * ref->argb_stride] >> (c * 8); - } - } - if (type >= 2) { - AccumulateLSIM(tmp1, w, tmp2, w, w, h, &stats[c]); - } else { - VP8SSIMAccumulatePlane(tmp1, w, tmp2, w, w, h, &stats[c]); - } - } - free(tmp_plane); - } - } else { - int has_alpha, uv_w, uv_h; - if (src->y == NULL || ref->y == NULL || - src->u == NULL || ref->u == NULL || - src->v == NULL || ref->v == NULL) { - return 0; - } - has_alpha = !!(src->colorspace & WEBP_CSP_ALPHA_BIT); - if (has_alpha != !!(ref->colorspace & WEBP_CSP_ALPHA_BIT) || - (has_alpha && (src->a == NULL || ref->a == NULL))) { - return 0; - } - - uv_w = (src->width + 1) >> 1; - uv_h = (src->height + 1) >> 1; - if (type >= 2) { - AccumulateLSIM(src->y, src->y_stride, ref->y, ref->y_stride, - w, h, &stats[0]); - AccumulateLSIM(src->u, src->uv_stride, ref->u, ref->uv_stride, - uv_w, uv_h, &stats[1]); - AccumulateLSIM(src->v, src->uv_stride, ref->v, ref->uv_stride, - uv_w, uv_h, &stats[2]); - if (has_alpha) { - AccumulateLSIM(src->a, src->a_stride, ref->a, ref->a_stride, - w, h, &stats[3]); - } - } else { - VP8SSIMAccumulatePlane(src->y, src->y_stride, - ref->y, ref->y_stride, - w, h, &stats[0]); - VP8SSIMAccumulatePlane(src->u, src->uv_stride, - ref->u, ref->uv_stride, - uv_w, uv_h, &stats[1]); - VP8SSIMAccumulatePlane(src->v, src->uv_stride, - ref->v, ref->uv_stride, - uv_w, uv_h, &stats[2]); - if (has_alpha) { - VP8SSIMAccumulatePlane(src->a, src->a_stride, - ref->a, ref->a_stride, - w, h, &stats[3]); - } - } - } - // Final stat calculations. - { - int c; - for (c = 0; c <= 4; ++c) { - if (type == 1) { - const double v = VP8SSIMGet(&stats[c]); - result[c] = (float)((v < 1.) ? -10.0 * log10(1. - v) - : kMinDistortion_dB); - } else { - const double v = VP8SSIMGetSquaredError(&stats[c]); - result[c] = GetPSNR(v); - } - // Accumulate forward - if (c < 4) VP8SSIMAddStats(&stats[c], &stats[4]); - } - } - return 1; -} - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/enc/picture_rescale.c b/Example-Mac/Pods/libwebp/src/enc/picture_rescale.c deleted file mode 100644 index 9f19e8e8..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/picture_rescale.c +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// WebPPicture tools: copy, crop, rescaling and view. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include - -#include "./vp8enci.h" -#include "../utils/rescaler.h" -#include "../utils/utils.h" - -#define HALVE(x) (((x) + 1) >> 1) - -// Grab the 'specs' (writer, *opaque, width, height...) from 'src' and copy them -// into 'dst'. Mark 'dst' as not owning any memory. -static void PictureGrabSpecs(const WebPPicture* const src, - WebPPicture* const dst) { - assert(src != NULL && dst != NULL); - *dst = *src; - WebPPictureResetBuffers(dst); -} - -//------------------------------------------------------------------------------ - -// Adjust top-left corner to chroma sample position. -static void SnapTopLeftPosition(const WebPPicture* const pic, - int* const left, int* const top) { - if (!pic->use_argb) { - *left &= ~1; - *top &= ~1; - } -} - -// Adjust top-left corner and verify that the sub-rectangle is valid. -static int AdjustAndCheckRectangle(const WebPPicture* const pic, - int* const left, int* const top, - int width, int height) { - SnapTopLeftPosition(pic, left, top); - if ((*left) < 0 || (*top) < 0) return 0; - if (width <= 0 || height <= 0) return 0; - if ((*left) + width > pic->width) return 0; - if ((*top) + height > pic->height) return 0; - return 1; -} - -int WebPPictureCopy(const WebPPicture* src, WebPPicture* dst) { - if (src == NULL || dst == NULL) return 0; - if (src == dst) return 1; - - PictureGrabSpecs(src, dst); - if (!WebPPictureAlloc(dst)) return 0; - - if (!src->use_argb) { - WebPCopyPlane(src->y, src->y_stride, - dst->y, dst->y_stride, dst->width, dst->height); - WebPCopyPlane(src->u, src->uv_stride, dst->u, dst->uv_stride, - HALVE(dst->width), HALVE(dst->height)); - WebPCopyPlane(src->v, src->uv_stride, dst->v, dst->uv_stride, - HALVE(dst->width), HALVE(dst->height)); - if (dst->a != NULL) { - WebPCopyPlane(src->a, src->a_stride, - dst->a, dst->a_stride, dst->width, dst->height); - } - } else { - WebPCopyPlane((const uint8_t*)src->argb, 4 * src->argb_stride, - (uint8_t*)dst->argb, 4 * dst->argb_stride, - 4 * dst->width, dst->height); - } - return 1; -} - -int WebPPictureIsView(const WebPPicture* picture) { - if (picture == NULL) return 0; - if (picture->use_argb) { - return (picture->memory_argb_ == NULL); - } - return (picture->memory_ == NULL); -} - -int WebPPictureView(const WebPPicture* src, - int left, int top, int width, int height, - WebPPicture* dst) { - if (src == NULL || dst == NULL) return 0; - - // verify rectangle position. - if (!AdjustAndCheckRectangle(src, &left, &top, width, height)) return 0; - - if (src != dst) { // beware of aliasing! We don't want to leak 'memory_'. - PictureGrabSpecs(src, dst); - } - dst->width = width; - dst->height = height; - if (!src->use_argb) { - dst->y = src->y + top * src->y_stride + left; - dst->u = src->u + (top >> 1) * src->uv_stride + (left >> 1); - dst->v = src->v + (top >> 1) * src->uv_stride + (left >> 1); - dst->y_stride = src->y_stride; - dst->uv_stride = src->uv_stride; - if (src->a != NULL) { - dst->a = src->a + top * src->a_stride + left; - dst->a_stride = src->a_stride; - } - } else { - dst->argb = src->argb + top * src->argb_stride + left; - dst->argb_stride = src->argb_stride; - } - return 1; -} - -//------------------------------------------------------------------------------ -// Picture cropping - -int WebPPictureCrop(WebPPicture* pic, - int left, int top, int width, int height) { - WebPPicture tmp; - - if (pic == NULL) return 0; - if (!AdjustAndCheckRectangle(pic, &left, &top, width, height)) return 0; - - PictureGrabSpecs(pic, &tmp); - tmp.width = width; - tmp.height = height; - if (!WebPPictureAlloc(&tmp)) return 0; - - if (!pic->use_argb) { - const int y_offset = top * pic->y_stride + left; - const int uv_offset = (top / 2) * pic->uv_stride + left / 2; - WebPCopyPlane(pic->y + y_offset, pic->y_stride, - tmp.y, tmp.y_stride, width, height); - WebPCopyPlane(pic->u + uv_offset, pic->uv_stride, - tmp.u, tmp.uv_stride, HALVE(width), HALVE(height)); - WebPCopyPlane(pic->v + uv_offset, pic->uv_stride, - tmp.v, tmp.uv_stride, HALVE(width), HALVE(height)); - - if (tmp.a != NULL) { - const int a_offset = top * pic->a_stride + left; - WebPCopyPlane(pic->a + a_offset, pic->a_stride, - tmp.a, tmp.a_stride, width, height); - } - } else { - const uint8_t* const src = - (const uint8_t*)(pic->argb + top * pic->argb_stride + left); - WebPCopyPlane(src, pic->argb_stride * 4, (uint8_t*)tmp.argb, - tmp.argb_stride * 4, width * 4, height); - } - WebPPictureFree(pic); - *pic = tmp; - return 1; -} - -//------------------------------------------------------------------------------ -// Simple picture rescaler - -static void RescalePlane(const uint8_t* src, - int src_width, int src_height, int src_stride, - uint8_t* dst, - int dst_width, int dst_height, int dst_stride, - rescaler_t* const work, - int num_channels) { - WebPRescaler rescaler; - int y = 0; - WebPRescalerInit(&rescaler, src_width, src_height, - dst, dst_width, dst_height, dst_stride, - num_channels, work); - while (y < src_height) { - y += WebPRescalerImport(&rescaler, src_height - y, - src + y * src_stride, src_stride); - WebPRescalerExport(&rescaler); - } -} - -static void AlphaMultiplyARGB(WebPPicture* const pic, int inverse) { - assert(pic->argb != NULL); - WebPMultARGBRows((uint8_t*)pic->argb, pic->argb_stride * sizeof(*pic->argb), - pic->width, pic->height, inverse); -} - -static void AlphaMultiplyY(WebPPicture* const pic, int inverse) { - if (pic->a != NULL) { - WebPMultRows(pic->y, pic->y_stride, pic->a, pic->a_stride, - pic->width, pic->height, inverse); - } -} - -int WebPPictureRescale(WebPPicture* pic, int width, int height) { - WebPPicture tmp; - int prev_width, prev_height; - rescaler_t* work; - - if (pic == NULL) return 0; - prev_width = pic->width; - prev_height = pic->height; - if (!WebPRescalerGetScaledDimensions( - prev_width, prev_height, &width, &height)) { - return 0; - } - - PictureGrabSpecs(pic, &tmp); - tmp.width = width; - tmp.height = height; - if (!WebPPictureAlloc(&tmp)) return 0; - - if (!pic->use_argb) { - work = (rescaler_t*)WebPSafeMalloc(2ULL * width, sizeof(*work)); - if (work == NULL) { - WebPPictureFree(&tmp); - return 0; - } - // If present, we need to rescale alpha first (for AlphaMultiplyY). - if (pic->a != NULL) { - WebPInitAlphaProcessing(); - RescalePlane(pic->a, prev_width, prev_height, pic->a_stride, - tmp.a, width, height, tmp.a_stride, work, 1); - } - - // We take transparency into account on the luma plane only. That's not - // totally exact blending, but still is a good approximation. - AlphaMultiplyY(pic, 0); - RescalePlane(pic->y, prev_width, prev_height, pic->y_stride, - tmp.y, width, height, tmp.y_stride, work, 1); - AlphaMultiplyY(&tmp, 1); - - RescalePlane(pic->u, - HALVE(prev_width), HALVE(prev_height), pic->uv_stride, - tmp.u, - HALVE(width), HALVE(height), tmp.uv_stride, work, 1); - RescalePlane(pic->v, - HALVE(prev_width), HALVE(prev_height), pic->uv_stride, - tmp.v, - HALVE(width), HALVE(height), tmp.uv_stride, work, 1); - } else { - work = (rescaler_t*)WebPSafeMalloc(2ULL * width * 4, sizeof(*work)); - if (work == NULL) { - WebPPictureFree(&tmp); - return 0; - } - // In order to correctly interpolate colors, we need to apply the alpha - // weighting first (black-matting), scale the RGB values, and remove - // the premultiplication afterward (while preserving the alpha channel). - WebPInitAlphaProcessing(); - AlphaMultiplyARGB(pic, 0); - RescalePlane((const uint8_t*)pic->argb, prev_width, prev_height, - pic->argb_stride * 4, - (uint8_t*)tmp.argb, width, height, - tmp.argb_stride * 4, - work, 4); - AlphaMultiplyARGB(&tmp, 1); - } - WebPPictureFree(pic); - WebPSafeFree(work); - *pic = tmp; - return 1; -} - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/enc/picture_tools.c b/Example-Mac/Pods/libwebp/src/enc/picture_tools.c deleted file mode 100644 index bf97af84..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/picture_tools.c +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// WebPPicture tools: alpha handling, etc. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include - -#include "./vp8enci.h" -#include "../dsp/yuv.h" - -static WEBP_INLINE uint32_t MakeARGB32(int r, int g, int b) { - return (0xff000000u | (r << 16) | (g << 8) | b); -} - -//------------------------------------------------------------------------------ -// Helper: clean up fully transparent area to help compressibility. - -#define SIZE 8 -#define SIZE2 (SIZE / 2) -static int is_transparent_area(const uint8_t* ptr, int stride, int size) { - int y, x; - for (y = 0; y < size; ++y) { - for (x = 0; x < size; ++x) { - if (ptr[x]) { - return 0; - } - } - ptr += stride; - } - return 1; -} - -static int is_transparent_argb_area(const uint32_t* ptr, int stride, int size) { - int y, x; - for (y = 0; y < size; ++y) { - for (x = 0; x < size; ++x) { - if (ptr[x] & 0xff000000u) { - return 0; - } - } - ptr += stride; - } - return 1; -} - -static void flatten(uint8_t* ptr, int v, int stride, int size) { - int y; - for (y = 0; y < size; ++y) { - memset(ptr, v, size); - ptr += stride; - } -} - -static void flatten_argb(uint32_t* ptr, uint32_t v, int stride, int size) { - int x, y; - for (y = 0; y < size; ++y) { - for (x = 0; x < size; ++x) ptr[x] = v; - ptr += stride; - } -} - -void WebPCleanupTransparentArea(WebPPicture* pic) { - int x, y, w, h; - if (pic == NULL) return; - w = pic->width / SIZE; - h = pic->height / SIZE; - - // note: we ignore the left-overs on right/bottom - if (pic->use_argb) { - uint32_t argb_value = 0; - for (y = 0; y < h; ++y) { - int need_reset = 1; - for (x = 0; x < w; ++x) { - const int off = (y * pic->argb_stride + x) * SIZE; - if (is_transparent_argb_area(pic->argb + off, pic->argb_stride, SIZE)) { - if (need_reset) { - argb_value = pic->argb[off]; - need_reset = 0; - } - flatten_argb(pic->argb + off, argb_value, pic->argb_stride, SIZE); - } else { - need_reset = 1; - } - } - } - } else { - const uint8_t* const a_ptr = pic->a; - int values[3] = { 0 }; - if (a_ptr == NULL) return; // nothing to do - for (y = 0; y < h; ++y) { - int need_reset = 1; - for (x = 0; x < w; ++x) { - const int off_a = (y * pic->a_stride + x) * SIZE; - const int off_y = (y * pic->y_stride + x) * SIZE; - const int off_uv = (y * pic->uv_stride + x) * SIZE2; - if (is_transparent_area(a_ptr + off_a, pic->a_stride, SIZE)) { - if (need_reset) { - values[0] = pic->y[off_y]; - values[1] = pic->u[off_uv]; - values[2] = pic->v[off_uv]; - need_reset = 0; - } - flatten(pic->y + off_y, values[0], pic->y_stride, SIZE); - flatten(pic->u + off_uv, values[1], pic->uv_stride, SIZE2); - flatten(pic->v + off_uv, values[2], pic->uv_stride, SIZE2); - } else { - need_reset = 1; - } - } - } - } -} - -#undef SIZE -#undef SIZE2 - -void WebPCleanupTransparentAreaLossless(WebPPicture* const pic) { - int x, y, w, h; - uint32_t* argb; - assert(pic != NULL && pic->use_argb); - w = pic->width; - h = pic->height; - argb = pic->argb; - - for (y = 0; y < h; ++y) { - for (x = 0; x < w; ++x) { - if ((argb[x] & 0xff000000) == 0) { - argb[x] = 0x00000000; - } - } - argb += pic->argb_stride; - } -} - -//------------------------------------------------------------------------------ -// Blend color and remove transparency info - -#define BLEND(V0, V1, ALPHA) \ - ((((V0) * (255 - (ALPHA)) + (V1) * (ALPHA)) * 0x101) >> 16) -#define BLEND_10BIT(V0, V1, ALPHA) \ - ((((V0) * (1020 - (ALPHA)) + (V1) * (ALPHA)) * 0x101) >> 18) - -void WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb) { - const int red = (background_rgb >> 16) & 0xff; - const int green = (background_rgb >> 8) & 0xff; - const int blue = (background_rgb >> 0) & 0xff; - int x, y; - if (pic == NULL) return; - if (!pic->use_argb) { - const int uv_width = (pic->width >> 1); // omit last pixel during u/v loop - const int Y0 = VP8RGBToY(red, green, blue, YUV_HALF); - // VP8RGBToU/V expects the u/v values summed over four pixels - const int U0 = VP8RGBToU(4 * red, 4 * green, 4 * blue, 4 * YUV_HALF); - const int V0 = VP8RGBToV(4 * red, 4 * green, 4 * blue, 4 * YUV_HALF); - const int has_alpha = pic->colorspace & WEBP_CSP_ALPHA_BIT; - if (!has_alpha || pic->a == NULL) return; // nothing to do - for (y = 0; y < pic->height; ++y) { - // Luma blending - uint8_t* const y_ptr = pic->y + y * pic->y_stride; - uint8_t* const a_ptr = pic->a + y * pic->a_stride; - for (x = 0; x < pic->width; ++x) { - const int alpha = a_ptr[x]; - if (alpha < 0xff) { - y_ptr[x] = BLEND(Y0, y_ptr[x], a_ptr[x]); - } - } - // Chroma blending every even line - if ((y & 1) == 0) { - uint8_t* const u = pic->u + (y >> 1) * pic->uv_stride; - uint8_t* const v = pic->v + (y >> 1) * pic->uv_stride; - uint8_t* const a_ptr2 = - (y + 1 == pic->height) ? a_ptr : a_ptr + pic->a_stride; - for (x = 0; x < uv_width; ++x) { - // Average four alpha values into a single blending weight. - // TODO(skal): might lead to visible contouring. Can we do better? - const int alpha = - a_ptr[2 * x + 0] + a_ptr[2 * x + 1] + - a_ptr2[2 * x + 0] + a_ptr2[2 * x + 1]; - u[x] = BLEND_10BIT(U0, u[x], alpha); - v[x] = BLEND_10BIT(V0, v[x], alpha); - } - if (pic->width & 1) { // rightmost pixel - const int alpha = 2 * (a_ptr[2 * x + 0] + a_ptr2[2 * x + 0]); - u[x] = BLEND_10BIT(U0, u[x], alpha); - v[x] = BLEND_10BIT(V0, v[x], alpha); - } - } - memset(a_ptr, 0xff, pic->width); - } - } else { - uint32_t* argb = pic->argb; - const uint32_t background = MakeARGB32(red, green, blue); - for (y = 0; y < pic->height; ++y) { - for (x = 0; x < pic->width; ++x) { - const int alpha = (argb[x] >> 24) & 0xff; - if (alpha != 0xff) { - if (alpha > 0) { - int r = (argb[x] >> 16) & 0xff; - int g = (argb[x] >> 8) & 0xff; - int b = (argb[x] >> 0) & 0xff; - r = BLEND(red, r, alpha); - g = BLEND(green, g, alpha); - b = BLEND(blue, b, alpha); - argb[x] = MakeARGB32(r, g, b); - } else { - argb[x] = background; - } - } - } - argb += pic->argb_stride; - } - } -} - -#undef BLEND -#undef BLEND_10BIT - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/enc/quant.c b/Example-Mac/Pods/libwebp/src/enc/quant.c deleted file mode 100644 index dd6885ab..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/quant.c +++ /dev/null @@ -1,1253 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Quantization -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include -#include // for abs() - -#include "./vp8enci.h" -#include "./cost.h" - -#define DO_TRELLIS_I4 1 -#define DO_TRELLIS_I16 1 // not a huge gain, but ok at low bitrate. -#define DO_TRELLIS_UV 0 // disable trellis for UV. Risky. Not worth. -#define USE_TDISTO 1 - -#define MID_ALPHA 64 // neutral value for susceptibility -#define MIN_ALPHA 30 // lowest usable value for susceptibility -#define MAX_ALPHA 100 // higher meaningful value for susceptibility - -#define SNS_TO_DQ 0.9 // Scaling constant between the sns value and the QP - // power-law modulation. Must be strictly less than 1. - -#define I4_PENALTY 14000 // Rate-penalty for quick i4/i16 decision - -// number of non-zero coeffs below which we consider the block very flat -// (and apply a penalty to complex predictions) -#define FLATNESS_LIMIT_I16 10 // I16 mode -#define FLATNESS_LIMIT_I4 3 // I4 mode -#define FLATNESS_LIMIT_UV 2 // UV mode -#define FLATNESS_PENALTY 140 // roughly ~1bit per block - -#define MULT_8B(a, b) (((a) * (b) + 128) >> 8) - -#define RD_DISTO_MULT 256 // distortion multiplier (equivalent of lambda) - -// #define DEBUG_BLOCK - -//------------------------------------------------------------------------------ - -#if defined(DEBUG_BLOCK) - -#include -#include - -static void PrintBlockInfo(const VP8EncIterator* const it, - const VP8ModeScore* const rd) { - int i, j; - const int is_i16 = (it->mb_->type_ == 1); - const uint8_t* const y_in = it->yuv_in_ + Y_OFF_ENC; - const uint8_t* const y_out = it->yuv_out_ + Y_OFF_ENC; - const uint8_t* const uv_in = it->yuv_in_ + U_OFF_ENC; - const uint8_t* const uv_out = it->yuv_out_ + U_OFF_ENC; - printf("SOURCE / OUTPUT / ABS DELTA\n"); - for (j = 0; j < 16; ++j) { - for (i = 0; i < 16; ++i) printf("%3d ", y_in[i + j * BPS]); - printf(" "); - for (i = 0; i < 16; ++i) printf("%3d ", y_out[i + j * BPS]); - printf(" "); - for (i = 0; i < 16; ++i) { - printf("%1d ", abs(y_in[i + j * BPS] - y_out[i + j * BPS])); - } - printf("\n"); - } - printf("\n"); // newline before the U/V block - for (j = 0; j < 8; ++j) { - for (i = 0; i < 8; ++i) printf("%3d ", uv_in[i + j * BPS]); - printf(" "); - for (i = 8; i < 16; ++i) printf("%3d ", uv_in[i + j * BPS]); - printf(" "); - for (i = 0; i < 8; ++i) printf("%3d ", uv_out[i + j * BPS]); - printf(" "); - for (i = 8; i < 16; ++i) printf("%3d ", uv_out[i + j * BPS]); - printf(" "); - for (i = 0; i < 8; ++i) { - printf("%1d ", abs(uv_out[i + j * BPS] - uv_in[i + j * BPS])); - } - printf(" "); - for (i = 8; i < 16; ++i) { - printf("%1d ", abs(uv_out[i + j * BPS] - uv_in[i + j * BPS])); - } - printf("\n"); - } - printf("\nD:%d SD:%d R:%d H:%d nz:0x%x score:%d\n", - (int)rd->D, (int)rd->SD, (int)rd->R, (int)rd->H, (int)rd->nz, - (int)rd->score); - if (is_i16) { - printf("Mode: %d\n", rd->mode_i16); - printf("y_dc_levels:"); - for (i = 0; i < 16; ++i) printf("%3d ", rd->y_dc_levels[i]); - printf("\n"); - } else { - printf("Modes[16]: "); - for (i = 0; i < 16; ++i) printf("%d ", rd->modes_i4[i]); - printf("\n"); - } - printf("y_ac_levels:\n"); - for (j = 0; j < 16; ++j) { - for (i = is_i16 ? 1 : 0; i < 16; ++i) { - printf("%4d ", rd->y_ac_levels[j][i]); - } - printf("\n"); - } - printf("\n"); - printf("uv_levels (mode=%d):\n", rd->mode_uv); - for (j = 0; j < 8; ++j) { - for (i = 0; i < 16; ++i) { - printf("%4d ", rd->uv_levels[j][i]); - } - printf("\n"); - } -} - -#endif // DEBUG_BLOCK - -//------------------------------------------------------------------------------ - -static WEBP_INLINE int clip(int v, int m, int M) { - return v < m ? m : v > M ? M : v; -} - -static const uint8_t kZigzag[16] = { - 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 -}; - -static const uint8_t kDcTable[128] = { - 4, 5, 6, 7, 8, 9, 10, 10, - 11, 12, 13, 14, 15, 16, 17, 17, - 18, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 25, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, - 37, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, - 91, 93, 95, 96, 98, 100, 101, 102, - 104, 106, 108, 110, 112, 114, 116, 118, - 122, 124, 126, 128, 130, 132, 134, 136, - 138, 140, 143, 145, 148, 151, 154, 157 -}; - -static const uint16_t kAcTable[128] = { - 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 60, - 62, 64, 66, 68, 70, 72, 74, 76, - 78, 80, 82, 84, 86, 88, 90, 92, - 94, 96, 98, 100, 102, 104, 106, 108, - 110, 112, 114, 116, 119, 122, 125, 128, - 131, 134, 137, 140, 143, 146, 149, 152, - 155, 158, 161, 164, 167, 170, 173, 177, - 181, 185, 189, 193, 197, 201, 205, 209, - 213, 217, 221, 225, 229, 234, 239, 245, - 249, 254, 259, 264, 269, 274, 279, 284 -}; - -static const uint16_t kAcTable2[128] = { - 8, 8, 9, 10, 12, 13, 15, 17, - 18, 20, 21, 23, 24, 26, 27, 29, - 31, 32, 34, 35, 37, 38, 40, 41, - 43, 44, 46, 48, 49, 51, 52, 54, - 55, 57, 58, 60, 62, 63, 65, 66, - 68, 69, 71, 72, 74, 75, 77, 79, - 80, 82, 83, 85, 86, 88, 89, 93, - 96, 99, 102, 105, 108, 111, 114, 117, - 120, 124, 127, 130, 133, 136, 139, 142, - 145, 148, 151, 155, 158, 161, 164, 167, - 170, 173, 176, 179, 184, 189, 193, 198, - 203, 207, 212, 217, 221, 226, 230, 235, - 240, 244, 249, 254, 258, 263, 268, 274, - 280, 286, 292, 299, 305, 311, 317, 323, - 330, 336, 342, 348, 354, 362, 370, 379, - 385, 393, 401, 409, 416, 424, 432, 440 -}; - -static const uint8_t kBiasMatrices[3][2] = { // [luma-ac,luma-dc,chroma][dc,ac] - { 96, 110 }, { 96, 108 }, { 110, 115 } -}; - -// Sharpening by (slightly) raising the hi-frequency coeffs. -// Hack-ish but helpful for mid-bitrate range. Use with care. -#define SHARPEN_BITS 11 // number of descaling bits for sharpening bias -static const uint8_t kFreqSharpening[16] = { - 0, 30, 60, 90, - 30, 60, 90, 90, - 60, 90, 90, 90, - 90, 90, 90, 90 -}; - -//------------------------------------------------------------------------------ -// Initialize quantization parameters in VP8Matrix - -// Returns the average quantizer -static int ExpandMatrix(VP8Matrix* const m, int type) { - int i, sum; - for (i = 0; i < 2; ++i) { - const int is_ac_coeff = (i > 0); - const int bias = kBiasMatrices[type][is_ac_coeff]; - m->iq_[i] = (1 << QFIX) / m->q_[i]; - m->bias_[i] = BIAS(bias); - // zthresh_ is the exact value such that QUANTDIV(coeff, iQ, B) is: - // * zero if coeff <= zthresh - // * non-zero if coeff > zthresh - m->zthresh_[i] = ((1 << QFIX) - 1 - m->bias_[i]) / m->iq_[i]; - } - for (i = 2; i < 16; ++i) { - m->q_[i] = m->q_[1]; - m->iq_[i] = m->iq_[1]; - m->bias_[i] = m->bias_[1]; - m->zthresh_[i] = m->zthresh_[1]; - } - for (sum = 0, i = 0; i < 16; ++i) { - if (type == 0) { // we only use sharpening for AC luma coeffs - m->sharpen_[i] = (kFreqSharpening[i] * m->q_[i]) >> SHARPEN_BITS; - } else { - m->sharpen_[i] = 0; - } - sum += m->q_[i]; - } - return (sum + 8) >> 4; -} - -static void SetupMatrices(VP8Encoder* enc) { - int i; - const int tlambda_scale = - (enc->method_ >= 4) ? enc->config_->sns_strength - : 0; - const int num_segments = enc->segment_hdr_.num_segments_; - for (i = 0; i < num_segments; ++i) { - VP8SegmentInfo* const m = &enc->dqm_[i]; - const int q = m->quant_; - int q4, q16, quv; - m->y1_.q_[0] = kDcTable[clip(q + enc->dq_y1_dc_, 0, 127)]; - m->y1_.q_[1] = kAcTable[clip(q, 0, 127)]; - - m->y2_.q_[0] = kDcTable[ clip(q + enc->dq_y2_dc_, 0, 127)] * 2; - m->y2_.q_[1] = kAcTable2[clip(q + enc->dq_y2_ac_, 0, 127)]; - - m->uv_.q_[0] = kDcTable[clip(q + enc->dq_uv_dc_, 0, 117)]; - m->uv_.q_[1] = kAcTable[clip(q + enc->dq_uv_ac_, 0, 127)]; - - q4 = ExpandMatrix(&m->y1_, 0); - q16 = ExpandMatrix(&m->y2_, 1); - quv = ExpandMatrix(&m->uv_, 2); - - m->lambda_i4_ = (3 * q4 * q4) >> 7; - m->lambda_i16_ = (3 * q16 * q16); - m->lambda_uv_ = (3 * quv * quv) >> 6; - m->lambda_mode_ = (1 * q4 * q4) >> 7; - m->lambda_trellis_i4_ = (7 * q4 * q4) >> 3; - m->lambda_trellis_i16_ = (q16 * q16) >> 2; - m->lambda_trellis_uv_ = (quv *quv) << 1; - m->tlambda_ = (tlambda_scale * q4) >> 5; - - m->min_disto_ = 10 * m->y1_.q_[0]; // quantization-aware min disto - m->max_edge_ = 0; - } -} - -//------------------------------------------------------------------------------ -// Initialize filtering parameters - -// Very small filter-strength values have close to no visual effect. So we can -// save a little decoding-CPU by turning filtering off for these. -#define FSTRENGTH_CUTOFF 2 - -static void SetupFilterStrength(VP8Encoder* const enc) { - int i; - // level0 is in [0..500]. Using '-f 50' as filter_strength is mid-filtering. - const int level0 = 5 * enc->config_->filter_strength; - for (i = 0; i < NUM_MB_SEGMENTS; ++i) { - VP8SegmentInfo* const m = &enc->dqm_[i]; - // We focus on the quantization of AC coeffs. - const int qstep = kAcTable[clip(m->quant_, 0, 127)] >> 2; - const int base_strength = - VP8FilterStrengthFromDelta(enc->filter_hdr_.sharpness_, qstep); - // Segments with lower complexity ('beta') will be less filtered. - const int f = base_strength * level0 / (256 + m->beta_); - m->fstrength_ = (f < FSTRENGTH_CUTOFF) ? 0 : (f > 63) ? 63 : f; - } - // We record the initial strength (mainly for the case of 1-segment only). - enc->filter_hdr_.level_ = enc->dqm_[0].fstrength_; - enc->filter_hdr_.simple_ = (enc->config_->filter_type == 0); - enc->filter_hdr_.sharpness_ = enc->config_->filter_sharpness; -} - -//------------------------------------------------------------------------------ - -// Note: if you change the values below, remember that the max range -// allowed by the syntax for DQ_UV is [-16,16]. -#define MAX_DQ_UV (6) -#define MIN_DQ_UV (-4) - -// We want to emulate jpeg-like behaviour where the expected "good" quality -// is around q=75. Internally, our "good" middle is around c=50. So we -// map accordingly using linear piece-wise function -static double QualityToCompression(double c) { - const double linear_c = (c < 0.75) ? c * (2. / 3.) : 2. * c - 1.; - // The file size roughly scales as pow(quantizer, 3.). Actually, the - // exponent is somewhere between 2.8 and 3.2, but we're mostly interested - // in the mid-quant range. So we scale the compressibility inversely to - // this power-law: quant ~= compression ^ 1/3. This law holds well for - // low quant. Finer modeling for high-quant would make use of kAcTable[] - // more explicitly. - const double v = pow(linear_c, 1 / 3.); - return v; -} - -static double QualityToJPEGCompression(double c, double alpha) { - // We map the complexity 'alpha' and quality setting 'c' to a compression - // exponent empirically matched to the compression curve of libjpeg6b. - // On average, the WebP output size will be roughly similar to that of a - // JPEG file compressed with same quality factor. - const double amin = 0.30; - const double amax = 0.85; - const double exp_min = 0.4; - const double exp_max = 0.9; - const double slope = (exp_min - exp_max) / (amax - amin); - // Linearly interpolate 'expn' from exp_min to exp_max - // in the [amin, amax] range. - const double expn = (alpha > amax) ? exp_min - : (alpha < amin) ? exp_max - : exp_max + slope * (alpha - amin); - const double v = pow(c, expn); - return v; -} - -static int SegmentsAreEquivalent(const VP8SegmentInfo* const S1, - const VP8SegmentInfo* const S2) { - return (S1->quant_ == S2->quant_) && (S1->fstrength_ == S2->fstrength_); -} - -static void SimplifySegments(VP8Encoder* const enc) { - int map[NUM_MB_SEGMENTS] = { 0, 1, 2, 3 }; - const int num_segments = enc->segment_hdr_.num_segments_; - int num_final_segments = 1; - int s1, s2; - for (s1 = 1; s1 < num_segments; ++s1) { // find similar segments - const VP8SegmentInfo* const S1 = &enc->dqm_[s1]; - int found = 0; - // check if we already have similar segment - for (s2 = 0; s2 < num_final_segments; ++s2) { - const VP8SegmentInfo* const S2 = &enc->dqm_[s2]; - if (SegmentsAreEquivalent(S1, S2)) { - found = 1; - break; - } - } - map[s1] = s2; - if (!found) { - if (num_final_segments != s1) { - enc->dqm_[num_final_segments] = enc->dqm_[s1]; - } - ++num_final_segments; - } - } - if (num_final_segments < num_segments) { // Remap - int i = enc->mb_w_ * enc->mb_h_; - while (i-- > 0) enc->mb_info_[i].segment_ = map[enc->mb_info_[i].segment_]; - enc->segment_hdr_.num_segments_ = num_final_segments; - // Replicate the trailing segment infos (it's mostly cosmetics) - for (i = num_final_segments; i < num_segments; ++i) { - enc->dqm_[i] = enc->dqm_[num_final_segments - 1]; - } - } -} - -void VP8SetSegmentParams(VP8Encoder* const enc, float quality) { - int i; - int dq_uv_ac, dq_uv_dc; - const int num_segments = enc->segment_hdr_.num_segments_; - const double amp = SNS_TO_DQ * enc->config_->sns_strength / 100. / 128.; - const double Q = quality / 100.; - const double c_base = enc->config_->emulate_jpeg_size ? - QualityToJPEGCompression(Q, enc->alpha_ / 255.) : - QualityToCompression(Q); - for (i = 0; i < num_segments; ++i) { - // We modulate the base coefficient to accommodate for the quantization - // susceptibility and allow denser segments to be quantized more. - const double expn = 1. - amp * enc->dqm_[i].alpha_; - const double c = pow(c_base, expn); - const int q = (int)(127. * (1. - c)); - assert(expn > 0.); - enc->dqm_[i].quant_ = clip(q, 0, 127); - } - - // purely indicative in the bitstream (except for the 1-segment case) - enc->base_quant_ = enc->dqm_[0].quant_; - - // fill-in values for the unused segments (required by the syntax) - for (i = num_segments; i < NUM_MB_SEGMENTS; ++i) { - enc->dqm_[i].quant_ = enc->base_quant_; - } - - // uv_alpha_ is normally spread around ~60. The useful range is - // typically ~30 (quite bad) to ~100 (ok to decimate UV more). - // We map it to the safe maximal range of MAX/MIN_DQ_UV for dq_uv. - dq_uv_ac = (enc->uv_alpha_ - MID_ALPHA) * (MAX_DQ_UV - MIN_DQ_UV) - / (MAX_ALPHA - MIN_ALPHA); - // we rescale by the user-defined strength of adaptation - dq_uv_ac = dq_uv_ac * enc->config_->sns_strength / 100; - // and make it safe. - dq_uv_ac = clip(dq_uv_ac, MIN_DQ_UV, MAX_DQ_UV); - // We also boost the dc-uv-quant a little, based on sns-strength, since - // U/V channels are quite more reactive to high quants (flat DC-blocks - // tend to appear, and are unpleasant). - dq_uv_dc = -4 * enc->config_->sns_strength / 100; - dq_uv_dc = clip(dq_uv_dc, -15, 15); // 4bit-signed max allowed - - enc->dq_y1_dc_ = 0; // TODO(skal): dq-lum - enc->dq_y2_dc_ = 0; - enc->dq_y2_ac_ = 0; - enc->dq_uv_dc_ = dq_uv_dc; - enc->dq_uv_ac_ = dq_uv_ac; - - SetupFilterStrength(enc); // initialize segments' filtering, eventually - - if (num_segments > 1) SimplifySegments(enc); - - SetupMatrices(enc); // finalize quantization matrices -} - -//------------------------------------------------------------------------------ -// Form the predictions in cache - -// Must be ordered using {DC_PRED, TM_PRED, V_PRED, H_PRED} as index -const int VP8I16ModeOffsets[4] = { I16DC16, I16TM16, I16VE16, I16HE16 }; -const int VP8UVModeOffsets[4] = { C8DC8, C8TM8, C8VE8, C8HE8 }; - -// Must be indexed using {B_DC_PRED -> B_HU_PRED} as index -const int VP8I4ModeOffsets[NUM_BMODES] = { - I4DC4, I4TM4, I4VE4, I4HE4, I4RD4, I4VR4, I4LD4, I4VL4, I4HD4, I4HU4 -}; - -void VP8MakeLuma16Preds(const VP8EncIterator* const it) { - const uint8_t* const left = it->x_ ? it->y_left_ : NULL; - const uint8_t* const top = it->y_ ? it->y_top_ : NULL; - VP8EncPredLuma16(it->yuv_p_, left, top); -} - -void VP8MakeChroma8Preds(const VP8EncIterator* const it) { - const uint8_t* const left = it->x_ ? it->u_left_ : NULL; - const uint8_t* const top = it->y_ ? it->uv_top_ : NULL; - VP8EncPredChroma8(it->yuv_p_, left, top); -} - -void VP8MakeIntra4Preds(const VP8EncIterator* const it) { - VP8EncPredLuma4(it->yuv_p_, it->i4_top_); -} - -//------------------------------------------------------------------------------ -// Quantize - -// Layout: -// +----+----+ -// |YYYY|UUVV| 0 -// |YYYY|UUVV| 4 -// |YYYY|....| 8 -// |YYYY|....| 12 -// +----+----+ - -const int VP8Scan[16] = { // Luma - 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS, - 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS, - 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS, - 0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS, -}; - -static const int VP8ScanUV[4 + 4] = { - 0 + 0 * BPS, 4 + 0 * BPS, 0 + 4 * BPS, 4 + 4 * BPS, // U - 8 + 0 * BPS, 12 + 0 * BPS, 8 + 4 * BPS, 12 + 4 * BPS // V -}; - -//------------------------------------------------------------------------------ -// Distortion measurement - -static const uint16_t kWeightY[16] = { - 38, 32, 20, 9, 32, 28, 17, 7, 20, 17, 10, 4, 9, 7, 4, 2 -}; - -static const uint16_t kWeightTrellis[16] = { -#if USE_TDISTO == 0 - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 -#else - 30, 27, 19, 11, - 27, 24, 17, 10, - 19, 17, 12, 8, - 11, 10, 8, 6 -#endif -}; - -// Init/Copy the common fields in score. -static void InitScore(VP8ModeScore* const rd) { - rd->D = 0; - rd->SD = 0; - rd->R = 0; - rd->H = 0; - rd->nz = 0; - rd->score = MAX_COST; -} - -static void CopyScore(VP8ModeScore* const dst, const VP8ModeScore* const src) { - dst->D = src->D; - dst->SD = src->SD; - dst->R = src->R; - dst->H = src->H; - dst->nz = src->nz; // note that nz is not accumulated, but just copied. - dst->score = src->score; -} - -static void AddScore(VP8ModeScore* const dst, const VP8ModeScore* const src) { - dst->D += src->D; - dst->SD += src->SD; - dst->R += src->R; - dst->H += src->H; - dst->nz |= src->nz; // here, new nz bits are accumulated. - dst->score += src->score; -} - -//------------------------------------------------------------------------------ -// Performs trellis-optimized quantization. - -// Trellis node -typedef struct { - int8_t prev; // best previous node - int8_t sign; // sign of coeff_i - int16_t level; // level -} Node; - -// Score state -typedef struct { - score_t score; // partial RD score - const uint16_t* costs; // shortcut to cost tables -} ScoreState; - -// If a coefficient was quantized to a value Q (using a neutral bias), -// we test all alternate possibilities between [Q-MIN_DELTA, Q+MAX_DELTA] -// We don't test negative values though. -#define MIN_DELTA 0 // how much lower level to try -#define MAX_DELTA 1 // how much higher -#define NUM_NODES (MIN_DELTA + 1 + MAX_DELTA) -#define NODE(n, l) (nodes[(n)][(l) + MIN_DELTA]) -#define SCORE_STATE(n, l) (score_states[n][(l) + MIN_DELTA]) - -static WEBP_INLINE void SetRDScore(int lambda, VP8ModeScore* const rd) { - rd->score = (rd->R + rd->H) * lambda + RD_DISTO_MULT * (rd->D + rd->SD); -} - -static WEBP_INLINE score_t RDScoreTrellis(int lambda, score_t rate, - score_t distortion) { - return rate * lambda + RD_DISTO_MULT * distortion; -} - -static int TrellisQuantizeBlock(const VP8Encoder* const enc, - int16_t in[16], int16_t out[16], - int ctx0, int coeff_type, - const VP8Matrix* const mtx, - int lambda) { - const ProbaArray* const probas = enc->proba_.coeffs_[coeff_type]; - CostArrayPtr const costs = - (CostArrayPtr)enc->proba_.remapped_costs_[coeff_type]; - const int first = (coeff_type == 0) ? 1 : 0; - Node nodes[16][NUM_NODES]; - ScoreState score_states[2][NUM_NODES]; - ScoreState* ss_cur = &SCORE_STATE(0, MIN_DELTA); - ScoreState* ss_prev = &SCORE_STATE(1, MIN_DELTA); - int best_path[3] = {-1, -1, -1}; // store best-last/best-level/best-previous - score_t best_score; - int n, m, p, last; - - { - score_t cost; - const int thresh = mtx->q_[1] * mtx->q_[1] / 4; - const int last_proba = probas[VP8EncBands[first]][ctx0][0]; - - // compute the position of the last interesting coefficient - last = first - 1; - for (n = 15; n >= first; --n) { - const int j = kZigzag[n]; - const int err = in[j] * in[j]; - if (err > thresh) { - last = n; - break; - } - } - // we don't need to go inspect up to n = 16 coeffs. We can just go up - // to last + 1 (inclusive) without losing much. - if (last < 15) ++last; - - // compute 'skip' score. This is the max score one can do. - cost = VP8BitCost(0, last_proba); - best_score = RDScoreTrellis(lambda, cost, 0); - - // initialize source node. - for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) { - const score_t rate = (ctx0 == 0) ? VP8BitCost(1, last_proba) : 0; - ss_cur[m].score = RDScoreTrellis(lambda, rate, 0); - ss_cur[m].costs = costs[first][ctx0]; - } - } - - // traverse trellis. - for (n = first; n <= last; ++n) { - const int j = kZigzag[n]; - const uint32_t Q = mtx->q_[j]; - const uint32_t iQ = mtx->iq_[j]; - const uint32_t B = BIAS(0x00); // neutral bias - // note: it's important to take sign of the _original_ coeff, - // so we don't have to consider level < 0 afterward. - const int sign = (in[j] < 0); - const uint32_t coeff0 = (sign ? -in[j] : in[j]) + mtx->sharpen_[j]; - int level0 = QUANTDIV(coeff0, iQ, B); - if (level0 > MAX_LEVEL) level0 = MAX_LEVEL; - - { // Swap current and previous score states - ScoreState* const tmp = ss_cur; - ss_cur = ss_prev; - ss_prev = tmp; - } - - // test all alternate level values around level0. - for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) { - Node* const cur = &NODE(n, m); - int level = level0 + m; - const int ctx = (level > 2) ? 2 : level; - const int band = VP8EncBands[n + 1]; - score_t base_score, last_pos_score; - score_t best_cur_score = MAX_COST; - int best_prev = 0; // default, in case - - ss_cur[m].score = MAX_COST; - ss_cur[m].costs = costs[n + 1][ctx]; - if (level > MAX_LEVEL || level < 0) { // node is dead? - continue; - } - - // Compute extra rate cost if last coeff's position is < 15 - { - const score_t last_pos_cost = - (n < 15) ? VP8BitCost(0, probas[band][ctx][0]) : 0; - last_pos_score = RDScoreTrellis(lambda, last_pos_cost, 0); - } - - { - // Compute delta_error = how much coding this level will - // subtract to max_error as distortion. - // Here, distortion = sum of (|coeff_i| - level_i * Q_i)^2 - const int new_error = coeff0 - level * Q; - const int delta_error = - kWeightTrellis[j] * (new_error * new_error - coeff0 * coeff0); - base_score = RDScoreTrellis(lambda, 0, delta_error); - } - - // Inspect all possible non-dead predecessors. Retain only the best one. - for (p = -MIN_DELTA; p <= MAX_DELTA; ++p) { - // Dead nodes (with ss_prev[p].score >= MAX_COST) are automatically - // eliminated since their score can't be better than the current best. - const score_t cost = VP8LevelCost(ss_prev[p].costs, level); - // Examine node assuming it's a non-terminal one. - const score_t score = - base_score + ss_prev[p].score + RDScoreTrellis(lambda, cost, 0); - if (score < best_cur_score) { - best_cur_score = score; - best_prev = p; - } - } - // Store best finding in current node. - cur->sign = sign; - cur->level = level; - cur->prev = best_prev; - ss_cur[m].score = best_cur_score; - - // Now, record best terminal node (and thus best entry in the graph). - if (level != 0) { - const score_t score = best_cur_score + last_pos_score; - if (score < best_score) { - best_score = score; - best_path[0] = n; // best eob position - best_path[1] = m; // best node index - best_path[2] = best_prev; // best predecessor - } - } - } - } - - // Fresh start - memset(in + first, 0, (16 - first) * sizeof(*in)); - memset(out + first, 0, (16 - first) * sizeof(*out)); - if (best_path[0] == -1) { - return 0; // skip! - } - - { - // Unwind the best path. - // Note: best-prev on terminal node is not necessarily equal to the - // best_prev for non-terminal. So we patch best_path[2] in. - int nz = 0; - int best_node = best_path[1]; - n = best_path[0]; - NODE(n, best_node).prev = best_path[2]; // force best-prev for terminal - - for (; n >= first; --n) { - const Node* const node = &NODE(n, best_node); - const int j = kZigzag[n]; - out[n] = node->sign ? -node->level : node->level; - nz |= node->level; - in[j] = out[n] * mtx->q_[j]; - best_node = node->prev; - } - return (nz != 0); - } -} - -#undef NODE - -//------------------------------------------------------------------------------ -// Performs: difference, transform, quantize, back-transform, add -// all at once. Output is the reconstructed block in *yuv_out, and the -// quantized levels in *levels. - -static int ReconstructIntra16(VP8EncIterator* const it, - VP8ModeScore* const rd, - uint8_t* const yuv_out, - int mode) { - const VP8Encoder* const enc = it->enc_; - const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode]; - const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC; - const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; - int nz = 0; - int n; - int16_t tmp[16][16], dc_tmp[16]; - - for (n = 0; n < 16; n += 2) { - VP8FTransform2(src + VP8Scan[n], ref + VP8Scan[n], tmp[n]); - } - VP8FTransformWHT(tmp[0], dc_tmp); - nz |= VP8EncQuantizeBlockWHT(dc_tmp, rd->y_dc_levels, &dqm->y2_) << 24; - - if (DO_TRELLIS_I16 && it->do_trellis_) { - int x, y; - VP8IteratorNzToBytes(it); - for (y = 0, n = 0; y < 4; ++y) { - for (x = 0; x < 4; ++x, ++n) { - const int ctx = it->top_nz_[x] + it->left_nz_[y]; - const int non_zero = - TrellisQuantizeBlock(enc, tmp[n], rd->y_ac_levels[n], ctx, 0, - &dqm->y1_, dqm->lambda_trellis_i16_); - it->top_nz_[x] = it->left_nz_[y] = non_zero; - rd->y_ac_levels[n][0] = 0; - nz |= non_zero << n; - } - } - } else { - for (n = 0; n < 16; n += 2) { - // Zero-out the first coeff, so that: a) nz is correct below, and - // b) finding 'last' non-zero coeffs in SetResidualCoeffs() is simplified. - tmp[n][0] = tmp[n + 1][0] = 0; - nz |= VP8EncQuantize2Blocks(tmp[n], rd->y_ac_levels[n], &dqm->y1_) << n; - assert(rd->y_ac_levels[n + 0][0] == 0); - assert(rd->y_ac_levels[n + 1][0] == 0); - } - } - - // Transform back - VP8TransformWHT(dc_tmp, tmp[0]); - for (n = 0; n < 16; n += 2) { - VP8ITransform(ref + VP8Scan[n], tmp[n], yuv_out + VP8Scan[n], 1); - } - - return nz; -} - -static int ReconstructIntra4(VP8EncIterator* const it, - int16_t levels[16], - const uint8_t* const src, - uint8_t* const yuv_out, - int mode) { - const VP8Encoder* const enc = it->enc_; - const uint8_t* const ref = it->yuv_p_ + VP8I4ModeOffsets[mode]; - const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; - int nz = 0; - int16_t tmp[16]; - - VP8FTransform(src, ref, tmp); - if (DO_TRELLIS_I4 && it->do_trellis_) { - const int x = it->i4_ & 3, y = it->i4_ >> 2; - const int ctx = it->top_nz_[x] + it->left_nz_[y]; - nz = TrellisQuantizeBlock(enc, tmp, levels, ctx, 3, &dqm->y1_, - dqm->lambda_trellis_i4_); - } else { - nz = VP8EncQuantizeBlock(tmp, levels, &dqm->y1_); - } - VP8ITransform(ref, tmp, yuv_out, 0); - return nz; -} - -static int ReconstructUV(VP8EncIterator* const it, VP8ModeScore* const rd, - uint8_t* const yuv_out, int mode) { - const VP8Encoder* const enc = it->enc_; - const uint8_t* const ref = it->yuv_p_ + VP8UVModeOffsets[mode]; - const uint8_t* const src = it->yuv_in_ + U_OFF_ENC; - const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; - int nz = 0; - int n; - int16_t tmp[8][16]; - - for (n = 0; n < 8; n += 2) { - VP8FTransform2(src + VP8ScanUV[n], ref + VP8ScanUV[n], tmp[n]); - } - if (DO_TRELLIS_UV && it->do_trellis_) { - int ch, x, y; - for (ch = 0, n = 0; ch <= 2; ch += 2) { - for (y = 0; y < 2; ++y) { - for (x = 0; x < 2; ++x, ++n) { - const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; - const int non_zero = - TrellisQuantizeBlock(enc, tmp[n], rd->uv_levels[n], ctx, 2, - &dqm->uv_, dqm->lambda_trellis_uv_); - it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = non_zero; - nz |= non_zero << n; - } - } - } - } else { - for (n = 0; n < 8; n += 2) { - nz |= VP8EncQuantize2Blocks(tmp[n], rd->uv_levels[n], &dqm->uv_) << n; - } - } - - for (n = 0; n < 8; n += 2) { - VP8ITransform(ref + VP8ScanUV[n], tmp[n], yuv_out + VP8ScanUV[n], 1); - } - return (nz << 16); -} - -//------------------------------------------------------------------------------ -// RD-opt decision. Reconstruct each modes, evalue distortion and bit-cost. -// Pick the mode is lower RD-cost = Rate + lambda * Distortion. - -static void StoreMaxDelta(VP8SegmentInfo* const dqm, const int16_t DCs[16]) { - // We look at the first three AC coefficients to determine what is the average - // delta between each sub-4x4 block. - const int v0 = abs(DCs[1]); - const int v1 = abs(DCs[4]); - const int v2 = abs(DCs[5]); - int max_v = (v0 > v1) ? v1 : v0; - max_v = (v2 > max_v) ? v2 : max_v; - if (max_v > dqm->max_edge_) dqm->max_edge_ = max_v; -} - -static void SwapModeScore(VP8ModeScore** a, VP8ModeScore** b) { - VP8ModeScore* const tmp = *a; - *a = *b; - *b = tmp; -} - -static void SwapPtr(uint8_t** a, uint8_t** b) { - uint8_t* const tmp = *a; - *a = *b; - *b = tmp; -} - -static void SwapOut(VP8EncIterator* const it) { - SwapPtr(&it->yuv_out_, &it->yuv_out2_); -} - -static score_t IsFlat(const int16_t* levels, int num_blocks, score_t thresh) { - score_t score = 0; - while (num_blocks-- > 0) { // TODO(skal): refine positional scoring? - int i; - for (i = 1; i < 16; ++i) { // omit DC, we're only interested in AC - score += (levels[i] != 0); - if (score > thresh) return 0; - } - levels += 16; - } - return 1; -} - -static void PickBestIntra16(VP8EncIterator* const it, VP8ModeScore* rd) { - const int kNumBlocks = 16; - VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_]; - const int lambda = dqm->lambda_i16_; - const int tlambda = dqm->tlambda_; - const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC; - VP8ModeScore rd_tmp; - VP8ModeScore* rd_cur = &rd_tmp; - VP8ModeScore* rd_best = rd; - int mode; - - rd->mode_i16 = -1; - for (mode = 0; mode < NUM_PRED_MODES; ++mode) { - uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF_ENC; // scratch buffer - rd_cur->mode_i16 = mode; - - // Reconstruct - rd_cur->nz = ReconstructIntra16(it, rd_cur, tmp_dst, mode); - - // Measure RD-score - rd_cur->D = VP8SSE16x16(src, tmp_dst); - rd_cur->SD = - tlambda ? MULT_8B(tlambda, VP8TDisto16x16(src, tmp_dst, kWeightY)) : 0; - rd_cur->H = VP8FixedCostsI16[mode]; - rd_cur->R = VP8GetCostLuma16(it, rd_cur); - if (mode > 0 && - IsFlat(rd_cur->y_ac_levels[0], kNumBlocks, FLATNESS_LIMIT_I16)) { - // penalty to avoid flat area to be mispredicted by complex mode - rd_cur->R += FLATNESS_PENALTY * kNumBlocks; - } - - // Since we always examine Intra16 first, we can overwrite *rd directly. - SetRDScore(lambda, rd_cur); - if (mode == 0 || rd_cur->score < rd_best->score) { - SwapModeScore(&rd_cur, &rd_best); - SwapOut(it); - } - } - if (rd_best != rd) { - memcpy(rd, rd_best, sizeof(*rd)); - } - SetRDScore(dqm->lambda_mode_, rd); // finalize score for mode decision. - VP8SetIntra16Mode(it, rd->mode_i16); - - // we have a blocky macroblock (only DCs are non-zero) with fairly high - // distortion, record max delta so we can later adjust the minimal filtering - // strength needed to smooth these blocks out. - if ((rd->nz & 0xffff) == 0 && rd->D > dqm->min_disto_) { - StoreMaxDelta(dqm, rd->y_dc_levels); - } -} - -//------------------------------------------------------------------------------ - -// return the cost array corresponding to the surrounding prediction modes. -static const uint16_t* GetCostModeI4(VP8EncIterator* const it, - const uint8_t modes[16]) { - const int preds_w = it->enc_->preds_w_; - const int x = (it->i4_ & 3), y = it->i4_ >> 2; - const int left = (x == 0) ? it->preds_[y * preds_w - 1] : modes[it->i4_ - 1]; - const int top = (y == 0) ? it->preds_[-preds_w + x] : modes[it->i4_ - 4]; - return VP8FixedCostsI4[top][left]; -} - -static int PickBestIntra4(VP8EncIterator* const it, VP8ModeScore* const rd) { - const VP8Encoder* const enc = it->enc_; - const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; - const int lambda = dqm->lambda_i4_; - const int tlambda = dqm->tlambda_; - const uint8_t* const src0 = it->yuv_in_ + Y_OFF_ENC; - uint8_t* const best_blocks = it->yuv_out2_ + Y_OFF_ENC; - int total_header_bits = 0; - VP8ModeScore rd_best; - - if (enc->max_i4_header_bits_ == 0) { - return 0; - } - - InitScore(&rd_best); - rd_best.H = 211; // '211' is the value of VP8BitCost(0, 145) - SetRDScore(dqm->lambda_mode_, &rd_best); - VP8IteratorStartI4(it); - do { - const int kNumBlocks = 1; - VP8ModeScore rd_i4; - int mode; - int best_mode = -1; - const uint8_t* const src = src0 + VP8Scan[it->i4_]; - const uint16_t* const mode_costs = GetCostModeI4(it, rd->modes_i4); - uint8_t* best_block = best_blocks + VP8Scan[it->i4_]; - uint8_t* tmp_dst = it->yuv_p_ + I4TMP; // scratch buffer. - - InitScore(&rd_i4); - VP8MakeIntra4Preds(it); - for (mode = 0; mode < NUM_BMODES; ++mode) { - VP8ModeScore rd_tmp; - int16_t tmp_levels[16]; - - // Reconstruct - rd_tmp.nz = - ReconstructIntra4(it, tmp_levels, src, tmp_dst, mode) << it->i4_; - - // Compute RD-score - rd_tmp.D = VP8SSE4x4(src, tmp_dst); - rd_tmp.SD = - tlambda ? MULT_8B(tlambda, VP8TDisto4x4(src, tmp_dst, kWeightY)) - : 0; - rd_tmp.H = mode_costs[mode]; - - // Add flatness penalty - if (mode > 0 && IsFlat(tmp_levels, kNumBlocks, FLATNESS_LIMIT_I4)) { - rd_tmp.R = FLATNESS_PENALTY * kNumBlocks; - } else { - rd_tmp.R = 0; - } - - // early-out check - SetRDScore(lambda, &rd_tmp); - if (best_mode >= 0 && rd_tmp.score >= rd_i4.score) continue; - - // finish computing score - rd_tmp.R += VP8GetCostLuma4(it, tmp_levels); - SetRDScore(lambda, &rd_tmp); - - if (best_mode < 0 || rd_tmp.score < rd_i4.score) { - CopyScore(&rd_i4, &rd_tmp); - best_mode = mode; - SwapPtr(&tmp_dst, &best_block); - memcpy(rd_best.y_ac_levels[it->i4_], tmp_levels, - sizeof(rd_best.y_ac_levels[it->i4_])); - } - } - SetRDScore(dqm->lambda_mode_, &rd_i4); - AddScore(&rd_best, &rd_i4); - if (rd_best.score >= rd->score) { - return 0; - } - total_header_bits += (int)rd_i4.H; // <- equal to mode_costs[best_mode]; - if (total_header_bits > enc->max_i4_header_bits_) { - return 0; - } - // Copy selected samples if not in the right place already. - if (best_block != best_blocks + VP8Scan[it->i4_]) { - VP8Copy4x4(best_block, best_blocks + VP8Scan[it->i4_]); - } - rd->modes_i4[it->i4_] = best_mode; - it->top_nz_[it->i4_ & 3] = it->left_nz_[it->i4_ >> 2] = (rd_i4.nz ? 1 : 0); - } while (VP8IteratorRotateI4(it, best_blocks)); - - // finalize state - CopyScore(rd, &rd_best); - VP8SetIntra4Mode(it, rd->modes_i4); - SwapOut(it); - memcpy(rd->y_ac_levels, rd_best.y_ac_levels, sizeof(rd->y_ac_levels)); - return 1; // select intra4x4 over intra16x16 -} - -//------------------------------------------------------------------------------ - -static void PickBestUV(VP8EncIterator* const it, VP8ModeScore* const rd) { - const int kNumBlocks = 8; - const VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_]; - const int lambda = dqm->lambda_uv_; - const uint8_t* const src = it->yuv_in_ + U_OFF_ENC; - uint8_t* tmp_dst = it->yuv_out2_ + U_OFF_ENC; // scratch buffer - uint8_t* dst0 = it->yuv_out_ + U_OFF_ENC; - uint8_t* dst = dst0; - VP8ModeScore rd_best; - int mode; - - rd->mode_uv = -1; - InitScore(&rd_best); - for (mode = 0; mode < NUM_PRED_MODES; ++mode) { - VP8ModeScore rd_uv; - - // Reconstruct - rd_uv.nz = ReconstructUV(it, &rd_uv, tmp_dst, mode); - - // Compute RD-score - rd_uv.D = VP8SSE16x8(src, tmp_dst); - rd_uv.SD = 0; // not calling TDisto here: it tends to flatten areas. - rd_uv.H = VP8FixedCostsUV[mode]; - rd_uv.R = VP8GetCostUV(it, &rd_uv); - if (mode > 0 && IsFlat(rd_uv.uv_levels[0], kNumBlocks, FLATNESS_LIMIT_UV)) { - rd_uv.R += FLATNESS_PENALTY * kNumBlocks; - } - - SetRDScore(lambda, &rd_uv); - if (mode == 0 || rd_uv.score < rd_best.score) { - CopyScore(&rd_best, &rd_uv); - rd->mode_uv = mode; - memcpy(rd->uv_levels, rd_uv.uv_levels, sizeof(rd->uv_levels)); - SwapPtr(&dst, &tmp_dst); - } - } - VP8SetIntraUVMode(it, rd->mode_uv); - AddScore(rd, &rd_best); - if (dst != dst0) { // copy 16x8 block if needed - VP8Copy16x8(dst, dst0); - } -} - -//------------------------------------------------------------------------------ -// Final reconstruction and quantization. - -static void SimpleQuantize(VP8EncIterator* const it, VP8ModeScore* const rd) { - const VP8Encoder* const enc = it->enc_; - const int is_i16 = (it->mb_->type_ == 1); - int nz = 0; - - if (is_i16) { - nz = ReconstructIntra16(it, rd, it->yuv_out_ + Y_OFF_ENC, it->preds_[0]); - } else { - VP8IteratorStartI4(it); - do { - const int mode = - it->preds_[(it->i4_ & 3) + (it->i4_ >> 2) * enc->preds_w_]; - const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_]; - uint8_t* const dst = it->yuv_out_ + Y_OFF_ENC + VP8Scan[it->i4_]; - VP8MakeIntra4Preds(it); - nz |= ReconstructIntra4(it, rd->y_ac_levels[it->i4_], - src, dst, mode) << it->i4_; - } while (VP8IteratorRotateI4(it, it->yuv_out_ + Y_OFF_ENC)); - } - - nz |= ReconstructUV(it, rd, it->yuv_out_ + U_OFF_ENC, it->mb_->uv_mode_); - rd->nz = nz; -} - -// Refine intra16/intra4 sub-modes based on distortion only (not rate). -static void RefineUsingDistortion(VP8EncIterator* const it, - int try_both_modes, int refine_uv_mode, - VP8ModeScore* const rd) { - score_t best_score = MAX_COST; - score_t score_i4 = (score_t)I4_PENALTY; - int16_t tmp_levels[16][16]; - uint8_t modes_i4[16]; - int nz = 0; - int mode; - int is_i16 = try_both_modes || (it->mb_->type_ == 1); - - if (is_i16) { // First, evaluate Intra16 distortion - int best_mode = -1; - const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC; - for (mode = 0; mode < NUM_PRED_MODES; ++mode) { - const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode]; - const score_t score = VP8SSE16x16(src, ref); - if (score < best_score) { - best_mode = mode; - best_score = score; - } - } - VP8SetIntra16Mode(it, best_mode); - // we'll reconstruct later, if i16 mode actually gets selected - } - - // Next, evaluate Intra4 - if (try_both_modes || !is_i16) { - // We don't evaluate the rate here, but just account for it through a - // constant penalty (i4 mode usually needs more bits compared to i16). - is_i16 = 0; - VP8IteratorStartI4(it); - do { - int best_i4_mode = -1; - score_t best_i4_score = MAX_COST; - const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_]; - - VP8MakeIntra4Preds(it); - for (mode = 0; mode < NUM_BMODES; ++mode) { - const uint8_t* const ref = it->yuv_p_ + VP8I4ModeOffsets[mode]; - const score_t score = VP8SSE4x4(src, ref); - if (score < best_i4_score) { - best_i4_mode = mode; - best_i4_score = score; - } - } - modes_i4[it->i4_] = best_i4_mode; - score_i4 += best_i4_score; - if (score_i4 >= best_score) { - // Intra4 won't be better than Intra16. Bail out and pick Intra16. - is_i16 = 1; - break; - } else { // reconstruct partial block inside yuv_out2_ buffer - uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF_ENC + VP8Scan[it->i4_]; - nz |= ReconstructIntra4(it, tmp_levels[it->i4_], - src, tmp_dst, best_i4_mode) << it->i4_; - } - } while (VP8IteratorRotateI4(it, it->yuv_out2_ + Y_OFF_ENC)); - } - - // Final reconstruction, depending on which mode is selected. - if (!is_i16) { - VP8SetIntra4Mode(it, modes_i4); - memcpy(rd->y_ac_levels, tmp_levels, sizeof(tmp_levels)); - SwapOut(it); - best_score = score_i4; - } else { - nz = ReconstructIntra16(it, rd, it->yuv_out_ + Y_OFF_ENC, it->preds_[0]); - } - - // ... and UV! - if (refine_uv_mode) { - int best_mode = -1; - score_t best_uv_score = MAX_COST; - const uint8_t* const src = it->yuv_in_ + U_OFF_ENC; - for (mode = 0; mode < NUM_PRED_MODES; ++mode) { - const uint8_t* const ref = it->yuv_p_ + VP8UVModeOffsets[mode]; - const score_t score = VP8SSE16x8(src, ref); - if (score < best_uv_score) { - best_mode = mode; - best_uv_score = score; - } - } - VP8SetIntraUVMode(it, best_mode); - } - nz |= ReconstructUV(it, rd, it->yuv_out_ + U_OFF_ENC, it->mb_->uv_mode_); - - rd->nz = nz; - rd->score = best_score; -} - -//------------------------------------------------------------------------------ -// Entry point - -int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, - VP8RDLevel rd_opt) { - int is_skipped; - const int method = it->enc_->method_; - - InitScore(rd); - - // We can perform predictions for Luma16x16 and Chroma8x8 already. - // Luma4x4 predictions needs to be done as-we-go. - VP8MakeLuma16Preds(it); - VP8MakeChroma8Preds(it); - - if (rd_opt > RD_OPT_NONE) { - it->do_trellis_ = (rd_opt >= RD_OPT_TRELLIS_ALL); - PickBestIntra16(it, rd); - if (method >= 2) { - PickBestIntra4(it, rd); - } - PickBestUV(it, rd); - if (rd_opt == RD_OPT_TRELLIS) { // finish off with trellis-optim now - it->do_trellis_ = 1; - SimpleQuantize(it, rd); - } - } else { - // At this point we have heuristically decided intra16 / intra4. - // For method >= 2, pick the best intra4/intra16 based on SSE (~tad slower). - // For method <= 1, we don't re-examine the decision but just go ahead with - // quantization/reconstruction. - RefineUsingDistortion(it, (method >= 2), (method >= 1), rd); - } - is_skipped = (rd->nz == 0); - VP8SetSkip(it, is_skipped); - return is_skipped; -} diff --git a/Example-Mac/Pods/libwebp/src/enc/syntax.c b/Example-Mac/Pods/libwebp/src/enc/syntax.c deleted file mode 100644 index a0e79ef4..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/syntax.c +++ /dev/null @@ -1,383 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Header syntax writing -// -// Author: Skal (pascal.massimino@gmail.com) - -#include - -#include "../utils/utils.h" -#include "../webp/format_constants.h" // RIFF constants -#include "../webp/mux_types.h" // ALPHA_FLAG -#include "./vp8enci.h" - -//------------------------------------------------------------------------------ -// Helper functions - -static int IsVP8XNeeded(const VP8Encoder* const enc) { - return !!enc->has_alpha_; // Currently the only case when VP8X is needed. - // This could change in the future. -} - -static int PutPaddingByte(const WebPPicture* const pic) { - const uint8_t pad_byte[1] = { 0 }; - return !!pic->writer(pad_byte, 1, pic); -} - -//------------------------------------------------------------------------------ -// Writers for header's various pieces (in order of appearance) - -static WebPEncodingError PutRIFFHeader(const VP8Encoder* const enc, - size_t riff_size) { - const WebPPicture* const pic = enc->pic_; - uint8_t riff[RIFF_HEADER_SIZE] = { - 'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P' - }; - assert(riff_size == (uint32_t)riff_size); - PutLE32(riff + TAG_SIZE, (uint32_t)riff_size); - if (!pic->writer(riff, sizeof(riff), pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - return VP8_ENC_OK; -} - -static WebPEncodingError PutVP8XHeader(const VP8Encoder* const enc) { - const WebPPicture* const pic = enc->pic_; - uint8_t vp8x[CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE] = { - 'V', 'P', '8', 'X' - }; - uint32_t flags = 0; - - assert(IsVP8XNeeded(enc)); - assert(pic->width >= 1 && pic->height >= 1); - assert(pic->width <= MAX_CANVAS_SIZE && pic->height <= MAX_CANVAS_SIZE); - - if (enc->has_alpha_) { - flags |= ALPHA_FLAG; - } - - PutLE32(vp8x + TAG_SIZE, VP8X_CHUNK_SIZE); - PutLE32(vp8x + CHUNK_HEADER_SIZE, flags); - PutLE24(vp8x + CHUNK_HEADER_SIZE + 4, pic->width - 1); - PutLE24(vp8x + CHUNK_HEADER_SIZE + 7, pic->height - 1); - if (!pic->writer(vp8x, sizeof(vp8x), pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - return VP8_ENC_OK; -} - -static WebPEncodingError PutAlphaChunk(const VP8Encoder* const enc) { - const WebPPicture* const pic = enc->pic_; - uint8_t alpha_chunk_hdr[CHUNK_HEADER_SIZE] = { - 'A', 'L', 'P', 'H' - }; - - assert(enc->has_alpha_); - - // Alpha chunk header. - PutLE32(alpha_chunk_hdr + TAG_SIZE, enc->alpha_data_size_); - if (!pic->writer(alpha_chunk_hdr, sizeof(alpha_chunk_hdr), pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - - // Alpha chunk data. - if (!pic->writer(enc->alpha_data_, enc->alpha_data_size_, pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - - // Padding. - if ((enc->alpha_data_size_ & 1) && !PutPaddingByte(pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - return VP8_ENC_OK; -} - -static WebPEncodingError PutVP8Header(const WebPPicture* const pic, - size_t vp8_size) { - uint8_t vp8_chunk_hdr[CHUNK_HEADER_SIZE] = { - 'V', 'P', '8', ' ' - }; - assert(vp8_size == (uint32_t)vp8_size); - PutLE32(vp8_chunk_hdr + TAG_SIZE, (uint32_t)vp8_size); - if (!pic->writer(vp8_chunk_hdr, sizeof(vp8_chunk_hdr), pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - return VP8_ENC_OK; -} - -static WebPEncodingError PutVP8FrameHeader(const WebPPicture* const pic, - int profile, size_t size0) { - uint8_t vp8_frm_hdr[VP8_FRAME_HEADER_SIZE]; - uint32_t bits; - - if (size0 >= VP8_MAX_PARTITION0_SIZE) { // partition #0 is too big to fit - return VP8_ENC_ERROR_PARTITION0_OVERFLOW; - } - - // Paragraph 9.1. - bits = 0 // keyframe (1b) - | (profile << 1) // profile (3b) - | (1 << 4) // visible (1b) - | ((uint32_t)size0 << 5); // partition length (19b) - vp8_frm_hdr[0] = (bits >> 0) & 0xff; - vp8_frm_hdr[1] = (bits >> 8) & 0xff; - vp8_frm_hdr[2] = (bits >> 16) & 0xff; - // signature - vp8_frm_hdr[3] = (VP8_SIGNATURE >> 16) & 0xff; - vp8_frm_hdr[4] = (VP8_SIGNATURE >> 8) & 0xff; - vp8_frm_hdr[5] = (VP8_SIGNATURE >> 0) & 0xff; - // dimensions - vp8_frm_hdr[6] = pic->width & 0xff; - vp8_frm_hdr[7] = pic->width >> 8; - vp8_frm_hdr[8] = pic->height & 0xff; - vp8_frm_hdr[9] = pic->height >> 8; - - if (!pic->writer(vp8_frm_hdr, sizeof(vp8_frm_hdr), pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - return VP8_ENC_OK; -} - -// WebP Headers. -static int PutWebPHeaders(const VP8Encoder* const enc, size_t size0, - size_t vp8_size, size_t riff_size) { - WebPPicture* const pic = enc->pic_; - WebPEncodingError err = VP8_ENC_OK; - - // RIFF header. - err = PutRIFFHeader(enc, riff_size); - if (err != VP8_ENC_OK) goto Error; - - // VP8X. - if (IsVP8XNeeded(enc)) { - err = PutVP8XHeader(enc); - if (err != VP8_ENC_OK) goto Error; - } - - // Alpha. - if (enc->has_alpha_) { - err = PutAlphaChunk(enc); - if (err != VP8_ENC_OK) goto Error; - } - - // VP8 header. - err = PutVP8Header(pic, vp8_size); - if (err != VP8_ENC_OK) goto Error; - - // VP8 frame header. - err = PutVP8FrameHeader(pic, enc->profile_, size0); - if (err != VP8_ENC_OK) goto Error; - - // All OK. - return 1; - - // Error. - Error: - return WebPEncodingSetError(pic, err); -} - -// Segmentation header -static void PutSegmentHeader(VP8BitWriter* const bw, - const VP8Encoder* const enc) { - const VP8EncSegmentHeader* const hdr = &enc->segment_hdr_; - const VP8EncProba* const proba = &enc->proba_; - if (VP8PutBitUniform(bw, (hdr->num_segments_ > 1))) { - // We always 'update' the quant and filter strength values - const int update_data = 1; - int s; - VP8PutBitUniform(bw, hdr->update_map_); - if (VP8PutBitUniform(bw, update_data)) { - // we always use absolute values, not relative ones - VP8PutBitUniform(bw, 1); // (segment_feature_mode = 1. Paragraph 9.3.) - for (s = 0; s < NUM_MB_SEGMENTS; ++s) { - VP8PutSignedBits(bw, enc->dqm_[s].quant_, 7); - } - for (s = 0; s < NUM_MB_SEGMENTS; ++s) { - VP8PutSignedBits(bw, enc->dqm_[s].fstrength_, 6); - } - } - if (hdr->update_map_) { - for (s = 0; s < 3; ++s) { - if (VP8PutBitUniform(bw, (proba->segments_[s] != 255u))) { - VP8PutBits(bw, proba->segments_[s], 8); - } - } - } - } -} - -// Filtering parameters header -static void PutFilterHeader(VP8BitWriter* const bw, - const VP8EncFilterHeader* const hdr) { - const int use_lf_delta = (hdr->i4x4_lf_delta_ != 0); - VP8PutBitUniform(bw, hdr->simple_); - VP8PutBits(bw, hdr->level_, 6); - VP8PutBits(bw, hdr->sharpness_, 3); - if (VP8PutBitUniform(bw, use_lf_delta)) { - // '0' is the default value for i4x4_lf_delta_ at frame #0. - const int need_update = (hdr->i4x4_lf_delta_ != 0); - if (VP8PutBitUniform(bw, need_update)) { - // we don't use ref_lf_delta => emit four 0 bits - VP8PutBits(bw, 0, 4); - // we use mode_lf_delta for i4x4 - VP8PutSignedBits(bw, hdr->i4x4_lf_delta_, 6); - VP8PutBits(bw, 0, 3); // all others unused - } - } -} - -// Nominal quantization parameters -static void PutQuant(VP8BitWriter* const bw, - const VP8Encoder* const enc) { - VP8PutBits(bw, enc->base_quant_, 7); - VP8PutSignedBits(bw, enc->dq_y1_dc_, 4); - VP8PutSignedBits(bw, enc->dq_y2_dc_, 4); - VP8PutSignedBits(bw, enc->dq_y2_ac_, 4); - VP8PutSignedBits(bw, enc->dq_uv_dc_, 4); - VP8PutSignedBits(bw, enc->dq_uv_ac_, 4); -} - -// Partition sizes -static int EmitPartitionsSize(const VP8Encoder* const enc, - WebPPicture* const pic) { - uint8_t buf[3 * (MAX_NUM_PARTITIONS - 1)]; - int p; - for (p = 0; p < enc->num_parts_ - 1; ++p) { - const size_t part_size = VP8BitWriterSize(enc->parts_ + p); - if (part_size >= VP8_MAX_PARTITION_SIZE) { - return WebPEncodingSetError(pic, VP8_ENC_ERROR_PARTITION_OVERFLOW); - } - buf[3 * p + 0] = (part_size >> 0) & 0xff; - buf[3 * p + 1] = (part_size >> 8) & 0xff; - buf[3 * p + 2] = (part_size >> 16) & 0xff; - } - return p ? pic->writer(buf, 3 * p, pic) : 1; -} - -//------------------------------------------------------------------------------ - -static int GeneratePartition0(VP8Encoder* const enc) { - VP8BitWriter* const bw = &enc->bw_; - const int mb_size = enc->mb_w_ * enc->mb_h_; - uint64_t pos1, pos2, pos3; - - pos1 = VP8BitWriterPos(bw); - if (!VP8BitWriterInit(bw, mb_size * 7 / 8)) { // ~7 bits per macroblock - return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); - } - VP8PutBitUniform(bw, 0); // colorspace - VP8PutBitUniform(bw, 0); // clamp type - - PutSegmentHeader(bw, enc); - PutFilterHeader(bw, &enc->filter_hdr_); - VP8PutBits(bw, enc->num_parts_ == 8 ? 3 : - enc->num_parts_ == 4 ? 2 : - enc->num_parts_ == 2 ? 1 : 0, 2); - PutQuant(bw, enc); - VP8PutBitUniform(bw, 0); // no proba update - VP8WriteProbas(bw, &enc->proba_); - pos2 = VP8BitWriterPos(bw); - VP8CodeIntraModes(enc); - VP8BitWriterFinish(bw); - - pos3 = VP8BitWriterPos(bw); - - if (enc->pic_->stats) { - enc->pic_->stats->header_bytes[0] = (int)((pos2 - pos1 + 7) >> 3); - enc->pic_->stats->header_bytes[1] = (int)((pos3 - pos2 + 7) >> 3); - enc->pic_->stats->alpha_data_size = (int)enc->alpha_data_size_; - } - if (bw->error_) { - return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); - } - return 1; -} - -void VP8EncFreeBitWriters(VP8Encoder* const enc) { - int p; - VP8BitWriterWipeOut(&enc->bw_); - for (p = 0; p < enc->num_parts_; ++p) { - VP8BitWriterWipeOut(enc->parts_ + p); - } -} - -int VP8EncWrite(VP8Encoder* const enc) { - WebPPicture* const pic = enc->pic_; - VP8BitWriter* const bw = &enc->bw_; - const int task_percent = 19; - const int percent_per_part = task_percent / enc->num_parts_; - const int final_percent = enc->percent_ + task_percent; - int ok = 0; - size_t vp8_size, pad, riff_size; - int p; - - // Partition #0 with header and partition sizes - ok = GeneratePartition0(enc); - if (!ok) return 0; - - // Compute VP8 size - vp8_size = VP8_FRAME_HEADER_SIZE + - VP8BitWriterSize(bw) + - 3 * (enc->num_parts_ - 1); - for (p = 0; p < enc->num_parts_; ++p) { - vp8_size += VP8BitWriterSize(enc->parts_ + p); - } - pad = vp8_size & 1; - vp8_size += pad; - - // Compute RIFF size - // At the minimum it is: "WEBPVP8 nnnn" + VP8 data size. - riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8_size; - if (IsVP8XNeeded(enc)) { // Add size for: VP8X header + data. - riff_size += CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE; - } - if (enc->has_alpha_) { // Add size for: ALPH header + data. - const uint32_t padded_alpha_size = enc->alpha_data_size_ + - (enc->alpha_data_size_ & 1); - riff_size += CHUNK_HEADER_SIZE + padded_alpha_size; - } - // Sanity check. - if (riff_size > 0xfffffffeU) { - return WebPEncodingSetError(pic, VP8_ENC_ERROR_FILE_TOO_BIG); - } - - // Emit headers and partition #0 - { - const uint8_t* const part0 = VP8BitWriterBuf(bw); - const size_t size0 = VP8BitWriterSize(bw); - ok = ok && PutWebPHeaders(enc, size0, vp8_size, riff_size) - && pic->writer(part0, size0, pic) - && EmitPartitionsSize(enc, pic); - VP8BitWriterWipeOut(bw); // will free the internal buffer. - } - - // Token partitions - for (p = 0; p < enc->num_parts_; ++p) { - const uint8_t* const buf = VP8BitWriterBuf(enc->parts_ + p); - const size_t size = VP8BitWriterSize(enc->parts_ + p); - if (size) - ok = ok && pic->writer(buf, size, pic); - VP8BitWriterWipeOut(enc->parts_ + p); // will free the internal buffer. - ok = ok && WebPReportProgress(pic, enc->percent_ + percent_per_part, - &enc->percent_); - } - - // Padding byte - if (ok && pad) { - ok = PutPaddingByte(pic); - } - - enc->coded_size_ = (int)(CHUNK_HEADER_SIZE + riff_size); - ok = ok && WebPReportProgress(pic, final_percent, &enc->percent_); - return ok; -} - -//------------------------------------------------------------------------------ - diff --git a/Example-Mac/Pods/libwebp/src/enc/token.c b/Example-Mac/Pods/libwebp/src/enc/token.c deleted file mode 100644 index e73256b3..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/token.c +++ /dev/null @@ -1,285 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Paginated token buffer -// -// A 'token' is a bit value associated with a probability, either fixed -// or a later-to-be-determined after statistics have been collected. -// For dynamic probability, we just record the slot id (idx) for the probability -// value in the final probability array (uint8_t* probas in VP8EmitTokens). -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include -#include - -#include "./cost.h" -#include "./vp8enci.h" -#include "../utils/utils.h" - -#if !defined(DISABLE_TOKEN_BUFFER) - -// we use pages to reduce the number of memcpy() -#define MIN_PAGE_SIZE 8192 // minimum number of token per page -#define FIXED_PROBA_BIT (1u << 14) - -typedef uint16_t token_t; // bit #15: bit value - // bit #14: flags for constant proba or idx - // bits #0..13: slot or constant proba -struct VP8Tokens { - VP8Tokens* next_; // pointer to next page -}; -// Token data is located in memory just after the next_ field. -// This macro is used to return their address and hide the trick. -#define TOKEN_DATA(p) ((const token_t*)&(p)[1]) - -//------------------------------------------------------------------------------ - -void VP8TBufferInit(VP8TBuffer* const b, int page_size) { - b->tokens_ = NULL; - b->pages_ = NULL; - b->last_page_ = &b->pages_; - b->left_ = 0; - b->page_size_ = (page_size < MIN_PAGE_SIZE) ? MIN_PAGE_SIZE : page_size; - b->error_ = 0; -} - -void VP8TBufferClear(VP8TBuffer* const b) { - if (b != NULL) { - VP8Tokens* p = b->pages_; - while (p != NULL) { - VP8Tokens* const next = p->next_; - WebPSafeFree(p); - p = next; - } - VP8TBufferInit(b, b->page_size_); - } -} - -static int TBufferNewPage(VP8TBuffer* const b) { - VP8Tokens* page = NULL; - if (!b->error_) { - const size_t size = sizeof(*page) + b->page_size_ * sizeof(token_t); - page = (VP8Tokens*)WebPSafeMalloc(1ULL, size); - } - if (page == NULL) { - b->error_ = 1; - return 0; - } - page->next_ = NULL; - - *b->last_page_ = page; - b->last_page_ = &page->next_; - b->left_ = b->page_size_; - b->tokens_ = (token_t*)TOKEN_DATA(page); - return 1; -} - -//------------------------------------------------------------------------------ - -#define TOKEN_ID(t, b, ctx) \ - (NUM_PROBAS * ((ctx) + NUM_CTX * ((b) + NUM_BANDS * (t)))) - -static WEBP_INLINE uint32_t AddToken(VP8TBuffer* const b, - uint32_t bit, uint32_t proba_idx) { - assert(proba_idx < FIXED_PROBA_BIT); - assert(bit <= 1); - if (b->left_ > 0 || TBufferNewPage(b)) { - const int slot = --b->left_; - b->tokens_[slot] = (bit << 15) | proba_idx; - } - return bit; -} - -static WEBP_INLINE void AddConstantToken(VP8TBuffer* const b, - uint32_t bit, uint32_t proba) { - assert(proba < 256); - assert(bit <= 1); - if (b->left_ > 0 || TBufferNewPage(b)) { - const int slot = --b->left_; - b->tokens_[slot] = (bit << 15) | FIXED_PROBA_BIT | proba; - } -} - -int VP8RecordCoeffTokens(const int ctx, const int coeff_type, - int first, int last, - const int16_t* const coeffs, - VP8TBuffer* const tokens) { - int n = first; - uint32_t base_id = TOKEN_ID(coeff_type, n, ctx); - if (!AddToken(tokens, last >= 0, base_id + 0)) { - return 0; - } - - while (n < 16) { - const int c = coeffs[n++]; - const int sign = c < 0; - const uint32_t v = sign ? -c : c; - if (!AddToken(tokens, v != 0, base_id + 1)) { - base_id = TOKEN_ID(coeff_type, VP8EncBands[n], 0); // ctx=0 - continue; - } - if (!AddToken(tokens, v > 1, base_id + 2)) { - base_id = TOKEN_ID(coeff_type, VP8EncBands[n], 1); // ctx=1 - } else { - if (!AddToken(tokens, v > 4, base_id + 3)) { - if (AddToken(tokens, v != 2, base_id + 4)) - AddToken(tokens, v == 4, base_id + 5); - } else if (!AddToken(tokens, v > 10, base_id + 6)) { - if (!AddToken(tokens, v > 6, base_id + 7)) { - AddConstantToken(tokens, v == 6, 159); - } else { - AddConstantToken(tokens, v >= 9, 165); - AddConstantToken(tokens, !(v & 1), 145); - } - } else { - int mask; - const uint8_t* tab; - uint32_t residue = v - 3; - if (residue < (8 << 1)) { // VP8Cat3 (3b) - AddToken(tokens, 0, base_id + 8); - AddToken(tokens, 0, base_id + 9); - residue -= (8 << 0); - mask = 1 << 2; - tab = VP8Cat3; - } else if (residue < (8 << 2)) { // VP8Cat4 (4b) - AddToken(tokens, 0, base_id + 8); - AddToken(tokens, 1, base_id + 9); - residue -= (8 << 1); - mask = 1 << 3; - tab = VP8Cat4; - } else if (residue < (8 << 3)) { // VP8Cat5 (5b) - AddToken(tokens, 1, base_id + 8); - AddToken(tokens, 0, base_id + 10); - residue -= (8 << 2); - mask = 1 << 4; - tab = VP8Cat5; - } else { // VP8Cat6 (11b) - AddToken(tokens, 1, base_id + 8); - AddToken(tokens, 1, base_id + 10); - residue -= (8 << 3); - mask = 1 << 10; - tab = VP8Cat6; - } - while (mask) { - AddConstantToken(tokens, !!(residue & mask), *tab++); - mask >>= 1; - } - } - base_id = TOKEN_ID(coeff_type, VP8EncBands[n], 2); // ctx=2 - } - AddConstantToken(tokens, sign, 128); - if (n == 16 || !AddToken(tokens, n <= last, base_id + 0)) { - return 1; // EOB - } - } - return 1; -} - -#undef TOKEN_ID - -//------------------------------------------------------------------------------ -// This function works, but isn't currently used. Saved for later. - -#if 0 - -static void Record(int bit, proba_t* const stats) { - proba_t p = *stats; - if (p >= 0xffff0000u) { // an overflow is inbound. - p = ((p + 1u) >> 1) & 0x7fff7fffu; // -> divide the stats by 2. - } - // record bit count (lower 16 bits) and increment total count (upper 16 bits). - p += 0x00010000u + bit; - *stats = p; -} - -void VP8TokenToStats(const VP8TBuffer* const b, proba_t* const stats) { - const VP8Tokens* p = b->pages_; - while (p != NULL) { - const int N = (p->next_ == NULL) ? b->left_ : 0; - int n = MAX_NUM_TOKEN; - const token_t* const tokens = TOKEN_DATA(p); - while (n-- > N) { - const token_t token = tokens[n]; - if (!(token & FIXED_PROBA_BIT)) { - Record((token >> 15) & 1, stats + (token & 0x3fffu)); - } - } - p = p->next_; - } -} - -#endif // 0 - -//------------------------------------------------------------------------------ -// Final coding pass, with known probabilities - -int VP8EmitTokens(VP8TBuffer* const b, VP8BitWriter* const bw, - const uint8_t* const probas, int final_pass) { - const VP8Tokens* p = b->pages_; - assert(!b->error_); - while (p != NULL) { - const VP8Tokens* const next = p->next_; - const int N = (next == NULL) ? b->left_ : 0; - int n = b->page_size_; - const token_t* const tokens = TOKEN_DATA(p); - while (n-- > N) { - const token_t token = tokens[n]; - const int bit = (token >> 15) & 1; - if (token & FIXED_PROBA_BIT) { - VP8PutBit(bw, bit, token & 0xffu); // constant proba - } else { - VP8PutBit(bw, bit, probas[token & 0x3fffu]); - } - } - if (final_pass) WebPSafeFree((void*)p); - p = next; - } - if (final_pass) b->pages_ = NULL; - return 1; -} - -// Size estimation -size_t VP8EstimateTokenSize(VP8TBuffer* const b, const uint8_t* const probas) { - size_t size = 0; - const VP8Tokens* p = b->pages_; - assert(!b->error_); - while (p != NULL) { - const VP8Tokens* const next = p->next_; - const int N = (next == NULL) ? b->left_ : 0; - int n = b->page_size_; - const token_t* const tokens = TOKEN_DATA(p); - while (n-- > N) { - const token_t token = tokens[n]; - const int bit = token & (1 << 15); - if (token & FIXED_PROBA_BIT) { - size += VP8BitCost(bit, token & 0xffu); - } else { - size += VP8BitCost(bit, probas[token & 0x3fffu]); - } - } - p = next; - } - return size; -} - -//------------------------------------------------------------------------------ - -#else // DISABLE_TOKEN_BUFFER - -void VP8TBufferInit(VP8TBuffer* const b) { - (void)b; -} -void VP8TBufferClear(VP8TBuffer* const b) { - (void)b; -} - -#endif // !DISABLE_TOKEN_BUFFER - diff --git a/Example-Mac/Pods/libwebp/src/enc/tree.c b/Example-Mac/Pods/libwebp/src/enc/tree.c deleted file mode 100644 index f141006d..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/tree.c +++ /dev/null @@ -1,504 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Coding of token probabilities, intra modes and segments. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./vp8enci.h" - -//------------------------------------------------------------------------------ -// Default probabilities - -// Paragraph 13.5 -const uint8_t - VP8CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = { - { { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } - }, - { { 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128 }, - { 189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128 }, - { 106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128 } - }, - { { 1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128 }, - { 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128 }, - { 78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128 }, - }, - { { 1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128 }, - { 184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128 }, - { 77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128 }, - }, - { { 1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128 }, - { 170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128 }, - { 37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128 } - }, - { { 1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128 }, - { 207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128 }, - { 102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128 } - }, - { { 1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128 }, - { 177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128 }, - { 80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128 } - }, - { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } - } - }, - { { { 198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62 }, - { 131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1 }, - { 68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128 } - }, - { { 1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128 }, - { 184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128 }, - { 81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128 } - }, - { { 1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128 }, - { 99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128 }, - { 23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128 } - }, - { { 1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128 }, - { 109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128 }, - { 44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128 } - }, - { { 1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128 }, - { 94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128 }, - { 22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128 } - }, - { { 1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128 }, - { 124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128 }, - { 35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128 } - }, - { { 1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128 }, - { 121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128 }, - { 45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128 } - }, - { { 1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128 }, - { 203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128 } - } - }, - { { { 253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128 }, - { 175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128 }, - { 73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128 } - }, - { { 1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128 }, - { 239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128 }, - { 155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128 } - }, - { { 1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128 }, - { 201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128 }, - { 69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128 } - }, - { { 1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128 }, - { 141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128 } - }, - { { 1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128 }, - { 149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 } - }, - { { 1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128 } - }, - { { 1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128 } - }, - { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } - } - }, - { { { 202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255 }, - { 126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128 }, - { 61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128 } - }, - { { 1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128 }, - { 166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128 }, - { 39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128 } - }, - { { 1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128 }, - { 124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128 }, - { 24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128 } - }, - { { 1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128 }, - { 149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128 }, - { 28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128 } - }, - { { 1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128 }, - { 123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128 }, - { 20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128 } - }, - { { 1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128 }, - { 168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128 }, - { 47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128 } - }, - { { 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128 }, - { 141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128 }, - { 42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128 } - }, - { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 } - } - } -}; - -void VP8DefaultProbas(VP8Encoder* const enc) { - VP8EncProba* const probas = &enc->proba_; - probas->use_skip_proba_ = 0; - memset(probas->segments_, 255u, sizeof(probas->segments_)); - memcpy(probas->coeffs_, VP8CoeffsProba0, sizeof(VP8CoeffsProba0)); - // Note: we could hard-code the level_costs_ corresponding to VP8CoeffsProba0, - // but that's ~11k of static data. Better call VP8CalculateLevelCosts() later. - probas->dirty_ = 1; -} - -// Paragraph 11.5. 900bytes. -static const uint8_t kBModesProba[NUM_BMODES][NUM_BMODES][NUM_BMODES - 1] = { - { { 231, 120, 48, 89, 115, 113, 120, 152, 112 }, - { 152, 179, 64, 126, 170, 118, 46, 70, 95 }, - { 175, 69, 143, 80, 85, 82, 72, 155, 103 }, - { 56, 58, 10, 171, 218, 189, 17, 13, 152 }, - { 114, 26, 17, 163, 44, 195, 21, 10, 173 }, - { 121, 24, 80, 195, 26, 62, 44, 64, 85 }, - { 144, 71, 10, 38, 171, 213, 144, 34, 26 }, - { 170, 46, 55, 19, 136, 160, 33, 206, 71 }, - { 63, 20, 8, 114, 114, 208, 12, 9, 226 }, - { 81, 40, 11, 96, 182, 84, 29, 16, 36 } }, - { { 134, 183, 89, 137, 98, 101, 106, 165, 148 }, - { 72, 187, 100, 130, 157, 111, 32, 75, 80 }, - { 66, 102, 167, 99, 74, 62, 40, 234, 128 }, - { 41, 53, 9, 178, 241, 141, 26, 8, 107 }, - { 74, 43, 26, 146, 73, 166, 49, 23, 157 }, - { 65, 38, 105, 160, 51, 52, 31, 115, 128 }, - { 104, 79, 12, 27, 217, 255, 87, 17, 7 }, - { 87, 68, 71, 44, 114, 51, 15, 186, 23 }, - { 47, 41, 14, 110, 182, 183, 21, 17, 194 }, - { 66, 45, 25, 102, 197, 189, 23, 18, 22 } }, - { { 88, 88, 147, 150, 42, 46, 45, 196, 205 }, - { 43, 97, 183, 117, 85, 38, 35, 179, 61 }, - { 39, 53, 200, 87, 26, 21, 43, 232, 171 }, - { 56, 34, 51, 104, 114, 102, 29, 93, 77 }, - { 39, 28, 85, 171, 58, 165, 90, 98, 64 }, - { 34, 22, 116, 206, 23, 34, 43, 166, 73 }, - { 107, 54, 32, 26, 51, 1, 81, 43, 31 }, - { 68, 25, 106, 22, 64, 171, 36, 225, 114 }, - { 34, 19, 21, 102, 132, 188, 16, 76, 124 }, - { 62, 18, 78, 95, 85, 57, 50, 48, 51 } }, - { { 193, 101, 35, 159, 215, 111, 89, 46, 111 }, - { 60, 148, 31, 172, 219, 228, 21, 18, 111 }, - { 112, 113, 77, 85, 179, 255, 38, 120, 114 }, - { 40, 42, 1, 196, 245, 209, 10, 25, 109 }, - { 88, 43, 29, 140, 166, 213, 37, 43, 154 }, - { 61, 63, 30, 155, 67, 45, 68, 1, 209 }, - { 100, 80, 8, 43, 154, 1, 51, 26, 71 }, - { 142, 78, 78, 16, 255, 128, 34, 197, 171 }, - { 41, 40, 5, 102, 211, 183, 4, 1, 221 }, - { 51, 50, 17, 168, 209, 192, 23, 25, 82 } }, - { { 138, 31, 36, 171, 27, 166, 38, 44, 229 }, - { 67, 87, 58, 169, 82, 115, 26, 59, 179 }, - { 63, 59, 90, 180, 59, 166, 93, 73, 154 }, - { 40, 40, 21, 116, 143, 209, 34, 39, 175 }, - { 47, 15, 16, 183, 34, 223, 49, 45, 183 }, - { 46, 17, 33, 183, 6, 98, 15, 32, 183 }, - { 57, 46, 22, 24, 128, 1, 54, 17, 37 }, - { 65, 32, 73, 115, 28, 128, 23, 128, 205 }, - { 40, 3, 9, 115, 51, 192, 18, 6, 223 }, - { 87, 37, 9, 115, 59, 77, 64, 21, 47 } }, - { { 104, 55, 44, 218, 9, 54, 53, 130, 226 }, - { 64, 90, 70, 205, 40, 41, 23, 26, 57 }, - { 54, 57, 112, 184, 5, 41, 38, 166, 213 }, - { 30, 34, 26, 133, 152, 116, 10, 32, 134 }, - { 39, 19, 53, 221, 26, 114, 32, 73, 255 }, - { 31, 9, 65, 234, 2, 15, 1, 118, 73 }, - { 75, 32, 12, 51, 192, 255, 160, 43, 51 }, - { 88, 31, 35, 67, 102, 85, 55, 186, 85 }, - { 56, 21, 23, 111, 59, 205, 45, 37, 192 }, - { 55, 38, 70, 124, 73, 102, 1, 34, 98 } }, - { { 125, 98, 42, 88, 104, 85, 117, 175, 82 }, - { 95, 84, 53, 89, 128, 100, 113, 101, 45 }, - { 75, 79, 123, 47, 51, 128, 81, 171, 1 }, - { 57, 17, 5, 71, 102, 57, 53, 41, 49 }, - { 38, 33, 13, 121, 57, 73, 26, 1, 85 }, - { 41, 10, 67, 138, 77, 110, 90, 47, 114 }, - { 115, 21, 2, 10, 102, 255, 166, 23, 6 }, - { 101, 29, 16, 10, 85, 128, 101, 196, 26 }, - { 57, 18, 10, 102, 102, 213, 34, 20, 43 }, - { 117, 20, 15, 36, 163, 128, 68, 1, 26 } }, - { { 102, 61, 71, 37, 34, 53, 31, 243, 192 }, - { 69, 60, 71, 38, 73, 119, 28, 222, 37 }, - { 68, 45, 128, 34, 1, 47, 11, 245, 171 }, - { 62, 17, 19, 70, 146, 85, 55, 62, 70 }, - { 37, 43, 37, 154, 100, 163, 85, 160, 1 }, - { 63, 9, 92, 136, 28, 64, 32, 201, 85 }, - { 75, 15, 9, 9, 64, 255, 184, 119, 16 }, - { 86, 6, 28, 5, 64, 255, 25, 248, 1 }, - { 56, 8, 17, 132, 137, 255, 55, 116, 128 }, - { 58, 15, 20, 82, 135, 57, 26, 121, 40 } }, - { { 164, 50, 31, 137, 154, 133, 25, 35, 218 }, - { 51, 103, 44, 131, 131, 123, 31, 6, 158 }, - { 86, 40, 64, 135, 148, 224, 45, 183, 128 }, - { 22, 26, 17, 131, 240, 154, 14, 1, 209 }, - { 45, 16, 21, 91, 64, 222, 7, 1, 197 }, - { 56, 21, 39, 155, 60, 138, 23, 102, 213 }, - { 83, 12, 13, 54, 192, 255, 68, 47, 28 }, - { 85, 26, 85, 85, 128, 128, 32, 146, 171 }, - { 18, 11, 7, 63, 144, 171, 4, 4, 246 }, - { 35, 27, 10, 146, 174, 171, 12, 26, 128 } }, - { { 190, 80, 35, 99, 180, 80, 126, 54, 45 }, - { 85, 126, 47, 87, 176, 51, 41, 20, 32 }, - { 101, 75, 128, 139, 118, 146, 116, 128, 85 }, - { 56, 41, 15, 176, 236, 85, 37, 9, 62 }, - { 71, 30, 17, 119, 118, 255, 17, 18, 138 }, - { 101, 38, 60, 138, 55, 70, 43, 26, 142 }, - { 146, 36, 19, 30, 171, 255, 97, 27, 20 }, - { 138, 45, 61, 62, 219, 1, 81, 188, 64 }, - { 32, 41, 20, 117, 151, 142, 20, 21, 163 }, - { 112, 19, 12, 61, 195, 128, 48, 4, 24 } } -}; - -static int PutI4Mode(VP8BitWriter* const bw, int mode, - const uint8_t* const prob) { - if (VP8PutBit(bw, mode != B_DC_PRED, prob[0])) { - if (VP8PutBit(bw, mode != B_TM_PRED, prob[1])) { - if (VP8PutBit(bw, mode != B_VE_PRED, prob[2])) { - if (!VP8PutBit(bw, mode >= B_LD_PRED, prob[3])) { - if (VP8PutBit(bw, mode != B_HE_PRED, prob[4])) { - VP8PutBit(bw, mode != B_RD_PRED, prob[5]); - } - } else { - if (VP8PutBit(bw, mode != B_LD_PRED, prob[6])) { - if (VP8PutBit(bw, mode != B_VL_PRED, prob[7])) { - VP8PutBit(bw, mode != B_HD_PRED, prob[8]); - } - } - } - } - } - } - return mode; -} - -static void PutI16Mode(VP8BitWriter* const bw, int mode) { - if (VP8PutBit(bw, (mode == TM_PRED || mode == H_PRED), 156)) { - VP8PutBit(bw, mode == TM_PRED, 128); // TM or HE - } else { - VP8PutBit(bw, mode == V_PRED, 163); // VE or DC - } -} - -static void PutUVMode(VP8BitWriter* const bw, int uv_mode) { - if (VP8PutBit(bw, uv_mode != DC_PRED, 142)) { - if (VP8PutBit(bw, uv_mode != V_PRED, 114)) { - VP8PutBit(bw, uv_mode != H_PRED, 183); // else: TM_PRED - } - } -} - -static void PutSegment(VP8BitWriter* const bw, int s, const uint8_t* p) { - if (VP8PutBit(bw, s >= 2, p[0])) p += 1; - VP8PutBit(bw, s & 1, p[1]); -} - -void VP8CodeIntraModes(VP8Encoder* const enc) { - VP8BitWriter* const bw = &enc->bw_; - VP8EncIterator it; - VP8IteratorInit(enc, &it); - do { - const VP8MBInfo* const mb = it.mb_; - const uint8_t* preds = it.preds_; - if (enc->segment_hdr_.update_map_) { - PutSegment(bw, mb->segment_, enc->proba_.segments_); - } - if (enc->proba_.use_skip_proba_) { - VP8PutBit(bw, mb->skip_, enc->proba_.skip_proba_); - } - if (VP8PutBit(bw, (mb->type_ != 0), 145)) { // i16x16 - PutI16Mode(bw, preds[0]); - } else { - const int preds_w = enc->preds_w_; - const uint8_t* top_pred = preds - preds_w; - int x, y; - for (y = 0; y < 4; ++y) { - int left = preds[-1]; - for (x = 0; x < 4; ++x) { - const uint8_t* const probas = kBModesProba[top_pred[x]][left]; - left = PutI4Mode(bw, preds[x], probas); - } - top_pred = preds; - preds += preds_w; - } - } - PutUVMode(bw, mb->uv_mode_); - } while (VP8IteratorNext(&it)); -} - -//------------------------------------------------------------------------------ -// Paragraph 13 - -const uint8_t - VP8CoeffsUpdateProba[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = { - { { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255 }, - { 250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - } - }, - { { { 217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255 }, - { 234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255 } - }, - { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - } - }, - { { { 186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255 }, - { 251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255 } - }, - { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - } - }, - { { { 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255 }, - { 248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - } - } -}; - -void VP8WriteProbas(VP8BitWriter* const bw, const VP8EncProba* const probas) { - int t, b, c, p; - for (t = 0; t < NUM_TYPES; ++t) { - for (b = 0; b < NUM_BANDS; ++b) { - for (c = 0; c < NUM_CTX; ++c) { - for (p = 0; p < NUM_PROBAS; ++p) { - const uint8_t p0 = probas->coeffs_[t][b][c][p]; - const int update = (p0 != VP8CoeffsProba0[t][b][c][p]); - if (VP8PutBit(bw, update, VP8CoeffsUpdateProba[t][b][c][p])) { - VP8PutBits(bw, p0, 8); - } - } - } - } - } - if (VP8PutBitUniform(bw, probas->use_skip_proba_)) { - VP8PutBits(bw, probas->skip_proba_, 8); - } -} - diff --git a/Example-Mac/Pods/libwebp/src/enc/vp8enci.h b/Example-Mac/Pods/libwebp/src/enc/vp8enci.h deleted file mode 100644 index b2cc8d19..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/vp8enci.h +++ /dev/null @@ -1,536 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// WebP encoder: internal header. -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_ENC_VP8ENCI_H_ -#define WEBP_ENC_VP8ENCI_H_ - -#include // for memcpy() -#include "../dec/common.h" -#include "../dsp/dsp.h" -#include "../utils/bit_writer.h" -#include "../utils/thread.h" -#include "../utils/utils.h" -#include "../webp/encode.h" - -#ifdef WEBP_EXPERIMENTAL_FEATURES -#include "./vp8li.h" -#endif // WEBP_EXPERIMENTAL_FEATURES - -#ifdef __cplusplus -extern "C" { -#endif - -//------------------------------------------------------------------------------ -// Various defines and enums - -// version numbers -#define ENC_MAJ_VERSION 0 -#define ENC_MIN_VERSION 5 -#define ENC_REV_VERSION 0 - -enum { MAX_LF_LEVELS = 64, // Maximum loop filter level - MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost - MAX_LEVEL = 2047 // max level (note: max codable is 2047 + 67) - }; - -typedef enum { // Rate-distortion optimization levels - RD_OPT_NONE = 0, // no rd-opt - RD_OPT_BASIC = 1, // basic scoring (no trellis) - RD_OPT_TRELLIS = 2, // perform trellis-quant on the final decision only - RD_OPT_TRELLIS_ALL = 3 // trellis-quant for every scoring (much slower) -} VP8RDLevel; - -// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline). -// The original or reconstructed samples can be accessed using VP8Scan[]. -// The predicted blocks can be accessed using offsets to yuv_p_ and -// the arrays VP8*ModeOffsets[]. -// * YUV Samples area (yuv_in_/yuv_out_/yuv_out2_) -// (see VP8Scan[] for accessing the blocks, along with -// Y_OFF_ENC/U_OFF_ENC/V_OFF_ENC): -// +----+----+ -// Y_OFF_ENC |YYYY|UUVV| -// U_OFF_ENC |YYYY|UUVV| -// V_OFF_ENC |YYYY|....| <- 25% wasted U/V area -// |YYYY|....| -// +----+----+ -// * Prediction area ('yuv_p_', size = PRED_SIZE_ENC) -// Intra16 predictions (16x16 block each, two per row): -// |I16DC16|I16TM16| -// |I16VE16|I16HE16| -// Chroma U/V predictions (16x8 block each, two per row): -// |C8DC8|C8TM8| -// |C8VE8|C8HE8| -// Intra 4x4 predictions (4x4 block each) -// |I4DC4 I4TM4 I4VE4 I4HE4|I4RD4 I4VR4 I4LD4 I4VL4| -// |I4HD4 I4HU4 I4TMP .....|.......................| <- ~31% wasted -#define YUV_SIZE_ENC (BPS * 16) -#define PRED_SIZE_ENC (32 * BPS + 16 * BPS + 8 * BPS) // I16+Chroma+I4 preds -#define Y_OFF_ENC (0) -#define U_OFF_ENC (16) -#define V_OFF_ENC (16 + 8) - -extern const int VP8Scan[16]; // in quant.c -extern const int VP8UVModeOffsets[4]; // in analyze.c -extern const int VP8I16ModeOffsets[4]; -extern const int VP8I4ModeOffsets[NUM_BMODES]; - -// Layout of prediction blocks -// intra 16x16 -#define I16DC16 (0 * 16 * BPS) -#define I16TM16 (I16DC16 + 16) -#define I16VE16 (1 * 16 * BPS) -#define I16HE16 (I16VE16 + 16) -// chroma 8x8, two U/V blocks side by side (hence: 16x8 each) -#define C8DC8 (2 * 16 * BPS) -#define C8TM8 (C8DC8 + 1 * 16) -#define C8VE8 (2 * 16 * BPS + 8 * BPS) -#define C8HE8 (C8VE8 + 1 * 16) -// intra 4x4 -#define I4DC4 (3 * 16 * BPS + 0) -#define I4TM4 (I4DC4 + 4) -#define I4VE4 (I4DC4 + 8) -#define I4HE4 (I4DC4 + 12) -#define I4RD4 (I4DC4 + 16) -#define I4VR4 (I4DC4 + 20) -#define I4LD4 (I4DC4 + 24) -#define I4VL4 (I4DC4 + 28) -#define I4HD4 (3 * 16 * BPS + 4 * BPS) -#define I4HU4 (I4HD4 + 4) -#define I4TMP (I4HD4 + 8) - -typedef int64_t score_t; // type used for scores, rate, distortion -// Note that MAX_COST is not the maximum allowed by sizeof(score_t), -// in order to allow overflowing computations. -#define MAX_COST ((score_t)0x7fffffffffffffLL) - -#define QFIX 17 -#define BIAS(b) ((b) << (QFIX - 8)) -// Fun fact: this is the _only_ line where we're actually being lossy and -// discarding bits. -static WEBP_INLINE int QUANTDIV(uint32_t n, uint32_t iQ, uint32_t B) { - return (int)((n * iQ + B) >> QFIX); -} - -// Uncomment the following to remove token-buffer code: -// #define DISABLE_TOKEN_BUFFER - -//------------------------------------------------------------------------------ -// Headers - -typedef uint32_t proba_t; // 16b + 16b -typedef uint8_t ProbaArray[NUM_CTX][NUM_PROBAS]; -typedef proba_t StatsArray[NUM_CTX][NUM_PROBAS]; -typedef uint16_t CostArray[NUM_CTX][MAX_VARIABLE_LEVEL + 1]; -typedef const uint16_t* (*CostArrayPtr)[NUM_CTX]; // for easy casting -typedef const uint16_t* CostArrayMap[16][NUM_CTX]; -typedef double LFStats[NUM_MB_SEGMENTS][MAX_LF_LEVELS]; // filter stats - -typedef struct VP8Encoder VP8Encoder; - -// segment features -typedef struct { - int num_segments_; // Actual number of segments. 1 segment only = unused. - int update_map_; // whether to update the segment map or not. - // must be 0 if there's only 1 segment. - int size_; // bit-cost for transmitting the segment map -} VP8EncSegmentHeader; - -// Struct collecting all frame-persistent probabilities. -typedef struct { - uint8_t segments_[3]; // probabilities for segment tree - uint8_t skip_proba_; // final probability of being skipped. - ProbaArray coeffs_[NUM_TYPES][NUM_BANDS]; // 1056 bytes - StatsArray stats_[NUM_TYPES][NUM_BANDS]; // 4224 bytes - CostArray level_cost_[NUM_TYPES][NUM_BANDS]; // 13056 bytes - CostArrayMap remapped_costs_[NUM_TYPES]; // 1536 bytes - int dirty_; // if true, need to call VP8CalculateLevelCosts() - int use_skip_proba_; // Note: we always use skip_proba for now. - int nb_skip_; // number of skipped blocks -} VP8EncProba; - -// Filter parameters. Not actually used in the code (we don't perform -// the in-loop filtering), but filled from user's config -typedef struct { - int simple_; // filtering type: 0=complex, 1=simple - int level_; // base filter level [0..63] - int sharpness_; // [0..7] - int i4x4_lf_delta_; // delta filter level for i4x4 relative to i16x16 -} VP8EncFilterHeader; - -//------------------------------------------------------------------------------ -// Informations about the macroblocks. - -typedef struct { - // block type - unsigned int type_:2; // 0=i4x4, 1=i16x16 - unsigned int uv_mode_:2; - unsigned int skip_:1; - unsigned int segment_:2; - uint8_t alpha_; // quantization-susceptibility -} VP8MBInfo; - -typedef struct VP8Matrix { - uint16_t q_[16]; // quantizer steps - uint16_t iq_[16]; // reciprocals, fixed point. - uint32_t bias_[16]; // rounding bias - uint32_t zthresh_[16]; // value below which a coefficient is zeroed - uint16_t sharpen_[16]; // frequency boosters for slight sharpening -} VP8Matrix; - -typedef struct { - VP8Matrix y1_, y2_, uv_; // quantization matrices - int alpha_; // quant-susceptibility, range [-127,127]. Zero is neutral. - // Lower values indicate a lower risk of blurriness. - int beta_; // filter-susceptibility, range [0,255]. - int quant_; // final segment quantizer. - int fstrength_; // final in-loop filtering strength - int max_edge_; // max edge delta (for filtering strength) - int min_disto_; // minimum distortion required to trigger filtering record - // reactivities - int lambda_i16_, lambda_i4_, lambda_uv_; - int lambda_mode_, lambda_trellis_, tlambda_; - int lambda_trellis_i16_, lambda_trellis_i4_, lambda_trellis_uv_; -} VP8SegmentInfo; - -// Handy transient struct to accumulate score and info during RD-optimization -// and mode evaluation. -typedef struct { - score_t D, SD; // Distortion, spectral distortion - score_t H, R, score; // header bits, rate, score. - int16_t y_dc_levels[16]; // Quantized levels for luma-DC, luma-AC, chroma. - int16_t y_ac_levels[16][16]; - int16_t uv_levels[4 + 4][16]; - int mode_i16; // mode number for intra16 prediction - uint8_t modes_i4[16]; // mode numbers for intra4 predictions - int mode_uv; // mode number of chroma prediction - uint32_t nz; // non-zero blocks -} VP8ModeScore; - -// Iterator structure to iterate through macroblocks, pointing to the -// right neighbouring data (samples, predictions, contexts, ...) -typedef struct { - int x_, y_; // current macroblock - int y_stride_, uv_stride_; // respective strides - uint8_t* yuv_in_; // input samples - uint8_t* yuv_out_; // output samples - uint8_t* yuv_out2_; // secondary buffer swapped with yuv_out_. - uint8_t* yuv_p_; // scratch buffer for prediction - VP8Encoder* enc_; // back-pointer - VP8MBInfo* mb_; // current macroblock - VP8BitWriter* bw_; // current bit-writer - uint8_t* preds_; // intra mode predictors (4x4 blocks) - uint32_t* nz_; // non-zero pattern - uint8_t i4_boundary_[37]; // 32+5 boundary samples needed by intra4x4 - uint8_t* i4_top_; // pointer to the current top boundary sample - int i4_; // current intra4x4 mode being tested - int top_nz_[9]; // top-non-zero context. - int left_nz_[9]; // left-non-zero. left_nz[8] is independent. - uint64_t bit_count_[4][3]; // bit counters for coded levels. - uint64_t luma_bits_; // macroblock bit-cost for luma - uint64_t uv_bits_; // macroblock bit-cost for chroma - LFStats* lf_stats_; // filter stats (borrowed from enc_) - int do_trellis_; // if true, perform extra level optimisation - int count_down_; // number of mb still to be processed - int count_down0_; // starting counter value (for progress) - int percent0_; // saved initial progress percent - - uint8_t* y_left_; // left luma samples (addressable from index -1 to 15). - uint8_t* u_left_; // left u samples (addressable from index -1 to 7) - uint8_t* v_left_; // left v samples (addressable from index -1 to 7) - - uint8_t* y_top_; // top luma samples at position 'x_' - uint8_t* uv_top_; // top u/v samples at position 'x_', packed as 16 bytes - - // memory for storing y/u/v_left_ - uint8_t yuv_left_mem_[17 + 16 + 16 + 8 + WEBP_ALIGN_CST]; - // memory for yuv_* - uint8_t yuv_mem_[3 * YUV_SIZE_ENC + PRED_SIZE_ENC + WEBP_ALIGN_CST]; -} VP8EncIterator; - - // in iterator.c -// must be called first -void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it); -// restart a scan -void VP8IteratorReset(VP8EncIterator* const it); -// reset iterator position to row 'y' -void VP8IteratorSetRow(VP8EncIterator* const it, int y); -// set count down (=number of iterations to go) -void VP8IteratorSetCountDown(VP8EncIterator* const it, int count_down); -// return true if iteration is finished -int VP8IteratorIsDone(const VP8EncIterator* const it); -// Import uncompressed samples from source. -// If tmp_32 is not NULL, import boundary samples too. -// tmp_32 is a 32-bytes scratch buffer that must be aligned in memory. -void VP8IteratorImport(VP8EncIterator* const it, uint8_t* tmp_32); -// export decimated samples -void VP8IteratorExport(const VP8EncIterator* const it); -// go to next macroblock. Returns false if not finished. -int VP8IteratorNext(VP8EncIterator* const it); -// save the yuv_out_ boundary values to top_/left_ arrays for next iterations. -void VP8IteratorSaveBoundary(VP8EncIterator* const it); -// Report progression based on macroblock rows. Return 0 for user-abort request. -int VP8IteratorProgress(const VP8EncIterator* const it, - int final_delta_percent); -// Intra4x4 iterations -void VP8IteratorStartI4(VP8EncIterator* const it); -// returns true if not done. -int VP8IteratorRotateI4(VP8EncIterator* const it, - const uint8_t* const yuv_out); - -// Non-zero context setup/teardown -void VP8IteratorNzToBytes(VP8EncIterator* const it); -void VP8IteratorBytesToNz(VP8EncIterator* const it); - -// Helper functions to set mode properties -void VP8SetIntra16Mode(const VP8EncIterator* const it, int mode); -void VP8SetIntra4Mode(const VP8EncIterator* const it, const uint8_t* modes); -void VP8SetIntraUVMode(const VP8EncIterator* const it, int mode); -void VP8SetSkip(const VP8EncIterator* const it, int skip); -void VP8SetSegment(const VP8EncIterator* const it, int segment); - -//------------------------------------------------------------------------------ -// Paginated token buffer - -typedef struct VP8Tokens VP8Tokens; // struct details in token.c - -typedef struct { -#if !defined(DISABLE_TOKEN_BUFFER) - VP8Tokens* pages_; // first page - VP8Tokens** last_page_; // last page - uint16_t* tokens_; // set to (*last_page_)->tokens_ - int left_; // how many free tokens left before the page is full - int page_size_; // number of tokens per page -#endif - int error_; // true in case of malloc error -} VP8TBuffer; - -// initialize an empty buffer -void VP8TBufferInit(VP8TBuffer* const b, int page_size); -void VP8TBufferClear(VP8TBuffer* const b); // de-allocate pages memory - -#if !defined(DISABLE_TOKEN_BUFFER) - -// Finalizes bitstream when probabilities are known. -// Deletes the allocated token memory if final_pass is true. -int VP8EmitTokens(VP8TBuffer* const b, VP8BitWriter* const bw, - const uint8_t* const probas, int final_pass); - -// record the coding of coefficients without knowing the probabilities yet -int VP8RecordCoeffTokens(const int ctx, const int coeff_type, - int first, int last, - const int16_t* const coeffs, - VP8TBuffer* const tokens); - -// Estimate the final coded size given a set of 'probas'. -size_t VP8EstimateTokenSize(VP8TBuffer* const b, const uint8_t* const probas); - -// unused for now -void VP8TokenToStats(const VP8TBuffer* const b, proba_t* const stats); - -#endif // !DISABLE_TOKEN_BUFFER - -//------------------------------------------------------------------------------ -// VP8Encoder - -struct VP8Encoder { - const WebPConfig* config_; // user configuration and parameters - WebPPicture* pic_; // input / output picture - - // headers - VP8EncFilterHeader filter_hdr_; // filtering information - VP8EncSegmentHeader segment_hdr_; // segment information - - int profile_; // VP8's profile, deduced from Config. - - // dimension, in macroblock units. - int mb_w_, mb_h_; - int preds_w_; // stride of the *preds_ prediction plane (=4*mb_w + 1) - - // number of partitions (1, 2, 4 or 8 = MAX_NUM_PARTITIONS) - int num_parts_; - - // per-partition boolean decoders. - VP8BitWriter bw_; // part0 - VP8BitWriter parts_[MAX_NUM_PARTITIONS]; // token partitions - VP8TBuffer tokens_; // token buffer - - int percent_; // for progress - - // transparency blob - int has_alpha_; - uint8_t* alpha_data_; // non-NULL if transparency is present - uint32_t alpha_data_size_; - WebPWorker alpha_worker_; - - // quantization info (one set of DC/AC dequant factor per segment) - VP8SegmentInfo dqm_[NUM_MB_SEGMENTS]; - int base_quant_; // nominal quantizer value. Only used - // for relative coding of segments' quant. - int alpha_; // global susceptibility (<=> complexity) - int uv_alpha_; // U/V quantization susceptibility - // global offset of quantizers, shared by all segments - int dq_y1_dc_; - int dq_y2_dc_, dq_y2_ac_; - int dq_uv_dc_, dq_uv_ac_; - - // probabilities and statistics - VP8EncProba proba_; - uint64_t sse_[4]; // sum of Y/U/V/A squared errors for all macroblocks - uint64_t sse_count_; // pixel count for the sse_[] stats - int coded_size_; - int residual_bytes_[3][4]; - int block_count_[3]; - - // quality/speed settings - int method_; // 0=fastest, 6=best/slowest. - VP8RDLevel rd_opt_level_; // Deduced from method_. - int max_i4_header_bits_; // partition #0 safeness factor - int thread_level_; // derived from config->thread_level - int do_search_; // derived from config->target_XXX - int use_tokens_; // if true, use token buffer - - // Memory - VP8MBInfo* mb_info_; // contextual macroblock infos (mb_w_ + 1) - uint8_t* preds_; // predictions modes: (4*mb_w+1) * (4*mb_h+1) - uint32_t* nz_; // non-zero bit context: mb_w+1 - uint8_t* y_top_; // top luma samples. - uint8_t* uv_top_; // top u/v samples. - // U and V are packed into 16 bytes (8 U + 8 V) - LFStats* lf_stats_; // autofilter stats (if NULL, autofilter is off) -}; - -//------------------------------------------------------------------------------ -// internal functions. Not public. - - // in tree.c -extern const uint8_t VP8CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS]; -extern const uint8_t - VP8CoeffsUpdateProba[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS]; -// Reset the token probabilities to their initial (default) values -void VP8DefaultProbas(VP8Encoder* const enc); -// Write the token probabilities -void VP8WriteProbas(VP8BitWriter* const bw, const VP8EncProba* const probas); -// Writes the partition #0 modes (that is: all intra modes) -void VP8CodeIntraModes(VP8Encoder* const enc); - - // in syntax.c -// Generates the final bitstream by coding the partition0 and headers, -// and appending an assembly of all the pre-coded token partitions. -// Return true if everything is ok. -int VP8EncWrite(VP8Encoder* const enc); -// Release memory allocated for bit-writing in VP8EncLoop & seq. -void VP8EncFreeBitWriters(VP8Encoder* const enc); - - // in frame.c -extern const uint8_t VP8Cat3[]; -extern const uint8_t VP8Cat4[]; -extern const uint8_t VP8Cat5[]; -extern const uint8_t VP8Cat6[]; - -// Form all the four Intra16x16 predictions in the yuv_p_ cache -void VP8MakeLuma16Preds(const VP8EncIterator* const it); -// Form all the four Chroma8x8 predictions in the yuv_p_ cache -void VP8MakeChroma8Preds(const VP8EncIterator* const it); -// Form all the ten Intra4x4 predictions in the yuv_p_ cache -// for the 4x4 block it->i4_ -void VP8MakeIntra4Preds(const VP8EncIterator* const it); -// Rate calculation -int VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd); -int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]); -int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd); -// Main coding calls -int VP8EncLoop(VP8Encoder* const enc); -int VP8EncTokenLoop(VP8Encoder* const enc); - - // in webpenc.c -// Assign an error code to a picture. Return false for convenience. -int WebPEncodingSetError(const WebPPicture* const pic, WebPEncodingError error); -int WebPReportProgress(const WebPPicture* const pic, - int percent, int* const percent_store); - - // in analysis.c -// Main analysis loop. Decides the segmentations and complexity. -// Assigns a first guess for Intra16 and uvmode_ prediction modes. -int VP8EncAnalyze(VP8Encoder* const enc); - - // in quant.c -// Sets up segment's quantization values, base_quant_ and filter strengths. -void VP8SetSegmentParams(VP8Encoder* const enc, float quality); -// Pick best modes and fills the levels. Returns true if skipped. -int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, - VP8RDLevel rd_opt); - - // in alpha.c -void VP8EncInitAlpha(VP8Encoder* const enc); // initialize alpha compression -int VP8EncStartAlpha(VP8Encoder* const enc); // start alpha coding process -int VP8EncFinishAlpha(VP8Encoder* const enc); // finalize compressed data -int VP8EncDeleteAlpha(VP8Encoder* const enc); // delete compressed data - - // in filter.c - -// SSIM utils -typedef struct { - double w, xm, ym, xxm, xym, yym; -} DistoStats; -void VP8SSIMAddStats(const DistoStats* const src, DistoStats* const dst); -void VP8SSIMAccumulatePlane(const uint8_t* src1, int stride1, - const uint8_t* src2, int stride2, - int W, int H, DistoStats* const stats); -double VP8SSIMGet(const DistoStats* const stats); -double VP8SSIMGetSquaredError(const DistoStats* const stats); - -// autofilter -void VP8InitFilter(VP8EncIterator* const it); -void VP8StoreFilterStats(VP8EncIterator* const it); -void VP8AdjustFilterStrength(VP8EncIterator* const it); - -// returns the approximate filtering strength needed to smooth a edge -// step of 'delta', given a sharpness parameter 'sharpness'. -int VP8FilterStrengthFromDelta(int sharpness, int delta); - - // misc utils for picture_*.c: - -// Remove reference to the ARGB/YUVA buffer (doesn't free anything). -void WebPPictureResetBuffers(WebPPicture* const picture); - -// Allocates ARGB buffer of given dimension (previous one is always free'd). -// Preserves the YUV(A) buffer. Returns false in case of error (invalid param, -// out-of-memory). -int WebPPictureAllocARGB(WebPPicture* const picture, int width, int height); - -// Allocates YUVA buffer of given dimension (previous one is always free'd). -// Uses picture->csp to determine whether an alpha buffer is needed. -// Preserves the ARGB buffer. -// Returns false in case of error (invalid param, out-of-memory). -int WebPPictureAllocYUVA(WebPPicture* const picture, int width, int height); - -// Clean-up the RGB samples under fully transparent area, to help lossless -// compressibility (no guarantee, though). Assumes that pic->use_argb is true. -void WebPCleanupTransparentAreaLossless(WebPPicture* const pic); - - // in near_lossless.c -// Near lossless preprocessing in RGB color-space. -int VP8ApplyNearLossless(int xsize, int ysize, uint32_t* argb, int quality); -// Near lossless adjustment for predictors. -void VP8ApplyNearLosslessPredict(int xsize, int ysize, int pred_bits, - const uint32_t* argb_orig, - uint32_t* argb, uint32_t* argb_scratch, - const uint32_t* const transform_data, - int quality, int subtract_green); -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_ENC_VP8ENCI_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/enc/vp8l.c b/Example-Mac/Pods/libwebp/src/enc/vp8l.c deleted file mode 100644 index db94e78a..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/vp8l.c +++ /dev/null @@ -1,1597 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// main entry for the lossless encoder. -// -// Author: Vikas Arora (vikaas.arora@gmail.com) -// - -#include -#include - -#include "./backward_references.h" -#include "./histogram.h" -#include "./vp8enci.h" -#include "./vp8li.h" -#include "../dsp/lossless.h" -#include "../utils/bit_writer.h" -#include "../utils/huffman_encode.h" -#include "../utils/utils.h" -#include "../webp/format_constants.h" - -#include "./delta_palettization.h" - -#define PALETTE_KEY_RIGHT_SHIFT 22 // Key for 1K buffer. -// Maximum number of histogram images (sub-blocks). -#define MAX_HUFF_IMAGE_SIZE 2600 - -// Palette reordering for smaller sum of deltas (and for smaller storage). - -static int PaletteCompareColorsForQsort(const void* p1, const void* p2) { - const uint32_t a = WebPMemToUint32(p1); - const uint32_t b = WebPMemToUint32(p2); - assert(a != b); - return (a < b) ? -1 : 1; -} - -static WEBP_INLINE uint32_t PaletteComponentDistance(uint32_t v) { - return (v <= 128) ? v : (256 - v); -} - -// Computes a value that is related to the entropy created by the -// palette entry diff. -// -// Note that the last & 0xff is a no-operation in the next statement, but -// removed by most compilers and is here only for regularity of the code. -static WEBP_INLINE uint32_t PaletteColorDistance(uint32_t col1, uint32_t col2) { - const uint32_t diff = VP8LSubPixels(col1, col2); - const int kMoreWeightForRGBThanForAlpha = 9; - uint32_t score; - score = PaletteComponentDistance((diff >> 0) & 0xff); - score += PaletteComponentDistance((diff >> 8) & 0xff); - score += PaletteComponentDistance((diff >> 16) & 0xff); - score *= kMoreWeightForRGBThanForAlpha; - score += PaletteComponentDistance((diff >> 24) & 0xff); - return score; -} - -static WEBP_INLINE void SwapColor(uint32_t* const col1, uint32_t* const col2) { - const uint32_t tmp = *col1; - *col1 = *col2; - *col2 = tmp; -} - -static void GreedyMinimizeDeltas(uint32_t palette[], int num_colors) { - // Find greedily always the closest color of the predicted color to minimize - // deltas in the palette. This reduces storage needs since the - // palette is stored with delta encoding. - uint32_t predict = 0x00000000; - int i, k; - for (i = 0; i < num_colors; ++i) { - int best_ix = i; - uint32_t best_score = ~0U; - for (k = i; k < num_colors; ++k) { - const uint32_t cur_score = PaletteColorDistance(palette[k], predict); - if (best_score > cur_score) { - best_score = cur_score; - best_ix = k; - } - } - SwapColor(&palette[best_ix], &palette[i]); - predict = palette[i]; - } -} - -// The palette has been sorted by alpha. This function checks if the other -// components of the palette have a monotonic development with regards to -// position in the palette. If all have monotonic development, there is -// no benefit to re-organize them greedily. A monotonic development -// would be spotted in green-only situations (like lossy alpha) or gray-scale -// images. -static int PaletteHasNonMonotonousDeltas(uint32_t palette[], int num_colors) { - uint32_t predict = 0x000000; - int i; - uint8_t sign_found = 0x00; - for (i = 0; i < num_colors; ++i) { - const uint32_t diff = VP8LSubPixels(palette[i], predict); - const uint8_t rd = (diff >> 16) & 0xff; - const uint8_t gd = (diff >> 8) & 0xff; - const uint8_t bd = (diff >> 0) & 0xff; - if (rd != 0x00) { - sign_found |= (rd < 0x80) ? 1 : 2; - } - if (gd != 0x00) { - sign_found |= (gd < 0x80) ? 8 : 16; - } - if (bd != 0x00) { - sign_found |= (bd < 0x80) ? 64 : 128; - } - predict = palette[i]; - } - return (sign_found & (sign_found << 1)) != 0; // two consequent signs. -} - -// ----------------------------------------------------------------------------- -// Palette - -// If number of colors in the image is less than or equal to MAX_PALETTE_SIZE, -// creates a palette and returns true, else returns false. -static int AnalyzeAndCreatePalette(const WebPPicture* const pic, - int low_effort, - uint32_t palette[MAX_PALETTE_SIZE], - int* const palette_size) { - int i, x, y, key; - int num_colors = 0; - uint8_t in_use[MAX_PALETTE_SIZE * 4] = { 0 }; - uint32_t colors[MAX_PALETTE_SIZE * 4]; - static const uint32_t kHashMul = 0x1e35a7bd; - const uint32_t* argb = pic->argb; - const int width = pic->width; - const int height = pic->height; - uint32_t last_pix = ~argb[0]; // so we're sure that last_pix != argb[0] - - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - if (argb[x] == last_pix) { - continue; - } - last_pix = argb[x]; - key = (kHashMul * last_pix) >> PALETTE_KEY_RIGHT_SHIFT; - while (1) { - if (!in_use[key]) { - colors[key] = last_pix; - in_use[key] = 1; - ++num_colors; - if (num_colors > MAX_PALETTE_SIZE) { - return 0; - } - break; - } else if (colors[key] == last_pix) { - // The color is already there. - break; - } else { - // Some other color sits there. - // Do linear conflict resolution. - ++key; - key &= (MAX_PALETTE_SIZE * 4 - 1); // key mask for 1K buffer. - } - } - } - argb += pic->argb_stride; - } - - // TODO(skal): could we reuse in_use[] to speed up EncodePalette()? - num_colors = 0; - for (i = 0; i < (int)(sizeof(in_use) / sizeof(in_use[0])); ++i) { - if (in_use[i]) { - palette[num_colors] = colors[i]; - ++num_colors; - } - } - *palette_size = num_colors; - qsort(palette, num_colors, sizeof(*palette), PaletteCompareColorsForQsort); - if (!low_effort && PaletteHasNonMonotonousDeltas(palette, num_colors)) { - GreedyMinimizeDeltas(palette, num_colors); - } - return 1; -} - -// These five modes are evaluated and their respective entropy is computed. -typedef enum { - kDirect = 0, - kSpatial = 1, - kSubGreen = 2, - kSpatialSubGreen = 3, - kPalette = 4, - kNumEntropyIx = 5 -} EntropyIx; - -typedef enum { - kHistoAlpha = 0, - kHistoAlphaPred, - kHistoGreen, - kHistoGreenPred, - kHistoRed, - kHistoRedPred, - kHistoBlue, - kHistoBluePred, - kHistoRedSubGreen, - kHistoRedPredSubGreen, - kHistoBlueSubGreen, - kHistoBluePredSubGreen, - kHistoPalette, - kHistoTotal // Must be last. -} HistoIx; - -static void AddSingleSubGreen(uint32_t p, uint32_t* r, uint32_t* b) { - const uint32_t green = p >> 8; // The upper bits are masked away later. - ++r[((p >> 16) - green) & 0xff]; - ++b[(p - green) & 0xff]; -} - -static void AddSingle(uint32_t p, - uint32_t* a, uint32_t* r, uint32_t* g, uint32_t* b) { - ++a[p >> 24]; - ++r[(p >> 16) & 0xff]; - ++g[(p >> 8) & 0xff]; - ++b[(p & 0xff)]; -} - -static int AnalyzeEntropy(const uint32_t* argb, - int width, int height, int argb_stride, - int use_palette, - EntropyIx* const min_entropy_ix, - int* const red_and_blue_always_zero) { - // Allocate histogram set with cache_bits = 0. - uint32_t* const histo = - (uint32_t*)WebPSafeCalloc(kHistoTotal, sizeof(*histo) * 256); - if (histo != NULL) { - int i, x, y; - const uint32_t* prev_row = argb; - const uint32_t* curr_row = argb + argb_stride; - for (y = 1; y < height; ++y) { - uint32_t prev_pix = curr_row[0]; - for (x = 1; x < width; ++x) { - const uint32_t pix = curr_row[x]; - const uint32_t pix_diff = VP8LSubPixels(pix, prev_pix); - if ((pix_diff == 0) || (pix == prev_row[x])) continue; - prev_pix = pix; - AddSingle(pix, - &histo[kHistoAlpha * 256], - &histo[kHistoRed * 256], - &histo[kHistoGreen * 256], - &histo[kHistoBlue * 256]); - AddSingle(pix_diff, - &histo[kHistoAlphaPred * 256], - &histo[kHistoRedPred * 256], - &histo[kHistoGreenPred * 256], - &histo[kHistoBluePred * 256]); - AddSingleSubGreen(pix, - &histo[kHistoRedSubGreen * 256], - &histo[kHistoBlueSubGreen * 256]); - AddSingleSubGreen(pix_diff, - &histo[kHistoRedPredSubGreen * 256], - &histo[kHistoBluePredSubGreen * 256]); - { - // Approximate the palette by the entropy of the multiplicative hash. - const int hash = ((pix + (pix >> 19)) * 0x39c5fba7) >> 24; - ++histo[kHistoPalette * 256 + (hash & 0xff)]; - } - } - prev_row = curr_row; - curr_row += argb_stride; - } - { - double entropy_comp[kHistoTotal]; - double entropy[kNumEntropyIx]; - EntropyIx k; - EntropyIx last_mode_to_analyze = - use_palette ? kPalette : kSpatialSubGreen; - int j; - // Let's add one zero to the predicted histograms. The zeros are removed - // too efficiently by the pix_diff == 0 comparison, at least one of the - // zeros is likely to exist. - ++histo[kHistoRedPredSubGreen * 256]; - ++histo[kHistoBluePredSubGreen * 256]; - ++histo[kHistoRedPred * 256]; - ++histo[kHistoGreenPred * 256]; - ++histo[kHistoBluePred * 256]; - ++histo[kHistoAlphaPred * 256]; - - for (j = 0; j < kHistoTotal; ++j) { - entropy_comp[j] = VP8LBitsEntropy(&histo[j * 256], 256, NULL); - } - entropy[kDirect] = entropy_comp[kHistoAlpha] + - entropy_comp[kHistoRed] + - entropy_comp[kHistoGreen] + - entropy_comp[kHistoBlue]; - entropy[kSpatial] = entropy_comp[kHistoAlphaPred] + - entropy_comp[kHistoRedPred] + - entropy_comp[kHistoGreenPred] + - entropy_comp[kHistoBluePred]; - entropy[kSubGreen] = entropy_comp[kHistoAlpha] + - entropy_comp[kHistoRedSubGreen] + - entropy_comp[kHistoGreen] + - entropy_comp[kHistoBlueSubGreen]; - entropy[kSpatialSubGreen] = entropy_comp[kHistoAlphaPred] + - entropy_comp[kHistoRedPredSubGreen] + - entropy_comp[kHistoGreenPred] + - entropy_comp[kHistoBluePredSubGreen]; - // Palette mode seems more efficient in a breakeven case. Bias with 1.0. - entropy[kPalette] = entropy_comp[kHistoPalette] - 1.0; - - *min_entropy_ix = kDirect; - for (k = kDirect + 1; k <= last_mode_to_analyze; ++k) { - if (entropy[*min_entropy_ix] > entropy[k]) { - *min_entropy_ix = k; - } - } - *red_and_blue_always_zero = 1; - // Let's check if the histogram of the chosen entropy mode has - // non-zero red and blue values. If all are zero, we can later skip - // the cross color optimization. - { - static const uint8_t kHistoPairs[5][2] = { - { kHistoRed, kHistoBlue }, - { kHistoRedPred, kHistoBluePred }, - { kHistoRedSubGreen, kHistoBlueSubGreen }, - { kHistoRedPredSubGreen, kHistoBluePredSubGreen }, - { kHistoRed, kHistoBlue } - }; - const uint32_t* const red_histo = - &histo[256 * kHistoPairs[*min_entropy_ix][0]]; - const uint32_t* const blue_histo = - &histo[256 * kHistoPairs[*min_entropy_ix][1]]; - for (i = 1; i < 256; ++i) { - if ((red_histo[i] | blue_histo[i]) != 0) { - *red_and_blue_always_zero = 0; - break; - } - } - } - } - free(histo); - return 1; - } else { - return 0; - } -} - -static int GetHistoBits(int method, int use_palette, int width, int height) { - // Make tile size a function of encoding method (Range: 0 to 6). - int histo_bits = (use_palette ? 9 : 7) - method; - while (1) { - const int huff_image_size = VP8LSubSampleSize(width, histo_bits) * - VP8LSubSampleSize(height, histo_bits); - if (huff_image_size <= MAX_HUFF_IMAGE_SIZE) break; - ++histo_bits; - } - return (histo_bits < MIN_HUFFMAN_BITS) ? MIN_HUFFMAN_BITS : - (histo_bits > MAX_HUFFMAN_BITS) ? MAX_HUFFMAN_BITS : histo_bits; -} - -static int GetTransformBits(int method, int histo_bits) { - const int max_transform_bits = (method < 4) ? 6 : (method > 4) ? 4 : 5; - return (histo_bits > max_transform_bits) ? max_transform_bits : histo_bits; -} - -static int AnalyzeAndInit(VP8LEncoder* const enc) { - const WebPPicture* const pic = enc->pic_; - const int width = pic->width; - const int height = pic->height; - const int pix_cnt = width * height; - const WebPConfig* const config = enc->config_; - const int method = config->method; - const int low_effort = (config->method == 0); - // we round the block size up, so we're guaranteed to have - // at max MAX_REFS_BLOCK_PER_IMAGE blocks used: - int refs_block_size = (pix_cnt - 1) / MAX_REFS_BLOCK_PER_IMAGE + 1; - assert(pic != NULL && pic->argb != NULL); - - enc->use_cross_color_ = 0; - enc->use_predict_ = 0; - enc->use_subtract_green_ = 0; - enc->use_palette_ = - AnalyzeAndCreatePalette(pic, low_effort, - enc->palette_, &enc->palette_size_); - - // TODO(jyrki): replace the decision to be based on an actual estimate - // of entropy, or even spatial variance of entropy. - enc->histo_bits_ = GetHistoBits(method, enc->use_palette_, - pic->width, pic->height); - enc->transform_bits_ = GetTransformBits(method, enc->histo_bits_); - - if (low_effort) { - // AnalyzeEntropy is somewhat slow. - enc->use_predict_ = !enc->use_palette_; - enc->use_subtract_green_ = !enc->use_palette_; - enc->use_cross_color_ = 0; - } else { - int red_and_blue_always_zero; - EntropyIx min_entropy_ix; - if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride, - enc->use_palette_, &min_entropy_ix, - &red_and_blue_always_zero)) { - return 0; - } - enc->use_palette_ = (min_entropy_ix == kPalette); - enc->use_subtract_green_ = - (min_entropy_ix == kSubGreen) || (min_entropy_ix == kSpatialSubGreen); - enc->use_predict_ = - (min_entropy_ix == kSpatial) || (min_entropy_ix == kSpatialSubGreen); - enc->use_cross_color_ = red_and_blue_always_zero ? 0 : enc->use_predict_; - } - - if (!VP8LHashChainInit(&enc->hash_chain_, pix_cnt)) return 0; - - // palette-friendly input typically uses less literals - // -> reduce block size a bit - if (enc->use_palette_) refs_block_size /= 2; - VP8LBackwardRefsInit(&enc->refs_[0], refs_block_size); - VP8LBackwardRefsInit(&enc->refs_[1], refs_block_size); - - return 1; -} - -// Returns false in case of memory error. -static int GetHuffBitLengthsAndCodes( - const VP8LHistogramSet* const histogram_image, - HuffmanTreeCode* const huffman_codes) { - int i, k; - int ok = 0; - uint64_t total_length_size = 0; - uint8_t* mem_buf = NULL; - const int histogram_image_size = histogram_image->size; - int max_num_symbols = 0; - uint8_t* buf_rle = NULL; - HuffmanTree* huff_tree = NULL; - - // Iterate over all histograms and get the aggregate number of codes used. - for (i = 0; i < histogram_image_size; ++i) { - const VP8LHistogram* const histo = histogram_image->histograms[i]; - HuffmanTreeCode* const codes = &huffman_codes[5 * i]; - for (k = 0; k < 5; ++k) { - const int num_symbols = - (k == 0) ? VP8LHistogramNumCodes(histo->palette_code_bits_) : - (k == 4) ? NUM_DISTANCE_CODES : 256; - codes[k].num_symbols = num_symbols; - total_length_size += num_symbols; - } - } - - // Allocate and Set Huffman codes. - { - uint16_t* codes; - uint8_t* lengths; - mem_buf = (uint8_t*)WebPSafeCalloc(total_length_size, - sizeof(*lengths) + sizeof(*codes)); - if (mem_buf == NULL) goto End; - - codes = (uint16_t*)mem_buf; - lengths = (uint8_t*)&codes[total_length_size]; - for (i = 0; i < 5 * histogram_image_size; ++i) { - const int bit_length = huffman_codes[i].num_symbols; - huffman_codes[i].codes = codes; - huffman_codes[i].code_lengths = lengths; - codes += bit_length; - lengths += bit_length; - if (max_num_symbols < bit_length) { - max_num_symbols = bit_length; - } - } - } - - buf_rle = (uint8_t*)WebPSafeMalloc(1ULL, max_num_symbols); - huff_tree = (HuffmanTree*)WebPSafeMalloc(3ULL * max_num_symbols, - sizeof(*huff_tree)); - if (buf_rle == NULL || huff_tree == NULL) goto End; - - // Create Huffman trees. - for (i = 0; i < histogram_image_size; ++i) { - HuffmanTreeCode* const codes = &huffman_codes[5 * i]; - VP8LHistogram* const histo = histogram_image->histograms[i]; - VP8LCreateHuffmanTree(histo->literal_, 15, buf_rle, huff_tree, codes + 0); - VP8LCreateHuffmanTree(histo->red_, 15, buf_rle, huff_tree, codes + 1); - VP8LCreateHuffmanTree(histo->blue_, 15, buf_rle, huff_tree, codes + 2); - VP8LCreateHuffmanTree(histo->alpha_, 15, buf_rle, huff_tree, codes + 3); - VP8LCreateHuffmanTree(histo->distance_, 15, buf_rle, huff_tree, codes + 4); - } - ok = 1; - End: - WebPSafeFree(huff_tree); - WebPSafeFree(buf_rle); - if (!ok) { - WebPSafeFree(mem_buf); - memset(huffman_codes, 0, 5 * histogram_image_size * sizeof(*huffman_codes)); - } - return ok; -} - -static void StoreHuffmanTreeOfHuffmanTreeToBitMask( - VP8LBitWriter* const bw, const uint8_t* code_length_bitdepth) { - // RFC 1951 will calm you down if you are worried about this funny sequence. - // This sequence is tuned from that, but more weighted for lower symbol count, - // and more spiking histograms. - static const uint8_t kStorageOrder[CODE_LENGTH_CODES] = { - 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - }; - int i; - // Throw away trailing zeros: - int codes_to_store = CODE_LENGTH_CODES; - for (; codes_to_store > 4; --codes_to_store) { - if (code_length_bitdepth[kStorageOrder[codes_to_store - 1]] != 0) { - break; - } - } - VP8LPutBits(bw, codes_to_store - 4, 4); - for (i = 0; i < codes_to_store; ++i) { - VP8LPutBits(bw, code_length_bitdepth[kStorageOrder[i]], 3); - } -} - -static void ClearHuffmanTreeIfOnlyOneSymbol( - HuffmanTreeCode* const huffman_code) { - int k; - int count = 0; - for (k = 0; k < huffman_code->num_symbols; ++k) { - if (huffman_code->code_lengths[k] != 0) { - ++count; - if (count > 1) return; - } - } - for (k = 0; k < huffman_code->num_symbols; ++k) { - huffman_code->code_lengths[k] = 0; - huffman_code->codes[k] = 0; - } -} - -static void StoreHuffmanTreeToBitMask( - VP8LBitWriter* const bw, - const HuffmanTreeToken* const tokens, const int num_tokens, - const HuffmanTreeCode* const huffman_code) { - int i; - for (i = 0; i < num_tokens; ++i) { - const int ix = tokens[i].code; - const int extra_bits = tokens[i].extra_bits; - VP8LPutBits(bw, huffman_code->codes[ix], huffman_code->code_lengths[ix]); - switch (ix) { - case 16: - VP8LPutBits(bw, extra_bits, 2); - break; - case 17: - VP8LPutBits(bw, extra_bits, 3); - break; - case 18: - VP8LPutBits(bw, extra_bits, 7); - break; - } - } -} - -// 'huff_tree' and 'tokens' are pre-alloacted buffers. -static void StoreFullHuffmanCode(VP8LBitWriter* const bw, - HuffmanTree* const huff_tree, - HuffmanTreeToken* const tokens, - const HuffmanTreeCode* const tree) { - uint8_t code_length_bitdepth[CODE_LENGTH_CODES] = { 0 }; - uint16_t code_length_bitdepth_symbols[CODE_LENGTH_CODES] = { 0 }; - const int max_tokens = tree->num_symbols; - int num_tokens; - HuffmanTreeCode huffman_code; - huffman_code.num_symbols = CODE_LENGTH_CODES; - huffman_code.code_lengths = code_length_bitdepth; - huffman_code.codes = code_length_bitdepth_symbols; - - VP8LPutBits(bw, 0, 1); - num_tokens = VP8LCreateCompressedHuffmanTree(tree, tokens, max_tokens); - { - uint32_t histogram[CODE_LENGTH_CODES] = { 0 }; - uint8_t buf_rle[CODE_LENGTH_CODES] = { 0 }; - int i; - for (i = 0; i < num_tokens; ++i) { - ++histogram[tokens[i].code]; - } - - VP8LCreateHuffmanTree(histogram, 7, buf_rle, huff_tree, &huffman_code); - } - - StoreHuffmanTreeOfHuffmanTreeToBitMask(bw, code_length_bitdepth); - ClearHuffmanTreeIfOnlyOneSymbol(&huffman_code); - { - int trailing_zero_bits = 0; - int trimmed_length = num_tokens; - int write_trimmed_length; - int length; - int i = num_tokens; - while (i-- > 0) { - const int ix = tokens[i].code; - if (ix == 0 || ix == 17 || ix == 18) { - --trimmed_length; // discount trailing zeros - trailing_zero_bits += code_length_bitdepth[ix]; - if (ix == 17) { - trailing_zero_bits += 3; - } else if (ix == 18) { - trailing_zero_bits += 7; - } - } else { - break; - } - } - write_trimmed_length = (trimmed_length > 1 && trailing_zero_bits > 12); - length = write_trimmed_length ? trimmed_length : num_tokens; - VP8LPutBits(bw, write_trimmed_length, 1); - if (write_trimmed_length) { - const int nbits = VP8LBitsLog2Ceiling(trimmed_length - 1); - const int nbitpairs = (nbits == 0) ? 1 : (nbits + 1) / 2; - VP8LPutBits(bw, nbitpairs - 1, 3); - assert(trimmed_length >= 2); - VP8LPutBits(bw, trimmed_length - 2, nbitpairs * 2); - } - StoreHuffmanTreeToBitMask(bw, tokens, length, &huffman_code); - } -} - -// 'huff_tree' and 'tokens' are pre-alloacted buffers. -static void StoreHuffmanCode(VP8LBitWriter* const bw, - HuffmanTree* const huff_tree, - HuffmanTreeToken* const tokens, - const HuffmanTreeCode* const huffman_code) { - int i; - int count = 0; - int symbols[2] = { 0, 0 }; - const int kMaxBits = 8; - const int kMaxSymbol = 1 << kMaxBits; - - // Check whether it's a small tree. - for (i = 0; i < huffman_code->num_symbols && count < 3; ++i) { - if (huffman_code->code_lengths[i] != 0) { - if (count < 2) symbols[count] = i; - ++count; - } - } - - if (count == 0) { // emit minimal tree for empty cases - // bits: small tree marker: 1, count-1: 0, large 8-bit code: 0, code: 0 - VP8LPutBits(bw, 0x01, 4); - } else if (count <= 2 && symbols[0] < kMaxSymbol && symbols[1] < kMaxSymbol) { - VP8LPutBits(bw, 1, 1); // Small tree marker to encode 1 or 2 symbols. - VP8LPutBits(bw, count - 1, 1); - if (symbols[0] <= 1) { - VP8LPutBits(bw, 0, 1); // Code bit for small (1 bit) symbol value. - VP8LPutBits(bw, symbols[0], 1); - } else { - VP8LPutBits(bw, 1, 1); - VP8LPutBits(bw, symbols[0], 8); - } - if (count == 2) { - VP8LPutBits(bw, symbols[1], 8); - } - } else { - StoreFullHuffmanCode(bw, huff_tree, tokens, huffman_code); - } -} - -static WEBP_INLINE void WriteHuffmanCode(VP8LBitWriter* const bw, - const HuffmanTreeCode* const code, - int code_index) { - const int depth = code->code_lengths[code_index]; - const int symbol = code->codes[code_index]; - VP8LPutBits(bw, symbol, depth); -} - -static WEBP_INLINE void WriteHuffmanCodeWithExtraBits( - VP8LBitWriter* const bw, - const HuffmanTreeCode* const code, - int code_index, - int bits, - int n_bits) { - const int depth = code->code_lengths[code_index]; - const int symbol = code->codes[code_index]; - VP8LPutBits(bw, (bits << depth) | symbol, depth + n_bits); -} - -static WebPEncodingError StoreImageToBitMask( - VP8LBitWriter* const bw, int width, int histo_bits, - VP8LBackwardRefs* const refs, - const uint16_t* histogram_symbols, - const HuffmanTreeCode* const huffman_codes) { - const int histo_xsize = histo_bits ? VP8LSubSampleSize(width, histo_bits) : 1; - const int tile_mask = (histo_bits == 0) ? 0 : -(1 << histo_bits); - // x and y trace the position in the image. - int x = 0; - int y = 0; - int tile_x = x & tile_mask; - int tile_y = y & tile_mask; - int histogram_ix = histogram_symbols[0]; - const HuffmanTreeCode* codes = huffman_codes + 5 * histogram_ix; - VP8LRefsCursor c = VP8LRefsCursorInit(refs); - while (VP8LRefsCursorOk(&c)) { - const PixOrCopy* const v = c.cur_pos; - if ((tile_x != (x & tile_mask)) || (tile_y != (y & tile_mask))) { - tile_x = x & tile_mask; - tile_y = y & tile_mask; - histogram_ix = histogram_symbols[(y >> histo_bits) * histo_xsize + - (x >> histo_bits)]; - codes = huffman_codes + 5 * histogram_ix; - } - if (PixOrCopyIsLiteral(v)) { - static const int order[] = { 1, 2, 0, 3 }; - int k; - for (k = 0; k < 4; ++k) { - const int code = PixOrCopyLiteral(v, order[k]); - WriteHuffmanCode(bw, codes + k, code); - } - } else if (PixOrCopyIsCacheIdx(v)) { - const int code = PixOrCopyCacheIdx(v); - const int literal_ix = 256 + NUM_LENGTH_CODES + code; - WriteHuffmanCode(bw, codes, literal_ix); - } else { - int bits, n_bits; - int code; - - const int distance = PixOrCopyDistance(v); - VP8LPrefixEncode(v->len, &code, &n_bits, &bits); - WriteHuffmanCodeWithExtraBits(bw, codes, 256 + code, bits, n_bits); - - // Don't write the distance with the extra bits code since - // the distance can be up to 18 bits of extra bits, and the prefix - // 15 bits, totaling to 33, and our PutBits only supports up to 32 bits. - // TODO(jyrki): optimize this further. - VP8LPrefixEncode(distance, &code, &n_bits, &bits); - WriteHuffmanCode(bw, codes + 4, code); - VP8LPutBits(bw, bits, n_bits); - } - x += PixOrCopyLength(v); - while (x >= width) { - x -= width; - ++y; - } - VP8LRefsCursorNext(&c); - } - return bw->error_ ? VP8_ENC_ERROR_OUT_OF_MEMORY : VP8_ENC_OK; -} - -// Special case of EncodeImageInternal() for cache-bits=0, histo_bits=31 -static WebPEncodingError EncodeImageNoHuffman(VP8LBitWriter* const bw, - const uint32_t* const argb, - VP8LHashChain* const hash_chain, - VP8LBackwardRefs refs_array[2], - int width, int height, - int quality) { - int i; - int max_tokens = 0; - WebPEncodingError err = VP8_ENC_OK; - VP8LBackwardRefs* refs; - HuffmanTreeToken* tokens = NULL; - HuffmanTreeCode huffman_codes[5] = { { 0, NULL, NULL } }; - const uint16_t histogram_symbols[1] = { 0 }; // only one tree, one symbol - int cache_bits = 0; - VP8LHistogramSet* histogram_image = NULL; - HuffmanTree* const huff_tree = (HuffmanTree*)WebPSafeMalloc( - 3ULL * CODE_LENGTH_CODES, sizeof(*huff_tree)); - if (huff_tree == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - // Calculate backward references from ARGB image. - refs = VP8LGetBackwardReferences(width, height, argb, quality, 0, &cache_bits, - hash_chain, refs_array); - if (refs == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - histogram_image = VP8LAllocateHistogramSet(1, cache_bits); - if (histogram_image == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - // Build histogram image and symbols from backward references. - VP8LHistogramStoreRefs(refs, histogram_image->histograms[0]); - - // Create Huffman bit lengths and codes for each histogram image. - assert(histogram_image->size == 1); - if (!GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - // No color cache, no Huffman image. - VP8LPutBits(bw, 0, 1); - - // Find maximum number of symbols for the huffman tree-set. - for (i = 0; i < 5; ++i) { - HuffmanTreeCode* const codes = &huffman_codes[i]; - if (max_tokens < codes->num_symbols) { - max_tokens = codes->num_symbols; - } - } - - tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, sizeof(*tokens)); - if (tokens == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - // Store Huffman codes. - for (i = 0; i < 5; ++i) { - HuffmanTreeCode* const codes = &huffman_codes[i]; - StoreHuffmanCode(bw, huff_tree, tokens, codes); - ClearHuffmanTreeIfOnlyOneSymbol(codes); - } - - // Store actual literals. - err = StoreImageToBitMask(bw, width, 0, refs, histogram_symbols, - huffman_codes); - - Error: - WebPSafeFree(tokens); - WebPSafeFree(huff_tree); - VP8LFreeHistogramSet(histogram_image); - WebPSafeFree(huffman_codes[0].codes); - return err; -} - -static WebPEncodingError EncodeImageInternal(VP8LBitWriter* const bw, - const uint32_t* const argb, - VP8LHashChain* const hash_chain, - VP8LBackwardRefs refs_array[2], - int width, int height, int quality, - int low_effort, int* cache_bits, - int histogram_bits, - size_t init_byte_position, - int* const hdr_size, - int* const data_size) { - WebPEncodingError err = VP8_ENC_OK; - const uint32_t histogram_image_xysize = - VP8LSubSampleSize(width, histogram_bits) * - VP8LSubSampleSize(height, histogram_bits); - VP8LHistogramSet* histogram_image = NULL; - VP8LHistogramSet* tmp_histos = NULL; - int histogram_image_size = 0; - size_t bit_array_size = 0; - HuffmanTree* huff_tree = NULL; - HuffmanTreeToken* tokens = NULL; - HuffmanTreeCode* huffman_codes = NULL; - VP8LBackwardRefs refs; - VP8LBackwardRefs* best_refs; - uint16_t* const histogram_symbols = - (uint16_t*)WebPSafeMalloc(histogram_image_xysize, - sizeof(*histogram_symbols)); - assert(histogram_bits >= MIN_HUFFMAN_BITS); - assert(histogram_bits <= MAX_HUFFMAN_BITS); - assert(hdr_size != NULL); - assert(data_size != NULL); - - VP8LBackwardRefsInit(&refs, refs_array[0].block_size_); - if (histogram_symbols == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - *cache_bits = MAX_COLOR_CACHE_BITS; - // 'best_refs' is the reference to the best backward refs and points to one - // of refs_array[0] or refs_array[1]. - // Calculate backward references from ARGB image. - best_refs = VP8LGetBackwardReferences(width, height, argb, quality, - low_effort, cache_bits, hash_chain, - refs_array); - if (best_refs == NULL || !VP8LBackwardRefsCopy(best_refs, &refs)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - histogram_image = - VP8LAllocateHistogramSet(histogram_image_xysize, *cache_bits); - tmp_histos = VP8LAllocateHistogramSet(2, *cache_bits); - if (histogram_image == NULL || tmp_histos == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - // Build histogram image and symbols from backward references. - if (!VP8LGetHistoImageSymbols(width, height, &refs, quality, low_effort, - histogram_bits, *cache_bits, histogram_image, - tmp_histos, histogram_symbols)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - // Create Huffman bit lengths and codes for each histogram image. - histogram_image_size = histogram_image->size; - bit_array_size = 5 * histogram_image_size; - huffman_codes = (HuffmanTreeCode*)WebPSafeCalloc(bit_array_size, - sizeof(*huffman_codes)); - // Note: some histogram_image entries may point to tmp_histos[], so the latter - // need to outlive the following call to GetHuffBitLengthsAndCodes(). - if (huffman_codes == NULL || - !GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - // Free combined histograms. - VP8LFreeHistogramSet(histogram_image); - histogram_image = NULL; - - // Free scratch histograms. - VP8LFreeHistogramSet(tmp_histos); - tmp_histos = NULL; - - // Color Cache parameters. - if (*cache_bits > 0) { - VP8LPutBits(bw, 1, 1); - VP8LPutBits(bw, *cache_bits, 4); - } else { - VP8LPutBits(bw, 0, 1); - } - - // Huffman image + meta huffman. - { - const int write_histogram_image = (histogram_image_size > 1); - VP8LPutBits(bw, write_histogram_image, 1); - if (write_histogram_image) { - uint32_t* const histogram_argb = - (uint32_t*)WebPSafeMalloc(histogram_image_xysize, - sizeof(*histogram_argb)); - int max_index = 0; - uint32_t i; - if (histogram_argb == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - for (i = 0; i < histogram_image_xysize; ++i) { - const int symbol_index = histogram_symbols[i] & 0xffff; - histogram_argb[i] = (symbol_index << 8); - if (symbol_index >= max_index) { - max_index = symbol_index + 1; - } - } - histogram_image_size = max_index; - - VP8LPutBits(bw, histogram_bits - 2, 3); - err = EncodeImageNoHuffman(bw, histogram_argb, hash_chain, refs_array, - VP8LSubSampleSize(width, histogram_bits), - VP8LSubSampleSize(height, histogram_bits), - quality); - WebPSafeFree(histogram_argb); - if (err != VP8_ENC_OK) goto Error; - } - } - - // Store Huffman codes. - { - int i; - int max_tokens = 0; - huff_tree = (HuffmanTree*)WebPSafeMalloc(3ULL * CODE_LENGTH_CODES, - sizeof(*huff_tree)); - if (huff_tree == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - // Find maximum number of symbols for the huffman tree-set. - for (i = 0; i < 5 * histogram_image_size; ++i) { - HuffmanTreeCode* const codes = &huffman_codes[i]; - if (max_tokens < codes->num_symbols) { - max_tokens = codes->num_symbols; - } - } - tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, - sizeof(*tokens)); - if (tokens == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - for (i = 0; i < 5 * histogram_image_size; ++i) { - HuffmanTreeCode* const codes = &huffman_codes[i]; - StoreHuffmanCode(bw, huff_tree, tokens, codes); - ClearHuffmanTreeIfOnlyOneSymbol(codes); - } - } - - *hdr_size = (int)(VP8LBitWriterNumBytes(bw) - init_byte_position); - // Store actual literals. - err = StoreImageToBitMask(bw, width, histogram_bits, &refs, - histogram_symbols, huffman_codes); - *data_size = - (int)(VP8LBitWriterNumBytes(bw) - init_byte_position - *hdr_size); - - Error: - WebPSafeFree(tokens); - WebPSafeFree(huff_tree); - VP8LFreeHistogramSet(histogram_image); - VP8LFreeHistogramSet(tmp_histos); - VP8LBackwardRefsClear(&refs); - if (huffman_codes != NULL) { - WebPSafeFree(huffman_codes->codes); - WebPSafeFree(huffman_codes); - } - WebPSafeFree(histogram_symbols); - return err; -} - -// ----------------------------------------------------------------------------- -// Transforms - -static void ApplySubtractGreen(VP8LEncoder* const enc, int width, int height, - VP8LBitWriter* const bw) { - VP8LPutBits(bw, TRANSFORM_PRESENT, 1); - VP8LPutBits(bw, SUBTRACT_GREEN, 2); - VP8LSubtractGreenFromBlueAndRed(enc->argb_, width * height); -} - -static WebPEncodingError ApplyPredictFilter(const VP8LEncoder* const enc, - int width, int height, - int quality, int low_effort, - VP8LBitWriter* const bw) { - const int pred_bits = enc->transform_bits_; - const int transform_width = VP8LSubSampleSize(width, pred_bits); - const int transform_height = VP8LSubSampleSize(height, pred_bits); - - VP8LResidualImage(width, height, pred_bits, low_effort, enc->argb_, - enc->argb_scratch_, enc->transform_data_, - enc->config_->exact); - VP8LPutBits(bw, TRANSFORM_PRESENT, 1); - VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2); - assert(pred_bits >= 2); - VP8LPutBits(bw, pred_bits - 2, 3); - return EncodeImageNoHuffman(bw, enc->transform_data_, - (VP8LHashChain*)&enc->hash_chain_, - (VP8LBackwardRefs*)enc->refs_, // cast const away - transform_width, transform_height, - quality); -} - -static WebPEncodingError ApplyCrossColorFilter(const VP8LEncoder* const enc, - int width, int height, - int quality, - VP8LBitWriter* const bw) { - const int ccolor_transform_bits = enc->transform_bits_; - const int transform_width = VP8LSubSampleSize(width, ccolor_transform_bits); - const int transform_height = VP8LSubSampleSize(height, ccolor_transform_bits); - - VP8LColorSpaceTransform(width, height, ccolor_transform_bits, quality, - enc->argb_, enc->transform_data_); - VP8LPutBits(bw, TRANSFORM_PRESENT, 1); - VP8LPutBits(bw, CROSS_COLOR_TRANSFORM, 2); - assert(ccolor_transform_bits >= 2); - VP8LPutBits(bw, ccolor_transform_bits - 2, 3); - return EncodeImageNoHuffman(bw, enc->transform_data_, - (VP8LHashChain*)&enc->hash_chain_, - (VP8LBackwardRefs*)enc->refs_, // cast const away - transform_width, transform_height, - quality); -} - -// ----------------------------------------------------------------------------- - -static WebPEncodingError WriteRiffHeader(const WebPPicture* const pic, - size_t riff_size, size_t vp8l_size) { - uint8_t riff[RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + VP8L_SIGNATURE_SIZE] = { - 'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P', - 'V', 'P', '8', 'L', 0, 0, 0, 0, VP8L_MAGIC_BYTE, - }; - PutLE32(riff + TAG_SIZE, (uint32_t)riff_size); - PutLE32(riff + RIFF_HEADER_SIZE + TAG_SIZE, (uint32_t)vp8l_size); - if (!pic->writer(riff, sizeof(riff), pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - return VP8_ENC_OK; -} - -static int WriteImageSize(const WebPPicture* const pic, - VP8LBitWriter* const bw) { - const int width = pic->width - 1; - const int height = pic->height - 1; - assert(width < WEBP_MAX_DIMENSION && height < WEBP_MAX_DIMENSION); - - VP8LPutBits(bw, width, VP8L_IMAGE_SIZE_BITS); - VP8LPutBits(bw, height, VP8L_IMAGE_SIZE_BITS); - return !bw->error_; -} - -static int WriteRealAlphaAndVersion(VP8LBitWriter* const bw, int has_alpha) { - VP8LPutBits(bw, has_alpha, 1); - VP8LPutBits(bw, VP8L_VERSION, VP8L_VERSION_BITS); - return !bw->error_; -} - -static WebPEncodingError WriteImage(const WebPPicture* const pic, - VP8LBitWriter* const bw, - size_t* const coded_size) { - WebPEncodingError err = VP8_ENC_OK; - const uint8_t* const webpll_data = VP8LBitWriterFinish(bw); - const size_t webpll_size = VP8LBitWriterNumBytes(bw); - const size_t vp8l_size = VP8L_SIGNATURE_SIZE + webpll_size; - const size_t pad = vp8l_size & 1; - const size_t riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8l_size + pad; - - err = WriteRiffHeader(pic, riff_size, vp8l_size); - if (err != VP8_ENC_OK) goto Error; - - if (!pic->writer(webpll_data, webpll_size, pic)) { - err = VP8_ENC_ERROR_BAD_WRITE; - goto Error; - } - - if (pad) { - const uint8_t pad_byte[1] = { 0 }; - if (!pic->writer(pad_byte, 1, pic)) { - err = VP8_ENC_ERROR_BAD_WRITE; - goto Error; - } - } - *coded_size = CHUNK_HEADER_SIZE + riff_size; - return VP8_ENC_OK; - - Error: - return err; -} - -// ----------------------------------------------------------------------------- - -// Allocates the memory for argb (W x H) buffer, 2 rows of context for -// prediction and transform data. -// Flags influencing the memory allocated: -// enc->transform_bits_ -// enc->use_predict_, enc->use_cross_color_ -static WebPEncodingError AllocateTransformBuffer(VP8LEncoder* const enc, - int width, int height) { - WebPEncodingError err = VP8_ENC_OK; - if (enc->argb_ == NULL) { - const int tile_size = 1 << enc->transform_bits_; - const uint64_t image_size = width * height; - // Ensure enough size for tiles, as well as for two scanlines and two - // extra pixels for CopyImageWithPrediction. - const uint64_t argb_scratch_size = - enc->use_predict_ ? tile_size * width + width + 2 : 0; - const int transform_data_size = - (enc->use_predict_ || enc->use_cross_color_) - ? VP8LSubSampleSize(width, enc->transform_bits_) * - VP8LSubSampleSize(height, enc->transform_bits_) - : 0; - const uint64_t total_size = - image_size + WEBP_ALIGN_CST + - argb_scratch_size + WEBP_ALIGN_CST + - (uint64_t)transform_data_size; - uint32_t* mem = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*mem)); - if (mem == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - enc->argb_ = mem; - mem = (uint32_t*)WEBP_ALIGN(mem + image_size); - enc->argb_scratch_ = mem; - mem = (uint32_t*)WEBP_ALIGN(mem + argb_scratch_size); - enc->transform_data_ = mem; - enc->current_width_ = width; - } - Error: - return err; -} - -static void ClearTransformBuffer(VP8LEncoder* const enc) { - WebPSafeFree(enc->argb_); - enc->argb_ = NULL; -} - -static WebPEncodingError MakeInputImageCopy(VP8LEncoder* const enc) { - WebPEncodingError err = VP8_ENC_OK; - const WebPPicture* const picture = enc->pic_; - const int width = picture->width; - const int height = picture->height; - int y; - err = AllocateTransformBuffer(enc, width, height); - if (err != VP8_ENC_OK) return err; - for (y = 0; y < height; ++y) { - memcpy(enc->argb_ + y * width, - picture->argb + y * picture->argb_stride, - width * sizeof(*enc->argb_)); - } - assert(enc->current_width_ == width); - return VP8_ENC_OK; -} - -// ----------------------------------------------------------------------------- - -static void MapToPalette(const uint32_t palette[], int num_colors, - uint32_t* const last_pix, int* const last_idx, - const uint32_t* src, uint8_t* dst, int width) { - int x; - int prev_idx = *last_idx; - uint32_t prev_pix = *last_pix; - for (x = 0; x < width; ++x) { - const uint32_t pix = src[x]; - if (pix != prev_pix) { - int i; - for (i = 0; i < num_colors; ++i) { - if (pix == palette[i]) { - prev_idx = i; - prev_pix = pix; - break; - } - } - } - dst[x] = prev_idx; - } - *last_idx = prev_idx; - *last_pix = prev_pix; -} - -// Remap argb values in src[] to packed palettes entries in dst[] -// using 'row' as a temporary buffer of size 'width'. -// We assume that all src[] values have a corresponding entry in the palette. -// Note: src[] can be the same as dst[] -static WebPEncodingError ApplyPalette(const uint32_t* src, uint32_t src_stride, - uint32_t* dst, uint32_t dst_stride, - const uint32_t* palette, int palette_size, - int width, int height, int xbits) { - // TODO(skal): this tmp buffer is not needed if VP8LBundleColorMap() can be - // made to work in-place. - uint8_t* const tmp_row = (uint8_t*)WebPSafeMalloc(width, sizeof(*tmp_row)); - int i, x, y; - int use_LUT = 1; - - if (tmp_row == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY; - for (i = 0; i < palette_size; ++i) { - if ((palette[i] & 0xffff00ffu) != 0) { - use_LUT = 0; - break; - } - } - - if (use_LUT) { - uint8_t inv_palette[MAX_PALETTE_SIZE] = { 0 }; - for (i = 0; i < palette_size; ++i) { - const int color = (palette[i] >> 8) & 0xff; - inv_palette[color] = i; - } - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - const int color = (src[x] >> 8) & 0xff; - tmp_row[x] = inv_palette[color]; - } - VP8LBundleColorMap(tmp_row, width, xbits, dst); - src += src_stride; - dst += dst_stride; - } - } else { - // Use 1 pixel cache for ARGB pixels. - uint32_t last_pix = palette[0]; - int last_idx = 0; - for (y = 0; y < height; ++y) { - MapToPalette(palette, palette_size, &last_pix, &last_idx, - src, tmp_row, width); - VP8LBundleColorMap(tmp_row, width, xbits, dst); - src += src_stride; - dst += dst_stride; - } - } - WebPSafeFree(tmp_row); - return VP8_ENC_OK; -} - -// Note: Expects "enc->palette_" to be set properly. -static WebPEncodingError MapImageFromPalette(VP8LEncoder* const enc, - int in_place) { - WebPEncodingError err = VP8_ENC_OK; - const WebPPicture* const pic = enc->pic_; - const int width = pic->width; - const int height = pic->height; - const uint32_t* const palette = enc->palette_; - const uint32_t* src = in_place ? enc->argb_ : pic->argb; - const int src_stride = in_place ? enc->current_width_ : pic->argb_stride; - const int palette_size = enc->palette_size_; - int xbits; - - // Replace each input pixel by corresponding palette index. - // This is done line by line. - if (palette_size <= 4) { - xbits = (palette_size <= 2) ? 3 : 2; - } else { - xbits = (palette_size <= 16) ? 1 : 0; - } - - err = AllocateTransformBuffer(enc, VP8LSubSampleSize(width, xbits), height); - if (err != VP8_ENC_OK) return err; - - err = ApplyPalette(src, src_stride, - enc->argb_, enc->current_width_, - palette, palette_size, width, height, xbits); - return err; -} - -// Save palette_[] to bitstream. -static WebPEncodingError EncodePalette(VP8LBitWriter* const bw, - VP8LEncoder* const enc) { - int i; - uint32_t tmp_palette[MAX_PALETTE_SIZE]; - const int palette_size = enc->palette_size_; - const uint32_t* const palette = enc->palette_; - VP8LPutBits(bw, TRANSFORM_PRESENT, 1); - VP8LPutBits(bw, COLOR_INDEXING_TRANSFORM, 2); - assert(palette_size >= 1 && palette_size <= MAX_PALETTE_SIZE); - VP8LPutBits(bw, palette_size - 1, 8); - for (i = palette_size - 1; i >= 1; --i) { - tmp_palette[i] = VP8LSubPixels(palette[i], palette[i - 1]); - } - tmp_palette[0] = palette[0]; - return EncodeImageNoHuffman(bw, tmp_palette, &enc->hash_chain_, enc->refs_, - palette_size, 1, 20 /* quality */); -} - -#ifdef WEBP_EXPERIMENTAL_FEATURES - -static WebPEncodingError EncodeDeltaPalettePredictorImage( - VP8LBitWriter* const bw, VP8LEncoder* const enc, int quality) { - const WebPPicture* const pic = enc->pic_; - const int width = pic->width; - const int height = pic->height; - - const int pred_bits = 5; - const int transform_width = VP8LSubSampleSize(width, pred_bits); - const int transform_height = VP8LSubSampleSize(height, pred_bits); - const int pred = 7; // default is Predictor7 (Top/Left Average) - const int tiles_per_row = VP8LSubSampleSize(width, pred_bits); - const int tiles_per_col = VP8LSubSampleSize(height, pred_bits); - uint32_t* predictors; - int tile_x, tile_y; - WebPEncodingError err = VP8_ENC_OK; - - predictors = (uint32_t*)WebPSafeMalloc(tiles_per_col * tiles_per_row, - sizeof(*predictors)); - if (predictors == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY; - - for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) { - for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) { - predictors[tile_y * tiles_per_row + tile_x] = 0xff000000u | (pred << 8); - } - } - - VP8LPutBits(bw, TRANSFORM_PRESENT, 1); - VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2); - VP8LPutBits(bw, pred_bits - 2, 3); - err = EncodeImageNoHuffman(bw, predictors, &enc->hash_chain_, - (VP8LBackwardRefs*)enc->refs_, // cast const away - transform_width, transform_height, - quality); - WebPSafeFree(predictors); - return err; -} - -#endif // WEBP_EXPERIMENTAL_FEATURES - -// ----------------------------------------------------------------------------- -// VP8LEncoder - -static VP8LEncoder* VP8LEncoderNew(const WebPConfig* const config, - const WebPPicture* const picture) { - VP8LEncoder* const enc = (VP8LEncoder*)WebPSafeCalloc(1ULL, sizeof(*enc)); - if (enc == NULL) { - WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); - return NULL; - } - enc->config_ = config; - enc->pic_ = picture; - - VP8LEncDspInit(); - - return enc; -} - -static void VP8LEncoderDelete(VP8LEncoder* enc) { - if (enc != NULL) { - VP8LHashChainClear(&enc->hash_chain_); - VP8LBackwardRefsClear(&enc->refs_[0]); - VP8LBackwardRefsClear(&enc->refs_[1]); - ClearTransformBuffer(enc); - WebPSafeFree(enc); - } -} - -// ----------------------------------------------------------------------------- -// Main call - -WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, - const WebPPicture* const picture, - VP8LBitWriter* const bw) { - WebPEncodingError err = VP8_ENC_OK; - const int quality = (int)config->quality; - const int low_effort = (config->method == 0); - const int width = picture->width; - const int height = picture->height; - VP8LEncoder* const enc = VP8LEncoderNew(config, picture); - const size_t byte_position = VP8LBitWriterNumBytes(bw); - int use_near_lossless = 0; - int hdr_size = 0; - int data_size = 0; - int use_delta_palettization = 0; - - if (enc == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - // --------------------------------------------------------------------------- - // Analyze image (entropy, num_palettes etc) - - if (!AnalyzeAndInit(enc)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - // Apply near-lossless preprocessing. - use_near_lossless = !enc->use_palette_ && (config->near_lossless < 100); - if (use_near_lossless) { - if (!VP8ApplyNearLossless(width, height, picture->argb, - config->near_lossless)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - } - -#ifdef WEBP_EXPERIMENTAL_FEATURES - if (config->delta_palettization) { - enc->use_predict_ = 1; - enc->use_cross_color_ = 0; - enc->use_subtract_green_ = 0; - enc->use_palette_ = 1; - err = MakeInputImageCopy(enc); - if (err != VP8_ENC_OK) goto Error; - err = WebPSearchOptimalDeltaPalette(enc); - if (err != VP8_ENC_OK) goto Error; - if (enc->use_palette_) { - err = AllocateTransformBuffer(enc, width, height); - if (err != VP8_ENC_OK) goto Error; - err = EncodeDeltaPalettePredictorImage(bw, enc, quality); - if (err != VP8_ENC_OK) goto Error; - use_delta_palettization = 1; - } - } -#endif // WEBP_EXPERIMENTAL_FEATURES - - // Encode palette - if (enc->use_palette_) { - err = EncodePalette(bw, enc); - if (err != VP8_ENC_OK) goto Error; - err = MapImageFromPalette(enc, use_delta_palettization); - if (err != VP8_ENC_OK) goto Error; - } - if (!use_delta_palettization) { - // In case image is not packed. - if (enc->argb_ == NULL) { - err = MakeInputImageCopy(enc); - if (err != VP8_ENC_OK) goto Error; - } - - // ------------------------------------------------------------------------- - // Apply transforms and write transform data. - - if (enc->use_subtract_green_) { - ApplySubtractGreen(enc, enc->current_width_, height, bw); - } - - if (enc->use_predict_) { - err = ApplyPredictFilter(enc, enc->current_width_, height, quality, - low_effort, bw); - if (err != VP8_ENC_OK) goto Error; - } - - if (enc->use_cross_color_) { - err = ApplyCrossColorFilter(enc, enc->current_width_, - height, quality, bw); - if (err != VP8_ENC_OK) goto Error; - } - } - - VP8LPutBits(bw, !TRANSFORM_PRESENT, 1); // No more transforms. - - // --------------------------------------------------------------------------- - // Encode and write the transformed image. - err = EncodeImageInternal(bw, enc->argb_, &enc->hash_chain_, enc->refs_, - enc->current_width_, height, quality, low_effort, - &enc->cache_bits_, enc->histo_bits_, byte_position, - &hdr_size, &data_size); - if (err != VP8_ENC_OK) goto Error; - - if (picture->stats != NULL) { - WebPAuxStats* const stats = picture->stats; - stats->lossless_features = 0; - if (enc->use_predict_) stats->lossless_features |= 1; - if (enc->use_cross_color_) stats->lossless_features |= 2; - if (enc->use_subtract_green_) stats->lossless_features |= 4; - if (enc->use_palette_) stats->lossless_features |= 8; - stats->histogram_bits = enc->histo_bits_; - stats->transform_bits = enc->transform_bits_; - stats->cache_bits = enc->cache_bits_; - stats->palette_size = enc->palette_size_; - stats->lossless_size = (int)(VP8LBitWriterNumBytes(bw) - byte_position); - stats->lossless_hdr_size = hdr_size; - stats->lossless_data_size = data_size; - } - - Error: - VP8LEncoderDelete(enc); - return err; -} - -int VP8LEncodeImage(const WebPConfig* const config, - const WebPPicture* const picture) { - int width, height; - int has_alpha; - size_t coded_size; - int percent = 0; - int initial_size; - WebPEncodingError err = VP8_ENC_OK; - VP8LBitWriter bw; - - if (picture == NULL) return 0; - - if (config == NULL || picture->argb == NULL) { - err = VP8_ENC_ERROR_NULL_PARAMETER; - WebPEncodingSetError(picture, err); - return 0; - } - - width = picture->width; - height = picture->height; - // Initialize BitWriter with size corresponding to 16 bpp to photo images and - // 8 bpp for graphical images. - initial_size = (config->image_hint == WEBP_HINT_GRAPH) ? - width * height : width * height * 2; - if (!VP8LBitWriterInit(&bw, initial_size)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - if (!WebPReportProgress(picture, 1, &percent)) { - UserAbort: - err = VP8_ENC_ERROR_USER_ABORT; - goto Error; - } - // Reset stats (for pure lossless coding) - if (picture->stats != NULL) { - WebPAuxStats* const stats = picture->stats; - memset(stats, 0, sizeof(*stats)); - stats->PSNR[0] = 99.f; - stats->PSNR[1] = 99.f; - stats->PSNR[2] = 99.f; - stats->PSNR[3] = 99.f; - stats->PSNR[4] = 99.f; - } - - // Write image size. - if (!WriteImageSize(picture, &bw)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - has_alpha = WebPPictureHasTransparency(picture); - // Write the non-trivial Alpha flag and lossless version. - if (!WriteRealAlphaAndVersion(&bw, has_alpha)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - if (!WebPReportProgress(picture, 5, &percent)) goto UserAbort; - - // Encode main image stream. - err = VP8LEncodeStream(config, picture, &bw); - if (err != VP8_ENC_OK) goto Error; - - // TODO(skal): have a fine-grained progress report in VP8LEncodeStream(). - if (!WebPReportProgress(picture, 90, &percent)) goto UserAbort; - - // Finish the RIFF chunk. - err = WriteImage(picture, &bw, &coded_size); - if (err != VP8_ENC_OK) goto Error; - - if (!WebPReportProgress(picture, 100, &percent)) goto UserAbort; - - // Save size. - if (picture->stats != NULL) { - picture->stats->coded_size += (int)coded_size; - picture->stats->lossless_size = (int)coded_size; - } - - if (picture->extra_info != NULL) { - const int mb_w = (width + 15) >> 4; - const int mb_h = (height + 15) >> 4; - memset(picture->extra_info, 0, mb_w * mb_h * sizeof(*picture->extra_info)); - } - - Error: - if (bw.error_) err = VP8_ENC_ERROR_OUT_OF_MEMORY; - VP8LBitWriterWipeOut(&bw); - if (err != VP8_ENC_OK) { - WebPEncodingSetError(picture, err); - return 0; - } - return 1; -} - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/enc/vp8li.h b/Example-Mac/Pods/libwebp/src/enc/vp8li.h deleted file mode 100644 index 6b6db127..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/vp8li.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Lossless encoder: internal header. -// -// Author: Vikas Arora (vikaas.arora@gmail.com) - -#ifndef WEBP_ENC_VP8LI_H_ -#define WEBP_ENC_VP8LI_H_ - -#include "./backward_references.h" -#include "./histogram.h" -#include "../utils/bit_writer.h" -#include "../webp/encode.h" -#include "../webp/format_constants.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - const WebPConfig* config_; // user configuration and parameters - const WebPPicture* pic_; // input picture. - - uint32_t* argb_; // Transformed argb image data. - uint32_t* argb_scratch_; // Scratch memory for argb rows - // (used for prediction). - uint32_t* transform_data_; // Scratch memory for transform data. - int current_width_; // Corresponds to packed image width. - - // Encoding parameters derived from quality parameter. - int histo_bits_; - int transform_bits_; - int cache_bits_; // If equal to 0, don't use color cache. - - // Encoding parameters derived from image characteristics. - int use_cross_color_; - int use_subtract_green_; - int use_predict_; - int use_palette_; - int palette_size_; - uint32_t palette_[MAX_PALETTE_SIZE]; - - // Some 'scratch' (potentially large) objects. - struct VP8LBackwardRefs refs_[2]; // Backward Refs array corresponding to - // LZ77 & RLE coding. - VP8LHashChain hash_chain_; // HashChain data for constructing - // backward references. -} VP8LEncoder; - -//------------------------------------------------------------------------------ -// internal functions. Not public. - -// Encodes the picture. -// Returns 0 if config or picture is NULL or picture doesn't have valid argb -// input. -int VP8LEncodeImage(const WebPConfig* const config, - const WebPPicture* const picture); - -// Encodes the main image stream using the supplied bit writer. -WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, - const WebPPicture* const picture, - VP8LBitWriter* const bw); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_ENC_VP8LI_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/enc/webpenc.c b/Example-Mac/Pods/libwebp/src/enc/webpenc.c deleted file mode 100644 index fece7369..00000000 --- a/Example-Mac/Pods/libwebp/src/enc/webpenc.c +++ /dev/null @@ -1,391 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// WebP encoder: main entry point -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include -#include -#include - -#include "./cost.h" -#include "./vp8enci.h" -#include "./vp8li.h" -#include "../utils/utils.h" - -// #define PRINT_MEMORY_INFO - -#ifdef PRINT_MEMORY_INFO -#include -#endif - -//------------------------------------------------------------------------------ - -int WebPGetEncoderVersion(void) { - return (ENC_MAJ_VERSION << 16) | (ENC_MIN_VERSION << 8) | ENC_REV_VERSION; -} - -//------------------------------------------------------------------------------ -// VP8Encoder -//------------------------------------------------------------------------------ - -static void ResetSegmentHeader(VP8Encoder* const enc) { - VP8EncSegmentHeader* const hdr = &enc->segment_hdr_; - hdr->num_segments_ = enc->config_->segments; - hdr->update_map_ = (hdr->num_segments_ > 1); - hdr->size_ = 0; -} - -static void ResetFilterHeader(VP8Encoder* const enc) { - VP8EncFilterHeader* const hdr = &enc->filter_hdr_; - hdr->simple_ = 1; - hdr->level_ = 0; - hdr->sharpness_ = 0; - hdr->i4x4_lf_delta_ = 0; -} - -static void ResetBoundaryPredictions(VP8Encoder* const enc) { - // init boundary values once for all - // Note: actually, initializing the preds_[] is only needed for intra4. - int i; - uint8_t* const top = enc->preds_ - enc->preds_w_; - uint8_t* const left = enc->preds_ - 1; - for (i = -1; i < 4 * enc->mb_w_; ++i) { - top[i] = B_DC_PRED; - } - for (i = 0; i < 4 * enc->mb_h_; ++i) { - left[i * enc->preds_w_] = B_DC_PRED; - } - enc->nz_[-1] = 0; // constant -} - -// Mapping from config->method_ to coding tools used. -//-------------------+---+---+---+---+---+---+---+ -// Method | 0 | 1 | 2 | 3 |(4)| 5 | 6 | -//-------------------+---+---+---+---+---+---+---+ -// fast probe | x | | | x | | | | -//-------------------+---+---+---+---+---+---+---+ -// dynamic proba | ~ | x | x | x | x | x | x | -//-------------------+---+---+---+---+---+---+---+ -// fast mode analysis| | | | | x | x | x | -//-------------------+---+---+---+---+---+---+---+ -// basic rd-opt | | | | x | x | x | x | -//-------------------+---+---+---+---+---+---+---+ -// disto-refine i4/16| x | x | x | | | | | -//-------------------+---+---+---+---+---+---+---+ -// disto-refine uv | | x | x | | | | | -//-------------------+---+---+---+---+---+---+---+ -// rd-opt i4/16 | | | ~ | x | x | x | x | -//-------------------+---+---+---+---+---+---+---+ -// token buffer (opt)| | | | x | x | x | x | -//-------------------+---+---+---+---+---+---+---+ -// Trellis | | | | | | x |Ful| -//-------------------+---+---+---+---+---+---+---+ -// full-SNS | | | | | x | x | x | -//-------------------+---+---+---+---+---+---+---+ - -static void MapConfigToTools(VP8Encoder* const enc) { - const WebPConfig* const config = enc->config_; - const int method = config->method; - const int limit = 100 - config->partition_limit; - enc->method_ = method; - enc->rd_opt_level_ = (method >= 6) ? RD_OPT_TRELLIS_ALL - : (method >= 5) ? RD_OPT_TRELLIS - : (method >= 3) ? RD_OPT_BASIC - : RD_OPT_NONE; - enc->max_i4_header_bits_ = - 256 * 16 * 16 * // upper bound: up to 16bit per 4x4 block - (limit * limit) / (100 * 100); // ... modulated with a quadratic curve. - - enc->thread_level_ = config->thread_level; - - enc->do_search_ = (config->target_size > 0 || config->target_PSNR > 0); - if (!config->low_memory) { -#if !defined(DISABLE_TOKEN_BUFFER) - enc->use_tokens_ = (enc->rd_opt_level_ >= RD_OPT_BASIC); // need rd stats -#endif - if (enc->use_tokens_) { - enc->num_parts_ = 1; // doesn't work with multi-partition - } - } -} - -// Memory scaling with dimensions: -// memory (bytes) ~= 2.25 * w + 0.0625 * w * h -// -// Typical memory footprint (614x440 picture) -// encoder: 22111 -// info: 4368 -// preds: 17741 -// top samples: 1263 -// non-zero: 175 -// lf-stats: 0 -// total: 45658 -// Transient object sizes: -// VP8EncIterator: 3360 -// VP8ModeScore: 872 -// VP8SegmentInfo: 732 -// VP8EncProba: 18352 -// LFStats: 2048 -// Picture size (yuv): 419328 - -static VP8Encoder* InitVP8Encoder(const WebPConfig* const config, - WebPPicture* const picture) { - VP8Encoder* enc; - const int use_filter = - (config->filter_strength > 0) || (config->autofilter > 0); - const int mb_w = (picture->width + 15) >> 4; - const int mb_h = (picture->height + 15) >> 4; - const int preds_w = 4 * mb_w + 1; - const int preds_h = 4 * mb_h + 1; - const size_t preds_size = preds_w * preds_h * sizeof(*enc->preds_); - const int top_stride = mb_w * 16; - const size_t nz_size = (mb_w + 1) * sizeof(*enc->nz_) + WEBP_ALIGN_CST; - const size_t info_size = mb_w * mb_h * sizeof(*enc->mb_info_); - const size_t samples_size = - 2 * top_stride * sizeof(*enc->y_top_) // top-luma/u/v - + WEBP_ALIGN_CST; // align all - const size_t lf_stats_size = - config->autofilter ? sizeof(*enc->lf_stats_) + WEBP_ALIGN_CST : 0; - uint8_t* mem; - const uint64_t size = (uint64_t)sizeof(*enc) // main struct - + WEBP_ALIGN_CST // cache alignment - + info_size // modes info - + preds_size // prediction modes - + samples_size // top/left samples - + nz_size // coeff context bits - + lf_stats_size; // autofilter stats - -#ifdef PRINT_MEMORY_INFO - printf("===================================\n"); - printf("Memory used:\n" - " encoder: %ld\n" - " info: %ld\n" - " preds: %ld\n" - " top samples: %ld\n" - " non-zero: %ld\n" - " lf-stats: %ld\n" - " total: %ld\n", - sizeof(*enc) + WEBP_ALIGN_CST, info_size, - preds_size, samples_size, nz_size, lf_stats_size, size); - printf("Transient object sizes:\n" - " VP8EncIterator: %ld\n" - " VP8ModeScore: %ld\n" - " VP8SegmentInfo: %ld\n" - " VP8EncProba: %ld\n" - " LFStats: %ld\n", - sizeof(VP8EncIterator), sizeof(VP8ModeScore), - sizeof(VP8SegmentInfo), sizeof(VP8EncProba), - sizeof(LFStats)); - printf("Picture size (yuv): %ld\n", - mb_w * mb_h * 384 * sizeof(uint8_t)); - printf("===================================\n"); -#endif - mem = (uint8_t*)WebPSafeMalloc(size, sizeof(*mem)); - if (mem == NULL) { - WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); - return NULL; - } - enc = (VP8Encoder*)mem; - mem = (uint8_t*)WEBP_ALIGN(mem + sizeof(*enc)); - memset(enc, 0, sizeof(*enc)); - enc->num_parts_ = 1 << config->partitions; - enc->mb_w_ = mb_w; - enc->mb_h_ = mb_h; - enc->preds_w_ = preds_w; - enc->mb_info_ = (VP8MBInfo*)mem; - mem += info_size; - enc->preds_ = ((uint8_t*)mem) + 1 + enc->preds_w_; - mem += preds_size; - enc->nz_ = 1 + (uint32_t*)WEBP_ALIGN(mem); - mem += nz_size; - enc->lf_stats_ = lf_stats_size ? (LFStats*)WEBP_ALIGN(mem) : NULL; - mem += lf_stats_size; - - // top samples (all 16-aligned) - mem = (uint8_t*)WEBP_ALIGN(mem); - enc->y_top_ = (uint8_t*)mem; - enc->uv_top_ = enc->y_top_ + top_stride; - mem += 2 * top_stride; - assert(mem <= (uint8_t*)enc + size); - - enc->config_ = config; - enc->profile_ = use_filter ? ((config->filter_type == 1) ? 0 : 1) : 2; - enc->pic_ = picture; - enc->percent_ = 0; - - MapConfigToTools(enc); - VP8EncDspInit(); - VP8DefaultProbas(enc); - ResetSegmentHeader(enc); - ResetFilterHeader(enc); - ResetBoundaryPredictions(enc); - VP8EncDspCostInit(); - VP8EncInitAlpha(enc); - - // lower quality means smaller output -> we modulate a little the page - // size based on quality. This is just a crude 1rst-order prediction. - { - const float scale = 1.f + config->quality * 5.f / 100.f; // in [1,6] - VP8TBufferInit(&enc->tokens_, (int)(mb_w * mb_h * 4 * scale)); - } - return enc; -} - -static int DeleteVP8Encoder(VP8Encoder* enc) { - int ok = 1; - if (enc != NULL) { - ok = VP8EncDeleteAlpha(enc); - VP8TBufferClear(&enc->tokens_); - WebPSafeFree(enc); - } - return ok; -} - -//------------------------------------------------------------------------------ - -static double GetPSNR(uint64_t err, uint64_t size) { - return (err > 0 && size > 0) ? 10. * log10(255. * 255. * size / err) : 99.; -} - -static void FinalizePSNR(const VP8Encoder* const enc) { - WebPAuxStats* stats = enc->pic_->stats; - const uint64_t size = enc->sse_count_; - const uint64_t* const sse = enc->sse_; - stats->PSNR[0] = (float)GetPSNR(sse[0], size); - stats->PSNR[1] = (float)GetPSNR(sse[1], size / 4); - stats->PSNR[2] = (float)GetPSNR(sse[2], size / 4); - stats->PSNR[3] = (float)GetPSNR(sse[0] + sse[1] + sse[2], size * 3 / 2); - stats->PSNR[4] = (float)GetPSNR(sse[3], size); -} - -static void StoreStats(VP8Encoder* const enc) { - WebPAuxStats* const stats = enc->pic_->stats; - if (stats != NULL) { - int i, s; - for (i = 0; i < NUM_MB_SEGMENTS; ++i) { - stats->segment_level[i] = enc->dqm_[i].fstrength_; - stats->segment_quant[i] = enc->dqm_[i].quant_; - for (s = 0; s <= 2; ++s) { - stats->residual_bytes[s][i] = enc->residual_bytes_[s][i]; - } - } - FinalizePSNR(enc); - stats->coded_size = enc->coded_size_; - for (i = 0; i < 3; ++i) { - stats->block_count[i] = enc->block_count_[i]; - } - } - WebPReportProgress(enc->pic_, 100, &enc->percent_); // done! -} - -int WebPEncodingSetError(const WebPPicture* const pic, - WebPEncodingError error) { - assert((int)error < VP8_ENC_ERROR_LAST); - assert((int)error >= VP8_ENC_OK); - ((WebPPicture*)pic)->error_code = error; - return 0; -} - -int WebPReportProgress(const WebPPicture* const pic, - int percent, int* const percent_store) { - if (percent_store != NULL && percent != *percent_store) { - *percent_store = percent; - if (pic->progress_hook && !pic->progress_hook(percent, pic)) { - // user abort requested - WebPEncodingSetError(pic, VP8_ENC_ERROR_USER_ABORT); - return 0; - } - } - return 1; // ok -} -//------------------------------------------------------------------------------ - -int WebPEncode(const WebPConfig* config, WebPPicture* pic) { - int ok = 0; - - if (pic == NULL) - return 0; - WebPEncodingSetError(pic, VP8_ENC_OK); // all ok so far - if (config == NULL) // bad params - return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER); - if (!WebPValidateConfig(config)) - return WebPEncodingSetError(pic, VP8_ENC_ERROR_INVALID_CONFIGURATION); - if (pic->width <= 0 || pic->height <= 0) - return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION); - if (pic->width > WEBP_MAX_DIMENSION || pic->height > WEBP_MAX_DIMENSION) - return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION); - - if (pic->stats != NULL) memset(pic->stats, 0, sizeof(*pic->stats)); - - if (!config->lossless) { - VP8Encoder* enc = NULL; - - if (!config->exact) { - WebPCleanupTransparentArea(pic); - } - - if (pic->use_argb || pic->y == NULL || pic->u == NULL || pic->v == NULL) { - // Make sure we have YUVA samples. - if (config->preprocessing & 4) { - if (!WebPPictureSmartARGBToYUVA(pic)) { - return 0; - } - } else { - float dithering = 0.f; - if (config->preprocessing & 2) { - const float x = config->quality / 100.f; - const float x2 = x * x; - // slowly decreasing from max dithering at low quality (q->0) - // to 0.5 dithering amplitude at high quality (q->100) - dithering = 1.0f + (0.5f - 1.0f) * x2 * x2; - } - if (!WebPPictureARGBToYUVADithered(pic, WEBP_YUV420, dithering)) { - return 0; - } - } - } - - enc = InitVP8Encoder(config, pic); - if (enc == NULL) return 0; // pic->error is already set. - // Note: each of the tasks below account for 20% in the progress report. - ok = VP8EncAnalyze(enc); - - // Analysis is done, proceed to actual coding. - ok = ok && VP8EncStartAlpha(enc); // possibly done in parallel - if (!enc->use_tokens_) { - ok = ok && VP8EncLoop(enc); - } else { - ok = ok && VP8EncTokenLoop(enc); - } - ok = ok && VP8EncFinishAlpha(enc); - - ok = ok && VP8EncWrite(enc); - StoreStats(enc); - if (!ok) { - VP8EncFreeBitWriters(enc); - } - ok &= DeleteVP8Encoder(enc); // must always be called, even if !ok - } else { - // Make sure we have ARGB samples. - if (pic->argb == NULL && !WebPPictureYUVAToARGB(pic)) { - return 0; - } - - if (!config->exact) { - WebPCleanupTransparentAreaLossless(pic); - } - - ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem. - } - - return ok; -} diff --git a/Example-Mac/Pods/libwebp/src/mux/anim_encode.c b/Example-Mac/Pods/libwebp/src/mux/anim_encode.c deleted file mode 100644 index fa86eaac..00000000 --- a/Example-Mac/Pods/libwebp/src/mux/anim_encode.c +++ /dev/null @@ -1,1404 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// AnimEncoder implementation. -// - -#include -#include -#include - -#include "../utils/utils.h" -#include "../webp/decode.h" -#include "../webp/encode.h" -#include "../webp/format_constants.h" -#include "../webp/mux.h" - -#if defined(_MSC_VER) && _MSC_VER < 1900 -#define snprintf _snprintf -#endif - -#define ERROR_STR_MAX_LENGTH 100 - -//------------------------------------------------------------------------------ -// Internal structs. - -// Stores frame rectangle dimensions. -typedef struct { - int x_offset_, y_offset_, width_, height_; -} FrameRect; - -// Used to store two candidates of encoded data for an animation frame. One of -// the two will be chosen later. -typedef struct { - WebPMuxFrameInfo sub_frame_; // Encoded frame rectangle. - WebPMuxFrameInfo key_frame_; // Encoded frame if it is a key-frame. - int is_key_frame_; // True if 'key_frame' has been chosen. -} EncodedFrame; - -struct WebPAnimEncoder { - const int canvas_width_; // Canvas width. - const int canvas_height_; // Canvas height. - const WebPAnimEncoderOptions options_; // Global encoding options. - - FrameRect prev_rect_; // Previous WebP frame rectangle. - WebPConfig last_config_; // Cached in case a re-encode is needed. - WebPConfig last_config2_; // 2nd cached config; only valid if - // 'options_.allow_mixed' is true. - - WebPPicture* curr_canvas_; // Only pointer; we don't own memory. - - // Canvas buffers. - WebPPicture curr_canvas_copy_; // Possibly modified current canvas. - int curr_canvas_copy_modified_; // True if pixels in 'curr_canvas_copy_' - // differ from those in 'curr_canvas_'. - - WebPPicture prev_canvas_; // Previous canvas. - WebPPicture prev_canvas_disposed_; // Previous canvas disposed to background. - - // Encoded data. - EncodedFrame* encoded_frames_; // Array of encoded frames. - size_t size_; // Number of allocated frames. - size_t start_; // Frame start index. - size_t count_; // Number of valid frames. - size_t flush_count_; // If >0, 'flush_count' frames starting from - // 'start' are ready to be added to mux. - - // key-frame related. - int64_t best_delta_; // min(canvas size - frame size) over the frames. - // Can be negative in certain cases due to - // transparent pixels in a frame. - int keyframe_; // Index of selected key-frame relative to 'start_'. - int count_since_key_frame_; // Frames seen since the last key-frame. - - int first_timestamp_; // Timestamp of the first frame. - int prev_timestamp_; // Timestamp of the last added frame. - int prev_candidate_undecided_; // True if it's not yet decided if previous - // frame would be a sub-frame or a key-frame. - - // Misc. - int is_first_frame_; // True if first frame is yet to be added/being added. - int got_null_frame_; // True if WebPAnimEncoderAdd() has already been called - // with a NULL frame. - - size_t in_frame_count_; // Number of input frames processed so far. - size_t out_frame_count_; // Number of frames added to mux so far. This may be - // different from 'in_frame_count_' due to merging. - - WebPMux* mux_; // Muxer to assemble the WebP bitstream. - char error_str_[ERROR_STR_MAX_LENGTH]; // Error string. Empty if no error. -}; - -// ----------------------------------------------------------------------------- -// Life of WebPAnimEncoder object. - -#define DELTA_INFINITY (1ULL << 32) -#define KEYFRAME_NONE (-1) - -// Reset the counters in the WebPAnimEncoder. -static void ResetCounters(WebPAnimEncoder* const enc) { - enc->start_ = 0; - enc->count_ = 0; - enc->flush_count_ = 0; - enc->best_delta_ = DELTA_INFINITY; - enc->keyframe_ = KEYFRAME_NONE; -} - -static void DisableKeyframes(WebPAnimEncoderOptions* const enc_options) { - enc_options->kmax = INT_MAX; - enc_options->kmin = enc_options->kmax - 1; -} - -#define MAX_CACHED_FRAMES 30 - -static void SanitizeEncoderOptions(WebPAnimEncoderOptions* const enc_options) { - int print_warning = enc_options->verbose; - - if (enc_options->minimize_size) { - DisableKeyframes(enc_options); - } - - if (enc_options->kmin <= 0) { - DisableKeyframes(enc_options); - print_warning = 0; - } - if (enc_options->kmax <= 0) { // All frames will be key-frames. - enc_options->kmin = 0; - enc_options->kmax = 0; - return; - } - - if (enc_options->kmin >= enc_options->kmax) { - enc_options->kmin = enc_options->kmax - 1; - if (print_warning) { - fprintf(stderr, "WARNING: Setting kmin = %d, so that kmin < kmax.\n", - enc_options->kmin); - } - } else { - const int kmin_limit = enc_options->kmax / 2 + 1; - if (enc_options->kmin < kmin_limit && kmin_limit < enc_options->kmax) { - // This ensures that enc.keyframe + kmin >= kmax is always true. So, we - // can flush all the frames in the 'count_since_key_frame == kmax' case. - enc_options->kmin = kmin_limit; - if (print_warning) { - fprintf(stderr, - "WARNING: Setting kmin = %d, so that kmin >= kmax / 2 + 1.\n", - enc_options->kmin); - } - } - } - // Limit the max number of frames that are allocated. - if (enc_options->kmax - enc_options->kmin > MAX_CACHED_FRAMES) { - enc_options->kmin = enc_options->kmax - MAX_CACHED_FRAMES; - if (print_warning) { - fprintf(stderr, - "WARNING: Setting kmin = %d, so that kmax - kmin <= %d.\n", - enc_options->kmin, MAX_CACHED_FRAMES); - } - } - assert(enc_options->kmin < enc_options->kmax); -} - -#undef MAX_CACHED_FRAMES - -static void DefaultEncoderOptions(WebPAnimEncoderOptions* const enc_options) { - enc_options->anim_params.loop_count = 0; - enc_options->anim_params.bgcolor = 0xffffffff; // White. - enc_options->minimize_size = 0; - DisableKeyframes(enc_options); - enc_options->allow_mixed = 0; -} - -int WebPAnimEncoderOptionsInitInternal(WebPAnimEncoderOptions* enc_options, - int abi_version) { - if (enc_options == NULL || - WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_MUX_ABI_VERSION)) { - return 0; - } - DefaultEncoderOptions(enc_options); - return 1; -} - -#define TRANSPARENT_COLOR 0x00ffffff - -static void ClearRectangle(WebPPicture* const picture, - int left, int top, int width, int height) { - int j; - for (j = top; j < top + height; ++j) { - uint32_t* const dst = picture->argb + j * picture->argb_stride; - int i; - for (i = left; i < left + width; ++i) { - dst[i] = TRANSPARENT_COLOR; - } - } -} - -static void WebPUtilClearPic(WebPPicture* const picture, - const FrameRect* const rect) { - if (rect != NULL) { - ClearRectangle(picture, rect->x_offset_, rect->y_offset_, - rect->width_, rect->height_); - } else { - ClearRectangle(picture, 0, 0, picture->width, picture->height); - } -} - -static void MarkNoError(WebPAnimEncoder* const enc) { - enc->error_str_[0] = '\0'; // Empty string. -} - -static void MarkError(WebPAnimEncoder* const enc, const char* str) { - if (snprintf(enc->error_str_, ERROR_STR_MAX_LENGTH, "%s.", str) < 0) { - assert(0); // FIX ME! - } -} - -static void MarkError2(WebPAnimEncoder* const enc, - const char* str, int error_code) { - if (snprintf(enc->error_str_, ERROR_STR_MAX_LENGTH, "%s: %d.", str, - error_code) < 0) { - assert(0); // FIX ME! - } -} - -WebPAnimEncoder* WebPAnimEncoderNewInternal( - int width, int height, const WebPAnimEncoderOptions* enc_options, - int abi_version) { - WebPAnimEncoder* enc; - - if (WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_MUX_ABI_VERSION)) { - return NULL; - } - if (width <= 0 || height <= 0 || - (width * (uint64_t)height) >= MAX_IMAGE_AREA) { - return NULL; - } - - enc = (WebPAnimEncoder*)WebPSafeCalloc(1, sizeof(*enc)); - if (enc == NULL) return NULL; - // sanity inits, so we can call WebPAnimEncoderDelete(): - enc->encoded_frames_ = NULL; - enc->mux_ = NULL; - MarkNoError(enc); - - // Dimensions and options. - *(int*)&enc->canvas_width_ = width; - *(int*)&enc->canvas_height_ = height; - if (enc_options != NULL) { - *(WebPAnimEncoderOptions*)&enc->options_ = *enc_options; - SanitizeEncoderOptions((WebPAnimEncoderOptions*)&enc->options_); - } else { - DefaultEncoderOptions((WebPAnimEncoderOptions*)&enc->options_); - } - - // Canvas buffers. - if (!WebPPictureInit(&enc->curr_canvas_copy_) || - !WebPPictureInit(&enc->prev_canvas_) || - !WebPPictureInit(&enc->prev_canvas_disposed_)) { - goto Err; - } - enc->curr_canvas_copy_.width = width; - enc->curr_canvas_copy_.height = height; - enc->curr_canvas_copy_.use_argb = 1; - if (!WebPPictureAlloc(&enc->curr_canvas_copy_) || - !WebPPictureCopy(&enc->curr_canvas_copy_, &enc->prev_canvas_) || - !WebPPictureCopy(&enc->curr_canvas_copy_, &enc->prev_canvas_disposed_)) { - goto Err; - } - WebPUtilClearPic(&enc->prev_canvas_, NULL); - enc->curr_canvas_copy_modified_ = 1; - - // Encoded frames. - ResetCounters(enc); - // Note: one extra storage is for the previous frame. - enc->size_ = enc->options_.kmax - enc->options_.kmin + 1; - // We need space for at least 2 frames. But when kmin, kmax are both zero, - // enc->size_ will be 1. So we handle that special case below. - if (enc->size_ < 2) enc->size_ = 2; - enc->encoded_frames_ = - (EncodedFrame*)WebPSafeCalloc(enc->size_, sizeof(*enc->encoded_frames_)); - if (enc->encoded_frames_ == NULL) goto Err; - - enc->mux_ = WebPMuxNew(); - if (enc->mux_ == NULL) goto Err; - - enc->count_since_key_frame_ = 0; - enc->first_timestamp_ = 0; - enc->prev_timestamp_ = 0; - enc->prev_candidate_undecided_ = 0; - enc->is_first_frame_ = 1; - enc->got_null_frame_ = 0; - - return enc; // All OK. - - Err: - WebPAnimEncoderDelete(enc); - return NULL; -} - -// Release the data contained by 'encoded_frame'. -static void FrameRelease(EncodedFrame* const encoded_frame) { - if (encoded_frame != NULL) { - WebPDataClear(&encoded_frame->sub_frame_.bitstream); - WebPDataClear(&encoded_frame->key_frame_.bitstream); - memset(encoded_frame, 0, sizeof(*encoded_frame)); - } -} - -void WebPAnimEncoderDelete(WebPAnimEncoder* enc) { - if (enc != NULL) { - WebPPictureFree(&enc->curr_canvas_copy_); - WebPPictureFree(&enc->prev_canvas_); - WebPPictureFree(&enc->prev_canvas_disposed_); - if (enc->encoded_frames_ != NULL) { - size_t i; - for (i = 0; i < enc->size_; ++i) { - FrameRelease(&enc->encoded_frames_[i]); - } - WebPSafeFree(enc->encoded_frames_); - } - WebPMuxDelete(enc->mux_); - WebPSafeFree(enc); - } -} - -// ----------------------------------------------------------------------------- -// Frame addition. - -// Returns cached frame at the given 'position'. -static EncodedFrame* GetFrame(const WebPAnimEncoder* const enc, - size_t position) { - assert(enc->start_ + position < enc->size_); - return &enc->encoded_frames_[enc->start_ + position]; -} - -// Returns true if 'length' number of pixels in 'src' and 'dst' are identical, -// assuming the given step sizes between pixels. -static WEBP_INLINE int ComparePixels(const uint32_t* src, int src_step, - const uint32_t* dst, int dst_step, - int length) { - assert(length > 0); - while (length-- > 0) { - if (*src != *dst) { - return 0; - } - src += src_step; - dst += dst_step; - } - return 1; -} - -static int IsEmptyRect(const FrameRect* const rect) { - return (rect->width_ == 0) || (rect->height_ == 0); -} - -// Assumes that an initial valid guess of change rectangle 'rect' is passed. -static void MinimizeChangeRectangle(const WebPPicture* const src, - const WebPPicture* const dst, - FrameRect* const rect) { - int i, j; - // Sanity checks. - assert(src->width == dst->width && src->height == dst->height); - assert(rect->x_offset_ + rect->width_ <= dst->width); - assert(rect->y_offset_ + rect->height_ <= dst->height); - - // Left boundary. - for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) { - const uint32_t* const src_argb = - &src->argb[rect->y_offset_ * src->argb_stride + i]; - const uint32_t* const dst_argb = - &dst->argb[rect->y_offset_ * dst->argb_stride + i]; - if (ComparePixels(src_argb, src->argb_stride, dst_argb, dst->argb_stride, - rect->height_)) { - --rect->width_; // Redundant column. - ++rect->x_offset_; - } else { - break; - } - } - if (rect->width_ == 0) goto NoChange; - - // Right boundary. - for (i = rect->x_offset_ + rect->width_ - 1; i >= rect->x_offset_; --i) { - const uint32_t* const src_argb = - &src->argb[rect->y_offset_ * src->argb_stride + i]; - const uint32_t* const dst_argb = - &dst->argb[rect->y_offset_ * dst->argb_stride + i]; - if (ComparePixels(src_argb, src->argb_stride, dst_argb, dst->argb_stride, - rect->height_)) { - --rect->width_; // Redundant column. - } else { - break; - } - } - if (rect->width_ == 0) goto NoChange; - - // Top boundary. - for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) { - const uint32_t* const src_argb = - &src->argb[j * src->argb_stride + rect->x_offset_]; - const uint32_t* const dst_argb = - &dst->argb[j * dst->argb_stride + rect->x_offset_]; - if (ComparePixels(src_argb, 1, dst_argb, 1, rect->width_)) { - --rect->height_; // Redundant row. - ++rect->y_offset_; - } else { - break; - } - } - if (rect->height_ == 0) goto NoChange; - - // Bottom boundary. - for (j = rect->y_offset_ + rect->height_ - 1; j >= rect->y_offset_; --j) { - const uint32_t* const src_argb = - &src->argb[j * src->argb_stride + rect->x_offset_]; - const uint32_t* const dst_argb = - &dst->argb[j * dst->argb_stride + rect->x_offset_]; - if (ComparePixels(src_argb, 1, dst_argb, 1, rect->width_)) { - --rect->height_; // Redundant row. - } else { - break; - } - } - if (rect->height_ == 0) goto NoChange; - - if (IsEmptyRect(rect)) { - NoChange: - rect->x_offset_ = 0; - rect->y_offset_ = 0; - rect->width_ = 0; - rect->height_ = 0; - } -} - -// Snap rectangle to even offsets (and adjust dimensions if needed). -static WEBP_INLINE void SnapToEvenOffsets(FrameRect* const rect) { - rect->width_ += (rect->x_offset_ & 1); - rect->height_ += (rect->y_offset_ & 1); - rect->x_offset_ &= ~1; - rect->y_offset_ &= ~1; -} - -// Given previous and current canvas, picks the optimal rectangle for the -// current frame. The initial guess for 'rect' will be the full canvas. -static int GetSubRect(const WebPPicture* const prev_canvas, - const WebPPicture* const curr_canvas, int is_key_frame, - int is_first_frame, int empty_rect_allowed, - FrameRect* const rect, WebPPicture* const sub_frame) { - rect->x_offset_ = 0; - rect->y_offset_ = 0; - rect->width_ = curr_canvas->width; - rect->height_ = curr_canvas->height; - if (!is_key_frame || is_first_frame) { // Optimize frame rectangle. - // Note: This behaves as expected for first frame, as 'prev_canvas' is - // initialized to a fully transparent canvas in the beginning. - MinimizeChangeRectangle(prev_canvas, curr_canvas, rect); - } - - if (IsEmptyRect(rect)) { - if (empty_rect_allowed) { // No need to get 'sub_frame'. - return 1; - } else { // Force a 1x1 rectangle. - rect->width_ = 1; - rect->height_ = 1; - assert(rect->x_offset_ == 0); - assert(rect->y_offset_ == 0); - } - } - - SnapToEvenOffsets(rect); - return WebPPictureView(curr_canvas, rect->x_offset_, rect->y_offset_, - rect->width_, rect->height_, sub_frame); -} - -static void DisposeFrameRectangle(int dispose_method, - const FrameRect* const rect, - WebPPicture* const curr_canvas) { - assert(rect != NULL); - if (dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { - WebPUtilClearPic(curr_canvas, rect); - } -} - -static uint32_t RectArea(const FrameRect* const rect) { - return (uint32_t)rect->width_ * rect->height_; -} - -static int IsBlendingPossible(const WebPPicture* const src, - const WebPPicture* const dst, - const FrameRect* const rect) { - int i, j; - assert(src->width == dst->width && src->height == dst->height); - assert(rect->x_offset_ + rect->width_ <= dst->width); - assert(rect->y_offset_ + rect->height_ <= dst->height); - for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) { - for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) { - const uint32_t src_pixel = src->argb[j * src->argb_stride + i]; - const uint32_t dst_pixel = dst->argb[j * dst->argb_stride + i]; - const uint32_t dst_alpha = dst_pixel >> 24; - if (dst_alpha != 0xff && src_pixel != dst_pixel) { - // In this case, if we use blending, we can't attain the desired - // 'dst_pixel' value for this pixel. So, blending is not possible. - return 0; - } - } - } - return 1; -} - -#define MIN_COLORS_LOSSY 31 // Don't try lossy below this threshold. -#define MAX_COLORS_LOSSLESS 194 // Don't try lossless above this threshold. -#define MAX_COLOR_COUNT 256 // Power of 2 greater than MAX_COLORS_LOSSLESS. -#define HASH_SIZE (MAX_COLOR_COUNT * 4) -#define HASH_RIGHT_SHIFT 22 // 32 - log2(HASH_SIZE). - -// TODO(urvang): Also used in enc/vp8l.c. Move to utils. -// If the number of colors in the 'pic' is at least MAX_COLOR_COUNT, return -// MAX_COLOR_COUNT. Otherwise, return the exact number of colors in the 'pic'. -static int GetColorCount(const WebPPicture* const pic) { - int x, y; - int num_colors = 0; - uint8_t in_use[HASH_SIZE] = { 0 }; - uint32_t colors[HASH_SIZE]; - static const uint32_t kHashMul = 0x1e35a7bd; - const uint32_t* argb = pic->argb; - const int width = pic->width; - const int height = pic->height; - uint32_t last_pix = ~argb[0]; // so we're sure that last_pix != argb[0] - - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - int key; - if (argb[x] == last_pix) { - continue; - } - last_pix = argb[x]; - key = (kHashMul * last_pix) >> HASH_RIGHT_SHIFT; - while (1) { - if (!in_use[key]) { - colors[key] = last_pix; - in_use[key] = 1; - ++num_colors; - if (num_colors >= MAX_COLOR_COUNT) { - return MAX_COLOR_COUNT; // Exact count not needed. - } - break; - } else if (colors[key] == last_pix) { - break; // The color is already there. - } else { - // Some other color sits here, so do linear conflict resolution. - ++key; - key &= (HASH_SIZE - 1); // Key mask. - } - } - } - argb += pic->argb_stride; - } - return num_colors; -} - -#undef MAX_COLOR_COUNT -#undef HASH_SIZE -#undef HASH_RIGHT_SHIFT - -// For pixels in 'rect', replace those pixels in 'dst' that are same as 'src' by -// transparent pixels. -static void IncreaseTransparency(const WebPPicture* const src, - const FrameRect* const rect, - WebPPicture* const dst) { - int i, j; - assert(src != NULL && dst != NULL && rect != NULL); - assert(src->width == dst->width && src->height == dst->height); - for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) { - const uint32_t* const psrc = src->argb + j * src->argb_stride; - uint32_t* const pdst = dst->argb + j * dst->argb_stride; - for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) { - if (psrc[i] == pdst[i]) { - pdst[i] = TRANSPARENT_COLOR; - } - } - } -} - -#undef TRANSPARENT_COLOR - -// Replace similar blocks of pixels by a 'see-through' transparent block -// with uniform average color. -static void FlattenSimilarBlocks(const WebPPicture* const src, - const FrameRect* const rect, - WebPPicture* const dst) { - int i, j; - const int block_size = 8; - const int y_start = (rect->y_offset_ + block_size) & ~(block_size - 1); - const int y_end = (rect->y_offset_ + rect->height_) & ~(block_size - 1); - const int x_start = (rect->x_offset_ + block_size) & ~(block_size - 1); - const int x_end = (rect->x_offset_ + rect->width_) & ~(block_size - 1); - assert(src != NULL && dst != NULL && rect != NULL); - assert(src->width == dst->width && src->height == dst->height); - assert((block_size & (block_size - 1)) == 0); // must be a power of 2 - // Iterate over each block and count similar pixels. - for (j = y_start; j < y_end; j += block_size) { - for (i = x_start; i < x_end; i += block_size) { - int cnt = 0; - int avg_r = 0, avg_g = 0, avg_b = 0; - int x, y; - const uint32_t* const psrc = src->argb + j * src->argb_stride + i; - uint32_t* const pdst = dst->argb + j * dst->argb_stride + i; - for (y = 0; y < block_size; ++y) { - for (x = 0; x < block_size; ++x) { - const uint32_t src_pixel = psrc[x + y * src->argb_stride]; - const int alpha = src_pixel >> 24; - if (alpha == 0xff && - src_pixel == pdst[x + y * dst->argb_stride]) { - ++cnt; - avg_r += (src_pixel >> 16) & 0xff; - avg_g += (src_pixel >> 8) & 0xff; - avg_b += (src_pixel >> 0) & 0xff; - } - } - } - // If we have a fully similar block, we replace it with an - // average transparent block. This compresses better in lossy mode. - if (cnt == block_size * block_size) { - const uint32_t color = (0x00 << 24) | - ((avg_r / cnt) << 16) | - ((avg_g / cnt) << 8) | - ((avg_b / cnt) << 0); - for (y = 0; y < block_size; ++y) { - for (x = 0; x < block_size; ++x) { - pdst[x + y * dst->argb_stride] = color; - } - } - } - } - } -} - -static int EncodeFrame(const WebPConfig* const config, WebPPicture* const pic, - WebPMemoryWriter* const memory) { - pic->use_argb = 1; - pic->writer = WebPMemoryWrite; - pic->custom_ptr = memory; - if (!WebPEncode(config, pic)) { - return 0; - } - return 1; -} - -// Struct representing a candidate encoded frame including its metadata. -typedef struct { - WebPMemoryWriter mem_; - WebPMuxFrameInfo info_; - FrameRect rect_; - int evaluate_; // True if this candidate should be evaluated. -} Candidate; - -// Generates a candidate encoded frame given a picture and metadata. -static WebPEncodingError EncodeCandidate(WebPPicture* const sub_frame, - const FrameRect* const rect, - const WebPConfig* const config, - int use_blending, - Candidate* const candidate) { - WebPEncodingError error_code = VP8_ENC_OK; - assert(candidate != NULL); - memset(candidate, 0, sizeof(*candidate)); - - // Set frame rect and info. - candidate->rect_ = *rect; - candidate->info_.id = WEBP_CHUNK_ANMF; - candidate->info_.x_offset = rect->x_offset_; - candidate->info_.y_offset = rect->y_offset_; - candidate->info_.dispose_method = WEBP_MUX_DISPOSE_NONE; // Set later. - candidate->info_.blend_method = - use_blending ? WEBP_MUX_BLEND : WEBP_MUX_NO_BLEND; - candidate->info_.duration = 0; // Set in next call to WebPAnimEncoderAdd(). - - // Encode picture. - WebPMemoryWriterInit(&candidate->mem_); - - if (!EncodeFrame(config, sub_frame, &candidate->mem_)) { - error_code = sub_frame->error_code; - goto Err; - } - - candidate->evaluate_ = 1; - return error_code; - - Err: - WebPMemoryWriterClear(&candidate->mem_); - return error_code; -} - -static void CopyCurrentCanvas(WebPAnimEncoder* const enc) { - if (enc->curr_canvas_copy_modified_) { - WebPCopyPixels(enc->curr_canvas_, &enc->curr_canvas_copy_); - enc->curr_canvas_copy_modified_ = 0; - } -} - -enum { - LL_DISP_NONE = 0, - LL_DISP_BG, - LOSSY_DISP_NONE, - LOSSY_DISP_BG, - CANDIDATE_COUNT -}; - -// Generates candidates for a given dispose method given pre-filled 'rect' -// and 'sub_frame'. -static WebPEncodingError GenerateCandidates( - WebPAnimEncoder* const enc, Candidate candidates[CANDIDATE_COUNT], - WebPMuxAnimDispose dispose_method, int is_lossless, int is_key_frame, - const FrameRect* const rect, WebPPicture* sub_frame, - const WebPConfig* const config_ll, const WebPConfig* const config_lossy) { - WebPEncodingError error_code = VP8_ENC_OK; - const int is_dispose_none = (dispose_method == WEBP_MUX_DISPOSE_NONE); - Candidate* const candidate_ll = - is_dispose_none ? &candidates[LL_DISP_NONE] : &candidates[LL_DISP_BG]; - Candidate* const candidate_lossy = is_dispose_none - ? &candidates[LOSSY_DISP_NONE] - : &candidates[LOSSY_DISP_BG]; - WebPPicture* const curr_canvas = &enc->curr_canvas_copy_; - const WebPPicture* const prev_canvas = - is_dispose_none ? &enc->prev_canvas_ : &enc->prev_canvas_disposed_; - const int use_blending = - !is_key_frame && - IsBlendingPossible(prev_canvas, curr_canvas, rect); - - // Pick candidates to be tried. - if (!enc->options_.allow_mixed) { - candidate_ll->evaluate_ = is_lossless; - candidate_lossy->evaluate_ = !is_lossless; - } else { // Use a heuristic for trying lossless and/or lossy compression. - const int num_colors = GetColorCount(sub_frame); - candidate_ll->evaluate_ = (num_colors < MAX_COLORS_LOSSLESS); - candidate_lossy->evaluate_ = (num_colors >= MIN_COLORS_LOSSY); - } - - // Generate candidates. - if (candidate_ll->evaluate_) { - CopyCurrentCanvas(enc); - if (use_blending) { - IncreaseTransparency(prev_canvas, rect, curr_canvas); - enc->curr_canvas_copy_modified_ = 1; - } - error_code = EncodeCandidate(sub_frame, rect, config_ll, use_blending, - candidate_ll); - if (error_code != VP8_ENC_OK) return error_code; - } - if (candidate_lossy->evaluate_) { - CopyCurrentCanvas(enc); - if (use_blending) { - FlattenSimilarBlocks(prev_canvas, rect, curr_canvas); - enc->curr_canvas_copy_modified_ = 1; - } - error_code = EncodeCandidate(sub_frame, rect, config_lossy, use_blending, - candidate_lossy); - if (error_code != VP8_ENC_OK) return error_code; - } - return error_code; -} - -#undef MIN_COLORS_LOSSY -#undef MAX_COLORS_LOSSLESS - -static void GetEncodedData(const WebPMemoryWriter* const memory, - WebPData* const encoded_data) { - encoded_data->bytes = memory->mem; - encoded_data->size = memory->size; -} - -// Sets dispose method of the previous frame to be 'dispose_method'. -static void SetPreviousDisposeMethod(WebPAnimEncoder* const enc, - WebPMuxAnimDispose dispose_method) { - const size_t position = enc->count_ - 2; - EncodedFrame* const prev_enc_frame = GetFrame(enc, position); - assert(enc->count_ >= 2); // As current and previous frames are in enc. - - if (enc->prev_candidate_undecided_) { - assert(dispose_method == WEBP_MUX_DISPOSE_NONE); - prev_enc_frame->sub_frame_.dispose_method = dispose_method; - prev_enc_frame->key_frame_.dispose_method = dispose_method; - } else { - WebPMuxFrameInfo* const prev_info = prev_enc_frame->is_key_frame_ - ? &prev_enc_frame->key_frame_ - : &prev_enc_frame->sub_frame_; - prev_info->dispose_method = dispose_method; - } -} - -static int IncreasePreviousDuration(WebPAnimEncoder* const enc, int duration) { - const size_t position = enc->count_ - 1; - EncodedFrame* const prev_enc_frame = GetFrame(enc, position); - int new_duration; - - assert(enc->count_ >= 1); - assert(prev_enc_frame->sub_frame_.duration == - prev_enc_frame->key_frame_.duration); - assert(prev_enc_frame->sub_frame_.duration == - (prev_enc_frame->sub_frame_.duration & (MAX_DURATION - 1))); - assert(duration == (duration & (MAX_DURATION - 1))); - - new_duration = prev_enc_frame->sub_frame_.duration + duration; - if (new_duration >= MAX_DURATION) { // Special case. - // Separate out previous frame from earlier merged frames to avoid overflow. - // We add a 1x1 transparent frame for the previous frame, with blending on. - const FrameRect rect = { 0, 0, 1, 1 }; - const uint8_t lossless_1x1_bytes[] = { - 0x52, 0x49, 0x46, 0x46, 0x14, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, - 0x56, 0x50, 0x38, 0x4c, 0x08, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, - 0x10, 0x88, 0x88, 0x08 - }; - const WebPData lossless_1x1 = { - lossless_1x1_bytes, sizeof(lossless_1x1_bytes) - }; - const uint8_t lossy_1x1_bytes[] = { - 0x52, 0x49, 0x46, 0x46, 0x40, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, - 0x56, 0x50, 0x38, 0x58, 0x0a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x4c, 0x50, 0x48, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x56, 0x50, 0x38, 0x20, 0x18, 0x00, 0x00, 0x00, - 0x30, 0x01, 0x00, 0x9d, 0x01, 0x2a, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, - 0x34, 0x25, 0xa4, 0x00, 0x03, 0x70, 0x00, 0xfe, 0xfb, 0xfd, 0x50, 0x00 - }; - const WebPData lossy_1x1 = { lossy_1x1_bytes, sizeof(lossy_1x1_bytes) }; - const int can_use_lossless = - (enc->last_config_.lossless || enc->options_.allow_mixed); - EncodedFrame* const curr_enc_frame = GetFrame(enc, enc->count_); - curr_enc_frame->is_key_frame_ = 0; - curr_enc_frame->sub_frame_.id = WEBP_CHUNK_ANMF; - curr_enc_frame->sub_frame_.x_offset = 0; - curr_enc_frame->sub_frame_.y_offset = 0; - curr_enc_frame->sub_frame_.dispose_method = WEBP_MUX_DISPOSE_NONE; - curr_enc_frame->sub_frame_.blend_method = WEBP_MUX_BLEND; - curr_enc_frame->sub_frame_.duration = duration; - if (!WebPDataCopy(can_use_lossless ? &lossless_1x1 : &lossy_1x1, - &curr_enc_frame->sub_frame_.bitstream)) { - return 0; - } - ++enc->count_; - ++enc->count_since_key_frame_; - enc->flush_count_ = enc->count_ - 1; - enc->prev_candidate_undecided_ = 0; - enc->prev_rect_ = rect; - } else { // Regular case. - // Increase duration of the previous frame by 'duration'. - prev_enc_frame->sub_frame_.duration = new_duration; - prev_enc_frame->key_frame_.duration = new_duration; - } - return 1; -} - -// Pick the candidate encoded frame with smallest size and release other -// candidates. -// TODO(later): Perhaps a rough SSIM/PSNR produced by the encoder should -// also be a criteria, in addition to sizes. -static void PickBestCandidate(WebPAnimEncoder* const enc, - Candidate* const candidates, int is_key_frame, - EncodedFrame* const encoded_frame) { - int i; - int best_idx = -1; - size_t best_size = ~0; - for (i = 0; i < CANDIDATE_COUNT; ++i) { - if (candidates[i].evaluate_) { - const size_t candidate_size = candidates[i].mem_.size; - if (candidate_size < best_size) { - best_idx = i; - best_size = candidate_size; - } - } - } - assert(best_idx != -1); - for (i = 0; i < CANDIDATE_COUNT; ++i) { - if (candidates[i].evaluate_) { - if (i == best_idx) { - WebPMuxFrameInfo* const dst = is_key_frame - ? &encoded_frame->key_frame_ - : &encoded_frame->sub_frame_; - *dst = candidates[i].info_; - GetEncodedData(&candidates[i].mem_, &dst->bitstream); - if (!is_key_frame) { - // Note: Previous dispose method only matters for non-keyframes. - // Also, we don't want to modify previous dispose method that was - // selected when a non key-frame was assumed. - const WebPMuxAnimDispose prev_dispose_method = - (best_idx == LL_DISP_NONE || best_idx == LOSSY_DISP_NONE) - ? WEBP_MUX_DISPOSE_NONE - : WEBP_MUX_DISPOSE_BACKGROUND; - SetPreviousDisposeMethod(enc, prev_dispose_method); - } - enc->prev_rect_ = candidates[i].rect_; // save for next frame. - } else { - WebPMemoryWriterClear(&candidates[i].mem_); - candidates[i].evaluate_ = 0; - } - } - } -} - -// Depending on the configuration, tries different compressions -// (lossy/lossless), dispose methods, blending methods etc to encode the current -// frame and outputs the best one in 'encoded_frame'. -// 'frame_skipped' will be set to true if this frame should actually be skipped. -static WebPEncodingError SetFrame(WebPAnimEncoder* const enc, - const WebPConfig* const config, - int is_key_frame, - EncodedFrame* const encoded_frame, - int* const frame_skipped) { - int i; - WebPEncodingError error_code = VP8_ENC_OK; - const WebPPicture* const curr_canvas = &enc->curr_canvas_copy_; - const WebPPicture* const prev_canvas = &enc->prev_canvas_; - Candidate candidates[CANDIDATE_COUNT]; - const int is_lossless = config->lossless; - const int is_first_frame = enc->is_first_frame_; - - int try_dispose_none = 1; // Default. - FrameRect rect_none; - WebPPicture sub_frame_none; - // First frame cannot be skipped as there is no 'previous frame' to merge it - // to. So, empty rectangle is not allowed for the first frame. - const int empty_rect_allowed_none = !is_first_frame; - - // If current frame is a key-frame, dispose method of previous frame doesn't - // matter, so we don't try dispose to background. - // Also, if key-frame insertion is on, and previous frame could be picked as - // either a sub-frame or a key-frame, then we can't be sure about what frame - // rectangle would be disposed. In that case too, we don't try dispose to - // background. - const int dispose_bg_possible = - !is_key_frame && !enc->prev_candidate_undecided_; - int try_dispose_bg = 0; // Default. - FrameRect rect_bg; - WebPPicture sub_frame_bg; - - WebPConfig config_ll = *config; - WebPConfig config_lossy = *config; - config_ll.lossless = 1; - config_lossy.lossless = 0; - enc->last_config_ = *config; - enc->last_config2_ = config->lossless ? config_lossy : config_ll; - *frame_skipped = 0; - - if (!WebPPictureInit(&sub_frame_none) || !WebPPictureInit(&sub_frame_bg)) { - return VP8_ENC_ERROR_INVALID_CONFIGURATION; - } - - for (i = 0; i < CANDIDATE_COUNT; ++i) { - candidates[i].evaluate_ = 0; - } - - // Change-rectangle assuming previous frame was DISPOSE_NONE. - GetSubRect(prev_canvas, curr_canvas, is_key_frame, is_first_frame, - empty_rect_allowed_none, &rect_none, &sub_frame_none); - - if (IsEmptyRect(&rect_none)) { - // Don't encode the frame at all. Instead, the duration of the previous - // frame will be increased later. - assert(empty_rect_allowed_none); - *frame_skipped = 1; - goto End; - } - - if (dispose_bg_possible) { - // Change-rectangle assuming previous frame was DISPOSE_BACKGROUND. - WebPPicture* const prev_canvas_disposed = &enc->prev_canvas_disposed_; - WebPCopyPixels(prev_canvas, prev_canvas_disposed); - DisposeFrameRectangle(WEBP_MUX_DISPOSE_BACKGROUND, &enc->prev_rect_, - prev_canvas_disposed); - // Even if there is exact pixel match between 'disposed previous canvas' and - // 'current canvas', we can't skip current frame, as there may not be exact - // pixel match between 'previous canvas' and 'current canvas'. So, we don't - // allow empty rectangle in this case. - GetSubRect(prev_canvas_disposed, curr_canvas, is_key_frame, is_first_frame, - 0 /* empty_rect_allowed */, &rect_bg, &sub_frame_bg); - assert(!IsEmptyRect(&rect_bg)); - - if (enc->options_.minimize_size) { // Try both dispose methods. - try_dispose_bg = 1; - try_dispose_none = 1; - } else if (RectArea(&rect_bg) < RectArea(&rect_none)) { - try_dispose_bg = 1; // Pick DISPOSE_BACKGROUND. - try_dispose_none = 0; - } - } - - if (try_dispose_none) { - error_code = GenerateCandidates( - enc, candidates, WEBP_MUX_DISPOSE_NONE, is_lossless, is_key_frame, - &rect_none, &sub_frame_none, &config_ll, &config_lossy); - if (error_code != VP8_ENC_OK) goto Err; - } - - if (try_dispose_bg) { - assert(!enc->is_first_frame_); - assert(dispose_bg_possible); - error_code = GenerateCandidates( - enc, candidates, WEBP_MUX_DISPOSE_BACKGROUND, is_lossless, is_key_frame, - &rect_bg, &sub_frame_bg, &config_ll, &config_lossy); - if (error_code != VP8_ENC_OK) goto Err; - } - - PickBestCandidate(enc, candidates, is_key_frame, encoded_frame); - - goto End; - - Err: - for (i = 0; i < CANDIDATE_COUNT; ++i) { - if (candidates[i].evaluate_) { - WebPMemoryWriterClear(&candidates[i].mem_); - } - } - - End: - WebPPictureFree(&sub_frame_none); - WebPPictureFree(&sub_frame_bg); - return error_code; -} - -// Calculate the penalty incurred if we encode given frame as a key frame -// instead of a sub-frame. -static int64_t KeyFramePenalty(const EncodedFrame* const encoded_frame) { - return ((int64_t)encoded_frame->key_frame_.bitstream.size - - encoded_frame->sub_frame_.bitstream.size); -} - -static int CacheFrame(WebPAnimEncoder* const enc, - const WebPConfig* const config) { - int ok = 0; - int frame_skipped = 0; - WebPEncodingError error_code = VP8_ENC_OK; - const size_t position = enc->count_; - EncodedFrame* const encoded_frame = GetFrame(enc, position); - - ++enc->count_; - - if (enc->is_first_frame_) { // Add this as a key-frame. - error_code = SetFrame(enc, config, 1, encoded_frame, &frame_skipped); - if (error_code != VP8_ENC_OK) goto End; - assert(frame_skipped == 0); // First frame can't be skipped, even if empty. - assert(position == 0 && enc->count_ == 1); - encoded_frame->is_key_frame_ = 1; - enc->flush_count_ = 0; - enc->count_since_key_frame_ = 0; - enc->prev_candidate_undecided_ = 0; - } else { - ++enc->count_since_key_frame_; - if (enc->count_since_key_frame_ <= enc->options_.kmin) { - // Add this as a frame rectangle. - error_code = SetFrame(enc, config, 0, encoded_frame, &frame_skipped); - if (error_code != VP8_ENC_OK) goto End; - if (frame_skipped) goto Skip; - encoded_frame->is_key_frame_ = 0; - enc->flush_count_ = enc->count_ - 1; - enc->prev_candidate_undecided_ = 0; - } else { - int64_t curr_delta; - - // Add this as a frame rectangle to enc. - error_code = SetFrame(enc, config, 0, encoded_frame, &frame_skipped); - if (error_code != VP8_ENC_OK) goto End; - if (frame_skipped) goto Skip; - - // Add this as a key-frame to enc, too. - error_code = SetFrame(enc, config, 1, encoded_frame, &frame_skipped); - if (error_code != VP8_ENC_OK) goto End; - assert(frame_skipped == 0); // Key-frame cannot be an empty rectangle. - - // Analyze size difference of the two variants. - curr_delta = KeyFramePenalty(encoded_frame); - if (curr_delta <= enc->best_delta_) { // Pick this as the key-frame. - if (enc->keyframe_ != KEYFRAME_NONE) { - EncodedFrame* const old_keyframe = GetFrame(enc, enc->keyframe_); - assert(old_keyframe->is_key_frame_); - old_keyframe->is_key_frame_ = 0; - } - encoded_frame->is_key_frame_ = 1; - enc->keyframe_ = (int)position; - enc->best_delta_ = curr_delta; - enc->flush_count_ = enc->count_ - 1; // We can flush previous frames. - } else { - encoded_frame->is_key_frame_ = 0; - } - // Note: We need '>=' below because when kmin and kmax are both zero, - // count_since_key_frame will always be > kmax. - if (enc->count_since_key_frame_ >= enc->options_.kmax) { - enc->flush_count_ = enc->count_ - 1; - enc->count_since_key_frame_ = 0; - enc->keyframe_ = KEYFRAME_NONE; - enc->best_delta_ = DELTA_INFINITY; - } - enc->prev_candidate_undecided_ = 1; - } - } - - // Update previous to previous and previous canvases for next call. - WebPCopyPixels(enc->curr_canvas_, &enc->prev_canvas_); - enc->is_first_frame_ = 0; - - Skip: - ok = 1; - ++enc->in_frame_count_; - - End: - if (!ok || frame_skipped) { - FrameRelease(encoded_frame); - // We reset some counters, as the frame addition failed/was skipped. - --enc->count_; - if (!enc->is_first_frame_) --enc->count_since_key_frame_; - if (!ok) { - MarkError2(enc, "ERROR adding frame. WebPEncodingError", error_code); - } - } - enc->curr_canvas_->error_code = error_code; // report error_code - assert(ok || error_code != VP8_ENC_OK); - return ok; -} - -static int FlushFrames(WebPAnimEncoder* const enc) { - while (enc->flush_count_ > 0) { - WebPMuxError err; - EncodedFrame* const curr = GetFrame(enc, 0); - const WebPMuxFrameInfo* const info = - curr->is_key_frame_ ? &curr->key_frame_ : &curr->sub_frame_; - assert(enc->mux_ != NULL); - err = WebPMuxPushFrame(enc->mux_, info, 1); - if (err != WEBP_MUX_OK) { - MarkError2(enc, "ERROR adding frame. WebPMuxError", err); - return 0; - } - if (enc->options_.verbose) { - fprintf(stderr, "INFO: Added frame. offset:%d,%d dispose:%d blend:%d\n", - info->x_offset, info->y_offset, info->dispose_method, - info->blend_method); - } - ++enc->out_frame_count_; - FrameRelease(curr); - ++enc->start_; - --enc->flush_count_; - --enc->count_; - if (enc->keyframe_ != KEYFRAME_NONE) --enc->keyframe_; - } - - if (enc->count_ == 1 && enc->start_ != 0) { - // Move enc->start to index 0. - const int enc_start_tmp = (int)enc->start_; - EncodedFrame temp = enc->encoded_frames_[0]; - enc->encoded_frames_[0] = enc->encoded_frames_[enc_start_tmp]; - enc->encoded_frames_[enc_start_tmp] = temp; - FrameRelease(&enc->encoded_frames_[enc_start_tmp]); - enc->start_ = 0; - } - return 1; -} - -#undef DELTA_INFINITY -#undef KEYFRAME_NONE - -int WebPAnimEncoderAdd(WebPAnimEncoder* enc, WebPPicture* frame, int timestamp, - const WebPConfig* encoder_config) { - WebPConfig config; - - if (enc == NULL) { - return 0; - } - MarkNoError(enc); - - if (!enc->is_first_frame_) { - // Make sure timestamps are non-decreasing (integer wrap-around is OK). - const uint32_t prev_frame_duration = - (uint32_t)timestamp - enc->prev_timestamp_; - if (prev_frame_duration >= MAX_DURATION) { - if (frame != NULL) { - frame->error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION; - } - MarkError(enc, "ERROR adding frame: timestamps must be non-decreasing"); - return 0; - } - if (!IncreasePreviousDuration(enc, (int)prev_frame_duration)) { - return 0; - } - } else { - enc->first_timestamp_ = timestamp; - } - - if (frame == NULL) { // Special: last call. - enc->got_null_frame_ = 1; - enc->prev_timestamp_ = timestamp; - return 1; - } - - if (frame->width != enc->canvas_width_ || - frame->height != enc->canvas_height_) { - frame->error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION; - MarkError(enc, "ERROR adding frame: Invalid frame dimensions"); - return 0; - } - - if (!frame->use_argb) { // Convert frame from YUV(A) to ARGB. - if (enc->options_.verbose) { - fprintf(stderr, "WARNING: Converting frame from YUV(A) to ARGB format; " - "this incurs a small loss.\n"); - } - if (!WebPPictureYUVAToARGB(frame)) { - MarkError(enc, "ERROR converting frame from YUV(A) to ARGB"); - return 0; - } - } - - if (encoder_config != NULL) { - config = *encoder_config; - } else { - WebPConfigInit(&config); - config.lossless = 1; - } - assert(enc->curr_canvas_ == NULL); - enc->curr_canvas_ = frame; // Store reference. - assert(enc->curr_canvas_copy_modified_ == 1); - CopyCurrentCanvas(enc); - - if (!CacheFrame(enc, &config)) { - return 0; - } - - if (!FlushFrames(enc)) { - return 0; - } - enc->curr_canvas_ = NULL; - enc->curr_canvas_copy_modified_ = 1; - enc->prev_timestamp_ = timestamp; - return 1; -} - -// ----------------------------------------------------------------------------- -// Bitstream assembly. - -static int DecodeFrameOntoCanvas(const WebPMuxFrameInfo* const frame, - WebPPicture* const canvas) { - const WebPData* const image = &frame->bitstream; - WebPPicture sub_image; - WebPDecoderConfig config; - WebPInitDecoderConfig(&config); - WebPUtilClearPic(canvas, NULL); - if (WebPGetFeatures(image->bytes, image->size, &config.input) != - VP8_STATUS_OK) { - return 0; - } - if (!WebPPictureView(canvas, frame->x_offset, frame->y_offset, - config.input.width, config.input.height, &sub_image)) { - return 0; - } - config.output.is_external_memory = 1; - config.output.colorspace = MODE_BGRA; - config.output.u.RGBA.rgba = (uint8_t*)sub_image.argb; - config.output.u.RGBA.stride = sub_image.argb_stride * 4; - config.output.u.RGBA.size = config.output.u.RGBA.stride * sub_image.height; - - if (WebPDecode(image->bytes, image->size, &config) != VP8_STATUS_OK) { - return 0; - } - return 1; -} - -static int FrameToFullCanvas(WebPAnimEncoder* const enc, - const WebPMuxFrameInfo* const frame, - WebPData* const full_image) { - WebPPicture* const canvas_buf = &enc->curr_canvas_copy_; - WebPMemoryWriter mem1, mem2; - WebPMemoryWriterInit(&mem1); - WebPMemoryWriterInit(&mem2); - - if (!DecodeFrameOntoCanvas(frame, canvas_buf)) goto Err; - if (!EncodeFrame(&enc->last_config_, canvas_buf, &mem1)) goto Err; - GetEncodedData(&mem1, full_image); - - if (enc->options_.allow_mixed) { - if (!EncodeFrame(&enc->last_config_, canvas_buf, &mem2)) goto Err; - if (mem2.size < mem1.size) { - GetEncodedData(&mem2, full_image); - WebPMemoryWriterClear(&mem1); - } else { - WebPMemoryWriterClear(&mem2); - } - } - return 1; - - Err: - WebPMemoryWriterClear(&mem1); - WebPMemoryWriterClear(&mem2); - return 0; -} - -// Convert a single-frame animation to a non-animated image if appropriate. -// TODO(urvang): Can we pick one of the two heuristically (based on frame -// rectangle and/or presence of alpha)? -static WebPMuxError OptimizeSingleFrame(WebPAnimEncoder* const enc, - WebPData* const webp_data) { - WebPMuxError err = WEBP_MUX_OK; - int canvas_width, canvas_height; - WebPMuxFrameInfo frame; - WebPData full_image; - WebPData webp_data2; - WebPMux* const mux = WebPMuxCreate(webp_data, 0); - if (mux == NULL) return WEBP_MUX_BAD_DATA; - assert(enc->out_frame_count_ == 1); - WebPDataInit(&frame.bitstream); - WebPDataInit(&full_image); - WebPDataInit(&webp_data2); - - err = WebPMuxGetFrame(mux, 1, &frame); - if (err != WEBP_MUX_OK) goto End; - if (frame.id != WEBP_CHUNK_ANMF) goto End; // Non-animation: nothing to do. - err = WebPMuxGetCanvasSize(mux, &canvas_width, &canvas_height); - if (err != WEBP_MUX_OK) goto End; - if (!FrameToFullCanvas(enc, &frame, &full_image)) { - err = WEBP_MUX_BAD_DATA; - goto End; - } - err = WebPMuxSetImage(mux, &full_image, 1); - if (err != WEBP_MUX_OK) goto End; - err = WebPMuxAssemble(mux, &webp_data2); - if (err != WEBP_MUX_OK) goto End; - - if (webp_data2.size < webp_data->size) { // Pick 'webp_data2' if smaller. - WebPDataClear(webp_data); - *webp_data = webp_data2; - WebPDataInit(&webp_data2); - } - - End: - WebPDataClear(&frame.bitstream); - WebPDataClear(&full_image); - WebPMuxDelete(mux); - WebPDataClear(&webp_data2); - return err; -} - -int WebPAnimEncoderAssemble(WebPAnimEncoder* enc, WebPData* webp_data) { - WebPMux* mux; - WebPMuxError err; - - if (enc == NULL) { - return 0; - } - MarkNoError(enc); - - if (webp_data == NULL) { - MarkError(enc, "ERROR assembling: NULL input"); - return 0; - } - - if (enc->in_frame_count_ == 0) { - MarkError(enc, "ERROR: No frames to assemble"); - return 0; - } - - if (!enc->got_null_frame_ && enc->in_frame_count_ > 1 && enc->count_ > 0) { - // set duration of the last frame to be avg of durations of previous frames. - const double delta_time = enc->prev_timestamp_ - enc->first_timestamp_; - const int average_duration = (int)(delta_time / (enc->in_frame_count_ - 1)); - if (!IncreasePreviousDuration(enc, average_duration)) { - return 0; - } - } - - // Flush any remaining frames. - enc->flush_count_ = enc->count_; - if (!FlushFrames(enc)) { - return 0; - } - - // Set definitive canvas size. - mux = enc->mux_; - err = WebPMuxSetCanvasSize(mux, enc->canvas_width_, enc->canvas_height_); - if (err != WEBP_MUX_OK) goto Err; - - err = WebPMuxSetAnimationParams(mux, &enc->options_.anim_params); - if (err != WEBP_MUX_OK) goto Err; - - // Assemble into a WebP bitstream. - err = WebPMuxAssemble(mux, webp_data); - if (err != WEBP_MUX_OK) goto Err; - - if (enc->out_frame_count_ == 1) { - err = OptimizeSingleFrame(enc, webp_data); - if (err != WEBP_MUX_OK) goto Err; - } - return 1; - - Err: - MarkError2(enc, "ERROR assembling WebP", err); - return 0; -} - -const char* WebPAnimEncoderGetError(WebPAnimEncoder* enc) { - if (enc == NULL) return NULL; - return enc->error_str_; -} - -// ----------------------------------------------------------------------------- diff --git a/Example-Mac/Pods/libwebp/src/mux/muxedit.c b/Example-Mac/Pods/libwebp/src/mux/muxedit.c deleted file mode 100644 index b27663f8..00000000 --- a/Example-Mac/Pods/libwebp/src/mux/muxedit.c +++ /dev/null @@ -1,696 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Set and delete APIs for mux. -// -// Authors: Urvang (urvang@google.com) -// Vikas (vikasa@google.com) - -#include -#include "./muxi.h" -#include "../utils/utils.h" - -//------------------------------------------------------------------------------ -// Life of a mux object. - -static void MuxInit(WebPMux* const mux) { - assert(mux != NULL); - memset(mux, 0, sizeof(*mux)); - mux->canvas_width_ = 0; // just to be explicit - mux->canvas_height_ = 0; -} - -WebPMux* WebPNewInternal(int version) { - if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_MUX_ABI_VERSION)) { - return NULL; - } else { - WebPMux* const mux = (WebPMux*)WebPSafeMalloc(1ULL, sizeof(WebPMux)); - if (mux != NULL) MuxInit(mux); - return mux; - } -} - -// Delete all images in 'wpi_list'. -static void DeleteAllImages(WebPMuxImage** const wpi_list) { - while (*wpi_list != NULL) { - *wpi_list = MuxImageDelete(*wpi_list); - } -} - -static void MuxRelease(WebPMux* const mux) { - assert(mux != NULL); - DeleteAllImages(&mux->images_); - ChunkListDelete(&mux->vp8x_); - ChunkListDelete(&mux->iccp_); - ChunkListDelete(&mux->anim_); - ChunkListDelete(&mux->exif_); - ChunkListDelete(&mux->xmp_); - ChunkListDelete(&mux->unknown_); -} - -void WebPMuxDelete(WebPMux* mux) { - if (mux != NULL) { - MuxRelease(mux); - WebPSafeFree(mux); - } -} - -//------------------------------------------------------------------------------ -// Helper method(s). - -// Handy MACRO, makes MuxSet() very symmetric to MuxGet(). -#define SWITCH_ID_LIST(INDEX, LIST) \ - if (idx == (INDEX)) { \ - err = ChunkAssignData(&chunk, data, copy_data, tag); \ - if (err == WEBP_MUX_OK) { \ - err = ChunkSetNth(&chunk, (LIST), nth); \ - } \ - return err; \ - } - -static WebPMuxError MuxSet(WebPMux* const mux, uint32_t tag, uint32_t nth, - const WebPData* const data, int copy_data) { - WebPChunk chunk; - WebPMuxError err = WEBP_MUX_NOT_FOUND; - const CHUNK_INDEX idx = ChunkGetIndexFromTag(tag); - assert(mux != NULL); - assert(!IsWPI(kChunks[idx].id)); - - ChunkInit(&chunk); - SWITCH_ID_LIST(IDX_VP8X, &mux->vp8x_); - SWITCH_ID_LIST(IDX_ICCP, &mux->iccp_); - SWITCH_ID_LIST(IDX_ANIM, &mux->anim_); - SWITCH_ID_LIST(IDX_EXIF, &mux->exif_); - SWITCH_ID_LIST(IDX_XMP, &mux->xmp_); - SWITCH_ID_LIST(IDX_UNKNOWN, &mux->unknown_); - return err; -} -#undef SWITCH_ID_LIST - -// Create data for frame/fragment given image data, offsets and duration. -static WebPMuxError CreateFrameFragmentData( - int width, int height, const WebPMuxFrameInfo* const info, int is_frame, - WebPData* const frame_frgm) { - uint8_t* frame_frgm_bytes; - const size_t frame_frgm_size = kChunks[is_frame ? IDX_ANMF : IDX_FRGM].size; - - assert(width > 0 && height > 0 && info->duration >= 0); - assert(info->dispose_method == (info->dispose_method & 1)); - // Note: assertion on upper bounds is done in PutLE24(). - - frame_frgm_bytes = (uint8_t*)WebPSafeMalloc(1ULL, frame_frgm_size); - if (frame_frgm_bytes == NULL) return WEBP_MUX_MEMORY_ERROR; - - PutLE24(frame_frgm_bytes + 0, info->x_offset / 2); - PutLE24(frame_frgm_bytes + 3, info->y_offset / 2); - - if (is_frame) { - PutLE24(frame_frgm_bytes + 6, width - 1); - PutLE24(frame_frgm_bytes + 9, height - 1); - PutLE24(frame_frgm_bytes + 12, info->duration); - frame_frgm_bytes[15] = - (info->blend_method == WEBP_MUX_NO_BLEND ? 2 : 0) | - (info->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND ? 1 : 0); - } - - frame_frgm->bytes = frame_frgm_bytes; - frame_frgm->size = frame_frgm_size; - return WEBP_MUX_OK; -} - -// Outputs image data given a bitstream. The bitstream can either be a -// single-image WebP file or raw VP8/VP8L data. -// Also outputs 'is_lossless' to be true if the given bitstream is lossless. -static WebPMuxError GetImageData(const WebPData* const bitstream, - WebPData* const image, WebPData* const alpha, - int* const is_lossless) { - WebPDataInit(alpha); // Default: no alpha. - if (bitstream->size < TAG_SIZE || - memcmp(bitstream->bytes, "RIFF", TAG_SIZE)) { - // It is NOT webp file data. Return input data as is. - *image = *bitstream; - } else { - // It is webp file data. Extract image data from it. - const WebPMuxImage* wpi; - WebPMux* const mux = WebPMuxCreate(bitstream, 0); - if (mux == NULL) return WEBP_MUX_BAD_DATA; - wpi = mux->images_; - assert(wpi != NULL && wpi->img_ != NULL); - *image = wpi->img_->data_; - if (wpi->alpha_ != NULL) { - *alpha = wpi->alpha_->data_; - } - WebPMuxDelete(mux); - } - *is_lossless = VP8LCheckSignature(image->bytes, image->size); - return WEBP_MUX_OK; -} - -static WebPMuxError DeleteChunks(WebPChunk** chunk_list, uint32_t tag) { - WebPMuxError err = WEBP_MUX_NOT_FOUND; - assert(chunk_list); - while (*chunk_list) { - WebPChunk* const chunk = *chunk_list; - if (chunk->tag_ == tag) { - *chunk_list = ChunkDelete(chunk); - err = WEBP_MUX_OK; - } else { - chunk_list = &chunk->next_; - } - } - return err; -} - -static WebPMuxError MuxDeleteAllNamedData(WebPMux* const mux, uint32_t tag) { - const WebPChunkId id = ChunkGetIdFromTag(tag); - assert(mux != NULL); - if (IsWPI(id)) return WEBP_MUX_INVALID_ARGUMENT; - return DeleteChunks(MuxGetChunkListFromId(mux, id), tag); -} - -//------------------------------------------------------------------------------ -// Set API(s). - -WebPMuxError WebPMuxSetChunk(WebPMux* mux, const char fourcc[4], - const WebPData* chunk_data, int copy_data) { - uint32_t tag; - WebPMuxError err; - if (mux == NULL || fourcc == NULL || chunk_data == NULL || - chunk_data->bytes == NULL || chunk_data->size > MAX_CHUNK_PAYLOAD) { - return WEBP_MUX_INVALID_ARGUMENT; - } - tag = ChunkGetTagFromFourCC(fourcc); - - // Delete existing chunk(s) with the same 'fourcc'. - err = MuxDeleteAllNamedData(mux, tag); - if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; - - // Add the given chunk. - return MuxSet(mux, tag, 1, chunk_data, copy_data); -} - -// Creates a chunk from given 'data' and sets it as 1st chunk in 'chunk_list'. -static WebPMuxError AddDataToChunkList( - const WebPData* const data, int copy_data, uint32_t tag, - WebPChunk** chunk_list) { - WebPChunk chunk; - WebPMuxError err; - ChunkInit(&chunk); - err = ChunkAssignData(&chunk, data, copy_data, tag); - if (err != WEBP_MUX_OK) goto Err; - err = ChunkSetNth(&chunk, chunk_list, 1); - if (err != WEBP_MUX_OK) goto Err; - return WEBP_MUX_OK; - Err: - ChunkRelease(&chunk); - return err; -} - -// Extracts image & alpha data from the given bitstream and then sets wpi.alpha_ -// and wpi.img_ appropriately. -static WebPMuxError SetAlphaAndImageChunks( - const WebPData* const bitstream, int copy_data, WebPMuxImage* const wpi) { - int is_lossless = 0; - WebPData image, alpha; - WebPMuxError err = GetImageData(bitstream, &image, &alpha, &is_lossless); - const int image_tag = - is_lossless ? kChunks[IDX_VP8L].tag : kChunks[IDX_VP8].tag; - if (err != WEBP_MUX_OK) return err; - if (alpha.bytes != NULL) { - err = AddDataToChunkList(&alpha, copy_data, kChunks[IDX_ALPHA].tag, - &wpi->alpha_); - if (err != WEBP_MUX_OK) return err; - } - err = AddDataToChunkList(&image, copy_data, image_tag, &wpi->img_); - if (err != WEBP_MUX_OK) return err; - return MuxImageFinalize(wpi) ? WEBP_MUX_OK : WEBP_MUX_INVALID_ARGUMENT; -} - -WebPMuxError WebPMuxSetImage(WebPMux* mux, const WebPData* bitstream, - int copy_data) { - WebPMuxImage wpi; - WebPMuxError err; - - // Sanity checks. - if (mux == NULL || bitstream == NULL || bitstream->bytes == NULL || - bitstream->size > MAX_CHUNK_PAYLOAD) { - return WEBP_MUX_INVALID_ARGUMENT; - } - - if (mux->images_ != NULL) { - // Only one 'simple image' can be added in mux. So, remove present images. - DeleteAllImages(&mux->images_); - } - - MuxImageInit(&wpi); - err = SetAlphaAndImageChunks(bitstream, copy_data, &wpi); - if (err != WEBP_MUX_OK) goto Err; - - // Add this WebPMuxImage to mux. - err = MuxImagePush(&wpi, &mux->images_); - if (err != WEBP_MUX_OK) goto Err; - - // All is well. - return WEBP_MUX_OK; - - Err: // Something bad happened. - MuxImageRelease(&wpi); - return err; -} - -WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* frame, - int copy_data) { - WebPMuxImage wpi; - WebPMuxError err; - int is_frame; - const WebPData* const bitstream = &frame->bitstream; - - // Sanity checks. - if (mux == NULL || frame == NULL) return WEBP_MUX_INVALID_ARGUMENT; - - is_frame = (frame->id == WEBP_CHUNK_ANMF); - if (!(is_frame || (frame->id == WEBP_CHUNK_FRGM))) { - return WEBP_MUX_INVALID_ARGUMENT; - } - if (frame->id == WEBP_CHUNK_FRGM) { // Dead experiment. - return WEBP_MUX_INVALID_ARGUMENT; - } - - if (bitstream->bytes == NULL || bitstream->size > MAX_CHUNK_PAYLOAD) { - return WEBP_MUX_INVALID_ARGUMENT; - } - - if (mux->images_ != NULL) { - const WebPMuxImage* const image = mux->images_; - const uint32_t image_id = (image->header_ != NULL) ? - ChunkGetIdFromTag(image->header_->tag_) : WEBP_CHUNK_IMAGE; - if (image_id != frame->id) { - return WEBP_MUX_INVALID_ARGUMENT; // Conflicting frame types. - } - } - - MuxImageInit(&wpi); - err = SetAlphaAndImageChunks(bitstream, copy_data, &wpi); - if (err != WEBP_MUX_OK) goto Err; - assert(wpi.img_ != NULL); // As SetAlphaAndImageChunks() was successful. - - { - WebPData frame_frgm; - const uint32_t tag = kChunks[is_frame ? IDX_ANMF : IDX_FRGM].tag; - WebPMuxFrameInfo tmp = *frame; - tmp.x_offset &= ~1; // Snap offsets to even. - tmp.y_offset &= ~1; - if (!is_frame) { // Reset unused values. - tmp.duration = 1; - tmp.dispose_method = WEBP_MUX_DISPOSE_NONE; - tmp.blend_method = WEBP_MUX_BLEND; - } - if (tmp.x_offset < 0 || tmp.x_offset >= MAX_POSITION_OFFSET || - tmp.y_offset < 0 || tmp.y_offset >= MAX_POSITION_OFFSET || - (tmp.duration < 0 || tmp.duration >= MAX_DURATION) || - tmp.dispose_method != (tmp.dispose_method & 1)) { - err = WEBP_MUX_INVALID_ARGUMENT; - goto Err; - } - err = CreateFrameFragmentData(wpi.width_, wpi.height_, &tmp, is_frame, - &frame_frgm); - if (err != WEBP_MUX_OK) goto Err; - // Add frame/fragment chunk (with copy_data = 1). - err = AddDataToChunkList(&frame_frgm, 1, tag, &wpi.header_); - WebPDataClear(&frame_frgm); // frame_frgm owned by wpi.header_ now. - if (err != WEBP_MUX_OK) goto Err; - } - - // Add this WebPMuxImage to mux. - err = MuxImagePush(&wpi, &mux->images_); - if (err != WEBP_MUX_OK) goto Err; - - // All is well. - return WEBP_MUX_OK; - - Err: // Something bad happened. - MuxImageRelease(&wpi); - return err; -} - -WebPMuxError WebPMuxSetAnimationParams(WebPMux* mux, - const WebPMuxAnimParams* params) { - WebPMuxError err; - uint8_t data[ANIM_CHUNK_SIZE]; - const WebPData anim = { data, ANIM_CHUNK_SIZE }; - - if (mux == NULL || params == NULL) return WEBP_MUX_INVALID_ARGUMENT; - if (params->loop_count < 0 || params->loop_count >= MAX_LOOP_COUNT) { - return WEBP_MUX_INVALID_ARGUMENT; - } - - // Delete any existing ANIM chunk(s). - err = MuxDeleteAllNamedData(mux, kChunks[IDX_ANIM].tag); - if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; - - // Set the animation parameters. - PutLE32(data, params->bgcolor); - PutLE16(data + 4, params->loop_count); - return MuxSet(mux, kChunks[IDX_ANIM].tag, 1, &anim, 1); -} - -WebPMuxError WebPMuxSetCanvasSize(WebPMux* mux, - int width, int height) { - WebPMuxError err; - if (mux == NULL) { - return WEBP_MUX_INVALID_ARGUMENT; - } - if (width < 0 || height < 0 || - width > MAX_CANVAS_SIZE || height > MAX_CANVAS_SIZE) { - return WEBP_MUX_INVALID_ARGUMENT; - } - if (width * (uint64_t)height >= MAX_IMAGE_AREA) { - return WEBP_MUX_INVALID_ARGUMENT; - } - if ((width * height) == 0 && (width | height) != 0) { - // one of width / height is zero, but not both -> invalid! - return WEBP_MUX_INVALID_ARGUMENT; - } - // If we already assembled a VP8X chunk, invalidate it. - err = MuxDeleteAllNamedData(mux, kChunks[IDX_VP8X].tag); - if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; - - mux->canvas_width_ = width; - mux->canvas_height_ = height; - return WEBP_MUX_OK; -} - -//------------------------------------------------------------------------------ -// Delete API(s). - -WebPMuxError WebPMuxDeleteChunk(WebPMux* mux, const char fourcc[4]) { - if (mux == NULL || fourcc == NULL) return WEBP_MUX_INVALID_ARGUMENT; - return MuxDeleteAllNamedData(mux, ChunkGetTagFromFourCC(fourcc)); -} - -WebPMuxError WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth) { - if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT; - return MuxImageDeleteNth(&mux->images_, nth); -} - -//------------------------------------------------------------------------------ -// Assembly of the WebP RIFF file. - -static WebPMuxError GetFrameFragmentInfo( - const WebPChunk* const frame_frgm_chunk, - int* const x_offset, int* const y_offset, int* const duration) { - const uint32_t tag = frame_frgm_chunk->tag_; - const int is_frame = (tag == kChunks[IDX_ANMF].tag); - const WebPData* const data = &frame_frgm_chunk->data_; - const size_t expected_data_size = - is_frame ? ANMF_CHUNK_SIZE : FRGM_CHUNK_SIZE; - assert(frame_frgm_chunk != NULL); - assert(tag == kChunks[IDX_ANMF].tag || tag == kChunks[IDX_FRGM].tag); - if (data->size != expected_data_size) return WEBP_MUX_INVALID_ARGUMENT; - - *x_offset = 2 * GetLE24(data->bytes + 0); - *y_offset = 2 * GetLE24(data->bytes + 3); - if (is_frame) *duration = GetLE24(data->bytes + 12); - return WEBP_MUX_OK; -} - -static WebPMuxError GetImageInfo(const WebPMuxImage* const wpi, - int* const x_offset, int* const y_offset, - int* const duration, - int* const width, int* const height) { - const WebPChunk* const frame_frgm_chunk = wpi->header_; - WebPMuxError err; - assert(wpi != NULL); - assert(frame_frgm_chunk != NULL); - - // Get offsets and duration from ANMF/FRGM chunk. - err = GetFrameFragmentInfo(frame_frgm_chunk, x_offset, y_offset, duration); - if (err != WEBP_MUX_OK) return err; - - // Get width and height from VP8/VP8L chunk. - if (width != NULL) *width = wpi->width_; - if (height != NULL) *height = wpi->height_; - return WEBP_MUX_OK; -} - -// Returns the tightest dimension for the canvas considering the image list. -static WebPMuxError GetAdjustedCanvasSize(const WebPMux* const mux, - uint32_t flags, - int* const width, int* const height) { - WebPMuxImage* wpi = NULL; - assert(mux != NULL); - assert(width != NULL && height != NULL); - - wpi = mux->images_; - assert(wpi != NULL); - assert(wpi->img_ != NULL); - - if (wpi->next_ != NULL) { - int max_x = 0; - int max_y = 0; - int64_t image_area = 0; - // if we have a chain of wpi's, header_ is necessarily set - assert(wpi->header_ != NULL); - // Aggregate the bounding box for animation frames & fragmented images. - for (; wpi != NULL; wpi = wpi->next_) { - int x_offset = 0, y_offset = 0, duration = 0, w = 0, h = 0; - const WebPMuxError err = GetImageInfo(wpi, &x_offset, &y_offset, - &duration, &w, &h); - const int max_x_pos = x_offset + w; - const int max_y_pos = y_offset + h; - if (err != WEBP_MUX_OK) return err; - assert(x_offset < MAX_POSITION_OFFSET); - assert(y_offset < MAX_POSITION_OFFSET); - - if (max_x_pos > max_x) max_x = max_x_pos; - if (max_y_pos > max_y) max_y = max_y_pos; - image_area += w * h; - } - *width = max_x; - *height = max_y; - // Crude check to validate that there are no image overlaps/holes for - // fragmented images. Check that the aggregated image area for individual - // fragments exactly matches the image area of the constructed canvas. - // However, the area-match is necessary but not sufficient condition. - if ((flags & FRAGMENTS_FLAG) && (image_area != (max_x * max_y))) { - *width = 0; - *height = 0; - return WEBP_MUX_INVALID_ARGUMENT; - } - } else { - // For a single image, canvas dimensions are same as image dimensions. - *width = wpi->width_; - *height = wpi->height_; - } - return WEBP_MUX_OK; -} - -// VP8X format: -// Total Size : 10, -// Flags : 4 bytes, -// Width : 3 bytes, -// Height : 3 bytes. -static WebPMuxError CreateVP8XChunk(WebPMux* const mux) { - WebPMuxError err = WEBP_MUX_OK; - uint32_t flags = 0; - int width = 0; - int height = 0; - uint8_t data[VP8X_CHUNK_SIZE]; - const WebPData vp8x = { data, VP8X_CHUNK_SIZE }; - const WebPMuxImage* images = NULL; - - assert(mux != NULL); - images = mux->images_; // First image. - if (images == NULL || images->img_ == NULL || - images->img_->data_.bytes == NULL) { - return WEBP_MUX_INVALID_ARGUMENT; - } - - // If VP8X chunk(s) is(are) already present, remove them (and later add new - // VP8X chunk with updated flags). - err = MuxDeleteAllNamedData(mux, kChunks[IDX_VP8X].tag); - if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; - - // Set flags. - if (mux->iccp_ != NULL && mux->iccp_->data_.bytes != NULL) { - flags |= ICCP_FLAG; - } - if (mux->exif_ != NULL && mux->exif_->data_.bytes != NULL) { - flags |= EXIF_FLAG; - } - if (mux->xmp_ != NULL && mux->xmp_->data_.bytes != NULL) { - flags |= XMP_FLAG; - } - if (images->header_ != NULL) { - if (images->header_->tag_ == kChunks[IDX_FRGM].tag) { - // This is a fragmented image. - flags |= FRAGMENTS_FLAG; - } else if (images->header_->tag_ == kChunks[IDX_ANMF].tag) { - // This is an image with animation. - flags |= ANIMATION_FLAG; - } - } - if (MuxImageCount(images, WEBP_CHUNK_ALPHA) > 0) { - flags |= ALPHA_FLAG; // Some images have an alpha channel. - } - - err = GetAdjustedCanvasSize(mux, flags, &width, &height); - if (err != WEBP_MUX_OK) return err; - - if (width <= 0 || height <= 0) { - return WEBP_MUX_INVALID_ARGUMENT; - } - if (width > MAX_CANVAS_SIZE || height > MAX_CANVAS_SIZE) { - return WEBP_MUX_INVALID_ARGUMENT; - } - - if (mux->canvas_width_ != 0 || mux->canvas_height_ != 0) { - if (width > mux->canvas_width_ || height > mux->canvas_height_) { - return WEBP_MUX_INVALID_ARGUMENT; - } - width = mux->canvas_width_; - height = mux->canvas_height_; - } - - if (flags == 0) { - // For Simple Image, VP8X chunk should not be added. - return WEBP_MUX_OK; - } - - if (MuxHasAlpha(images)) { - // This means some frames explicitly/implicitly contain alpha. - // Note: This 'flags' update must NOT be done for a lossless image - // without a VP8X chunk! - flags |= ALPHA_FLAG; - } - - PutLE32(data + 0, flags); // VP8X chunk flags. - PutLE24(data + 4, width - 1); // canvas width. - PutLE24(data + 7, height - 1); // canvas height. - - return MuxSet(mux, kChunks[IDX_VP8X].tag, 1, &vp8x, 1); -} - -// Cleans up 'mux' by removing any unnecessary chunks. -static WebPMuxError MuxCleanup(WebPMux* const mux) { - int num_frames; - int num_fragments; - int num_anim_chunks; - - // If we have an image with a single fragment or frame, and its rectangle - // covers the whole canvas, convert it to a non-animated non-fragmented image - // (to avoid writing FRGM/ANMF chunk unnecessarily). - WebPMuxError err = WebPMuxNumChunks(mux, kChunks[IDX_ANMF].id, &num_frames); - if (err != WEBP_MUX_OK) return err; - err = WebPMuxNumChunks(mux, kChunks[IDX_FRGM].id, &num_fragments); - if (err != WEBP_MUX_OK) return err; - if (num_frames == 1 || num_fragments == 1) { - WebPMuxImage* frame_frag; - err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, 1, &frame_frag); - assert(err == WEBP_MUX_OK); // We know that one frame/fragment does exist. - assert(frame_frag != NULL); - if (frame_frag->header_ != NULL && - ((mux->canvas_width_ == 0 && mux->canvas_height_ == 0) || - (frame_frag->width_ == mux->canvas_width_ && - frame_frag->height_ == mux->canvas_height_))) { - assert(frame_frag->header_->tag_ == kChunks[IDX_ANMF].tag || - frame_frag->header_->tag_ == kChunks[IDX_FRGM].tag); - ChunkDelete(frame_frag->header_); // Removes ANMF/FRGM chunk. - frame_frag->header_ = NULL; - num_frames = 0; - num_fragments = 0; - } - } - // Remove ANIM chunk if this is a non-animated image. - err = WebPMuxNumChunks(mux, kChunks[IDX_ANIM].id, &num_anim_chunks); - if (err != WEBP_MUX_OK) return err; - if (num_anim_chunks >= 1 && num_frames == 0) { - err = MuxDeleteAllNamedData(mux, kChunks[IDX_ANIM].tag); - if (err != WEBP_MUX_OK) return err; - } - return WEBP_MUX_OK; -} - -// Total size of a list of images. -static size_t ImageListDiskSize(const WebPMuxImage* wpi_list) { - size_t size = 0; - while (wpi_list != NULL) { - size += MuxImageDiskSize(wpi_list); - wpi_list = wpi_list->next_; - } - return size; -} - -// Write out the given list of images into 'dst'. -static uint8_t* ImageListEmit(const WebPMuxImage* wpi_list, uint8_t* dst) { - while (wpi_list != NULL) { - dst = MuxImageEmit(wpi_list, dst); - wpi_list = wpi_list->next_; - } - return dst; -} - -WebPMuxError WebPMuxAssemble(WebPMux* mux, WebPData* assembled_data) { - size_t size = 0; - uint8_t* data = NULL; - uint8_t* dst = NULL; - WebPMuxError err; - - if (assembled_data == NULL) { - return WEBP_MUX_INVALID_ARGUMENT; - } - // Clean up returned data, in case something goes wrong. - memset(assembled_data, 0, sizeof(*assembled_data)); - - if (mux == NULL) { - return WEBP_MUX_INVALID_ARGUMENT; - } - - // Finalize mux. - err = MuxCleanup(mux); - if (err != WEBP_MUX_OK) return err; - err = CreateVP8XChunk(mux); - if (err != WEBP_MUX_OK) return err; - - // Allocate data. - size = ChunkListDiskSize(mux->vp8x_) + ChunkListDiskSize(mux->iccp_) - + ChunkListDiskSize(mux->anim_) + ImageListDiskSize(mux->images_) - + ChunkListDiskSize(mux->exif_) + ChunkListDiskSize(mux->xmp_) - + ChunkListDiskSize(mux->unknown_) + RIFF_HEADER_SIZE; - - data = (uint8_t*)WebPSafeMalloc(1ULL, size); - if (data == NULL) return WEBP_MUX_MEMORY_ERROR; - - // Emit header & chunks. - dst = MuxEmitRiffHeader(data, size); - dst = ChunkListEmit(mux->vp8x_, dst); - dst = ChunkListEmit(mux->iccp_, dst); - dst = ChunkListEmit(mux->anim_, dst); - dst = ImageListEmit(mux->images_, dst); - dst = ChunkListEmit(mux->exif_, dst); - dst = ChunkListEmit(mux->xmp_, dst); - dst = ChunkListEmit(mux->unknown_, dst); - assert(dst == data + size); - - // Validate mux. - err = MuxValidate(mux); - if (err != WEBP_MUX_OK) { - WebPSafeFree(data); - data = NULL; - size = 0; - } - - // Finalize data. - assembled_data->bytes = data; - assembled_data->size = size; - - return err; -} - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/mux/muxi.h b/Example-Mac/Pods/libwebp/src/mux/muxi.h deleted file mode 100644 index 5e8ba2e8..00000000 --- a/Example-Mac/Pods/libwebp/src/mux/muxi.h +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Internal header for mux library. -// -// Author: Urvang (urvang@google.com) - -#ifndef WEBP_MUX_MUXI_H_ -#define WEBP_MUX_MUXI_H_ - -#include -#include "../dec/vp8i.h" -#include "../dec/vp8li.h" -#include "../webp/mux.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//------------------------------------------------------------------------------ -// Defines and constants. - -#define MUX_MAJ_VERSION 0 -#define MUX_MIN_VERSION 3 -#define MUX_REV_VERSION 0 - -// Chunk object. -typedef struct WebPChunk WebPChunk; -struct WebPChunk { - uint32_t tag_; - int owner_; // True if *data_ memory is owned internally. - // VP8X, ANIM, and other internally created chunks - // like ANMF/FRGM are always owned. - WebPData data_; - WebPChunk* next_; -}; - -// MuxImage object. Store a full WebP image (including ANMF/FRGM chunk, ALPH -// chunk and VP8/VP8L chunk), -typedef struct WebPMuxImage WebPMuxImage; -struct WebPMuxImage { - WebPChunk* header_; // Corresponds to WEBP_CHUNK_ANMF/WEBP_CHUNK_FRGM. - WebPChunk* alpha_; // Corresponds to WEBP_CHUNK_ALPHA. - WebPChunk* img_; // Corresponds to WEBP_CHUNK_IMAGE. - WebPChunk* unknown_; // Corresponds to WEBP_CHUNK_UNKNOWN. - int width_; - int height_; - int has_alpha_; // Through ALPH chunk or as part of VP8L. - int is_partial_; // True if only some of the chunks are filled. - WebPMuxImage* next_; -}; - -// Main mux object. Stores data chunks. -struct WebPMux { - WebPMuxImage* images_; - WebPChunk* iccp_; - WebPChunk* exif_; - WebPChunk* xmp_; - WebPChunk* anim_; - WebPChunk* vp8x_; - - WebPChunk* unknown_; - int canvas_width_; - int canvas_height_; -}; - -// CHUNK_INDEX enum: used for indexing within 'kChunks' (defined below) only. -// Note: the reason for having two enums ('WebPChunkId' and 'CHUNK_INDEX') is to -// allow two different chunks to have the same id (e.g. WebPChunkId -// 'WEBP_CHUNK_IMAGE' can correspond to CHUNK_INDEX 'IDX_VP8' or 'IDX_VP8L'). -typedef enum { - IDX_VP8X = 0, - IDX_ICCP, - IDX_ANIM, - IDX_ANMF, - IDX_FRGM, - IDX_ALPHA, - IDX_VP8, - IDX_VP8L, - IDX_EXIF, - IDX_XMP, - IDX_UNKNOWN, - - IDX_NIL, - IDX_LAST_CHUNK -} CHUNK_INDEX; - -#define NIL_TAG 0x00000000u // To signal void chunk. - -typedef struct { - uint32_t tag; - WebPChunkId id; - uint32_t size; -} ChunkInfo; - -extern const ChunkInfo kChunks[IDX_LAST_CHUNK]; - -//------------------------------------------------------------------------------ -// Chunk object management. - -// Initialize. -void ChunkInit(WebPChunk* const chunk); - -// Get chunk index from chunk tag. Returns IDX_UNKNOWN if not found. -CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag); - -// Get chunk id from chunk tag. Returns WEBP_CHUNK_UNKNOWN if not found. -WebPChunkId ChunkGetIdFromTag(uint32_t tag); - -// Convert a fourcc string to a tag. -uint32_t ChunkGetTagFromFourCC(const char fourcc[4]); - -// Get chunk index from fourcc. Returns IDX_UNKNOWN if given fourcc is unknown. -CHUNK_INDEX ChunkGetIndexFromFourCC(const char fourcc[4]); - -// Search for nth chunk with given 'tag' in the chunk list. -// nth = 0 means "last of the list". -WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag); - -// Fill the chunk with the given data. -WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data, - int copy_data, uint32_t tag); - -// Sets 'chunk' at nth position in the 'chunk_list'. -// nth = 0 has the special meaning "last of the list". -// On success ownership is transferred from 'chunk' to the 'chunk_list'. -WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list, - uint32_t nth); - -// Releases chunk and returns chunk->next_. -WebPChunk* ChunkRelease(WebPChunk* const chunk); - -// Deletes given chunk & returns chunk->next_. -WebPChunk* ChunkDelete(WebPChunk* const chunk); - -// Deletes all chunks in the given chunk list. -void ChunkListDelete(WebPChunk** const chunk_list); - -// Returns size of the chunk including chunk header and padding byte (if any). -static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) { - return CHUNK_HEADER_SIZE + ((chunk_size + 1) & ~1U); -} - -// Size of a chunk including header and padding. -static WEBP_INLINE size_t ChunkDiskSize(const WebPChunk* chunk) { - const size_t data_size = chunk->data_.size; - assert(data_size < MAX_CHUNK_PAYLOAD); - return SizeWithPadding(data_size); -} - -// Total size of a list of chunks. -size_t ChunkListDiskSize(const WebPChunk* chunk_list); - -// Write out the given list of chunks into 'dst'. -uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst); - -//------------------------------------------------------------------------------ -// MuxImage object management. - -// Initialize. -void MuxImageInit(WebPMuxImage* const wpi); - -// Releases image 'wpi' and returns wpi->next. -WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi); - -// Delete image 'wpi' and return the next image in the list or NULL. -// 'wpi' can be NULL. -WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi); - -// Count number of images matching the given tag id in the 'wpi_list'. -// If id == WEBP_CHUNK_NIL, all images will be matched. -int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id); - -// Update width/height/has_alpha info from chunks within wpi. -// Also remove ALPH chunk if not needed. -int MuxImageFinalize(WebPMuxImage* const wpi); - -// Check if given ID corresponds to an image related chunk. -static WEBP_INLINE int IsWPI(WebPChunkId id) { - switch (id) { - case WEBP_CHUNK_ANMF: - case WEBP_CHUNK_FRGM: - case WEBP_CHUNK_ALPHA: - case WEBP_CHUNK_IMAGE: return 1; - default: return 0; - } -} - -// Pushes 'wpi' at the end of 'wpi_list'. -WebPMuxError MuxImagePush(const WebPMuxImage* wpi, WebPMuxImage** wpi_list); - -// Delete nth image in the image list. -WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth); - -// Get nth image in the image list. -WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth, - WebPMuxImage** wpi); - -// Total size of the given image. -size_t MuxImageDiskSize(const WebPMuxImage* const wpi); - -// Write out the given image into 'dst'. -uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst); - -//------------------------------------------------------------------------------ -// Helper methods for mux. - -// Checks if the given image list contains at least one image with alpha. -int MuxHasAlpha(const WebPMuxImage* images); - -// Write out RIFF header into 'data', given total data size 'size'. -uint8_t* MuxEmitRiffHeader(uint8_t* const data, size_t size); - -// Returns the list where chunk with given ID is to be inserted in mux. -WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id); - -// Validates the given mux object. -WebPMuxError MuxValidate(const WebPMux* const mux); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_MUX_MUXI_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/mux/muxinternal.c b/Example-Mac/Pods/libwebp/src/mux/muxinternal.c deleted file mode 100644 index 4babbe82..00000000 --- a/Example-Mac/Pods/libwebp/src/mux/muxinternal.c +++ /dev/null @@ -1,551 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Internal objects and utils for mux. -// -// Authors: Urvang (urvang@google.com) -// Vikas (vikasa@google.com) - -#include -#include "./muxi.h" -#include "../utils/utils.h" - -#define UNDEFINED_CHUNK_SIZE (-1) - -const ChunkInfo kChunks[] = { - { MKFOURCC('V', 'P', '8', 'X'), WEBP_CHUNK_VP8X, VP8X_CHUNK_SIZE }, - { MKFOURCC('I', 'C', 'C', 'P'), WEBP_CHUNK_ICCP, UNDEFINED_CHUNK_SIZE }, - { MKFOURCC('A', 'N', 'I', 'M'), WEBP_CHUNK_ANIM, ANIM_CHUNK_SIZE }, - { MKFOURCC('A', 'N', 'M', 'F'), WEBP_CHUNK_ANMF, ANMF_CHUNK_SIZE }, - { MKFOURCC('F', 'R', 'G', 'M'), WEBP_CHUNK_FRGM, FRGM_CHUNK_SIZE }, - { MKFOURCC('A', 'L', 'P', 'H'), WEBP_CHUNK_ALPHA, UNDEFINED_CHUNK_SIZE }, - { MKFOURCC('V', 'P', '8', ' '), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE }, - { MKFOURCC('V', 'P', '8', 'L'), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE }, - { MKFOURCC('E', 'X', 'I', 'F'), WEBP_CHUNK_EXIF, UNDEFINED_CHUNK_SIZE }, - { MKFOURCC('X', 'M', 'P', ' '), WEBP_CHUNK_XMP, UNDEFINED_CHUNK_SIZE }, - { NIL_TAG, WEBP_CHUNK_UNKNOWN, UNDEFINED_CHUNK_SIZE }, - - { NIL_TAG, WEBP_CHUNK_NIL, UNDEFINED_CHUNK_SIZE } -}; - -//------------------------------------------------------------------------------ - -int WebPGetMuxVersion(void) { - return (MUX_MAJ_VERSION << 16) | (MUX_MIN_VERSION << 8) | MUX_REV_VERSION; -} - -//------------------------------------------------------------------------------ -// Life of a chunk object. - -void ChunkInit(WebPChunk* const chunk) { - assert(chunk); - memset(chunk, 0, sizeof(*chunk)); - chunk->tag_ = NIL_TAG; -} - -WebPChunk* ChunkRelease(WebPChunk* const chunk) { - WebPChunk* next; - if (chunk == NULL) return NULL; - if (chunk->owner_) { - WebPDataClear(&chunk->data_); - } - next = chunk->next_; - ChunkInit(chunk); - return next; -} - -//------------------------------------------------------------------------------ -// Chunk misc methods. - -CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag) { - int i; - for (i = 0; kChunks[i].tag != NIL_TAG; ++i) { - if (tag == kChunks[i].tag) return (CHUNK_INDEX)i; - } - return IDX_UNKNOWN; -} - -WebPChunkId ChunkGetIdFromTag(uint32_t tag) { - int i; - for (i = 0; kChunks[i].tag != NIL_TAG; ++i) { - if (tag == kChunks[i].tag) return kChunks[i].id; - } - return WEBP_CHUNK_UNKNOWN; -} - -uint32_t ChunkGetTagFromFourCC(const char fourcc[4]) { - return MKFOURCC(fourcc[0], fourcc[1], fourcc[2], fourcc[3]); -} - -CHUNK_INDEX ChunkGetIndexFromFourCC(const char fourcc[4]) { - const uint32_t tag = ChunkGetTagFromFourCC(fourcc); - return ChunkGetIndexFromTag(tag); -} - -//------------------------------------------------------------------------------ -// Chunk search methods. - -// Returns next chunk in the chunk list with the given tag. -static WebPChunk* ChunkSearchNextInList(WebPChunk* chunk, uint32_t tag) { - while (chunk != NULL && chunk->tag_ != tag) { - chunk = chunk->next_; - } - return chunk; -} - -WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag) { - uint32_t iter = nth; - first = ChunkSearchNextInList(first, tag); - if (first == NULL) return NULL; - - while (--iter != 0) { - WebPChunk* next_chunk = ChunkSearchNextInList(first->next_, tag); - if (next_chunk == NULL) break; - first = next_chunk; - } - return ((nth > 0) && (iter > 0)) ? NULL : first; -} - -// Outputs a pointer to 'prev_chunk->next_', -// where 'prev_chunk' is the pointer to the chunk at position (nth - 1). -// Returns true if nth chunk was found. -static int ChunkSearchListToSet(WebPChunk** chunk_list, uint32_t nth, - WebPChunk*** const location) { - uint32_t count = 0; - assert(chunk_list != NULL); - *location = chunk_list; - - while (*chunk_list != NULL) { - WebPChunk* const cur_chunk = *chunk_list; - ++count; - if (count == nth) return 1; // Found. - chunk_list = &cur_chunk->next_; - *location = chunk_list; - } - - // *chunk_list is ok to be NULL if adding at last location. - return (nth == 0 || (count == nth - 1)) ? 1 : 0; -} - -//------------------------------------------------------------------------------ -// Chunk writer methods. - -WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data, - int copy_data, uint32_t tag) { - // For internally allocated chunks, always copy data & make it owner of data. - if (tag == kChunks[IDX_VP8X].tag || tag == kChunks[IDX_ANIM].tag) { - copy_data = 1; - } - - ChunkRelease(chunk); - - if (data != NULL) { - if (copy_data) { // Copy data. - if (!WebPDataCopy(data, &chunk->data_)) return WEBP_MUX_MEMORY_ERROR; - chunk->owner_ = 1; // Chunk is owner of data. - } else { // Don't copy data. - chunk->data_ = *data; - } - } - chunk->tag_ = tag; - return WEBP_MUX_OK; -} - -WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list, - uint32_t nth) { - WebPChunk* new_chunk; - - if (!ChunkSearchListToSet(chunk_list, nth, &chunk_list)) { - return WEBP_MUX_NOT_FOUND; - } - - new_chunk = (WebPChunk*)WebPSafeMalloc(1ULL, sizeof(*new_chunk)); - if (new_chunk == NULL) return WEBP_MUX_MEMORY_ERROR; - *new_chunk = *chunk; - chunk->owner_ = 0; - new_chunk->next_ = *chunk_list; - *chunk_list = new_chunk; - return WEBP_MUX_OK; -} - -//------------------------------------------------------------------------------ -// Chunk deletion method(s). - -WebPChunk* ChunkDelete(WebPChunk* const chunk) { - WebPChunk* const next = ChunkRelease(chunk); - WebPSafeFree(chunk); - return next; -} - -void ChunkListDelete(WebPChunk** const chunk_list) { - while (*chunk_list != NULL) { - *chunk_list = ChunkDelete(*chunk_list); - } -} - -//------------------------------------------------------------------------------ -// Chunk serialization methods. - -static uint8_t* ChunkEmit(const WebPChunk* const chunk, uint8_t* dst) { - const size_t chunk_size = chunk->data_.size; - assert(chunk); - assert(chunk->tag_ != NIL_TAG); - PutLE32(dst + 0, chunk->tag_); - PutLE32(dst + TAG_SIZE, (uint32_t)chunk_size); - assert(chunk_size == (uint32_t)chunk_size); - memcpy(dst + CHUNK_HEADER_SIZE, chunk->data_.bytes, chunk_size); - if (chunk_size & 1) - dst[CHUNK_HEADER_SIZE + chunk_size] = 0; // Add padding. - return dst + ChunkDiskSize(chunk); -} - -uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst) { - while (chunk_list != NULL) { - dst = ChunkEmit(chunk_list, dst); - chunk_list = chunk_list->next_; - } - return dst; -} - -size_t ChunkListDiskSize(const WebPChunk* chunk_list) { - size_t size = 0; - while (chunk_list != NULL) { - size += ChunkDiskSize(chunk_list); - chunk_list = chunk_list->next_; - } - return size; -} - -//------------------------------------------------------------------------------ -// Life of a MuxImage object. - -void MuxImageInit(WebPMuxImage* const wpi) { - assert(wpi); - memset(wpi, 0, sizeof(*wpi)); -} - -WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi) { - WebPMuxImage* next; - if (wpi == NULL) return NULL; - ChunkDelete(wpi->header_); - ChunkDelete(wpi->alpha_); - ChunkDelete(wpi->img_); - ChunkListDelete(&wpi->unknown_); - - next = wpi->next_; - MuxImageInit(wpi); - return next; -} - -//------------------------------------------------------------------------------ -// MuxImage search methods. - -// Get a reference to appropriate chunk list within an image given chunk tag. -static WebPChunk** GetChunkListFromId(const WebPMuxImage* const wpi, - WebPChunkId id) { - assert(wpi != NULL); - switch (id) { - case WEBP_CHUNK_ANMF: - case WEBP_CHUNK_FRGM: return (WebPChunk**)&wpi->header_; - case WEBP_CHUNK_ALPHA: return (WebPChunk**)&wpi->alpha_; - case WEBP_CHUNK_IMAGE: return (WebPChunk**)&wpi->img_; - default: return NULL; - } -} - -int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id) { - int count = 0; - const WebPMuxImage* current; - for (current = wpi_list; current != NULL; current = current->next_) { - if (id == WEBP_CHUNK_NIL) { - ++count; // Special case: count all images. - } else { - const WebPChunk* const wpi_chunk = *GetChunkListFromId(current, id); - if (wpi_chunk != NULL) { - const WebPChunkId wpi_chunk_id = ChunkGetIdFromTag(wpi_chunk->tag_); - if (wpi_chunk_id == id) ++count; // Count images with a matching 'id'. - } - } - } - return count; -} - -// Outputs a pointer to 'prev_wpi->next_', -// where 'prev_wpi' is the pointer to the image at position (nth - 1). -// Returns true if nth image was found. -static int SearchImageToGetOrDelete(WebPMuxImage** wpi_list, uint32_t nth, - WebPMuxImage*** const location) { - uint32_t count = 0; - assert(wpi_list); - *location = wpi_list; - - if (nth == 0) { - nth = MuxImageCount(*wpi_list, WEBP_CHUNK_NIL); - if (nth == 0) return 0; // Not found. - } - - while (*wpi_list != NULL) { - WebPMuxImage* const cur_wpi = *wpi_list; - ++count; - if (count == nth) return 1; // Found. - wpi_list = &cur_wpi->next_; - *location = wpi_list; - } - return 0; // Not found. -} - -//------------------------------------------------------------------------------ -// MuxImage writer methods. - -WebPMuxError MuxImagePush(const WebPMuxImage* wpi, WebPMuxImage** wpi_list) { - WebPMuxImage* new_wpi; - - while (*wpi_list != NULL) { - WebPMuxImage* const cur_wpi = *wpi_list; - if (cur_wpi->next_ == NULL) break; - wpi_list = &cur_wpi->next_; - } - - new_wpi = (WebPMuxImage*)WebPSafeMalloc(1ULL, sizeof(*new_wpi)); - if (new_wpi == NULL) return WEBP_MUX_MEMORY_ERROR; - *new_wpi = *wpi; - new_wpi->next_ = NULL; - - if (*wpi_list != NULL) { - (*wpi_list)->next_ = new_wpi; - } else { - *wpi_list = new_wpi; - } - return WEBP_MUX_OK; -} - -//------------------------------------------------------------------------------ -// MuxImage deletion methods. - -WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi) { - // Delete the components of wpi. If wpi is NULL this is a noop. - WebPMuxImage* const next = MuxImageRelease(wpi); - WebPSafeFree(wpi); - return next; -} - -WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth) { - assert(wpi_list); - if (!SearchImageToGetOrDelete(wpi_list, nth, &wpi_list)) { - return WEBP_MUX_NOT_FOUND; - } - *wpi_list = MuxImageDelete(*wpi_list); - return WEBP_MUX_OK; -} - -//------------------------------------------------------------------------------ -// MuxImage reader methods. - -WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth, - WebPMuxImage** wpi) { - assert(wpi_list); - assert(wpi); - if (!SearchImageToGetOrDelete((WebPMuxImage**)wpi_list, nth, - (WebPMuxImage***)&wpi_list)) { - return WEBP_MUX_NOT_FOUND; - } - *wpi = (WebPMuxImage*)*wpi_list; - return WEBP_MUX_OK; -} - -//------------------------------------------------------------------------------ -// MuxImage serialization methods. - -// Size of an image. -size_t MuxImageDiskSize(const WebPMuxImage* const wpi) { - size_t size = 0; - if (wpi->header_ != NULL) size += ChunkDiskSize(wpi->header_); - if (wpi->alpha_ != NULL) size += ChunkDiskSize(wpi->alpha_); - if (wpi->img_ != NULL) size += ChunkDiskSize(wpi->img_); - if (wpi->unknown_ != NULL) size += ChunkListDiskSize(wpi->unknown_); - return size; -} - -// Special case as ANMF/FRGM chunk encapsulates other image chunks. -static uint8_t* ChunkEmitSpecial(const WebPChunk* const header, - size_t total_size, uint8_t* dst) { - const size_t header_size = header->data_.size; - const size_t offset_to_next = total_size - CHUNK_HEADER_SIZE; - assert(header->tag_ == kChunks[IDX_ANMF].tag || - header->tag_ == kChunks[IDX_FRGM].tag); - PutLE32(dst + 0, header->tag_); - PutLE32(dst + TAG_SIZE, (uint32_t)offset_to_next); - assert(header_size == (uint32_t)header_size); - memcpy(dst + CHUNK_HEADER_SIZE, header->data_.bytes, header_size); - if (header_size & 1) { - dst[CHUNK_HEADER_SIZE + header_size] = 0; // Add padding. - } - return dst + ChunkDiskSize(header); -} - -uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst) { - // Ordering of chunks to be emitted is strictly as follows: - // 1. ANMF/FRGM chunk (if present). - // 2. ALPH chunk (if present). - // 3. VP8/VP8L chunk. - assert(wpi); - if (wpi->header_ != NULL) { - dst = ChunkEmitSpecial(wpi->header_, MuxImageDiskSize(wpi), dst); - } - if (wpi->alpha_ != NULL) dst = ChunkEmit(wpi->alpha_, dst); - if (wpi->img_ != NULL) dst = ChunkEmit(wpi->img_, dst); - if (wpi->unknown_ != NULL) dst = ChunkListEmit(wpi->unknown_, dst); - return dst; -} - -//------------------------------------------------------------------------------ -// Helper methods for mux. - -int MuxHasAlpha(const WebPMuxImage* images) { - while (images != NULL) { - if (images->has_alpha_) return 1; - images = images->next_; - } - return 0; -} - -uint8_t* MuxEmitRiffHeader(uint8_t* const data, size_t size) { - PutLE32(data + 0, MKFOURCC('R', 'I', 'F', 'F')); - PutLE32(data + TAG_SIZE, (uint32_t)size - CHUNK_HEADER_SIZE); - assert(size == (uint32_t)size); - PutLE32(data + TAG_SIZE + CHUNK_SIZE_BYTES, MKFOURCC('W', 'E', 'B', 'P')); - return data + RIFF_HEADER_SIZE; -} - -WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id) { - assert(mux != NULL); - switch (id) { - case WEBP_CHUNK_VP8X: return (WebPChunk**)&mux->vp8x_; - case WEBP_CHUNK_ICCP: return (WebPChunk**)&mux->iccp_; - case WEBP_CHUNK_ANIM: return (WebPChunk**)&mux->anim_; - case WEBP_CHUNK_EXIF: return (WebPChunk**)&mux->exif_; - case WEBP_CHUNK_XMP: return (WebPChunk**)&mux->xmp_; - default: return (WebPChunk**)&mux->unknown_; - } -} - -static int IsNotCompatible(int feature, int num_items) { - return (feature != 0) != (num_items > 0); -} - -#define NO_FLAG 0 - -// Test basic constraints: -// retrieval, maximum number of chunks by index (use -1 to skip) -// and feature incompatibility (use NO_FLAG to skip). -// On success returns WEBP_MUX_OK and stores the chunk count in *num. -static WebPMuxError ValidateChunk(const WebPMux* const mux, CHUNK_INDEX idx, - WebPFeatureFlags feature, - uint32_t vp8x_flags, - int max, int* num) { - const WebPMuxError err = - WebPMuxNumChunks(mux, kChunks[idx].id, num); - if (err != WEBP_MUX_OK) return err; - if (max > -1 && *num > max) return WEBP_MUX_INVALID_ARGUMENT; - if (feature != NO_FLAG && IsNotCompatible(vp8x_flags & feature, *num)) { - return WEBP_MUX_INVALID_ARGUMENT; - } - return WEBP_MUX_OK; -} - -WebPMuxError MuxValidate(const WebPMux* const mux) { - int num_iccp; - int num_exif; - int num_xmp; - int num_anim; - int num_frames; - int num_fragments; - int num_vp8x; - int num_images; - int num_alpha; - uint32_t flags; - WebPMuxError err; - - // Verify mux is not NULL. - if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT; - - // Verify mux has at least one image. - if (mux->images_ == NULL) return WEBP_MUX_INVALID_ARGUMENT; - - err = WebPMuxGetFeatures(mux, &flags); - if (err != WEBP_MUX_OK) return err; - - // At most one color profile chunk. - err = ValidateChunk(mux, IDX_ICCP, ICCP_FLAG, flags, 1, &num_iccp); - if (err != WEBP_MUX_OK) return err; - - // At most one EXIF metadata. - err = ValidateChunk(mux, IDX_EXIF, EXIF_FLAG, flags, 1, &num_exif); - if (err != WEBP_MUX_OK) return err; - - // At most one XMP metadata. - err = ValidateChunk(mux, IDX_XMP, XMP_FLAG, flags, 1, &num_xmp); - if (err != WEBP_MUX_OK) return err; - - // Animation: ANIMATION_FLAG, ANIM chunk and ANMF chunk(s) are consistent. - // At most one ANIM chunk. - err = ValidateChunk(mux, IDX_ANIM, NO_FLAG, flags, 1, &num_anim); - if (err != WEBP_MUX_OK) return err; - err = ValidateChunk(mux, IDX_ANMF, NO_FLAG, flags, -1, &num_frames); - if (err != WEBP_MUX_OK) return err; - - { - const int has_animation = !!(flags & ANIMATION_FLAG); - if (has_animation && (num_anim == 0 || num_frames == 0)) { - return WEBP_MUX_INVALID_ARGUMENT; - } - if (!has_animation && (num_anim == 1 || num_frames > 0)) { - return WEBP_MUX_INVALID_ARGUMENT; - } - } - - // Fragmentation: FRAGMENTS_FLAG and FRGM chunk(s) are consistent. - err = ValidateChunk(mux, IDX_FRGM, FRAGMENTS_FLAG, flags, -1, &num_fragments); - if (err != WEBP_MUX_OK) return err; - - // Verify either VP8X chunk is present OR there is only one elem in - // mux->images_. - err = ValidateChunk(mux, IDX_VP8X, NO_FLAG, flags, 1, &num_vp8x); - if (err != WEBP_MUX_OK) return err; - err = ValidateChunk(mux, IDX_VP8, NO_FLAG, flags, -1, &num_images); - if (err != WEBP_MUX_OK) return err; - if (num_vp8x == 0 && num_images != 1) return WEBP_MUX_INVALID_ARGUMENT; - - // ALPHA_FLAG & alpha chunk(s) are consistent. - if (MuxHasAlpha(mux->images_)) { - if (num_vp8x > 0) { - // VP8X chunk is present, so it should contain ALPHA_FLAG. - if (!(flags & ALPHA_FLAG)) return WEBP_MUX_INVALID_ARGUMENT; - } else { - // VP8X chunk is not present, so ALPH chunks should NOT be present either. - err = WebPMuxNumChunks(mux, WEBP_CHUNK_ALPHA, &num_alpha); - if (err != WEBP_MUX_OK) return err; - if (num_alpha > 0) return WEBP_MUX_INVALID_ARGUMENT; - } - } else { // Mux doesn't need alpha. So, ALPHA_FLAG should NOT be present. - if (flags & ALPHA_FLAG) return WEBP_MUX_INVALID_ARGUMENT; - } - - // num_fragments & num_images are consistent. - if (num_fragments > 0 && num_images != num_fragments) { - return WEBP_MUX_INVALID_ARGUMENT; - } - - return WEBP_MUX_OK; -} - -#undef NO_FLAG - -//------------------------------------------------------------------------------ - diff --git a/Example-Mac/Pods/libwebp/src/mux/muxread.c b/Example-Mac/Pods/libwebp/src/mux/muxread.c deleted file mode 100644 index 8957a1e4..00000000 --- a/Example-Mac/Pods/libwebp/src/mux/muxread.c +++ /dev/null @@ -1,544 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Read APIs for mux. -// -// Authors: Urvang (urvang@google.com) -// Vikas (vikasa@google.com) - -#include -#include "./muxi.h" -#include "../utils/utils.h" - -//------------------------------------------------------------------------------ -// Helper method(s). - -// Handy MACRO. -#define SWITCH_ID_LIST(INDEX, LIST) \ - if (idx == (INDEX)) { \ - const WebPChunk* const chunk = ChunkSearchList((LIST), nth, \ - kChunks[(INDEX)].tag); \ - if (chunk) { \ - *data = chunk->data_; \ - return WEBP_MUX_OK; \ - } else { \ - return WEBP_MUX_NOT_FOUND; \ - } \ - } - -static WebPMuxError MuxGet(const WebPMux* const mux, CHUNK_INDEX idx, - uint32_t nth, WebPData* const data) { - assert(mux != NULL); - assert(!IsWPI(kChunks[idx].id)); - WebPDataInit(data); - - SWITCH_ID_LIST(IDX_VP8X, mux->vp8x_); - SWITCH_ID_LIST(IDX_ICCP, mux->iccp_); - SWITCH_ID_LIST(IDX_ANIM, mux->anim_); - SWITCH_ID_LIST(IDX_EXIF, mux->exif_); - SWITCH_ID_LIST(IDX_XMP, mux->xmp_); - SWITCH_ID_LIST(IDX_UNKNOWN, mux->unknown_); - return WEBP_MUX_NOT_FOUND; -} -#undef SWITCH_ID_LIST - -// Fill the chunk with the given data (includes chunk header bytes), after some -// verifications. -static WebPMuxError ChunkVerifyAndAssign(WebPChunk* chunk, - const uint8_t* data, size_t data_size, - size_t riff_size, int copy_data) { - uint32_t chunk_size; - WebPData chunk_data; - - // Sanity checks. - if (data_size < CHUNK_HEADER_SIZE) return WEBP_MUX_NOT_ENOUGH_DATA; - chunk_size = GetLE32(data + TAG_SIZE); - - { - const size_t chunk_disk_size = SizeWithPadding(chunk_size); - if (chunk_disk_size > riff_size) return WEBP_MUX_BAD_DATA; - if (chunk_disk_size > data_size) return WEBP_MUX_NOT_ENOUGH_DATA; - } - - // Data assignment. - chunk_data.bytes = data + CHUNK_HEADER_SIZE; - chunk_data.size = chunk_size; - return ChunkAssignData(chunk, &chunk_data, copy_data, GetLE32(data + 0)); -} - -int MuxImageFinalize(WebPMuxImage* const wpi) { - const WebPChunk* const img = wpi->img_; - const WebPData* const image = &img->data_; - const int is_lossless = (img->tag_ == kChunks[IDX_VP8L].tag); - int w, h; - int vp8l_has_alpha = 0; - const int ok = is_lossless ? - VP8LGetInfo(image->bytes, image->size, &w, &h, &vp8l_has_alpha) : - VP8GetInfo(image->bytes, image->size, image->size, &w, &h); - assert(img != NULL); - if (ok) { - // Ignore ALPH chunk accompanying VP8L. - if (is_lossless && (wpi->alpha_ != NULL)) { - ChunkDelete(wpi->alpha_); - wpi->alpha_ = NULL; - } - wpi->width_ = w; - wpi->height_ = h; - wpi->has_alpha_ = vp8l_has_alpha || (wpi->alpha_ != NULL); - } - return ok; -} - -static int MuxImageParse(const WebPChunk* const chunk, int copy_data, - WebPMuxImage* const wpi) { - const uint8_t* bytes = chunk->data_.bytes; - size_t size = chunk->data_.size; - const uint8_t* const last = bytes + size; - WebPChunk subchunk; - size_t subchunk_size; - ChunkInit(&subchunk); - - assert(chunk->tag_ == kChunks[IDX_ANMF].tag || - chunk->tag_ == kChunks[IDX_FRGM].tag); - assert(!wpi->is_partial_); - - // ANMF/FRGM. - { - const size_t hdr_size = (chunk->tag_ == kChunks[IDX_ANMF].tag) ? - ANMF_CHUNK_SIZE : FRGM_CHUNK_SIZE; - const WebPData temp = { bytes, hdr_size }; - // Each of ANMF and FRGM chunk contain a header at the beginning. So, its - // size should at least be 'hdr_size'. - if (size < hdr_size) goto Fail; - ChunkAssignData(&subchunk, &temp, copy_data, chunk->tag_); - } - ChunkSetNth(&subchunk, &wpi->header_, 1); - wpi->is_partial_ = 1; // Waiting for ALPH and/or VP8/VP8L chunks. - - // Rest of the chunks. - subchunk_size = ChunkDiskSize(&subchunk) - CHUNK_HEADER_SIZE; - bytes += subchunk_size; - size -= subchunk_size; - - while (bytes != last) { - ChunkInit(&subchunk); - if (ChunkVerifyAndAssign(&subchunk, bytes, size, size, - copy_data) != WEBP_MUX_OK) { - goto Fail; - } - switch (ChunkGetIdFromTag(subchunk.tag_)) { - case WEBP_CHUNK_ALPHA: - if (wpi->alpha_ != NULL) goto Fail; // Consecutive ALPH chunks. - if (ChunkSetNth(&subchunk, &wpi->alpha_, 1) != WEBP_MUX_OK) goto Fail; - wpi->is_partial_ = 1; // Waiting for a VP8 chunk. - break; - case WEBP_CHUNK_IMAGE: - if (ChunkSetNth(&subchunk, &wpi->img_, 1) != WEBP_MUX_OK) goto Fail; - if (!MuxImageFinalize(wpi)) goto Fail; - wpi->is_partial_ = 0; // wpi is completely filled. - break; - case WEBP_CHUNK_UNKNOWN: - if (wpi->is_partial_) goto Fail; // Encountered an unknown chunk - // before some image chunks. - if (ChunkSetNth(&subchunk, &wpi->unknown_, 0) != WEBP_MUX_OK) goto Fail; - break; - default: - goto Fail; - break; - } - subchunk_size = ChunkDiskSize(&subchunk); - bytes += subchunk_size; - size -= subchunk_size; - } - if (wpi->is_partial_) goto Fail; - return 1; - - Fail: - ChunkRelease(&subchunk); - return 0; -} - -//------------------------------------------------------------------------------ -// Create a mux object from WebP-RIFF data. - -WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data, - int version) { - size_t riff_size; - uint32_t tag; - const uint8_t* end; - WebPMux* mux = NULL; - WebPMuxImage* wpi = NULL; - const uint8_t* data; - size_t size; - WebPChunk chunk; - ChunkInit(&chunk); - - // Sanity checks. - if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_MUX_ABI_VERSION)) { - return NULL; // version mismatch - } - if (bitstream == NULL) return NULL; - - data = bitstream->bytes; - size = bitstream->size; - - if (data == NULL) return NULL; - if (size < RIFF_HEADER_SIZE) return NULL; - if (GetLE32(data + 0) != MKFOURCC('R', 'I', 'F', 'F') || - GetLE32(data + CHUNK_HEADER_SIZE) != MKFOURCC('W', 'E', 'B', 'P')) { - return NULL; - } - - mux = WebPMuxNew(); - if (mux == NULL) return NULL; - - if (size < RIFF_HEADER_SIZE + TAG_SIZE) goto Err; - - tag = GetLE32(data + RIFF_HEADER_SIZE); - if (tag != kChunks[IDX_VP8].tag && - tag != kChunks[IDX_VP8L].tag && - tag != kChunks[IDX_VP8X].tag) { - goto Err; // First chunk should be VP8, VP8L or VP8X. - } - - riff_size = SizeWithPadding(GetLE32(data + TAG_SIZE)); - if (riff_size > MAX_CHUNK_PAYLOAD || riff_size > size) { - goto Err; - } else { - if (riff_size < size) { // Redundant data after last chunk. - size = riff_size; // To make sure we don't read any data beyond mux_size. - } - } - - end = data + size; - data += RIFF_HEADER_SIZE; - size -= RIFF_HEADER_SIZE; - - wpi = (WebPMuxImage*)WebPSafeMalloc(1ULL, sizeof(*wpi)); - if (wpi == NULL) goto Err; - MuxImageInit(wpi); - - // Loop over chunks. - while (data != end) { - size_t data_size; - WebPChunkId id; - WebPChunk** chunk_list; - if (ChunkVerifyAndAssign(&chunk, data, size, riff_size, - copy_data) != WEBP_MUX_OK) { - goto Err; - } - data_size = ChunkDiskSize(&chunk); - id = ChunkGetIdFromTag(chunk.tag_); - switch (id) { - case WEBP_CHUNK_ALPHA: - if (wpi->alpha_ != NULL) goto Err; // Consecutive ALPH chunks. - if (ChunkSetNth(&chunk, &wpi->alpha_, 1) != WEBP_MUX_OK) goto Err; - wpi->is_partial_ = 1; // Waiting for a VP8 chunk. - break; - case WEBP_CHUNK_IMAGE: - if (ChunkSetNth(&chunk, &wpi->img_, 1) != WEBP_MUX_OK) goto Err; - if (!MuxImageFinalize(wpi)) goto Err; - wpi->is_partial_ = 0; // wpi is completely filled. - PushImage: - // Add this to mux->images_ list. - if (MuxImagePush(wpi, &mux->images_) != WEBP_MUX_OK) goto Err; - MuxImageInit(wpi); // Reset for reading next image. - break; - case WEBP_CHUNK_ANMF: - if (wpi->is_partial_) goto Err; // Previous wpi is still incomplete. - if (!MuxImageParse(&chunk, copy_data, wpi)) goto Err; - ChunkRelease(&chunk); - goto PushImage; - break; - default: // A non-image chunk. - if (wpi->is_partial_) goto Err; // Encountered a non-image chunk before - // getting all chunks of an image. - chunk_list = MuxGetChunkListFromId(mux, id); // List to add this chunk. - if (ChunkSetNth(&chunk, chunk_list, 0) != WEBP_MUX_OK) goto Err; - if (id == WEBP_CHUNK_VP8X) { // grab global specs - mux->canvas_width_ = GetLE24(data + 12) + 1; - mux->canvas_height_ = GetLE24(data + 15) + 1; - } - break; - } - data += data_size; - size -= data_size; - ChunkInit(&chunk); - } - - // Validate mux if complete. - if (MuxValidate(mux) != WEBP_MUX_OK) goto Err; - - MuxImageDelete(wpi); - return mux; // All OK; - - Err: // Something bad happened. - ChunkRelease(&chunk); - MuxImageDelete(wpi); - WebPMuxDelete(mux); - return NULL; -} - -//------------------------------------------------------------------------------ -// Get API(s). - -// Validates that the given mux has a single image. -static WebPMuxError ValidateForSingleImage(const WebPMux* const mux) { - const int num_images = MuxImageCount(mux->images_, WEBP_CHUNK_IMAGE); - const int num_frames = MuxImageCount(mux->images_, WEBP_CHUNK_ANMF); - const int num_fragments = MuxImageCount(mux->images_, WEBP_CHUNK_FRGM); - - if (num_images == 0) { - // No images in mux. - return WEBP_MUX_NOT_FOUND; - } else if (num_images == 1 && num_frames == 0 && num_fragments == 0) { - // Valid case (single image). - return WEBP_MUX_OK; - } else { - // Frame/Fragment case OR an invalid mux. - return WEBP_MUX_INVALID_ARGUMENT; - } -} - -// Get the canvas width, height and flags after validating that VP8X/VP8/VP8L -// chunk and canvas size are valid. -static WebPMuxError MuxGetCanvasInfo(const WebPMux* const mux, - int* width, int* height, uint32_t* flags) { - int w, h; - uint32_t f = 0; - WebPData data; - assert(mux != NULL); - - // Check if VP8X chunk is present. - if (MuxGet(mux, IDX_VP8X, 1, &data) == WEBP_MUX_OK) { - if (data.size < VP8X_CHUNK_SIZE) return WEBP_MUX_BAD_DATA; - f = GetLE32(data.bytes + 0); - w = GetLE24(data.bytes + 4) + 1; - h = GetLE24(data.bytes + 7) + 1; - } else { - const WebPMuxImage* const wpi = mux->images_; - // Grab user-forced canvas size as default. - w = mux->canvas_width_; - h = mux->canvas_height_; - if (w == 0 && h == 0 && ValidateForSingleImage(mux) == WEBP_MUX_OK) { - // single image and not forced canvas size => use dimension of first frame - assert(wpi != NULL); - w = wpi->width_; - h = wpi->height_; - } - if (wpi != NULL) { - if (wpi->has_alpha_) f |= ALPHA_FLAG; - } - } - if (w * (uint64_t)h >= MAX_IMAGE_AREA) return WEBP_MUX_BAD_DATA; - - if (width != NULL) *width = w; - if (height != NULL) *height = h; - if (flags != NULL) *flags = f; - return WEBP_MUX_OK; -} - -WebPMuxError WebPMuxGetCanvasSize(const WebPMux* mux, int* width, int* height) { - if (mux == NULL || width == NULL || height == NULL) { - return WEBP_MUX_INVALID_ARGUMENT; - } - return MuxGetCanvasInfo(mux, width, height, NULL); -} - -WebPMuxError WebPMuxGetFeatures(const WebPMux* mux, uint32_t* flags) { - if (mux == NULL || flags == NULL) return WEBP_MUX_INVALID_ARGUMENT; - return MuxGetCanvasInfo(mux, NULL, NULL, flags); -} - -static uint8_t* EmitVP8XChunk(uint8_t* const dst, int width, - int height, uint32_t flags) { - const size_t vp8x_size = CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE; - assert(width >= 1 && height >= 1); - assert(width <= MAX_CANVAS_SIZE && height <= MAX_CANVAS_SIZE); - assert(width * (uint64_t)height < MAX_IMAGE_AREA); - PutLE32(dst, MKFOURCC('V', 'P', '8', 'X')); - PutLE32(dst + TAG_SIZE, VP8X_CHUNK_SIZE); - PutLE32(dst + CHUNK_HEADER_SIZE, flags); - PutLE24(dst + CHUNK_HEADER_SIZE + 4, width - 1); - PutLE24(dst + CHUNK_HEADER_SIZE + 7, height - 1); - return dst + vp8x_size; -} - -// Assemble a single image WebP bitstream from 'wpi'. -static WebPMuxError SynthesizeBitstream(const WebPMuxImage* const wpi, - WebPData* const bitstream) { - uint8_t* dst; - - // Allocate data. - const int need_vp8x = (wpi->alpha_ != NULL); - const size_t vp8x_size = need_vp8x ? CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE : 0; - const size_t alpha_size = need_vp8x ? ChunkDiskSize(wpi->alpha_) : 0; - // Note: No need to output ANMF/FRGM chunk for a single image. - const size_t size = RIFF_HEADER_SIZE + vp8x_size + alpha_size + - ChunkDiskSize(wpi->img_); - uint8_t* const data = (uint8_t*)WebPSafeMalloc(1ULL, size); - if (data == NULL) return WEBP_MUX_MEMORY_ERROR; - - // Main RIFF header. - dst = MuxEmitRiffHeader(data, size); - - if (need_vp8x) { - dst = EmitVP8XChunk(dst, wpi->width_, wpi->height_, ALPHA_FLAG); // VP8X. - dst = ChunkListEmit(wpi->alpha_, dst); // ALPH. - } - - // Bitstream. - dst = ChunkListEmit(wpi->img_, dst); - assert(dst == data + size); - - // Output. - bitstream->bytes = data; - bitstream->size = size; - return WEBP_MUX_OK; -} - -WebPMuxError WebPMuxGetChunk(const WebPMux* mux, const char fourcc[4], - WebPData* chunk_data) { - CHUNK_INDEX idx; - if (mux == NULL || fourcc == NULL || chunk_data == NULL) { - return WEBP_MUX_INVALID_ARGUMENT; - } - idx = ChunkGetIndexFromFourCC(fourcc); - if (IsWPI(kChunks[idx].id)) { // An image chunk. - return WEBP_MUX_INVALID_ARGUMENT; - } else if (idx != IDX_UNKNOWN) { // A known chunk type. - return MuxGet(mux, idx, 1, chunk_data); - } else { // An unknown chunk type. - const WebPChunk* const chunk = - ChunkSearchList(mux->unknown_, 1, ChunkGetTagFromFourCC(fourcc)); - if (chunk == NULL) return WEBP_MUX_NOT_FOUND; - *chunk_data = chunk->data_; - return WEBP_MUX_OK; - } -} - -static WebPMuxError MuxGetImageInternal(const WebPMuxImage* const wpi, - WebPMuxFrameInfo* const info) { - // Set some defaults for unrelated fields. - info->x_offset = 0; - info->y_offset = 0; - info->duration = 1; - info->dispose_method = WEBP_MUX_DISPOSE_NONE; - info->blend_method = WEBP_MUX_BLEND; - // Extract data for related fields. - info->id = ChunkGetIdFromTag(wpi->img_->tag_); - return SynthesizeBitstream(wpi, &info->bitstream); -} - -static WebPMuxError MuxGetFrameFragmentInternal(const WebPMuxImage* const wpi, - WebPMuxFrameInfo* const frame) { - const int is_frame = (wpi->header_->tag_ == kChunks[IDX_ANMF].tag); - const CHUNK_INDEX idx = is_frame ? IDX_ANMF : IDX_FRGM; - const WebPData* frame_frgm_data; - if (!is_frame) return WEBP_MUX_INVALID_ARGUMENT; - assert(wpi->header_ != NULL); // Already checked by WebPMuxGetFrame(). - // Get frame/fragment chunk. - frame_frgm_data = &wpi->header_->data_; - if (frame_frgm_data->size < kChunks[idx].size) return WEBP_MUX_BAD_DATA; - // Extract info. - frame->x_offset = 2 * GetLE24(frame_frgm_data->bytes + 0); - frame->y_offset = 2 * GetLE24(frame_frgm_data->bytes + 3); - if (is_frame) { - const uint8_t bits = frame_frgm_data->bytes[15]; - frame->duration = GetLE24(frame_frgm_data->bytes + 12); - frame->dispose_method = - (bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE; - frame->blend_method = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND; - } else { // Defaults for unused values. - frame->duration = 1; - frame->dispose_method = WEBP_MUX_DISPOSE_NONE; - frame->blend_method = WEBP_MUX_BLEND; - } - frame->id = ChunkGetIdFromTag(wpi->header_->tag_); - return SynthesizeBitstream(wpi, &frame->bitstream); -} - -WebPMuxError WebPMuxGetFrame( - const WebPMux* mux, uint32_t nth, WebPMuxFrameInfo* frame) { - WebPMuxError err; - WebPMuxImage* wpi; - - // Sanity checks. - if (mux == NULL || frame == NULL) { - return WEBP_MUX_INVALID_ARGUMENT; - } - - // Get the nth WebPMuxImage. - err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, nth, &wpi); - if (err != WEBP_MUX_OK) return err; - - // Get frame info. - if (wpi->header_ == NULL) { - return MuxGetImageInternal(wpi, frame); - } else { - return MuxGetFrameFragmentInternal(wpi, frame); - } -} - -WebPMuxError WebPMuxGetAnimationParams(const WebPMux* mux, - WebPMuxAnimParams* params) { - WebPData anim; - WebPMuxError err; - - if (mux == NULL || params == NULL) return WEBP_MUX_INVALID_ARGUMENT; - - err = MuxGet(mux, IDX_ANIM, 1, &anim); - if (err != WEBP_MUX_OK) return err; - if (anim.size < kChunks[WEBP_CHUNK_ANIM].size) return WEBP_MUX_BAD_DATA; - params->bgcolor = GetLE32(anim.bytes); - params->loop_count = GetLE16(anim.bytes + 4); - - return WEBP_MUX_OK; -} - -// Get chunk index from chunk id. Returns IDX_NIL if not found. -static CHUNK_INDEX ChunkGetIndexFromId(WebPChunkId id) { - int i; - for (i = 0; kChunks[i].id != WEBP_CHUNK_NIL; ++i) { - if (id == kChunks[i].id) return (CHUNK_INDEX)i; - } - return IDX_NIL; -} - -// Count number of chunks matching 'tag' in the 'chunk_list'. -// If tag == NIL_TAG, any tag will be matched. -static int CountChunks(const WebPChunk* const chunk_list, uint32_t tag) { - int count = 0; - const WebPChunk* current; - for (current = chunk_list; current != NULL; current = current->next_) { - if (tag == NIL_TAG || current->tag_ == tag) { - count++; // Count chunks whose tags match. - } - } - return count; -} - -WebPMuxError WebPMuxNumChunks(const WebPMux* mux, - WebPChunkId id, int* num_elements) { - if (mux == NULL || num_elements == NULL) { - return WEBP_MUX_INVALID_ARGUMENT; - } - - if (IsWPI(id)) { - *num_elements = MuxImageCount(mux->images_, id); - } else { - WebPChunk* const* chunk_list = MuxGetChunkListFromId(mux, id); - const CHUNK_INDEX idx = ChunkGetIndexFromId(id); - *num_elements = CountChunks(*chunk_list, kChunks[idx].tag); - } - - return WEBP_MUX_OK; -} - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/utils/bit_reader.c b/Example-Mac/Pods/libwebp/src/utils/bit_reader.c deleted file mode 100644 index 45198e15..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/bit_reader.c +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Boolean decoder non-inlined methods -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifdef HAVE_CONFIG_H -#include "../webp/config.h" -#endif - -#include "./bit_reader_inl.h" - -//------------------------------------------------------------------------------ -// VP8BitReader - -void VP8BitReaderSetBuffer(VP8BitReader* const br, - const uint8_t* const start, - size_t size) { - br->buf_ = start; - br->buf_end_ = start + size; - br->buf_max_ = - (size >= sizeof(lbit_t)) ? start + size - sizeof(lbit_t) + 1 - : start; -} - -void VP8InitBitReader(VP8BitReader* const br, - const uint8_t* const start, size_t size) { - assert(br != NULL); - assert(start != NULL); - assert(size < (1u << 31)); // limit ensured by format and upstream checks - br->range_ = 255 - 1; - br->value_ = 0; - br->bits_ = -8; // to load the very first 8bits - br->eof_ = 0; - VP8BitReaderSetBuffer(br, start, size); - VP8LoadNewBytes(br); -} - -void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset) { - if (br->buf_ != NULL) { - br->buf_ += offset; - br->buf_end_ += offset; - br->buf_max_ += offset; - } -} - -const uint8_t kVP8Log2Range[128] = { - 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0 -}; - -// range = ((range - 1) << kVP8Log2Range[range]) + 1 -const uint8_t kVP8NewRange[128] = { - 127, 127, 191, 127, 159, 191, 223, 127, - 143, 159, 175, 191, 207, 223, 239, 127, - 135, 143, 151, 159, 167, 175, 183, 191, - 199, 207, 215, 223, 231, 239, 247, 127, - 131, 135, 139, 143, 147, 151, 155, 159, - 163, 167, 171, 175, 179, 183, 187, 191, - 195, 199, 203, 207, 211, 215, 219, 223, - 227, 231, 235, 239, 243, 247, 251, 127, - 129, 131, 133, 135, 137, 139, 141, 143, - 145, 147, 149, 151, 153, 155, 157, 159, - 161, 163, 165, 167, 169, 171, 173, 175, - 177, 179, 181, 183, 185, 187, 189, 191, - 193, 195, 197, 199, 201, 203, 205, 207, - 209, 211, 213, 215, 217, 219, 221, 223, - 225, 227, 229, 231, 233, 235, 237, 239, - 241, 243, 245, 247, 249, 251, 253, 127 -}; - -void VP8LoadFinalBytes(VP8BitReader* const br) { - assert(br != NULL && br->buf_ != NULL); - // Only read 8bits at a time - if (br->buf_ < br->buf_end_) { - br->bits_ += 8; - br->value_ = (bit_t)(*br->buf_++) | (br->value_ << 8); - } else if (!br->eof_) { - br->value_ <<= 8; - br->bits_ += 8; - br->eof_ = 1; - } else { - br->bits_ = 0; // This is to avoid undefined behaviour with shifts. - } -} - -//------------------------------------------------------------------------------ -// Higher-level calls - -uint32_t VP8GetValue(VP8BitReader* const br, int bits) { - uint32_t v = 0; - while (bits-- > 0) { - v |= VP8GetBit(br, 0x80) << bits; - } - return v; -} - -int32_t VP8GetSignedValue(VP8BitReader* const br, int bits) { - const int value = VP8GetValue(br, bits); - return VP8Get(br) ? -value : value; -} - -//------------------------------------------------------------------------------ -// VP8LBitReader - -#define VP8L_LOG8_WBITS 4 // Number of bytes needed to store VP8L_WBITS bits. - -#if !defined(WEBP_FORCE_ALIGNED) && \ - (defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || \ - defined(__i386__) || defined(_M_IX86) || \ - defined(__x86_64__) || defined(_M_X64)) -#define VP8L_USE_UNALIGNED_LOAD -#endif - -static const uint32_t kBitMask[VP8L_MAX_NUM_BIT_READ + 1] = { - 0, - 0x000001, 0x000003, 0x000007, 0x00000f, - 0x00001f, 0x00003f, 0x00007f, 0x0000ff, - 0x0001ff, 0x0003ff, 0x0007ff, 0x000fff, - 0x001fff, 0x003fff, 0x007fff, 0x00ffff, - 0x01ffff, 0x03ffff, 0x07ffff, 0x0fffff, - 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff -}; - -void VP8LInitBitReader(VP8LBitReader* const br, const uint8_t* const start, - size_t length) { - size_t i; - vp8l_val_t value = 0; - assert(br != NULL); - assert(start != NULL); - assert(length < 0xfffffff8u); // can't happen with a RIFF chunk. - - br->len_ = length; - br->val_ = 0; - br->bit_pos_ = 0; - br->eos_ = 0; - - if (length > sizeof(br->val_)) { - length = sizeof(br->val_); - } - for (i = 0; i < length; ++i) { - value |= (vp8l_val_t)start[i] << (8 * i); - } - br->val_ = value; - br->pos_ = length; - br->buf_ = start; -} - -void VP8LBitReaderSetBuffer(VP8LBitReader* const br, - const uint8_t* const buf, size_t len) { - assert(br != NULL); - assert(buf != NULL); - assert(len < 0xfffffff8u); // can't happen with a RIFF chunk. - br->buf_ = buf; - br->len_ = len; - // pos_ > len_ should be considered a param error. - br->eos_ = (br->pos_ > br->len_) || VP8LIsEndOfStream(br); -} - -static void VP8LSetEndOfStream(VP8LBitReader* const br) { - br->eos_ = 1; - br->bit_pos_ = 0; // To avoid undefined behaviour with shifts. -} - -// If not at EOS, reload up to VP8L_LBITS byte-by-byte -static void ShiftBytes(VP8LBitReader* const br) { - while (br->bit_pos_ >= 8 && br->pos_ < br->len_) { - br->val_ >>= 8; - br->val_ |= ((vp8l_val_t)br->buf_[br->pos_]) << (VP8L_LBITS - 8); - ++br->pos_; - br->bit_pos_ -= 8; - } - if (VP8LIsEndOfStream(br)) { - VP8LSetEndOfStream(br); - } -} - -void VP8LDoFillBitWindow(VP8LBitReader* const br) { - assert(br->bit_pos_ >= VP8L_WBITS); - // TODO(jzern): given the fixed read size it may be possible to force - // alignment in this block. -#if defined(VP8L_USE_UNALIGNED_LOAD) - if (br->pos_ + sizeof(br->val_) < br->len_) { - br->val_ >>= VP8L_WBITS; - br->bit_pos_ -= VP8L_WBITS; - // The expression below needs a little-endian arch to work correctly. - // This gives a large speedup for decoding speed. - br->val_ |= (vp8l_val_t)WebPMemToUint32(br->buf_ + br->pos_) << - (VP8L_LBITS - VP8L_WBITS); - br->pos_ += VP8L_LOG8_WBITS; - return; - } -#endif - ShiftBytes(br); // Slow path. -} - -uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits) { - assert(n_bits >= 0); - // Flag an error if end_of_stream or n_bits is more than allowed limit. - if (!br->eos_ && n_bits <= VP8L_MAX_NUM_BIT_READ) { - const uint32_t val = VP8LPrefetchBits(br) & kBitMask[n_bits]; - const int new_bits = br->bit_pos_ + n_bits; - br->bit_pos_ = new_bits; - ShiftBytes(br); - return val; - } else { - VP8LSetEndOfStream(br); - return 0; - } -} - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/utils/bit_reader.h b/Example-Mac/Pods/libwebp/src/utils/bit_reader.h deleted file mode 100644 index ec3426cd..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/bit_reader.h +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Boolean decoder -// -// Author: Skal (pascal.massimino@gmail.com) -// Vikas Arora (vikaas.arora@gmail.com) - -#ifndef WEBP_UTILS_BIT_READER_H_ -#define WEBP_UTILS_BIT_READER_H_ - -#include -#ifdef _MSC_VER -#include // _byteswap_ulong -#endif -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// The Boolean decoder needs to maintain infinite precision on the value_ field. -// However, since range_ is only 8bit, we only need an active window of 8 bits -// for value_. Left bits (MSB) gets zeroed and shifted away when value_ falls -// below 128, range_ is updated, and fresh bits read from the bitstream are -// brought in as LSB. To avoid reading the fresh bits one by one (slow), we -// cache BITS of them ahead. The total of (BITS + 8) bits must fit into a -// natural register (with type bit_t). To fetch BITS bits from bitstream we -// use a type lbit_t. -// -// BITS can be any multiple of 8 from 8 to 56 (inclusive). -// Pick values that fit natural register size. - -#if defined(__i386__) || defined(_M_IX86) // x86 32bit -#define BITS 24 -#elif defined(__x86_64__) || defined(_M_X64) // x86 64bit -#define BITS 56 -#elif defined(__arm__) || defined(_M_ARM) // ARM -#define BITS 24 -#elif defined(__aarch64__) // ARM 64bit -#define BITS 56 -#elif defined(__mips__) // MIPS -#define BITS 24 -#else // reasonable default -#define BITS 24 -#endif - -//------------------------------------------------------------------------------ -// Derived types and constants: -// bit_t = natural register type for storing 'value_' (which is BITS+8 bits) -// range_t = register for 'range_' (which is 8bits only) - -#if (BITS > 24) -typedef uint64_t bit_t; -#else -typedef uint32_t bit_t; -#endif - -typedef uint32_t range_t; - -//------------------------------------------------------------------------------ -// Bitreader - -typedef struct VP8BitReader VP8BitReader; -struct VP8BitReader { - // boolean decoder (keep the field ordering as is!) - bit_t value_; // current value - range_t range_; // current range minus 1. In [127, 254] interval. - int bits_; // number of valid bits left - // read buffer - const uint8_t* buf_; // next byte to be read - const uint8_t* buf_end_; // end of read buffer - const uint8_t* buf_max_; // max packed-read position on buffer - int eof_; // true if input is exhausted -}; - -// Initialize the bit reader and the boolean decoder. -void VP8InitBitReader(VP8BitReader* const br, - const uint8_t* const start, size_t size); -// Sets the working read buffer. -void VP8BitReaderSetBuffer(VP8BitReader* const br, - const uint8_t* const start, size_t size); - -// Update internal pointers to displace the byte buffer by the -// relative offset 'offset'. -void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset); - -// return the next value made of 'num_bits' bits -uint32_t VP8GetValue(VP8BitReader* const br, int num_bits); -static WEBP_INLINE uint32_t VP8Get(VP8BitReader* const br) { - return VP8GetValue(br, 1); -} - -// return the next value with sign-extension. -int32_t VP8GetSignedValue(VP8BitReader* const br, int num_bits); - -// bit_reader_inl.h will implement the following methods: -// static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob) -// static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v) -// and should be included by the .c files that actually need them. -// This is to avoid recompiling the whole library whenever this file is touched, -// and also allowing platform-specific ad-hoc hacks. - -// ----------------------------------------------------------------------------- -// Bitreader for lossless format - -// maximum number of bits (inclusive) the bit-reader can handle: -#define VP8L_MAX_NUM_BIT_READ 24 - -#define VP8L_LBITS 64 // Number of bits prefetched (= bit-size of vp8l_val_t). -#define VP8L_WBITS 32 // Minimum number of bytes ready after VP8LFillBitWindow. - -typedef uint64_t vp8l_val_t; // right now, this bit-reader can only use 64bit. - -typedef struct { - vp8l_val_t val_; // pre-fetched bits - const uint8_t* buf_; // input byte buffer - size_t len_; // buffer length - size_t pos_; // byte position in buf_ - int bit_pos_; // current bit-reading position in val_ - int eos_; // true if a bit was read past the end of buffer -} VP8LBitReader; - -void VP8LInitBitReader(VP8LBitReader* const br, - const uint8_t* const start, - size_t length); - -// Sets a new data buffer. -void VP8LBitReaderSetBuffer(VP8LBitReader* const br, - const uint8_t* const buffer, size_t length); - -// Reads the specified number of bits from read buffer. -// Flags an error in case end_of_stream or n_bits is more than the allowed limit -// of VP8L_MAX_NUM_BIT_READ (inclusive). -// Flags eos_ if this read attempt is going to cross the read buffer. -uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits); - -// Return the prefetched bits, so they can be looked up. -static WEBP_INLINE uint32_t VP8LPrefetchBits(VP8LBitReader* const br) { - return (uint32_t)(br->val_ >> (br->bit_pos_ & (VP8L_LBITS - 1))); -} - -// Returns true if there was an attempt at reading bit past the end of -// the buffer. Doesn't set br->eos_ flag. -static WEBP_INLINE int VP8LIsEndOfStream(const VP8LBitReader* const br) { - assert(br->pos_ <= br->len_); - return br->eos_ || ((br->pos_ == br->len_) && (br->bit_pos_ > VP8L_LBITS)); -} - -// For jumping over a number of bits in the bit stream when accessed with -// VP8LPrefetchBits and VP8LFillBitWindow. -static WEBP_INLINE void VP8LSetBitPos(VP8LBitReader* const br, int val) { - br->bit_pos_ = val; - br->eos_ = VP8LIsEndOfStream(br); -} - -// Advances the read buffer by 4 bytes to make room for reading next 32 bits. -// Speed critical, but infrequent part of the code can be non-inlined. -extern void VP8LDoFillBitWindow(VP8LBitReader* const br); -static WEBP_INLINE void VP8LFillBitWindow(VP8LBitReader* const br) { - if (br->bit_pos_ >= VP8L_WBITS) VP8LDoFillBitWindow(br); -} - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_BIT_READER_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/utils/bit_reader_inl.h b/Example-Mac/Pods/libwebp/src/utils/bit_reader_inl.h deleted file mode 100644 index 37215702..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/bit_reader_inl.h +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Specific inlined methods for boolean decoder [VP8GetBit() ...] -// This file should be included by the .c sources that actually need to call -// these methods. -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_UTILS_BIT_READER_INL_H_ -#define WEBP_UTILS_BIT_READER_INL_H_ - -#ifdef HAVE_CONFIG_H -#include "../webp/config.h" -#endif - -#ifdef WEBP_FORCE_ALIGNED -#include // memcpy -#endif - -#include "../dsp/dsp.h" -#include "./bit_reader.h" -#include "./endian_inl.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//------------------------------------------------------------------------------ -// Derived type lbit_t = natural type for memory I/O - -#if (BITS > 32) -typedef uint64_t lbit_t; -#elif (BITS > 16) -typedef uint32_t lbit_t; -#elif (BITS > 8) -typedef uint16_t lbit_t; -#else -typedef uint8_t lbit_t; -#endif - -extern const uint8_t kVP8Log2Range[128]; -extern const uint8_t kVP8NewRange[128]; - -// special case for the tail byte-reading -void VP8LoadFinalBytes(VP8BitReader* const br); - -//------------------------------------------------------------------------------ -// Inlined critical functions - -// makes sure br->value_ has at least BITS bits worth of data -static WEBP_INLINE void VP8LoadNewBytes(VP8BitReader* const br) { - assert(br != NULL && br->buf_ != NULL); - // Read 'BITS' bits at a time if possible. - if (br->buf_ < br->buf_max_) { - // convert memory type to register type (with some zero'ing!) - bit_t bits; -#if defined(WEBP_FORCE_ALIGNED) - lbit_t in_bits; - memcpy(&in_bits, br->buf_, sizeof(in_bits)); -#elif defined(WEBP_USE_MIPS32) - // This is needed because of un-aligned read. - lbit_t in_bits; - lbit_t* p_buf_ = (lbit_t*)br->buf_; - __asm__ volatile( - ".set push \n\t" - ".set at \n\t" - ".set macro \n\t" - "ulw %[in_bits], 0(%[p_buf_]) \n\t" - ".set pop \n\t" - : [in_bits]"=r"(in_bits) - : [p_buf_]"r"(p_buf_) - : "memory", "at" - ); -#else - const lbit_t in_bits = *(const lbit_t*)br->buf_; -#endif - br->buf_ += BITS >> 3; -#if !defined(WORDS_BIGENDIAN) -#if (BITS > 32) - bits = BSwap64(in_bits); - bits >>= 64 - BITS; -#elif (BITS >= 24) - bits = BSwap32(in_bits); - bits >>= (32 - BITS); -#elif (BITS == 16) - bits = BSwap16(in_bits); -#else // BITS == 8 - bits = (bit_t)in_bits; -#endif // BITS > 32 -#else // WORDS_BIGENDIAN - bits = (bit_t)in_bits; - if (BITS != 8 * sizeof(bit_t)) bits >>= (8 * sizeof(bit_t) - BITS); -#endif - br->value_ = bits | (br->value_ << BITS); - br->bits_ += BITS; - } else { - VP8LoadFinalBytes(br); // no need to be inlined - } -} - -// Read a bit with proba 'prob'. Speed-critical function! -static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob) { - // Don't move this declaration! It makes a big speed difference to store - // 'range' *before* calling VP8LoadNewBytes(), even if this function doesn't - // alter br->range_ value. - range_t range = br->range_; - if (br->bits_ < 0) { - VP8LoadNewBytes(br); - } - { - const int pos = br->bits_; - const range_t split = (range * prob) >> 8; - const range_t value = (range_t)(br->value_ >> pos); -#if defined(__arm__) || defined(_M_ARM) // ARM-specific - const int bit = ((int)(split - value) >> 31) & 1; - if (value > split) { - range -= split + 1; - br->value_ -= (bit_t)(split + 1) << pos; - } else { - range = split; - } -#else // faster version on x86 - int bit; // Don't use 'const int bit = (value > split);", it's slower. - if (value > split) { - range -= split + 1; - br->value_ -= (bit_t)(split + 1) << pos; - bit = 1; - } else { - range = split; - bit = 0; - } -#endif - if (range <= (range_t)0x7e) { - const int shift = kVP8Log2Range[range]; - range = kVP8NewRange[range]; - br->bits_ -= shift; - } - br->range_ = range; - return bit; - } -} - -// simplified version of VP8GetBit() for prob=0x80 (note shift is always 1 here) -static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v) { - if (br->bits_ < 0) { - VP8LoadNewBytes(br); - } - { - const int pos = br->bits_; - const range_t split = br->range_ >> 1; - const range_t value = (range_t)(br->value_ >> pos); - const int32_t mask = (int32_t)(split - value) >> 31; // -1 or 0 - br->bits_ -= 1; - br->range_ += mask; - br->range_ |= 1; - br->value_ -= (bit_t)((split + 1) & mask) << pos; - return (v ^ mask) - mask; - } -} - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // WEBP_UTILS_BIT_READER_INL_H_ diff --git a/Example-Mac/Pods/libwebp/src/utils/bit_writer.c b/Example-Mac/Pods/libwebp/src/utils/bit_writer.c deleted file mode 100644 index 06442869..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/bit_writer.c +++ /dev/null @@ -1,319 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Bit writing and boolean coder -// -// Author: Skal (pascal.massimino@gmail.com) -// Vikas Arora (vikaas.arora@gmail.com) - -#include -#include // for memcpy() -#include - -#include "./bit_writer.h" -#include "./endian_inl.h" -#include "./utils.h" - -//------------------------------------------------------------------------------ -// VP8BitWriter - -static int BitWriterResize(VP8BitWriter* const bw, size_t extra_size) { - uint8_t* new_buf; - size_t new_size; - const uint64_t needed_size_64b = (uint64_t)bw->pos_ + extra_size; - const size_t needed_size = (size_t)needed_size_64b; - if (needed_size_64b != needed_size) { - bw->error_ = 1; - return 0; - } - if (needed_size <= bw->max_pos_) return 1; - // If the following line wraps over 32bit, the test just after will catch it. - new_size = 2 * bw->max_pos_; - if (new_size < needed_size) new_size = needed_size; - if (new_size < 1024) new_size = 1024; - new_buf = (uint8_t*)WebPSafeMalloc(1ULL, new_size); - if (new_buf == NULL) { - bw->error_ = 1; - return 0; - } - if (bw->pos_ > 0) { - assert(bw->buf_ != NULL); - memcpy(new_buf, bw->buf_, bw->pos_); - } - WebPSafeFree(bw->buf_); - bw->buf_ = new_buf; - bw->max_pos_ = new_size; - return 1; -} - -static void Flush(VP8BitWriter* const bw) { - const int s = 8 + bw->nb_bits_; - const int32_t bits = bw->value_ >> s; - assert(bw->nb_bits_ >= 0); - bw->value_ -= bits << s; - bw->nb_bits_ -= 8; - if ((bits & 0xff) != 0xff) { - size_t pos = bw->pos_; - if (!BitWriterResize(bw, bw->run_ + 1)) { - return; - } - if (bits & 0x100) { // overflow -> propagate carry over pending 0xff's - if (pos > 0) bw->buf_[pos - 1]++; - } - if (bw->run_ > 0) { - const int value = (bits & 0x100) ? 0x00 : 0xff; - for (; bw->run_ > 0; --bw->run_) bw->buf_[pos++] = value; - } - bw->buf_[pos++] = bits; - bw->pos_ = pos; - } else { - bw->run_++; // delay writing of bytes 0xff, pending eventual carry. - } -} - -//------------------------------------------------------------------------------ -// renormalization - -static const uint8_t kNorm[128] = { // renorm_sizes[i] = 8 - log2(i) - 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0 -}; - -// range = ((range + 1) << kVP8Log2Range[range]) - 1 -static const uint8_t kNewRange[128] = { - 127, 127, 191, 127, 159, 191, 223, 127, 143, 159, 175, 191, 207, 223, 239, - 127, 135, 143, 151, 159, 167, 175, 183, 191, 199, 207, 215, 223, 231, 239, - 247, 127, 131, 135, 139, 143, 147, 151, 155, 159, 163, 167, 171, 175, 179, - 183, 187, 191, 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239, - 243, 247, 251, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, - 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, - 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, - 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239, - 241, 243, 245, 247, 249, 251, 253, 127 -}; - -int VP8PutBit(VP8BitWriter* const bw, int bit, int prob) { - const int split = (bw->range_ * prob) >> 8; - if (bit) { - bw->value_ += split + 1; - bw->range_ -= split + 1; - } else { - bw->range_ = split; - } - if (bw->range_ < 127) { // emit 'shift' bits out and renormalize - const int shift = kNorm[bw->range_]; - bw->range_ = kNewRange[bw->range_]; - bw->value_ <<= shift; - bw->nb_bits_ += shift; - if (bw->nb_bits_ > 0) Flush(bw); - } - return bit; -} - -int VP8PutBitUniform(VP8BitWriter* const bw, int bit) { - const int split = bw->range_ >> 1; - if (bit) { - bw->value_ += split + 1; - bw->range_ -= split + 1; - } else { - bw->range_ = split; - } - if (bw->range_ < 127) { - bw->range_ = kNewRange[bw->range_]; - bw->value_ <<= 1; - bw->nb_bits_ += 1; - if (bw->nb_bits_ > 0) Flush(bw); - } - return bit; -} - -void VP8PutBits(VP8BitWriter* const bw, uint32_t value, int nb_bits) { - uint32_t mask; - assert(nb_bits > 0 && nb_bits < 32); - for (mask = 1u << (nb_bits - 1); mask; mask >>= 1) - VP8PutBitUniform(bw, value & mask); -} - -void VP8PutSignedBits(VP8BitWriter* const bw, int value, int nb_bits) { - if (!VP8PutBitUniform(bw, value != 0)) - return; - if (value < 0) { - VP8PutBits(bw, ((-value) << 1) | 1, nb_bits + 1); - } else { - VP8PutBits(bw, value << 1, nb_bits + 1); - } -} - -//------------------------------------------------------------------------------ - -int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size) { - bw->range_ = 255 - 1; - bw->value_ = 0; - bw->run_ = 0; - bw->nb_bits_ = -8; - bw->pos_ = 0; - bw->max_pos_ = 0; - bw->error_ = 0; - bw->buf_ = NULL; - return (expected_size > 0) ? BitWriterResize(bw, expected_size) : 1; -} - -uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw) { - VP8PutBits(bw, 0, 9 - bw->nb_bits_); - bw->nb_bits_ = 0; // pad with zeroes - Flush(bw); - return bw->buf_; -} - -int VP8BitWriterAppend(VP8BitWriter* const bw, - const uint8_t* data, size_t size) { - assert(data != NULL); - if (bw->nb_bits_ != -8) return 0; // Flush() must have been called - if (!BitWriterResize(bw, size)) return 0; - memcpy(bw->buf_ + bw->pos_, data, size); - bw->pos_ += size; - return 1; -} - -void VP8BitWriterWipeOut(VP8BitWriter* const bw) { - if (bw != NULL) { - WebPSafeFree(bw->buf_); - memset(bw, 0, sizeof(*bw)); - } -} - -//------------------------------------------------------------------------------ -// VP8LBitWriter - -// This is the minimum amount of size the memory buffer is guaranteed to grow -// when extra space is needed. -#define MIN_EXTRA_SIZE (32768ULL) - -// Returns 1 on success. -static int VP8LBitWriterResize(VP8LBitWriter* const bw, size_t extra_size) { - uint8_t* allocated_buf; - size_t allocated_size; - const size_t max_bytes = bw->end_ - bw->buf_; - const size_t current_size = bw->cur_ - bw->buf_; - const uint64_t size_required_64b = (uint64_t)current_size + extra_size; - const size_t size_required = (size_t)size_required_64b; - if (size_required != size_required_64b) { - bw->error_ = 1; - return 0; - } - if (max_bytes > 0 && size_required <= max_bytes) return 1; - allocated_size = (3 * max_bytes) >> 1; - if (allocated_size < size_required) allocated_size = size_required; - // make allocated size multiple of 1k - allocated_size = (((allocated_size >> 10) + 1) << 10); - allocated_buf = (uint8_t*)WebPSafeMalloc(1ULL, allocated_size); - if (allocated_buf == NULL) { - bw->error_ = 1; - return 0; - } - if (current_size > 0) { - memcpy(allocated_buf, bw->buf_, current_size); - } - WebPSafeFree(bw->buf_); - bw->buf_ = allocated_buf; - bw->cur_ = bw->buf_ + current_size; - bw->end_ = bw->buf_ + allocated_size; - return 1; -} - -int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size) { - memset(bw, 0, sizeof(*bw)); - return VP8LBitWriterResize(bw, expected_size); -} - -void VP8LBitWriterWipeOut(VP8LBitWriter* const bw) { - if (bw != NULL) { - WebPSafeFree(bw->buf_); - memset(bw, 0, sizeof(*bw)); - } -} - -void VP8LPutBitsFlushBits(VP8LBitWriter* const bw) { - // If needed, make some room by flushing some bits out. - if (bw->cur_ + VP8L_WRITER_BYTES > bw->end_) { - const uint64_t extra_size = (bw->end_ - bw->buf_) + MIN_EXTRA_SIZE; - if (extra_size != (size_t)extra_size || - !VP8LBitWriterResize(bw, (size_t)extra_size)) { - bw->cur_ = bw->buf_; - bw->error_ = 1; - return; - } - } - *(vp8l_wtype_t*)bw->cur_ = (vp8l_wtype_t)WSWAP((vp8l_wtype_t)bw->bits_); - bw->cur_ += VP8L_WRITER_BYTES; - bw->bits_ >>= VP8L_WRITER_BITS; - bw->used_ -= VP8L_WRITER_BITS; -} - -void VP8LPutBitsInternal(VP8LBitWriter* const bw, uint32_t bits, int n_bits) { - assert(n_bits <= 32); - // That's the max we can handle: - assert(sizeof(vp8l_wtype_t) == 2); - if (n_bits > 0) { - vp8l_atype_t lbits = bw->bits_; - int used = bw->used_; - // Special case of overflow handling for 32bit accumulator (2-steps flush). -#if VP8L_WRITER_BITS == 16 - if (used + n_bits >= VP8L_WRITER_MAX_BITS) { - // Fill up all the VP8L_WRITER_MAX_BITS so it can be flushed out below. - const int shift = VP8L_WRITER_MAX_BITS - used; - lbits |= (vp8l_atype_t)bits << used; - used = VP8L_WRITER_MAX_BITS; - n_bits -= shift; - bits >>= shift; - assert(n_bits <= VP8L_WRITER_MAX_BITS); - } -#endif - // If needed, make some room by flushing some bits out. - while (used >= VP8L_WRITER_BITS) { - if (bw->cur_ + VP8L_WRITER_BYTES > bw->end_) { - const uint64_t extra_size = (bw->end_ - bw->buf_) + MIN_EXTRA_SIZE; - if (extra_size != (size_t)extra_size || - !VP8LBitWriterResize(bw, (size_t)extra_size)) { - bw->cur_ = bw->buf_; - bw->error_ = 1; - return; - } - } - *(vp8l_wtype_t*)bw->cur_ = (vp8l_wtype_t)WSWAP((vp8l_wtype_t)lbits); - bw->cur_ += VP8L_WRITER_BYTES; - lbits >>= VP8L_WRITER_BITS; - used -= VP8L_WRITER_BITS; - } - bw->bits_ = lbits | ((vp8l_atype_t)bits << used); - bw->used_ = used + n_bits; - } -} - -uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw) { - // flush leftover bits - if (VP8LBitWriterResize(bw, (bw->used_ + 7) >> 3)) { - while (bw->used_ > 0) { - *bw->cur_++ = (uint8_t)bw->bits_; - bw->bits_ >>= 8; - bw->used_ -= 8; - } - bw->used_ = 0; - } - return bw->buf_; -} - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/utils/bit_writer.h b/Example-Mac/Pods/libwebp/src/utils/bit_writer.h deleted file mode 100644 index ef360d1d..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/bit_writer.h +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Bit writing and boolean coder -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_UTILS_BIT_WRITER_H_ -#define WEBP_UTILS_BIT_WRITER_H_ - -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//------------------------------------------------------------------------------ -// Bit-writing - -typedef struct VP8BitWriter VP8BitWriter; -struct VP8BitWriter { - int32_t range_; // range-1 - int32_t value_; - int run_; // number of outstanding bits - int nb_bits_; // number of pending bits - uint8_t* buf_; // internal buffer. Re-allocated regularly. Not owned. - size_t pos_; - size_t max_pos_; - int error_; // true in case of error -}; - -// Initialize the object. Allocates some initial memory based on expected_size. -int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size); -// Finalize the bitstream coding. Returns a pointer to the internal buffer. -uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw); -// Release any pending memory and zeroes the object. Not a mandatory call. -// Only useful in case of error, when the internal buffer hasn't been grabbed! -void VP8BitWriterWipeOut(VP8BitWriter* const bw); - -int VP8PutBit(VP8BitWriter* const bw, int bit, int prob); -int VP8PutBitUniform(VP8BitWriter* const bw, int bit); -void VP8PutBits(VP8BitWriter* const bw, uint32_t value, int nb_bits); -void VP8PutSignedBits(VP8BitWriter* const bw, int value, int nb_bits); - -// Appends some bytes to the internal buffer. Data is copied. -int VP8BitWriterAppend(VP8BitWriter* const bw, - const uint8_t* data, size_t size); - -// return approximate write position (in bits) -static WEBP_INLINE uint64_t VP8BitWriterPos(const VP8BitWriter* const bw) { - return (uint64_t)(bw->pos_ + bw->run_) * 8 + 8 + bw->nb_bits_; -} - -// Returns a pointer to the internal buffer. -static WEBP_INLINE uint8_t* VP8BitWriterBuf(const VP8BitWriter* const bw) { - return bw->buf_; -} -// Returns the size of the internal buffer. -static WEBP_INLINE size_t VP8BitWriterSize(const VP8BitWriter* const bw) { - return bw->pos_; -} - -//------------------------------------------------------------------------------ -// VP8LBitWriter - -#if defined(__x86_64__) || defined(_M_X64) // 64bit -typedef uint64_t vp8l_atype_t; // accumulator type -typedef uint32_t vp8l_wtype_t; // writing type -#define WSWAP HToLE32 -#define VP8L_WRITER_BYTES 4 // sizeof(vp8l_wtype_t) -#define VP8L_WRITER_BITS 32 // 8 * sizeof(vp8l_wtype_t) -#define VP8L_WRITER_MAX_BITS 64 // 8 * sizeof(vp8l_atype_t) -#else -typedef uint32_t vp8l_atype_t; -typedef uint16_t vp8l_wtype_t; -#define WSWAP HToLE16 -#define VP8L_WRITER_BYTES 2 -#define VP8L_WRITER_BITS 16 -#define VP8L_WRITER_MAX_BITS 32 -#endif - -typedef struct { - vp8l_atype_t bits_; // bit accumulator - int used_; // number of bits used in accumulator - uint8_t* buf_; // start of buffer - uint8_t* cur_; // current write position - uint8_t* end_; // end of buffer - - // After all bits are written (VP8LBitWriterFinish()), the caller must observe - // the state of error_. A value of 1 indicates that a memory allocation - // failure has happened during bit writing. A value of 0 indicates successful - // writing of bits. - int error_; -} VP8LBitWriter; - -static WEBP_INLINE size_t VP8LBitWriterNumBytes(VP8LBitWriter* const bw) { - return (bw->cur_ - bw->buf_) + ((bw->used_ + 7) >> 3); -} - -// Returns false in case of memory allocation error. -int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size); -// Finalize the bitstream coding. Returns a pointer to the internal buffer. -uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw); -// Release any pending memory and zeroes the object. -void VP8LBitWriterWipeOut(VP8LBitWriter* const bw); - -// Internal function for VP8LPutBits flushing 32 bits from the written state. -void VP8LPutBitsFlushBits(VP8LBitWriter* const bw); - -// PutBits internal function used in the 16 bit vp8l_wtype_t case. -void VP8LPutBitsInternal(VP8LBitWriter* const bw, uint32_t bits, int n_bits); - -// This function writes bits into bytes in increasing addresses (little endian), -// and within a byte least-significant-bit first. -// This function can write up to 32 bits in one go, but VP8LBitReader can only -// read 24 bits max (VP8L_MAX_NUM_BIT_READ). -// VP8LBitWriter's error_ flag is set in case of memory allocation error. -static WEBP_INLINE void VP8LPutBits(VP8LBitWriter* const bw, - uint32_t bits, int n_bits) { - if (sizeof(vp8l_wtype_t) == 4) { - if (n_bits > 0) { - if (bw->used_ >= 32) { - VP8LPutBitsFlushBits(bw); - } - bw->bits_ |= (vp8l_atype_t)bits << bw->used_; - bw->used_ += n_bits; - } - } else { - VP8LPutBitsInternal(bw, bits, n_bits); - } -} - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_BIT_WRITER_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/utils/color_cache.c b/Example-Mac/Pods/libwebp/src/utils/color_cache.c deleted file mode 100644 index f9ff4b54..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/color_cache.c +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Color Cache for WebP Lossless -// -// Author: Jyrki Alakuijala (jyrki@google.com) - -#include -#include -#include -#include "./color_cache.h" -#include "../utils/utils.h" - -//------------------------------------------------------------------------------ -// VP8LColorCache. - -int VP8LColorCacheInit(VP8LColorCache* const cc, int hash_bits) { - const int hash_size = 1 << hash_bits; - assert(cc != NULL); - assert(hash_bits > 0); - cc->colors_ = (uint32_t*)WebPSafeCalloc((uint64_t)hash_size, - sizeof(*cc->colors_)); - if (cc->colors_ == NULL) return 0; - cc->hash_shift_ = 32 - hash_bits; - cc->hash_bits_ = hash_bits; - return 1; -} - -void VP8LColorCacheClear(VP8LColorCache* const cc) { - if (cc != NULL) { - WebPSafeFree(cc->colors_); - cc->colors_ = NULL; - } -} - -void VP8LColorCacheCopy(const VP8LColorCache* const src, - VP8LColorCache* const dst) { - assert(src != NULL); - assert(dst != NULL); - assert(src->hash_bits_ == dst->hash_bits_); - memcpy(dst->colors_, src->colors_, - ((size_t)1u << dst->hash_bits_) * sizeof(*dst->colors_)); -} diff --git a/Example-Mac/Pods/libwebp/src/utils/color_cache.h b/Example-Mac/Pods/libwebp/src/utils/color_cache.h deleted file mode 100644 index a9a9f642..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/color_cache.h +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Color Cache for WebP Lossless -// -// Authors: Jyrki Alakuijala (jyrki@google.com) -// Urvang Joshi (urvang@google.com) - -#ifndef WEBP_UTILS_COLOR_CACHE_H_ -#define WEBP_UTILS_COLOR_CACHE_H_ - -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Main color cache struct. -typedef struct { - uint32_t *colors_; // color entries - int hash_shift_; // Hash shift: 32 - hash_bits_. - int hash_bits_; -} VP8LColorCache; - -static const uint32_t kHashMul = 0x1e35a7bd; - -static WEBP_INLINE uint32_t VP8LColorCacheLookup( - const VP8LColorCache* const cc, uint32_t key) { - assert((key >> cc->hash_bits_) == 0u); - return cc->colors_[key]; -} - -static WEBP_INLINE void VP8LColorCacheSet(const VP8LColorCache* const cc, - uint32_t key, uint32_t argb) { - assert((key >> cc->hash_bits_) == 0u); - cc->colors_[key] = argb; -} - -static WEBP_INLINE void VP8LColorCacheInsert(const VP8LColorCache* const cc, - uint32_t argb) { - const uint32_t key = (kHashMul * argb) >> cc->hash_shift_; - cc->colors_[key] = argb; -} - -static WEBP_INLINE int VP8LColorCacheGetIndex(const VP8LColorCache* const cc, - uint32_t argb) { - return (kHashMul * argb) >> cc->hash_shift_; -} - -static WEBP_INLINE int VP8LColorCacheContains(const VP8LColorCache* const cc, - uint32_t argb) { - const uint32_t key = (kHashMul * argb) >> cc->hash_shift_; - return (cc->colors_[key] == argb); -} - -//------------------------------------------------------------------------------ - -// Initializes the color cache with 'hash_bits' bits for the keys. -// Returns false in case of memory error. -int VP8LColorCacheInit(VP8LColorCache* const color_cache, int hash_bits); - -void VP8LColorCacheCopy(const VP8LColorCache* const src, - VP8LColorCache* const dst); - -// Delete the memory associated to color cache. -void VP8LColorCacheClear(VP8LColorCache* const color_cache); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} -#endif - -#endif // WEBP_UTILS_COLOR_CACHE_H_ diff --git a/Example-Mac/Pods/libwebp/src/utils/endian_inl.h b/Example-Mac/Pods/libwebp/src/utils/endian_inl.h deleted file mode 100644 index e11260ff..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/endian_inl.h +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Endian related functions. - -#ifndef WEBP_UTILS_ENDIAN_INL_H_ -#define WEBP_UTILS_ENDIAN_INL_H_ - -#ifdef HAVE_CONFIG_H -#include "../webp/config.h" -#endif - -#include "../dsp/dsp.h" -#include "../webp/types.h" - -// some endian fix (e.g.: mips-gcc doesn't define __BIG_ENDIAN__) -#if !defined(WORDS_BIGENDIAN) && \ - (defined(__BIG_ENDIAN__) || defined(_M_PPC) || \ - (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))) -#define WORDS_BIGENDIAN -#endif - -#if defined(WORDS_BIGENDIAN) -#define HToLE32 BSwap32 -#define HToLE16 BSwap16 -#else -#define HToLE32(x) (x) -#define HToLE16(x) (x) -#endif - -#if !defined(HAVE_CONFIG_H) -#if LOCAL_GCC_PREREQ(4,8) || __has_builtin(__builtin_bswap16) -#define HAVE_BUILTIN_BSWAP16 -#endif -#if LOCAL_GCC_PREREQ(4,3) || __has_builtin(__builtin_bswap32) -#define HAVE_BUILTIN_BSWAP32 -#endif -#if LOCAL_GCC_PREREQ(4,3) || __has_builtin(__builtin_bswap64) -#define HAVE_BUILTIN_BSWAP64 -#endif -#endif // !HAVE_CONFIG_H - -static WEBP_INLINE uint16_t BSwap16(uint16_t x) { -#if defined(HAVE_BUILTIN_BSWAP16) - return __builtin_bswap16(x); -#elif defined(_MSC_VER) - return _byteswap_ushort(x); -#else - // gcc will recognize a 'rorw $8, ...' here: - return (x >> 8) | ((x & 0xff) << 8); -#endif // HAVE_BUILTIN_BSWAP16 -} - -static WEBP_INLINE uint32_t BSwap32(uint32_t x) { -#if defined(WEBP_USE_MIPS32_R2) - uint32_t ret; - __asm__ volatile ( - "wsbh %[ret], %[x] \n\t" - "rotr %[ret], %[ret], 16 \n\t" - : [ret]"=r"(ret) - : [x]"r"(x) - ); - return ret; -#elif defined(HAVE_BUILTIN_BSWAP32) - return __builtin_bswap32(x); -#elif defined(__i386__) || defined(__x86_64__) - uint32_t swapped_bytes; - __asm__ volatile("bswap %0" : "=r"(swapped_bytes) : "0"(x)); - return swapped_bytes; -#elif defined(_MSC_VER) - return (uint32_t)_byteswap_ulong(x); -#else - return (x >> 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | (x << 24); -#endif // HAVE_BUILTIN_BSWAP32 -} - -static WEBP_INLINE uint64_t BSwap64(uint64_t x) { -#if defined(HAVE_BUILTIN_BSWAP64) - return __builtin_bswap64(x); -#elif defined(__x86_64__) - uint64_t swapped_bytes; - __asm__ volatile("bswapq %0" : "=r"(swapped_bytes) : "0"(x)); - return swapped_bytes; -#elif defined(_MSC_VER) - return (uint64_t)_byteswap_uint64(x); -#else // generic code for swapping 64-bit values (suggested by bdb@) - x = ((x & 0xffffffff00000000ull) >> 32) | ((x & 0x00000000ffffffffull) << 32); - x = ((x & 0xffff0000ffff0000ull) >> 16) | ((x & 0x0000ffff0000ffffull) << 16); - x = ((x & 0xff00ff00ff00ff00ull) >> 8) | ((x & 0x00ff00ff00ff00ffull) << 8); - return x; -#endif // HAVE_BUILTIN_BSWAP64 -} - -#endif // WEBP_UTILS_ENDIAN_INL_H_ diff --git a/Example-Mac/Pods/libwebp/src/utils/filters.c b/Example-Mac/Pods/libwebp/src/utils/filters.c deleted file mode 100644 index 15543b12..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/filters.c +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// filter estimation -// -// Author: Urvang (urvang@google.com) - -#include "./filters.h" -#include -#include - -// ----------------------------------------------------------------------------- -// Quick estimate of a potentially interesting filter mode to try. - -#define SMAX 16 -#define SDIFF(a, b) (abs((a) - (b)) >> 4) // Scoring diff, in [0..SMAX) - -static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) { - const int g = a + b - c; - return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit -} - -WEBP_FILTER_TYPE WebPEstimateBestFilter(const uint8_t* data, - int width, int height, int stride) { - int i, j; - int bins[WEBP_FILTER_LAST][SMAX]; - memset(bins, 0, sizeof(bins)); - - // We only sample every other pixels. That's enough. - for (j = 2; j < height - 1; j += 2) { - const uint8_t* const p = data + j * stride; - int mean = p[0]; - for (i = 2; i < width - 1; i += 2) { - const int diff0 = SDIFF(p[i], mean); - const int diff1 = SDIFF(p[i], p[i - 1]); - const int diff2 = SDIFF(p[i], p[i - width]); - const int grad_pred = - GradientPredictor(p[i - 1], p[i - width], p[i - width - 1]); - const int diff3 = SDIFF(p[i], grad_pred); - bins[WEBP_FILTER_NONE][diff0] = 1; - bins[WEBP_FILTER_HORIZONTAL][diff1] = 1; - bins[WEBP_FILTER_VERTICAL][diff2] = 1; - bins[WEBP_FILTER_GRADIENT][diff3] = 1; - mean = (3 * mean + p[i] + 2) >> 2; - } - } - { - int filter; - WEBP_FILTER_TYPE best_filter = WEBP_FILTER_NONE; - int best_score = 0x7fffffff; - for (filter = WEBP_FILTER_NONE; filter < WEBP_FILTER_LAST; ++filter) { - int score = 0; - for (i = 0; i < SMAX; ++i) { - if (bins[filter][i] > 0) { - score += i; - } - } - if (score < best_score) { - best_score = score; - best_filter = (WEBP_FILTER_TYPE)filter; - } - } - return best_filter; - } -} - -#undef SMAX -#undef SDIFF - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/utils/filters.h b/Example-Mac/Pods/libwebp/src/utils/filters.h deleted file mode 100644 index 088b132f..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/filters.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Spatial prediction using various filters -// -// Author: Urvang (urvang@google.com) - -#ifndef WEBP_UTILS_FILTERS_H_ -#define WEBP_UTILS_FILTERS_H_ - -#include "../webp/types.h" -#include "../dsp/dsp.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Fast estimate of a potentially good filter. -WEBP_FILTER_TYPE WebPEstimateBestFilter(const uint8_t* data, - int width, int height, int stride); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_FILTERS_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/utils/huffman.c b/Example-Mac/Pods/libwebp/src/utils/huffman.c deleted file mode 100644 index d57376aa..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/huffman.c +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Utilities for building and looking up Huffman trees. -// -// Author: Urvang Joshi (urvang@google.com) - -#include -#include -#include -#include "./huffman.h" -#include "../utils/utils.h" -#include "../webp/format_constants.h" - -// Huffman data read via DecodeImageStream is represented in two (red and green) -// bytes. -#define MAX_HTREE_GROUPS 0x10000 - -HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups) { - HTreeGroup* const htree_groups = - (HTreeGroup*)WebPSafeMalloc(num_htree_groups, sizeof(*htree_groups)); - if (htree_groups == NULL) { - return NULL; - } - assert(num_htree_groups <= MAX_HTREE_GROUPS); - return htree_groups; -} - -void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups) { - if (htree_groups != NULL) { - WebPSafeFree(htree_groups); - } -} - -// Returns reverse(reverse(key, len) + 1, len), where reverse(key, len) is the -// bit-wise reversal of the len least significant bits of key. -static WEBP_INLINE uint32_t GetNextKey(uint32_t key, int len) { - uint32_t step = 1 << (len - 1); - while (key & step) { - step >>= 1; - } - return (key & (step - 1)) + step; -} - -// Stores code in table[0], table[step], table[2*step], ..., table[end]. -// Assumes that end is an integer multiple of step. -static WEBP_INLINE void ReplicateValue(HuffmanCode* table, - int step, int end, - HuffmanCode code) { - assert(end % step == 0); - do { - end -= step; - table[end] = code; - } while (end > 0); -} - -// Returns the table width of the next 2nd level table. count is the histogram -// of bit lengths for the remaining symbols, len is the code length of the next -// processed symbol -static WEBP_INLINE int NextTableBitSize(const int* const count, - int len, int root_bits) { - int left = 1 << (len - root_bits); - while (len < MAX_ALLOWED_CODE_LENGTH) { - left -= count[len]; - if (left <= 0) break; - ++len; - left <<= 1; - } - return len - root_bits; -} - -int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits, - const int code_lengths[], int code_lengths_size) { - HuffmanCode* table = root_table; // next available space in table - int total_size = 1 << root_bits; // total size root table + 2nd level table - int* sorted = NULL; // symbols sorted by code length - int len; // current code length - int symbol; // symbol index in original or sorted table - // number of codes of each length: - int count[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 }; - // offsets in sorted table for each length: - int offset[MAX_ALLOWED_CODE_LENGTH + 1]; - - assert(code_lengths_size != 0); - assert(code_lengths != NULL); - assert(root_table != NULL); - assert(root_bits > 0); - - // Build histogram of code lengths. - for (symbol = 0; symbol < code_lengths_size; ++symbol) { - if (code_lengths[symbol] > MAX_ALLOWED_CODE_LENGTH) { - return 0; - } - ++count[code_lengths[symbol]]; - } - - // Error, all code lengths are zeros. - if (count[0] == code_lengths_size) { - return 0; - } - - // Generate offsets into sorted symbol table by code length. - offset[1] = 0; - for (len = 1; len < MAX_ALLOWED_CODE_LENGTH; ++len) { - if (count[len] > (1 << len)) { - return 0; - } - offset[len + 1] = offset[len] + count[len]; - } - - sorted = (int*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted)); - if (sorted == NULL) { - return 0; - } - - // Sort symbols by length, by symbol order within each length. - for (symbol = 0; symbol < code_lengths_size; ++symbol) { - const int symbol_code_length = code_lengths[symbol]; - if (code_lengths[symbol] > 0) { - sorted[offset[symbol_code_length]++] = symbol; - } - } - - // Special case code with only one value. - if (offset[MAX_ALLOWED_CODE_LENGTH] == 1) { - HuffmanCode code; - code.bits = 0; - code.value = (uint16_t)sorted[0]; - ReplicateValue(table, 1, total_size, code); - WebPSafeFree(sorted); - return total_size; - } - - { - int step; // step size to replicate values in current table - uint32_t low = -1; // low bits for current root entry - uint32_t mask = total_size - 1; // mask for low bits - uint32_t key = 0; // reversed prefix code - int num_nodes = 1; // number of Huffman tree nodes - int num_open = 1; // number of open branches in current tree level - int table_bits = root_bits; // key length of current table - int table_size = 1 << table_bits; // size of current table - symbol = 0; - // Fill in root table. - for (len = 1, step = 2; len <= root_bits; ++len, step <<= 1) { - num_open <<= 1; - num_nodes += num_open; - num_open -= count[len]; - if (num_open < 0) { - WebPSafeFree(sorted); - return 0; - } - for (; count[len] > 0; --count[len]) { - HuffmanCode code; - code.bits = (uint8_t)len; - code.value = (uint16_t)sorted[symbol++]; - ReplicateValue(&table[key], step, table_size, code); - key = GetNextKey(key, len); - } - } - - // Fill in 2nd level tables and add pointers to root table. - for (len = root_bits + 1, step = 2; len <= MAX_ALLOWED_CODE_LENGTH; - ++len, step <<= 1) { - num_open <<= 1; - num_nodes += num_open; - num_open -= count[len]; - if (num_open < 0) { - WebPSafeFree(sorted); - return 0; - } - for (; count[len] > 0; --count[len]) { - HuffmanCode code; - if ((key & mask) != low) { - table += table_size; - table_bits = NextTableBitSize(count, len, root_bits); - table_size = 1 << table_bits; - total_size += table_size; - low = key & mask; - root_table[low].bits = (uint8_t)(table_bits + root_bits); - root_table[low].value = (uint16_t)((table - root_table) - low); - } - code.bits = (uint8_t)(len - root_bits); - code.value = (uint16_t)sorted[symbol++]; - ReplicateValue(&table[key >> root_bits], step, table_size, code); - key = GetNextKey(key, len); - } - } - - // Check if tree is full. - if (num_nodes != 2 * offset[MAX_ALLOWED_CODE_LENGTH] - 1) { - WebPSafeFree(sorted); - return 0; - } - } - - WebPSafeFree(sorted); - return total_size; -} diff --git a/Example-Mac/Pods/libwebp/src/utils/huffman.h b/Example-Mac/Pods/libwebp/src/utils/huffman.h deleted file mode 100644 index c6dd6aaa..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/huffman.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Utilities for building and looking up Huffman trees. -// -// Author: Urvang Joshi (urvang@google.com) - -#ifndef WEBP_UTILS_HUFFMAN_H_ -#define WEBP_UTILS_HUFFMAN_H_ - -#include -#include "../webp/format_constants.h" -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define HUFFMAN_TABLE_BITS 8 -#define HUFFMAN_TABLE_MASK ((1 << HUFFMAN_TABLE_BITS) - 1) - -#define LENGTHS_TABLE_BITS 7 -#define LENGTHS_TABLE_MASK ((1 << LENGTHS_TABLE_BITS) - 1) - - -// Huffman lookup table entry -typedef struct { - uint8_t bits; // number of bits used for this symbol - uint16_t value; // symbol value or table offset -} HuffmanCode; - -// long version for holding 32b values -typedef struct { - int bits; // number of bits used for this symbol, - // or an impossible value if not a literal code. - uint32_t value; // 32b packed ARGB value if literal, - // or non-literal symbol otherwise -} HuffmanCode32; - -#define HUFFMAN_PACKED_BITS 6 -#define HUFFMAN_PACKED_TABLE_SIZE (1u << HUFFMAN_PACKED_BITS) - -// Huffman table group. -// Includes special handling for the following cases: -// - is_trivial_literal: one common literal base for RED/BLUE/ALPHA (not GREEN) -// - is_trivial_code: only 1 code (no bit is read from bitstream) -// - use_packed_table: few enough literal symbols, so all the bit codes -// can fit into a small look-up table packed_table[] -// The common literal base, if applicable, is stored in 'literal_arb'. -typedef struct HTreeGroup HTreeGroup; -struct HTreeGroup { - HuffmanCode* htrees[HUFFMAN_CODES_PER_META_CODE]; - int is_trivial_literal; // True, if huffman trees for Red, Blue & Alpha - // Symbols are trivial (have a single code). - uint32_t literal_arb; // If is_trivial_literal is true, this is the - // ARGB value of the pixel, with Green channel - // being set to zero. - int is_trivial_code; // true if is_trivial_literal with only one code - int use_packed_table; // use packed table below for short literal code - // table mapping input bits to a packed values, or escape case to literal code - HuffmanCode32 packed_table[HUFFMAN_PACKED_TABLE_SIZE]; -}; - -// Creates the instance of HTreeGroup with specified number of tree-groups. -HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups); - -// Releases the memory allocated for HTreeGroup. -void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups); - -// Builds Huffman lookup table assuming code lengths are in symbol order. -// The 'code_lengths' is pre-allocated temporary memory buffer used for creating -// the huffman table. -// Returns built table size or 0 in case of error (invalid tree or -// memory error). -int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits, - const int code_lengths[], int code_lengths_size); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // WEBP_UTILS_HUFFMAN_H_ diff --git a/Example-Mac/Pods/libwebp/src/utils/huffman_encode.c b/Example-Mac/Pods/libwebp/src/utils/huffman_encode.c deleted file mode 100644 index 6421c2be..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/huffman_encode.c +++ /dev/null @@ -1,417 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Jyrki Alakuijala (jyrki@google.com) -// -// Entropy encoding (Huffman) for webp lossless. - -#include -#include -#include -#include "./huffman_encode.h" -#include "../utils/utils.h" -#include "../webp/format_constants.h" - -// ----------------------------------------------------------------------------- -// Util function to optimize the symbol map for RLE coding - -// Heuristics for selecting the stride ranges to collapse. -static int ValuesShouldBeCollapsedToStrideAverage(int a, int b) { - return abs(a - b) < 4; -} - -// Change the population counts in a way that the consequent -// Huffman tree compression, especially its RLE-part, give smaller output. -static void OptimizeHuffmanForRle(int length, uint8_t* const good_for_rle, - uint32_t* const counts) { - // 1) Let's make the Huffman code more compatible with rle encoding. - int i; - for (; length >= 0; --length) { - if (length == 0) { - return; // All zeros. - } - if (counts[length - 1] != 0) { - // Now counts[0..length - 1] does not have trailing zeros. - break; - } - } - // 2) Let's mark all population counts that already can be encoded - // with an rle code. - { - // Let's not spoil any of the existing good rle codes. - // Mark any seq of 0's that is longer as 5 as a good_for_rle. - // Mark any seq of non-0's that is longer as 7 as a good_for_rle. - uint32_t symbol = counts[0]; - int stride = 0; - for (i = 0; i < length + 1; ++i) { - if (i == length || counts[i] != symbol) { - if ((symbol == 0 && stride >= 5) || - (symbol != 0 && stride >= 7)) { - int k; - for (k = 0; k < stride; ++k) { - good_for_rle[i - k - 1] = 1; - } - } - stride = 1; - if (i != length) { - symbol = counts[i]; - } - } else { - ++stride; - } - } - } - // 3) Let's replace those population counts that lead to more rle codes. - { - uint32_t stride = 0; - uint32_t limit = counts[0]; - uint32_t sum = 0; - for (i = 0; i < length + 1; ++i) { - if (i == length || good_for_rle[i] || - (i != 0 && good_for_rle[i - 1]) || - !ValuesShouldBeCollapsedToStrideAverage(counts[i], limit)) { - if (stride >= 4 || (stride >= 3 && sum == 0)) { - uint32_t k; - // The stride must end, collapse what we have, if we have enough (4). - uint32_t count = (sum + stride / 2) / stride; - if (count < 1) { - count = 1; - } - if (sum == 0) { - // Don't make an all zeros stride to be upgraded to ones. - count = 0; - } - for (k = 0; k < stride; ++k) { - // We don't want to change value at counts[i], - // that is already belonging to the next stride. Thus - 1. - counts[i - k - 1] = count; - } - } - stride = 0; - sum = 0; - if (i < length - 3) { - // All interesting strides have a count of at least 4, - // at least when non-zeros. - limit = (counts[i] + counts[i + 1] + - counts[i + 2] + counts[i + 3] + 2) / 4; - } else if (i < length) { - limit = counts[i]; - } else { - limit = 0; - } - } - ++stride; - if (i != length) { - sum += counts[i]; - if (stride >= 4) { - limit = (sum + stride / 2) / stride; - } - } - } - } -} - -// A comparer function for two Huffman trees: sorts first by 'total count' -// (more comes first), and then by 'value' (more comes first). -static int CompareHuffmanTrees(const void* ptr1, const void* ptr2) { - const HuffmanTree* const t1 = (const HuffmanTree*)ptr1; - const HuffmanTree* const t2 = (const HuffmanTree*)ptr2; - if (t1->total_count_ > t2->total_count_) { - return -1; - } else if (t1->total_count_ < t2->total_count_) { - return 1; - } else { - assert(t1->value_ != t2->value_); - return (t1->value_ < t2->value_) ? -1 : 1; - } -} - -static void SetBitDepths(const HuffmanTree* const tree, - const HuffmanTree* const pool, - uint8_t* const bit_depths, int level) { - if (tree->pool_index_left_ >= 0) { - SetBitDepths(&pool[tree->pool_index_left_], pool, bit_depths, level + 1); - SetBitDepths(&pool[tree->pool_index_right_], pool, bit_depths, level + 1); - } else { - bit_depths[tree->value_] = level; - } -} - -// Create an optimal Huffman tree. -// -// (data,length): population counts. -// tree_limit: maximum bit depth (inclusive) of the codes. -// bit_depths[]: how many bits are used for the symbol. -// -// Returns 0 when an error has occurred. -// -// The catch here is that the tree cannot be arbitrarily deep -// -// count_limit is the value that is to be faked as the minimum value -// and this minimum value is raised until the tree matches the -// maximum length requirement. -// -// This algorithm is not of excellent performance for very long data blocks, -// especially when population counts are longer than 2**tree_limit, but -// we are not planning to use this with extremely long blocks. -// -// See http://en.wikipedia.org/wiki/Huffman_coding -static void GenerateOptimalTree(const uint32_t* const histogram, - int histogram_size, - HuffmanTree* tree, int tree_depth_limit, - uint8_t* const bit_depths) { - uint32_t count_min; - HuffmanTree* tree_pool; - int tree_size_orig = 0; - int i; - - for (i = 0; i < histogram_size; ++i) { - if (histogram[i] != 0) { - ++tree_size_orig; - } - } - - if (tree_size_orig == 0) { // pretty optimal already! - return; - } - - tree_pool = tree + tree_size_orig; - - // For block sizes with less than 64k symbols we never need to do a - // second iteration of this loop. - // If we actually start running inside this loop a lot, we would perhaps - // be better off with the Katajainen algorithm. - assert(tree_size_orig <= (1 << (tree_depth_limit - 1))); - for (count_min = 1; ; count_min *= 2) { - int tree_size = tree_size_orig; - // We need to pack the Huffman tree in tree_depth_limit bits. - // So, we try by faking histogram entries to be at least 'count_min'. - int idx = 0; - int j; - for (j = 0; j < histogram_size; ++j) { - if (histogram[j] != 0) { - const uint32_t count = - (histogram[j] < count_min) ? count_min : histogram[j]; - tree[idx].total_count_ = count; - tree[idx].value_ = j; - tree[idx].pool_index_left_ = -1; - tree[idx].pool_index_right_ = -1; - ++idx; - } - } - - // Build the Huffman tree. - qsort(tree, tree_size, sizeof(*tree), CompareHuffmanTrees); - - if (tree_size > 1) { // Normal case. - int tree_pool_size = 0; - while (tree_size > 1) { // Finish when we have only one root. - uint32_t count; - tree_pool[tree_pool_size++] = tree[tree_size - 1]; - tree_pool[tree_pool_size++] = tree[tree_size - 2]; - count = tree_pool[tree_pool_size - 1].total_count_ + - tree_pool[tree_pool_size - 2].total_count_; - tree_size -= 2; - { - // Search for the insertion point. - int k; - for (k = 0; k < tree_size; ++k) { - if (tree[k].total_count_ <= count) { - break; - } - } - memmove(tree + (k + 1), tree + k, (tree_size - k) * sizeof(*tree)); - tree[k].total_count_ = count; - tree[k].value_ = -1; - - tree[k].pool_index_left_ = tree_pool_size - 1; - tree[k].pool_index_right_ = tree_pool_size - 2; - tree_size = tree_size + 1; - } - } - SetBitDepths(&tree[0], tree_pool, bit_depths, 0); - } else if (tree_size == 1) { // Trivial case: only one element. - bit_depths[tree[0].value_] = 1; - } - - { - // Test if this Huffman tree satisfies our 'tree_depth_limit' criteria. - int max_depth = bit_depths[0]; - for (j = 1; j < histogram_size; ++j) { - if (max_depth < bit_depths[j]) { - max_depth = bit_depths[j]; - } - } - if (max_depth <= tree_depth_limit) { - break; - } - } - } -} - -// ----------------------------------------------------------------------------- -// Coding of the Huffman tree values - -static HuffmanTreeToken* CodeRepeatedValues(int repetitions, - HuffmanTreeToken* tokens, - int value, int prev_value) { - assert(value <= MAX_ALLOWED_CODE_LENGTH); - if (value != prev_value) { - tokens->code = value; - tokens->extra_bits = 0; - ++tokens; - --repetitions; - } - while (repetitions >= 1) { - if (repetitions < 3) { - int i; - for (i = 0; i < repetitions; ++i) { - tokens->code = value; - tokens->extra_bits = 0; - ++tokens; - } - break; - } else if (repetitions < 7) { - tokens->code = 16; - tokens->extra_bits = repetitions - 3; - ++tokens; - break; - } else { - tokens->code = 16; - tokens->extra_bits = 3; - ++tokens; - repetitions -= 6; - } - } - return tokens; -} - -static HuffmanTreeToken* CodeRepeatedZeros(int repetitions, - HuffmanTreeToken* tokens) { - while (repetitions >= 1) { - if (repetitions < 3) { - int i; - for (i = 0; i < repetitions; ++i) { - tokens->code = 0; // 0-value - tokens->extra_bits = 0; - ++tokens; - } - break; - } else if (repetitions < 11) { - tokens->code = 17; - tokens->extra_bits = repetitions - 3; - ++tokens; - break; - } else if (repetitions < 139) { - tokens->code = 18; - tokens->extra_bits = repetitions - 11; - ++tokens; - break; - } else { - tokens->code = 18; - tokens->extra_bits = 0x7f; // 138 repeated 0s - ++tokens; - repetitions -= 138; - } - } - return tokens; -} - -int VP8LCreateCompressedHuffmanTree(const HuffmanTreeCode* const tree, - HuffmanTreeToken* tokens, int max_tokens) { - HuffmanTreeToken* const starting_token = tokens; - HuffmanTreeToken* const ending_token = tokens + max_tokens; - const int depth_size = tree->num_symbols; - int prev_value = 8; // 8 is the initial value for rle. - int i = 0; - assert(tokens != NULL); - while (i < depth_size) { - const int value = tree->code_lengths[i]; - int k = i + 1; - int runs; - while (k < depth_size && tree->code_lengths[k] == value) ++k; - runs = k - i; - if (value == 0) { - tokens = CodeRepeatedZeros(runs, tokens); - } else { - tokens = CodeRepeatedValues(runs, tokens, value, prev_value); - prev_value = value; - } - i += runs; - assert(tokens <= ending_token); - } - (void)ending_token; // suppress 'unused variable' warning - return (int)(tokens - starting_token); -} - -// ----------------------------------------------------------------------------- - -// Pre-reversed 4-bit values. -static const uint8_t kReversedBits[16] = { - 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, - 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf -}; - -static uint32_t ReverseBits(int num_bits, uint32_t bits) { - uint32_t retval = 0; - int i = 0; - while (i < num_bits) { - i += 4; - retval |= kReversedBits[bits & 0xf] << (MAX_ALLOWED_CODE_LENGTH + 1 - i); - bits >>= 4; - } - retval >>= (MAX_ALLOWED_CODE_LENGTH + 1 - num_bits); - return retval; -} - -// Get the actual bit values for a tree of bit depths. -static void ConvertBitDepthsToSymbols(HuffmanTreeCode* const tree) { - // 0 bit-depth means that the symbol does not exist. - int i; - int len; - uint32_t next_code[MAX_ALLOWED_CODE_LENGTH + 1]; - int depth_count[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 }; - - assert(tree != NULL); - len = tree->num_symbols; - for (i = 0; i < len; ++i) { - const int code_length = tree->code_lengths[i]; - assert(code_length <= MAX_ALLOWED_CODE_LENGTH); - ++depth_count[code_length]; - } - depth_count[0] = 0; // ignore unused symbol - next_code[0] = 0; - { - uint32_t code = 0; - for (i = 1; i <= MAX_ALLOWED_CODE_LENGTH; ++i) { - code = (code + depth_count[i - 1]) << 1; - next_code[i] = code; - } - } - for (i = 0; i < len; ++i) { - const int code_length = tree->code_lengths[i]; - tree->codes[i] = ReverseBits(code_length, next_code[code_length]++); - } -} - -// ----------------------------------------------------------------------------- -// Main entry point - -void VP8LCreateHuffmanTree(uint32_t* const histogram, int tree_depth_limit, - uint8_t* const buf_rle, - HuffmanTree* const huff_tree, - HuffmanTreeCode* const huff_code) { - const int num_symbols = huff_code->num_symbols; - memset(buf_rle, 0, num_symbols * sizeof(*buf_rle)); - OptimizeHuffmanForRle(num_symbols, buf_rle, histogram); - GenerateOptimalTree(histogram, num_symbols, huff_tree, tree_depth_limit, - huff_code->code_lengths); - // Create the actual bit codes for the bit lengths. - ConvertBitDepthsToSymbols(huff_code); -} diff --git a/Example-Mac/Pods/libwebp/src/utils/huffman_encode.h b/Example-Mac/Pods/libwebp/src/utils/huffman_encode.h deleted file mode 100644 index a1571651..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/huffman_encode.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Jyrki Alakuijala (jyrki@google.com) -// -// Entropy encoding (Huffman) for webp lossless - -#ifndef WEBP_UTILS_HUFFMAN_ENCODE_H_ -#define WEBP_UTILS_HUFFMAN_ENCODE_H_ - -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Struct for holding the tree header in coded form. -typedef struct { - uint8_t code; // value (0..15) or escape code (16,17,18) - uint8_t extra_bits; // extra bits for escape codes -} HuffmanTreeToken; - -// Struct to represent the tree codes (depth and bits array). -typedef struct { - int num_symbols; // Number of symbols. - uint8_t* code_lengths; // Code lengths of the symbols. - uint16_t* codes; // Symbol Codes. -} HuffmanTreeCode; - -// Struct to represent the Huffman tree. -typedef struct { - uint32_t total_count_; // Symbol frequency. - int value_; // Symbol value. - int pool_index_left_; // Index for the left sub-tree. - int pool_index_right_; // Index for the right sub-tree. -} HuffmanTree; - -// Turn the Huffman tree into a token sequence. -// Returns the number of tokens used. -int VP8LCreateCompressedHuffmanTree(const HuffmanTreeCode* const tree, - HuffmanTreeToken* tokens, int max_tokens); - -// Create an optimized tree, and tokenize it. -// 'buf_rle' and 'huff_tree' are pre-allocated and the 'tree' is the constructed -// huffman code tree. -void VP8LCreateHuffmanTree(uint32_t* const histogram, int tree_depth_limit, - uint8_t* const buf_rle, HuffmanTree* const huff_tree, - HuffmanTreeCode* const tree); - -#ifdef __cplusplus -} -#endif - -#endif // WEBP_UTILS_HUFFMAN_ENCODE_H_ diff --git a/Example-Mac/Pods/libwebp/src/utils/quant_levels.c b/Example-Mac/Pods/libwebp/src/utils/quant_levels.c deleted file mode 100644 index d7c8aab9..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/quant_levels.c +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Quantize levels for specified number of quantization-levels ([2, 256]). -// Min and max values are preserved (usual 0 and 255 for alpha plane). -// -// Author: Skal (pascal.massimino@gmail.com) - -#include - -#include "./quant_levels.h" - -#define NUM_SYMBOLS 256 - -#define MAX_ITER 6 // Maximum number of convergence steps. -#define ERROR_THRESHOLD 1e-4 // MSE stopping criterion. - -// ----------------------------------------------------------------------------- -// Quantize levels. - -int QuantizeLevels(uint8_t* const data, int width, int height, - int num_levels, uint64_t* const sse) { - int freq[NUM_SYMBOLS] = { 0 }; - int q_level[NUM_SYMBOLS] = { 0 }; - double inv_q_level[NUM_SYMBOLS] = { 0 }; - int min_s = 255, max_s = 0; - const size_t data_size = height * width; - int i, num_levels_in, iter; - double last_err = 1.e38, err = 0.; - const double err_threshold = ERROR_THRESHOLD * data_size; - - if (data == NULL) { - return 0; - } - - if (width <= 0 || height <= 0) { - return 0; - } - - if (num_levels < 2 || num_levels > 256) { - return 0; - } - - { - size_t n; - num_levels_in = 0; - for (n = 0; n < data_size; ++n) { - num_levels_in += (freq[data[n]] == 0); - if (min_s > data[n]) min_s = data[n]; - if (max_s < data[n]) max_s = data[n]; - ++freq[data[n]]; - } - } - - if (num_levels_in <= num_levels) goto End; // nothing to do! - - // Start with uniformly spread centroids. - for (i = 0; i < num_levels; ++i) { - inv_q_level[i] = min_s + (double)(max_s - min_s) * i / (num_levels - 1); - } - - // Fixed values. Won't be changed. - q_level[min_s] = 0; - q_level[max_s] = num_levels - 1; - assert(inv_q_level[0] == min_s); - assert(inv_q_level[num_levels - 1] == max_s); - - // k-Means iterations. - for (iter = 0; iter < MAX_ITER; ++iter) { - double q_sum[NUM_SYMBOLS] = { 0 }; - double q_count[NUM_SYMBOLS] = { 0 }; - int s, slot = 0; - - // Assign classes to representatives. - for (s = min_s; s <= max_s; ++s) { - // Keep track of the nearest neighbour 'slot' - while (slot < num_levels - 1 && - 2 * s > inv_q_level[slot] + inv_q_level[slot + 1]) { - ++slot; - } - if (freq[s] > 0) { - q_sum[slot] += s * freq[s]; - q_count[slot] += freq[s]; - } - q_level[s] = slot; - } - - // Assign new representatives to classes. - if (num_levels > 2) { - for (slot = 1; slot < num_levels - 1; ++slot) { - const double count = q_count[slot]; - if (count > 0.) { - inv_q_level[slot] = q_sum[slot] / count; - } - } - } - - // Compute convergence error. - err = 0.; - for (s = min_s; s <= max_s; ++s) { - const double error = s - inv_q_level[q_level[s]]; - err += freq[s] * error * error; - } - - // Check for convergence: we stop as soon as the error is no - // longer improving. - if (last_err - err < err_threshold) break; - last_err = err; - } - - // Remap the alpha plane to quantized values. - { - // double->int rounding operation can be costly, so we do it - // once for all before remapping. We also perform the data[] -> slot - // mapping, while at it (avoid one indirection in the final loop). - uint8_t map[NUM_SYMBOLS]; - int s; - size_t n; - for (s = min_s; s <= max_s; ++s) { - const int slot = q_level[s]; - map[s] = (uint8_t)(inv_q_level[slot] + .5); - } - // Final pass. - for (n = 0; n < data_size; ++n) { - data[n] = map[data[n]]; - } - } - End: - // Store sum of squared error if needed. - if (sse != NULL) *sse = (uint64_t)err; - - return 1; -} - diff --git a/Example-Mac/Pods/libwebp/src/utils/quant_levels.h b/Example-Mac/Pods/libwebp/src/utils/quant_levels.h deleted file mode 100644 index 1cb5a32c..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/quant_levels.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Alpha plane quantization utility -// -// Author: Vikas Arora (vikasa@google.com) - -#ifndef WEBP_UTILS_QUANT_LEVELS_H_ -#define WEBP_UTILS_QUANT_LEVELS_H_ - -#include - -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Replace the input 'data' of size 'width'x'height' with 'num-levels' -// quantized values. If not NULL, 'sse' will contain the sum of squared error. -// Valid range for 'num_levels' is [2, 256]. -// Returns false in case of error (data is NULL, or parameters are invalid). -int QuantizeLevels(uint8_t* const data, int width, int height, int num_levels, - uint64_t* const sse); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_QUANT_LEVELS_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/utils/quant_levels_dec.c b/Example-Mac/Pods/libwebp/src/utils/quant_levels_dec.c deleted file mode 100644 index 5b8b8b49..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/quant_levels_dec.c +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Implement gradient smoothing: we replace a current alpha value by its -// surrounding average if it's close enough (that is: the change will be less -// than the minimum distance between two quantized level). -// We use sliding window for computing the 2d moving average. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./quant_levels_dec.h" - -#include // for memset - -#include "./utils.h" - -// #define USE_DITHERING // uncomment to enable ordered dithering (not vital) - -#define FIX 16 // fix-point precision for averaging -#define LFIX 2 // extra precision for look-up table -#define LUT_SIZE ((1 << (8 + LFIX)) - 1) // look-up table size - -#if defined(USE_DITHERING) - -#define DFIX 4 // extra precision for ordered dithering -#define DSIZE 4 // dithering size (must be a power of two) -// cf. http://en.wikipedia.org/wiki/Ordered_dithering -static const uint8_t kOrderedDither[DSIZE][DSIZE] = { - { 0, 8, 2, 10 }, // coefficients are in DFIX fixed-point precision - { 12, 4, 14, 6 }, - { 3, 11, 1, 9 }, - { 15, 7, 13, 5 } -}; - -#else -#define DFIX 0 -#endif - -typedef struct { - int width_, height_; // dimension - int row_; // current input row being processed - uint8_t* src_; // input pointer - uint8_t* dst_; // output pointer - - int radius_; // filter radius (=delay) - int scale_; // normalization factor, in FIX bits precision - - void* mem_; // all memory - - // various scratch buffers - uint16_t* start_; - uint16_t* cur_; - uint16_t* end_; - uint16_t* top_; - uint16_t* average_; - - // input levels distribution - int num_levels_; // number of quantized levels - int min_, max_; // min and max level values - int min_level_dist_; // smallest distance between two consecutive levels - - int16_t* correction_; // size = 1 + 2*LUT_SIZE -> ~4k memory -} SmoothParams; - -//------------------------------------------------------------------------------ - -#define CLIP_MASK (int)(~0U << (8 + DFIX)) -static WEBP_INLINE uint8_t clip_8b(int v) { - return (!(v & CLIP_MASK)) ? (uint8_t)(v >> DFIX) : (v < 0) ? 0u : 255u; -} - -// vertical accumulation -static void VFilter(SmoothParams* const p) { - const uint8_t* src = p->src_; - const int w = p->width_; - uint16_t* const cur = p->cur_; - const uint16_t* const top = p->top_; - uint16_t* const out = p->end_; - uint16_t sum = 0; // all arithmetic is modulo 16bit - int x; - - for (x = 0; x < w; ++x) { - uint16_t new_value; - sum += src[x]; - new_value = top[x] + sum; - out[x] = new_value - cur[x]; // vertical sum of 'r' pixels. - cur[x] = new_value; - } - // move input pointers one row down - p->top_ = p->cur_; - p->cur_ += w; - if (p->cur_ == p->end_) p->cur_ = p->start_; // roll-over - // We replicate edges, as it's somewhat easier as a boundary condition. - // That's why we don't update the 'src' pointer on top/bottom area: - if (p->row_ >= 0 && p->row_ < p->height_ - 1) { - p->src_ += p->width_; - } -} - -// horizontal accumulation. We use mirror replication of missing pixels, as it's -// a little easier to implement (surprisingly). -static void HFilter(SmoothParams* const p) { - const uint16_t* const in = p->end_; - uint16_t* const out = p->average_; - const uint32_t scale = p->scale_; - const int w = p->width_; - const int r = p->radius_; - - int x; - for (x = 0; x <= r; ++x) { // left mirroring - const uint16_t delta = in[x + r - 1] + in[r - x]; - out[x] = (delta * scale) >> FIX; - } - for (; x < w - r; ++x) { // bulk middle run - const uint16_t delta = in[x + r] - in[x - r - 1]; - out[x] = (delta * scale) >> FIX; - } - for (; x < w; ++x) { // right mirroring - const uint16_t delta = - 2 * in[w - 1] - in[2 * w - 2 - r - x] - in[x - r - 1]; - out[x] = (delta * scale) >> FIX; - } -} - -// emit one filtered output row -static void ApplyFilter(SmoothParams* const p) { - const uint16_t* const average = p->average_; - const int w = p->width_; - const int16_t* const correction = p->correction_; -#if defined(USE_DITHERING) - const uint8_t* const dither = kOrderedDither[p->row_ % DSIZE]; -#endif - uint8_t* const dst = p->dst_; - int x; - for (x = 0; x < w; ++x) { - const int v = dst[x]; - if (v < p->max_ && v > p->min_) { - const int c = (v << DFIX) + correction[average[x] - (v << LFIX)]; -#if defined(USE_DITHERING) - dst[x] = clip_8b(c + dither[x % DSIZE]); -#else - dst[x] = clip_8b(c); -#endif - } - } - p->dst_ += w; // advance output pointer -} - -//------------------------------------------------------------------------------ -// Initialize correction table - -static void InitCorrectionLUT(int16_t* const lut, int min_dist) { - // The correction curve is: - // f(x) = x for x <= threshold2 - // f(x) = 0 for x >= threshold1 - // and a linear interpolation for range x=[threshold2, threshold1] - // (along with f(-x) = -f(x) symmetry). - // Note that: threshold2 = 3/4 * threshold1 - const int threshold1 = min_dist << LFIX; - const int threshold2 = (3 * threshold1) >> 2; - const int max_threshold = threshold2 << DFIX; - const int delta = threshold1 - threshold2; - int i; - for (i = 1; i <= LUT_SIZE; ++i) { - int c = (i <= threshold2) ? (i << DFIX) - : (i < threshold1) ? max_threshold * (threshold1 - i) / delta - : 0; - c >>= LFIX; - lut[+i] = +c; - lut[-i] = -c; - } - lut[0] = 0; -} - -static void CountLevels(const uint8_t* const data, int size, - SmoothParams* const p) { - int i, last_level; - uint8_t used_levels[256] = { 0 }; - p->min_ = 255; - p->max_ = 0; - for (i = 0; i < size; ++i) { - const int v = data[i]; - if (v < p->min_) p->min_ = v; - if (v > p->max_) p->max_ = v; - used_levels[v] = 1; - } - // Compute the mininum distance between two non-zero levels. - p->min_level_dist_ = p->max_ - p->min_; - last_level = -1; - for (i = 0; i < 256; ++i) { - if (used_levels[i]) { - ++p->num_levels_; - if (last_level >= 0) { - const int level_dist = i - last_level; - if (level_dist < p->min_level_dist_) { - p->min_level_dist_ = level_dist; - } - } - last_level = i; - } - } -} - -// Initialize all params. -static int InitParams(uint8_t* const data, int width, int height, - int radius, SmoothParams* const p) { - const int R = 2 * radius + 1; // total size of the kernel - - const size_t size_scratch_m = (R + 1) * width * sizeof(*p->start_); - const size_t size_m = width * sizeof(*p->average_); - const size_t size_lut = (1 + 2 * LUT_SIZE) * sizeof(*p->correction_); - const size_t total_size = size_scratch_m + size_m + size_lut; - uint8_t* mem = (uint8_t*)WebPSafeMalloc(1U, total_size); - - if (mem == NULL) return 0; - p->mem_ = (void*)mem; - - p->start_ = (uint16_t*)mem; - p->cur_ = p->start_; - p->end_ = p->start_ + R * width; - p->top_ = p->end_ - width; - memset(p->top_, 0, width * sizeof(*p->top_)); - mem += size_scratch_m; - - p->average_ = (uint16_t*)mem; - mem += size_m; - - p->width_ = width; - p->height_ = height; - p->src_ = data; - p->dst_ = data; - p->radius_ = radius; - p->scale_ = (1 << (FIX + LFIX)) / (R * R); // normalization constant - p->row_ = -radius; - - // analyze the input distribution so we can best-fit the threshold - CountLevels(data, width * height, p); - - // correction table - p->correction_ = ((int16_t*)mem) + LUT_SIZE; - InitCorrectionLUT(p->correction_, p->min_level_dist_); - - return 1; -} - -static void CleanupParams(SmoothParams* const p) { - WebPSafeFree(p->mem_); -} - -int WebPDequantizeLevels(uint8_t* const data, int width, int height, - int strength) { - const int radius = 4 * strength / 100; - if (strength < 0 || strength > 100) return 0; - if (data == NULL || width <= 0 || height <= 0) return 0; // bad params - if (radius > 0) { - SmoothParams p; - memset(&p, 0, sizeof(p)); - if (!InitParams(data, width, height, radius, &p)) return 0; - if (p.num_levels_ > 2) { - for (; p.row_ < p.height_; ++p.row_) { - VFilter(&p); // accumulate average of input - // Need to wait few rows in order to prime the filter, - // before emitting some output. - if (p.row_ >= p.radius_) { - HFilter(&p); - ApplyFilter(&p); - } - } - } - CleanupParams(&p); - } - return 1; -} diff --git a/Example-Mac/Pods/libwebp/src/utils/quant_levels_dec.h b/Example-Mac/Pods/libwebp/src/utils/quant_levels_dec.h deleted file mode 100644 index 9aab0680..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/quant_levels_dec.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Alpha plane de-quantization utility -// -// Author: Vikas Arora (vikasa@google.com) - -#ifndef WEBP_UTILS_QUANT_LEVELS_DEC_H_ -#define WEBP_UTILS_QUANT_LEVELS_DEC_H_ - -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Apply post-processing to input 'data' of size 'width'x'height' assuming that -// the source was quantized to a reduced number of levels. -// Strength is in [0..100] and controls the amount of dithering applied. -// Returns false in case of error (data is NULL, invalid parameters, -// malloc failure, ...). -int WebPDequantizeLevels(uint8_t* const data, int width, int height, - int strength); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_QUANT_LEVELS_DEC_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/utils/random.c b/Example-Mac/Pods/libwebp/src/utils/random.c deleted file mode 100644 index 24e96ad6..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/random.c +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Pseudo-random utilities -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include "./random.h" - -//------------------------------------------------------------------------------ - -// 31b-range values -static const uint32_t kRandomTable[VP8_RANDOM_TABLE_SIZE] = { - 0x0de15230, 0x03b31886, 0x775faccb, 0x1c88626a, 0x68385c55, 0x14b3b828, - 0x4a85fef8, 0x49ddb84b, 0x64fcf397, 0x5c550289, 0x4a290000, 0x0d7ec1da, - 0x5940b7ab, 0x5492577d, 0x4e19ca72, 0x38d38c69, 0x0c01ee65, 0x32a1755f, - 0x5437f652, 0x5abb2c32, 0x0faa57b1, 0x73f533e7, 0x685feeda, 0x7563cce2, - 0x6e990e83, 0x4730a7ed, 0x4fc0d9c6, 0x496b153c, 0x4f1403fa, 0x541afb0c, - 0x73990b32, 0x26d7cb1c, 0x6fcc3706, 0x2cbb77d8, 0x75762f2a, 0x6425ccdd, - 0x24b35461, 0x0a7d8715, 0x220414a8, 0x141ebf67, 0x56b41583, 0x73e502e3, - 0x44cab16f, 0x28264d42, 0x73baaefb, 0x0a50ebed, 0x1d6ab6fb, 0x0d3ad40b, - 0x35db3b68, 0x2b081e83, 0x77ce6b95, 0x5181e5f0, 0x78853bbc, 0x009f9494, - 0x27e5ed3c -}; - -void VP8InitRandom(VP8Random* const rg, float dithering) { - memcpy(rg->tab_, kRandomTable, sizeof(rg->tab_)); - rg->index1_ = 0; - rg->index2_ = 31; - rg->amp_ = (dithering < 0.0) ? 0 - : (dithering > 1.0) ? (1 << VP8_RANDOM_DITHER_FIX) - : (uint32_t)((1 << VP8_RANDOM_DITHER_FIX) * dithering); -} - -//------------------------------------------------------------------------------ - diff --git a/Example-Mac/Pods/libwebp/src/utils/random.h b/Example-Mac/Pods/libwebp/src/utils/random.h deleted file mode 100644 index c392a615..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/random.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Pseudo-random utilities -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_UTILS_RANDOM_H_ -#define WEBP_UTILS_RANDOM_H_ - -#include -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define VP8_RANDOM_DITHER_FIX 8 // fixed-point precision for dithering -#define VP8_RANDOM_TABLE_SIZE 55 - -typedef struct { - int index1_, index2_; - uint32_t tab_[VP8_RANDOM_TABLE_SIZE]; - int amp_; -} VP8Random; - -// Initializes random generator with an amplitude 'dithering' in range [0..1]. -void VP8InitRandom(VP8Random* const rg, float dithering); - -// Returns a centered pseudo-random number with 'num_bits' amplitude. -// (uses D.Knuth's Difference-based random generator). -// 'amp' is in VP8_RANDOM_DITHER_FIX fixed-point precision. -static WEBP_INLINE int VP8RandomBits2(VP8Random* const rg, int num_bits, - int amp) { - int diff; - assert(num_bits + VP8_RANDOM_DITHER_FIX <= 31); - diff = rg->tab_[rg->index1_] - rg->tab_[rg->index2_]; - if (diff < 0) diff += (1u << 31); - rg->tab_[rg->index1_] = diff; - if (++rg->index1_ == VP8_RANDOM_TABLE_SIZE) rg->index1_ = 0; - if (++rg->index2_ == VP8_RANDOM_TABLE_SIZE) rg->index2_ = 0; - // sign-extend, 0-center - diff = (int)((uint32_t)diff << 1) >> (32 - num_bits); - diff = (diff * amp) >> VP8_RANDOM_DITHER_FIX; // restrict range - diff += 1 << (num_bits - 1); // shift back to 0.5-center - return diff; -} - -static WEBP_INLINE int VP8RandomBits(VP8Random* const rg, int num_bits) { - return VP8RandomBits2(rg, num_bits, rg->amp_); -} - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_RANDOM_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/utils/rescaler.c b/Example-Mac/Pods/libwebp/src/utils/rescaler.c deleted file mode 100644 index 00c9300b..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/rescaler.c +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Rescaling functions -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include -#include -#include "../dsp/dsp.h" -#include "./rescaler.h" - -//------------------------------------------------------------------------------ - -void WebPRescalerInit(WebPRescaler* const wrk, int src_width, int src_height, - uint8_t* const dst, - int dst_width, int dst_height, int dst_stride, - int num_channels, rescaler_t* const work) { - const int x_add = src_width, x_sub = dst_width; - const int y_add = src_height, y_sub = dst_height; - wrk->x_expand = (src_width < dst_width); - wrk->y_expand = (src_height < dst_height); - wrk->src_width = src_width; - wrk->src_height = src_height; - wrk->dst_width = dst_width; - wrk->dst_height = dst_height; - wrk->src_y = 0; - wrk->dst_y = 0; - wrk->dst = dst; - wrk->dst_stride = dst_stride; - wrk->num_channels = num_channels; - - // for 'x_expand', we use bilinear interpolation - wrk->x_add = wrk->x_expand ? (x_sub - 1) : x_add; - wrk->x_sub = wrk->x_expand ? (x_add - 1) : x_sub; - if (!wrk->x_expand) { // fx_scale is not used otherwise - wrk->fx_scale = WEBP_RESCALER_FRAC(1, wrk->x_sub); - } - // vertical scaling parameters - wrk->y_add = wrk->y_expand ? y_add - 1 : y_add; - wrk->y_sub = wrk->y_expand ? y_sub - 1 : y_sub; - wrk->y_accum = wrk->y_expand ? wrk->y_sub : wrk->y_add; - if (!wrk->y_expand) { - // this is WEBP_RESCALER_FRAC(dst_height, x_add * y_add) without the cast. - const uint64_t ratio = - (uint64_t)dst_height * WEBP_RESCALER_ONE / (wrk->x_add * wrk->y_add); - if (ratio != (uint32_t)ratio) { - // We can't represent the ratio with the current fixed-point precision. - // => We special-case fxy_scale = 0, in WebPRescalerExportRow(). - wrk->fxy_scale = 0; - } else { - wrk->fxy_scale = (uint32_t)ratio; - } - wrk->fy_scale = WEBP_RESCALER_FRAC(1, wrk->y_sub); - } else { - wrk->fy_scale = WEBP_RESCALER_FRAC(1, wrk->x_add); - // wrk->fxy_scale is unused here. - } - wrk->irow = work; - wrk->frow = work + num_channels * dst_width; - memset(work, 0, 2 * dst_width * num_channels * sizeof(*work)); - - WebPRescalerDspInit(); -} - -int WebPRescalerGetScaledDimensions(int src_width, int src_height, - int* const scaled_width, - int* const scaled_height) { - assert(scaled_width != NULL); - assert(scaled_height != NULL); - { - int width = *scaled_width; - int height = *scaled_height; - - // if width is unspecified, scale original proportionally to height ratio. - if (width == 0) { - width = (src_width * height + src_height / 2) / src_height; - } - // if height is unspecified, scale original proportionally to width ratio. - if (height == 0) { - height = (src_height * width + src_width / 2) / src_width; - } - // Check if the overall dimensions still make sense. - if (width <= 0 || height <= 0) { - return 0; - } - - *scaled_width = width; - *scaled_height = height; - return 1; - } -} - -//------------------------------------------------------------------------------ -// all-in-one calls - -int WebPRescaleNeededLines(const WebPRescaler* const wrk, int max_num_lines) { - const int num_lines = (wrk->y_accum + wrk->y_sub - 1) / wrk->y_sub; - return (num_lines > max_num_lines) ? max_num_lines : num_lines; -} - -int WebPRescalerImport(WebPRescaler* const wrk, int num_lines, - const uint8_t* src, int src_stride) { - int total_imported = 0; - while (total_imported < num_lines && !WebPRescalerHasPendingOutput(wrk)) { - if (wrk->y_expand) { - rescaler_t* const tmp = wrk->irow; - wrk->irow = wrk->frow; - wrk->frow = tmp; - } - WebPRescalerImportRow(wrk, src); - if (!wrk->y_expand) { // Accumulate the contribution of the new row. - int x; - for (x = 0; x < wrk->num_channels * wrk->dst_width; ++x) { - wrk->irow[x] += wrk->frow[x]; - } - } - ++wrk->src_y; - src += src_stride; - ++total_imported; - wrk->y_accum -= wrk->y_sub; - } - return total_imported; -} - -int WebPRescalerExport(WebPRescaler* const rescaler) { - int total_exported = 0; - while (WebPRescalerHasPendingOutput(rescaler)) { - WebPRescalerExportRow(rescaler); - ++total_exported; - } - return total_exported; -} - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/utils/rescaler.h b/Example-Mac/Pods/libwebp/src/utils/rescaler.h deleted file mode 100644 index 98b01a76..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/rescaler.h +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Rescaling functions -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_UTILS_RESCALER_H_ -#define WEBP_UTILS_RESCALER_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "../webp/types.h" - -#define WEBP_RESCALER_RFIX 32 // fixed-point precision for multiplies -#define WEBP_RESCALER_ONE (1ull << WEBP_RESCALER_RFIX) -#define WEBP_RESCALER_FRAC(x, y) \ - ((uint32_t)(((uint64_t)(x) << WEBP_RESCALER_RFIX) / (y))) - -// Structure used for on-the-fly rescaling -typedef uint32_t rescaler_t; // type for side-buffer -typedef struct WebPRescaler WebPRescaler; -struct WebPRescaler { - int x_expand; // true if we're expanding in the x direction - int y_expand; // true if we're expanding in the y direction - int num_channels; // bytes to jump between pixels - uint32_t fx_scale; // fixed-point scaling factors - uint32_t fy_scale; // '' - uint32_t fxy_scale; // '' - int y_accum; // vertical accumulator - int y_add, y_sub; // vertical increments - int x_add, x_sub; // horizontal increments - int src_width, src_height; // source dimensions - int dst_width, dst_height; // destination dimensions - int src_y, dst_y; // row counters for input and output - uint8_t* dst; - int dst_stride; - rescaler_t* irow, *frow; // work buffer -}; - -// Initialize a rescaler given scratch area 'work' and dimensions of src & dst. -void WebPRescalerInit(WebPRescaler* const rescaler, - int src_width, int src_height, - uint8_t* const dst, - int dst_width, int dst_height, int dst_stride, - int num_channels, - rescaler_t* const work); - -// If either 'scaled_width' or 'scaled_height' (but not both) is 0 the value -// will be calculated preserving the aspect ratio, otherwise the values are -// left unmodified. Returns true on success, false if either value is 0 after -// performing the scaling calculation. -int WebPRescalerGetScaledDimensions(int src_width, int src_height, - int* const scaled_width, - int* const scaled_height); - -// Returns the number of input lines needed next to produce one output line, -// considering that the maximum available input lines are 'max_num_lines'. -int WebPRescaleNeededLines(const WebPRescaler* const rescaler, - int max_num_lines); - -// Import multiple rows over all channels, until at least one row is ready to -// be exported. Returns the actual number of lines that were imported. -int WebPRescalerImport(WebPRescaler* const rescaler, int num_rows, - const uint8_t* src, int src_stride); - -// Export as many rows as possible. Return the numbers of rows written. -int WebPRescalerExport(WebPRescaler* const rescaler); - -// Return true if input is finished -static WEBP_INLINE -int WebPRescalerInputDone(const WebPRescaler* const rescaler) { - return (rescaler->src_y >= rescaler->src_height); -} -// Return true if output is finished -static WEBP_INLINE -int WebPRescalerOutputDone(const WebPRescaler* const rescaler) { - return (rescaler->dst_y >= rescaler->dst_height); -} - -// Return true if there are pending output rows ready. -static WEBP_INLINE -int WebPRescalerHasPendingOutput(const WebPRescaler* const rescaler) { - return !WebPRescalerOutputDone(rescaler) && (rescaler->y_accum <= 0); -} - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_RESCALER_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/utils/thread.c b/Example-Mac/Pods/libwebp/src/utils/thread.c deleted file mode 100644 index 93f76227..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/thread.c +++ /dev/null @@ -1,358 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Multi-threaded worker -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include // for memset() -#include "./thread.h" -#include "./utils.h" - -#ifdef WEBP_USE_THREAD - -#if defined(_WIN32) - -#include -typedef HANDLE pthread_t; -typedef CRITICAL_SECTION pthread_mutex_t; - -#if _WIN32_WINNT >= 0x0600 // Windows Vista / Server 2008 or greater -#define USE_WINDOWS_CONDITION_VARIABLE -typedef CONDITION_VARIABLE pthread_cond_t; -#else -typedef struct { - HANDLE waiting_sem_; - HANDLE received_sem_; - HANDLE signal_event_; -} pthread_cond_t; -#endif // _WIN32_WINNT >= 0x600 - -#ifndef WINAPI_FAMILY_PARTITION -#define WINAPI_PARTITION_DESKTOP 1 -#define WINAPI_FAMILY_PARTITION(x) x -#endif - -#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -#define USE_CREATE_THREAD -#endif - -#else // !_WIN32 - -#include - -#endif // _WIN32 - -struct WebPWorkerImpl { - pthread_mutex_t mutex_; - pthread_cond_t condition_; - pthread_t thread_; -}; - -#if defined(_WIN32) - -//------------------------------------------------------------------------------ -// simplistic pthread emulation layer - -#include - -// _beginthreadex requires __stdcall -#define THREADFN unsigned int __stdcall -#define THREAD_RETURN(val) (unsigned int)((DWORD_PTR)val) - -#if _WIN32_WINNT >= 0x0501 // Windows XP or greater -#define WaitForSingleObject(obj, timeout) \ - WaitForSingleObjectEx(obj, timeout, FALSE /*bAlertable*/) -#endif - -static int pthread_create(pthread_t* const thread, const void* attr, - unsigned int (__stdcall *start)(void*), void* arg) { - (void)attr; -#ifdef USE_CREATE_THREAD - *thread = CreateThread(NULL, /* lpThreadAttributes */ - 0, /* dwStackSize */ - start, - arg, - 0, /* dwStackSize */ - NULL); /* lpThreadId */ -#else - *thread = (pthread_t)_beginthreadex(NULL, /* void *security */ - 0, /* unsigned stack_size */ - start, - arg, - 0, /* unsigned initflag */ - NULL); /* unsigned *thrdaddr */ -#endif - if (*thread == NULL) return 1; - SetThreadPriority(*thread, THREAD_PRIORITY_ABOVE_NORMAL); - return 0; -} - -static int pthread_join(pthread_t thread, void** value_ptr) { - (void)value_ptr; - return (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0 || - CloseHandle(thread) == 0); -} - -// Mutex -static int pthread_mutex_init(pthread_mutex_t* const mutex, void* mutexattr) { - (void)mutexattr; -#if _WIN32_WINNT >= 0x0600 // Windows Vista / Server 2008 or greater - InitializeCriticalSectionEx(mutex, 0 /*dwSpinCount*/, 0 /*Flags*/); -#else - InitializeCriticalSection(mutex); -#endif - return 0; -} - -static int pthread_mutex_lock(pthread_mutex_t* const mutex) { - EnterCriticalSection(mutex); - return 0; -} - -static int pthread_mutex_unlock(pthread_mutex_t* const mutex) { - LeaveCriticalSection(mutex); - return 0; -} - -static int pthread_mutex_destroy(pthread_mutex_t* const mutex) { - DeleteCriticalSection(mutex); - return 0; -} - -// Condition -static int pthread_cond_destroy(pthread_cond_t* const condition) { - int ok = 1; -#ifdef USE_WINDOWS_CONDITION_VARIABLE - (void)condition; -#else - ok &= (CloseHandle(condition->waiting_sem_) != 0); - ok &= (CloseHandle(condition->received_sem_) != 0); - ok &= (CloseHandle(condition->signal_event_) != 0); -#endif - return !ok; -} - -static int pthread_cond_init(pthread_cond_t* const condition, void* cond_attr) { - (void)cond_attr; -#ifdef USE_WINDOWS_CONDITION_VARIABLE - InitializeConditionVariable(condition); -#else - condition->waiting_sem_ = CreateSemaphore(NULL, 0, 1, NULL); - condition->received_sem_ = CreateSemaphore(NULL, 0, 1, NULL); - condition->signal_event_ = CreateEvent(NULL, FALSE, FALSE, NULL); - if (condition->waiting_sem_ == NULL || - condition->received_sem_ == NULL || - condition->signal_event_ == NULL) { - pthread_cond_destroy(condition); - return 1; - } -#endif - return 0; -} - -static int pthread_cond_signal(pthread_cond_t* const condition) { - int ok = 1; -#ifdef USE_WINDOWS_CONDITION_VARIABLE - WakeConditionVariable(condition); -#else - if (WaitForSingleObject(condition->waiting_sem_, 0) == WAIT_OBJECT_0) { - // a thread is waiting in pthread_cond_wait: allow it to be notified - ok = SetEvent(condition->signal_event_); - // wait until the event is consumed so the signaler cannot consume - // the event via its own pthread_cond_wait. - ok &= (WaitForSingleObject(condition->received_sem_, INFINITE) != - WAIT_OBJECT_0); - } -#endif - return !ok; -} - -static int pthread_cond_wait(pthread_cond_t* const condition, - pthread_mutex_t* const mutex) { - int ok; -#ifdef USE_WINDOWS_CONDITION_VARIABLE - ok = SleepConditionVariableCS(condition, mutex, INFINITE); -#else - // note that there is a consumer available so the signal isn't dropped in - // pthread_cond_signal - if (!ReleaseSemaphore(condition->waiting_sem_, 1, NULL)) - return 1; - // now unlock the mutex so pthread_cond_signal may be issued - pthread_mutex_unlock(mutex); - ok = (WaitForSingleObject(condition->signal_event_, INFINITE) == - WAIT_OBJECT_0); - ok &= ReleaseSemaphore(condition->received_sem_, 1, NULL); - pthread_mutex_lock(mutex); -#endif - return !ok; -} - -#else // !_WIN32 -# define THREADFN void* -# define THREAD_RETURN(val) val -#endif // _WIN32 - -//------------------------------------------------------------------------------ - -static void Execute(WebPWorker* const worker); // Forward declaration. - -static THREADFN ThreadLoop(void* ptr) { - WebPWorker* const worker = (WebPWorker*)ptr; - int done = 0; - while (!done) { - pthread_mutex_lock(&worker->impl_->mutex_); - while (worker->status_ == OK) { // wait in idling mode - pthread_cond_wait(&worker->impl_->condition_, &worker->impl_->mutex_); - } - if (worker->status_ == WORK) { - Execute(worker); - worker->status_ = OK; - } else if (worker->status_ == NOT_OK) { // finish the worker - done = 1; - } - // signal to the main thread that we're done (for Sync()) - pthread_cond_signal(&worker->impl_->condition_); - pthread_mutex_unlock(&worker->impl_->mutex_); - } - return THREAD_RETURN(NULL); // Thread is finished -} - -// main thread state control -static void ChangeState(WebPWorker* const worker, - WebPWorkerStatus new_status) { - // No-op when attempting to change state on a thread that didn't come up. - // Checking status_ without acquiring the lock first would result in a data - // race. - if (worker->impl_ == NULL) return; - - pthread_mutex_lock(&worker->impl_->mutex_); - if (worker->status_ >= OK) { - // wait for the worker to finish - while (worker->status_ != OK) { - pthread_cond_wait(&worker->impl_->condition_, &worker->impl_->mutex_); - } - // assign new status and release the working thread if needed - if (new_status != OK) { - worker->status_ = new_status; - pthread_cond_signal(&worker->impl_->condition_); - } - } - pthread_mutex_unlock(&worker->impl_->mutex_); -} - -#endif // WEBP_USE_THREAD - -//------------------------------------------------------------------------------ - -static void Init(WebPWorker* const worker) { - memset(worker, 0, sizeof(*worker)); - worker->status_ = NOT_OK; -} - -static int Sync(WebPWorker* const worker) { -#ifdef WEBP_USE_THREAD - ChangeState(worker, OK); -#endif - assert(worker->status_ <= OK); - return !worker->had_error; -} - -static int Reset(WebPWorker* const worker) { - int ok = 1; - worker->had_error = 0; - if (worker->status_ < OK) { -#ifdef WEBP_USE_THREAD - worker->impl_ = (WebPWorkerImpl*)WebPSafeCalloc(1, sizeof(*worker->impl_)); - if (worker->impl_ == NULL) { - return 0; - } - if (pthread_mutex_init(&worker->impl_->mutex_, NULL)) { - goto Error; - } - if (pthread_cond_init(&worker->impl_->condition_, NULL)) { - pthread_mutex_destroy(&worker->impl_->mutex_); - goto Error; - } - pthread_mutex_lock(&worker->impl_->mutex_); - ok = !pthread_create(&worker->impl_->thread_, NULL, ThreadLoop, worker); - if (ok) worker->status_ = OK; - pthread_mutex_unlock(&worker->impl_->mutex_); - if (!ok) { - pthread_mutex_destroy(&worker->impl_->mutex_); - pthread_cond_destroy(&worker->impl_->condition_); - Error: - WebPSafeFree(worker->impl_); - worker->impl_ = NULL; - return 0; - } -#else - worker->status_ = OK; -#endif - } else if (worker->status_ > OK) { - ok = Sync(worker); - } - assert(!ok || (worker->status_ == OK)); - return ok; -} - -static void Execute(WebPWorker* const worker) { - if (worker->hook != NULL) { - worker->had_error |= !worker->hook(worker->data1, worker->data2); - } -} - -static void Launch(WebPWorker* const worker) { -#ifdef WEBP_USE_THREAD - ChangeState(worker, WORK); -#else - Execute(worker); -#endif -} - -static void End(WebPWorker* const worker) { -#ifdef WEBP_USE_THREAD - if (worker->impl_ != NULL) { - ChangeState(worker, NOT_OK); - pthread_join(worker->impl_->thread_, NULL); - pthread_mutex_destroy(&worker->impl_->mutex_); - pthread_cond_destroy(&worker->impl_->condition_); - WebPSafeFree(worker->impl_); - worker->impl_ = NULL; - } -#else - worker->status_ = NOT_OK; - assert(worker->impl_ == NULL); -#endif - assert(worker->status_ == NOT_OK); -} - -//------------------------------------------------------------------------------ - -static WebPWorkerInterface g_worker_interface = { - Init, Reset, Sync, Launch, Execute, End -}; - -int WebPSetWorkerInterface(const WebPWorkerInterface* const winterface) { - if (winterface == NULL || - winterface->Init == NULL || winterface->Reset == NULL || - winterface->Sync == NULL || winterface->Launch == NULL || - winterface->Execute == NULL || winterface->End == NULL) { - return 0; - } - g_worker_interface = *winterface; - return 1; -} - -const WebPWorkerInterface* WebPGetWorkerInterface(void) { - return &g_worker_interface; -} - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/utils/thread.h b/Example-Mac/Pods/libwebp/src/utils/thread.h deleted file mode 100644 index 84083118..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/thread.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Multi-threaded worker -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_UTILS_THREAD_H_ -#define WEBP_UTILS_THREAD_H_ - -#ifdef HAVE_CONFIG_H -#include "../webp/config.h" -#endif - -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// State of the worker thread object -typedef enum { - NOT_OK = 0, // object is unusable - OK, // ready to work - WORK // busy finishing the current task -} WebPWorkerStatus; - -// Function to be called by the worker thread. Takes two opaque pointers as -// arguments (data1 and data2), and should return false in case of error. -typedef int (*WebPWorkerHook)(void*, void*); - -// Platform-dependent implementation details for the worker. -typedef struct WebPWorkerImpl WebPWorkerImpl; - -// Synchronization object used to launch job in the worker thread -typedef struct { - WebPWorkerImpl* impl_; - WebPWorkerStatus status_; - WebPWorkerHook hook; // hook to call - void* data1; // first argument passed to 'hook' - void* data2; // second argument passed to 'hook' - int had_error; // return value of the last call to 'hook' -} WebPWorker; - -// The interface for all thread-worker related functions. All these functions -// must be implemented. -typedef struct { - // Must be called first, before any other method. - void (*Init)(WebPWorker* const worker); - // Must be called to initialize the object and spawn the thread. Re-entrant. - // Will potentially launch the thread. Returns false in case of error. - int (*Reset)(WebPWorker* const worker); - // Makes sure the previous work is finished. Returns true if worker->had_error - // was not set and no error condition was triggered by the working thread. - int (*Sync)(WebPWorker* const worker); - // Triggers the thread to call hook() with data1 and data2 arguments. These - // hook/data1/data2 values can be changed at any time before calling this - // function, but not be changed afterward until the next call to Sync(). - void (*Launch)(WebPWorker* const worker); - // This function is similar to Launch() except that it calls the - // hook directly instead of using a thread. Convenient to bypass the thread - // mechanism while still using the WebPWorker structs. Sync() must - // still be called afterward (for error reporting). - void (*Execute)(WebPWorker* const worker); - // Kill the thread and terminate the object. To use the object again, one - // must call Reset() again. - void (*End)(WebPWorker* const worker); -} WebPWorkerInterface; - -// Install a new set of threading functions, overriding the defaults. This -// should be done before any workers are started, i.e., before any encoding or -// decoding takes place. The contents of the interface struct are copied, it -// is safe to free the corresponding memory after this call. This function is -// not thread-safe. Return false in case of invalid pointer or methods. -WEBP_EXTERN(int) WebPSetWorkerInterface( - const WebPWorkerInterface* const winterface); - -// Retrieve the currently set thread worker interface. -WEBP_EXTERN(const WebPWorkerInterface*) WebPGetWorkerInterface(void); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_THREAD_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/utils/utils.c b/Example-Mac/Pods/libwebp/src/utils/utils.c deleted file mode 100644 index d8e30930..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/utils.c +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Misc. common utility functions -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include // for memcpy() -#include "../webp/decode.h" -#include "../webp/encode.h" -#include "./utils.h" - -// If PRINT_MEM_INFO is defined, extra info (like total memory used, number of -// alloc/free etc) is printed. For debugging/tuning purpose only (it's slow, -// and not multi-thread safe!). -// An interesting alternative is valgrind's 'massif' tool: -// http://valgrind.org/docs/manual/ms-manual.html -// Here is an example command line: -/* valgrind --tool=massif --massif-out-file=massif.out \ - --stacks=yes --alloc-fn=WebPSafeAlloc --alloc-fn=WebPSafeCalloc - ms_print massif.out -*/ -// In addition: -// * if PRINT_MEM_TRAFFIC is defined, all the details of the malloc/free cycles -// are printed. -// * if MALLOC_FAIL_AT is defined, the global environment variable -// $MALLOC_FAIL_AT is used to simulate a memory error when calloc or malloc -// is called for the nth time. Example usage: -// export MALLOC_FAIL_AT=50 && ./examples/cwebp input.png -// * if MALLOC_LIMIT is defined, the global environment variable $MALLOC_LIMIT -// sets the maximum amount of memory (in bytes) made available to libwebp. -// This can be used to emulate environment with very limited memory. -// Example: export MALLOC_LIMIT=64000000 && ./examples/dwebp picture.webp - -// #define PRINT_MEM_INFO -// #define PRINT_MEM_TRAFFIC -// #define MALLOC_FAIL_AT -// #define MALLOC_LIMIT - -//------------------------------------------------------------------------------ -// Checked memory allocation - -#if defined(PRINT_MEM_INFO) - -#include - -static int num_malloc_calls = 0; -static int num_calloc_calls = 0; -static int num_free_calls = 0; -static int countdown_to_fail = 0; // 0 = off - -typedef struct MemBlock MemBlock; -struct MemBlock { - void* ptr_; - size_t size_; - MemBlock* next_; -}; - -static MemBlock* all_blocks = NULL; -static size_t total_mem = 0; -static size_t total_mem_allocated = 0; -static size_t high_water_mark = 0; -static size_t mem_limit = 0; - -static int exit_registered = 0; - -static void PrintMemInfo(void) { - fprintf(stderr, "\nMEMORY INFO:\n"); - fprintf(stderr, "num calls to: malloc = %4d\n", num_malloc_calls); - fprintf(stderr, " calloc = %4d\n", num_calloc_calls); - fprintf(stderr, " free = %4d\n", num_free_calls); - fprintf(stderr, "total_mem: %u\n", (uint32_t)total_mem); - fprintf(stderr, "total_mem allocated: %u\n", (uint32_t)total_mem_allocated); - fprintf(stderr, "high-water mark: %u\n", (uint32_t)high_water_mark); - while (all_blocks != NULL) { - MemBlock* b = all_blocks; - all_blocks = b->next_; - free(b); - } -} - -static void Increment(int* const v) { - if (!exit_registered) { -#if defined(MALLOC_FAIL_AT) - { - const char* const malloc_fail_at_str = getenv("MALLOC_FAIL_AT"); - if (malloc_fail_at_str != NULL) { - countdown_to_fail = atoi(malloc_fail_at_str); - } - } -#endif -#if defined(MALLOC_LIMIT) - { - const char* const malloc_limit_str = getenv("MALLOC_LIMIT"); - if (malloc_limit_str != NULL) { - mem_limit = atoi(malloc_limit_str); - } - } -#endif - (void)countdown_to_fail; - (void)mem_limit; - atexit(PrintMemInfo); - exit_registered = 1; - } - ++*v; -} - -static void AddMem(void* ptr, size_t size) { - if (ptr != NULL) { - MemBlock* const b = (MemBlock*)malloc(sizeof(*b)); - if (b == NULL) abort(); - b->next_ = all_blocks; - all_blocks = b; - b->ptr_ = ptr; - b->size_ = size; - total_mem += size; - total_mem_allocated += size; -#if defined(PRINT_MEM_TRAFFIC) -#if defined(MALLOC_FAIL_AT) - fprintf(stderr, "fail-count: %5d [mem=%u]\n", - num_malloc_calls + num_calloc_calls, (uint32_t)total_mem); -#else - fprintf(stderr, "Mem: %u (+%u)\n", (uint32_t)total_mem, (uint32_t)size); -#endif -#endif - if (total_mem > high_water_mark) high_water_mark = total_mem; - } -} - -static void SubMem(void* ptr) { - if (ptr != NULL) { - MemBlock** b = &all_blocks; - // Inefficient search, but that's just for debugging. - while (*b != NULL && (*b)->ptr_ != ptr) b = &(*b)->next_; - if (*b == NULL) { - fprintf(stderr, "Invalid pointer free! (%p)\n", ptr); - abort(); - } - { - MemBlock* const block = *b; - *b = block->next_; - total_mem -= block->size_; -#if defined(PRINT_MEM_TRAFFIC) - fprintf(stderr, "Mem: %u (-%u)\n", - (uint32_t)total_mem, (uint32_t)block->size_); -#endif - free(block); - } - } -} - -#else -#define Increment(v) do {} while (0) -#define AddMem(p, s) do {} while (0) -#define SubMem(p) do {} while (0) -#endif - -// Returns 0 in case of overflow of nmemb * size. -static int CheckSizeArgumentsOverflow(uint64_t nmemb, size_t size) { - const uint64_t total_size = nmemb * size; - if (nmemb == 0) return 1; - if ((uint64_t)size > WEBP_MAX_ALLOCABLE_MEMORY / nmemb) return 0; - if (total_size != (size_t)total_size) return 0; -#if defined(PRINT_MEM_INFO) && defined(MALLOC_FAIL_AT) - if (countdown_to_fail > 0 && --countdown_to_fail == 0) { - return 0; // fake fail! - } -#endif -#if defined(MALLOC_LIMIT) - if (mem_limit > 0 && total_mem + total_size >= mem_limit) { - return 0; // fake fail! - } -#endif - - return 1; -} - -void* WebPSafeMalloc(uint64_t nmemb, size_t size) { - void* ptr; - Increment(&num_malloc_calls); - if (!CheckSizeArgumentsOverflow(nmemb, size)) return NULL; - assert(nmemb * size > 0); - ptr = malloc((size_t)(nmemb * size)); - AddMem(ptr, (size_t)(nmemb * size)); - return ptr; -} - -void* WebPSafeCalloc(uint64_t nmemb, size_t size) { - void* ptr; - Increment(&num_calloc_calls); - if (!CheckSizeArgumentsOverflow(nmemb, size)) return NULL; - assert(nmemb * size > 0); - ptr = calloc((size_t)nmemb, size); - AddMem(ptr, (size_t)(nmemb * size)); - return ptr; -} - -void WebPSafeFree(void* const ptr) { - if (ptr != NULL) { - Increment(&num_free_calls); - SubMem(ptr); - } - free(ptr); -} - -// Public API function. -void WebPFree(void* ptr) { - free(ptr); -} - -//------------------------------------------------------------------------------ - -void WebPCopyPlane(const uint8_t* src, int src_stride, - uint8_t* dst, int dst_stride, int width, int height) { - assert(src != NULL && dst != NULL); - assert(src_stride >= width && dst_stride >= width); - while (height-- > 0) { - memcpy(dst, src, width); - src += src_stride; - dst += dst_stride; - } -} - -void WebPCopyPixels(const WebPPicture* const src, WebPPicture* const dst) { - assert(src != NULL && dst != NULL); - assert(src->width == dst->width && src->height == dst->height); - assert(src->use_argb && dst->use_argb); - WebPCopyPlane((uint8_t*)src->argb, 4 * src->argb_stride, (uint8_t*)dst->argb, - 4 * dst->argb_stride, 4 * src->width, src->height); -} - -//------------------------------------------------------------------------------ diff --git a/Example-Mac/Pods/libwebp/src/utils/utils.h b/Example-Mac/Pods/libwebp/src/utils/utils.h deleted file mode 100644 index f506d668..00000000 --- a/Example-Mac/Pods/libwebp/src/utils/utils.h +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Misc. common utility functions -// -// Authors: Skal (pascal.massimino@gmail.com) -// Urvang (urvang@google.com) - -#ifndef WEBP_UTILS_UTILS_H_ -#define WEBP_UTILS_UTILS_H_ - -#ifdef HAVE_CONFIG_H -#include "../webp/config.h" -#endif - -#include - -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//------------------------------------------------------------------------------ -// Memory allocation - -// This is the maximum memory amount that libwebp will ever try to allocate. -#define WEBP_MAX_ALLOCABLE_MEMORY (1ULL << 40) - -// size-checking safe malloc/calloc: verify that the requested size is not too -// large, or return NULL. You don't need to call these for constructs like -// malloc(sizeof(foo)), but only if there's picture-dependent size involved -// somewhere (like: malloc(num_pixels * sizeof(*something))). That's why this -// safe malloc() borrows the signature from calloc(), pointing at the dangerous -// underlying multiply involved. -WEBP_EXTERN(void*) WebPSafeMalloc(uint64_t nmemb, size_t size); -// Note that WebPSafeCalloc() expects the second argument type to be 'size_t' -// in order to favor the "calloc(num_foo, sizeof(foo))" pattern. -WEBP_EXTERN(void*) WebPSafeCalloc(uint64_t nmemb, size_t size); - -// Companion deallocation function to the above allocations. -WEBP_EXTERN(void) WebPSafeFree(void* const ptr); - -//------------------------------------------------------------------------------ -// Alignment - -#define WEBP_ALIGN_CST 31 -#define WEBP_ALIGN(PTR) ((uintptr_t)((PTR) + WEBP_ALIGN_CST) & ~WEBP_ALIGN_CST) - -#if defined(WEBP_FORCE_ALIGNED) -#include -// memcpy() is the safe way of moving potentially unaligned 32b memory. -static WEBP_INLINE uint32_t WebPMemToUint32(const uint8_t* const ptr) { - uint32_t A; - memcpy(&A, (const int*)ptr, sizeof(A)); - return A; -} -static WEBP_INLINE void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) { - memcpy(ptr, &val, sizeof(val)); -} -#else -static WEBP_INLINE uint32_t WebPMemToUint32(const uint8_t* const ptr) { - return *(const uint32_t*)ptr; -} -static WEBP_INLINE void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) { - *(uint32_t*)ptr = val; -} -#endif - -//------------------------------------------------------------------------------ -// Reading/writing data. - -// Read 16, 24 or 32 bits stored in little-endian order. -static WEBP_INLINE int GetLE16(const uint8_t* const data) { - return (int)(data[0] << 0) | (data[1] << 8); -} - -static WEBP_INLINE int GetLE24(const uint8_t* const data) { - return GetLE16(data) | (data[2] << 16); -} - -static WEBP_INLINE uint32_t GetLE32(const uint8_t* const data) { - return GetLE16(data) | ((uint32_t)GetLE16(data + 2) << 16); -} - -// Store 16, 24 or 32 bits in little-endian order. -static WEBP_INLINE void PutLE16(uint8_t* const data, int val) { - assert(val < (1 << 16)); - data[0] = (val >> 0); - data[1] = (val >> 8); -} - -static WEBP_INLINE void PutLE24(uint8_t* const data, int val) { - assert(val < (1 << 24)); - PutLE16(data, val & 0xffff); - data[2] = (val >> 16); -} - -static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) { - PutLE16(data, (int)(val & 0xffff)); - PutLE16(data + 2, (int)(val >> 16)); -} - -// Returns (int)floor(log2(n)). n must be > 0. -// use GNU builtins where available. -#if defined(__GNUC__) && \ - ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4) -static WEBP_INLINE int BitsLog2Floor(uint32_t n) { - return 31 ^ __builtin_clz(n); -} -#elif defined(_MSC_VER) && _MSC_VER > 1310 && \ - (defined(_M_X64) || defined(_M_IX86)) -#include -#pragma intrinsic(_BitScanReverse) - -static WEBP_INLINE int BitsLog2Floor(uint32_t n) { - unsigned long first_set_bit; - _BitScanReverse(&first_set_bit, n); - return first_set_bit; -} -#else -static WEBP_INLINE int BitsLog2Floor(uint32_t n) { - int log = 0; - uint32_t value = n; - int i; - - for (i = 4; i >= 0; --i) { - const int shift = (1 << i); - const uint32_t x = value >> shift; - if (x != 0) { - value = x; - log += shift; - } - } - return log; -} -#endif - -//------------------------------------------------------------------------------ -// Pixel copying. - -struct WebPPicture; - -// Copy width x height pixels from 'src' to 'dst' honoring the strides. -WEBP_EXTERN(void) WebPCopyPlane(const uint8_t* src, int src_stride, - uint8_t* dst, int dst_stride, - int width, int height); - -// Copy ARGB pixels from 'src' to 'dst' honoring strides. 'src' and 'dst' are -// assumed to be already allocated and using ARGB data. -WEBP_EXTERN(void) WebPCopyPixels(const struct WebPPicture* const src, - struct WebPPicture* const dst); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_UTILS_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/webp/decode.h b/Example-Mac/Pods/libwebp/src/webp/decode.h deleted file mode 100644 index 143e4fbe..00000000 --- a/Example-Mac/Pods/libwebp/src/webp/decode.h +++ /dev/null @@ -1,488 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Main decoding functions for WebP images. -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_WEBP_DECODE_H_ -#define WEBP_WEBP_DECODE_H_ - -#include "./types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define WEBP_DECODER_ABI_VERSION 0x0208 // MAJOR(8b) + MINOR(8b) - -// Note: forward declaring enumerations is not allowed in (strict) C and C++, -// the types are left here for reference. -// typedef enum VP8StatusCode VP8StatusCode; -// typedef enum WEBP_CSP_MODE WEBP_CSP_MODE; -typedef struct WebPRGBABuffer WebPRGBABuffer; -typedef struct WebPYUVABuffer WebPYUVABuffer; -typedef struct WebPDecBuffer WebPDecBuffer; -typedef struct WebPIDecoder WebPIDecoder; -typedef struct WebPBitstreamFeatures WebPBitstreamFeatures; -typedef struct WebPDecoderOptions WebPDecoderOptions; -typedef struct WebPDecoderConfig WebPDecoderConfig; - -// Return the decoder's version number, packed in hexadecimal using 8bits for -// each of major/minor/revision. E.g: v2.5.7 is 0x020507. -WEBP_EXTERN(int) WebPGetDecoderVersion(void); - -// Retrieve basic header information: width, height. -// This function will also validate the header and return 0 in -// case of formatting error. -// Pointers 'width' and 'height' can be passed NULL if deemed irrelevant. -WEBP_EXTERN(int) WebPGetInfo(const uint8_t* data, size_t data_size, - int* width, int* height); - -// Decodes WebP images pointed to by 'data' and returns RGBA samples, along -// with the dimensions in *width and *height. The ordering of samples in -// memory is R, G, B, A, R, G, B, A... in scan order (endian-independent). -// The returned pointer should be deleted calling WebPFree(). -// Returns NULL in case of error. -WEBP_EXTERN(uint8_t*) WebPDecodeRGBA(const uint8_t* data, size_t data_size, - int* width, int* height); - -// Same as WebPDecodeRGBA, but returning A, R, G, B, A, R, G, B... ordered data. -WEBP_EXTERN(uint8_t*) WebPDecodeARGB(const uint8_t* data, size_t data_size, - int* width, int* height); - -// Same as WebPDecodeRGBA, but returning B, G, R, A, B, G, R, A... ordered data. -WEBP_EXTERN(uint8_t*) WebPDecodeBGRA(const uint8_t* data, size_t data_size, - int* width, int* height); - -// Same as WebPDecodeRGBA, but returning R, G, B, R, G, B... ordered data. -// If the bitstream contains transparency, it is ignored. -WEBP_EXTERN(uint8_t*) WebPDecodeRGB(const uint8_t* data, size_t data_size, - int* width, int* height); - -// Same as WebPDecodeRGB, but returning B, G, R, B, G, R... ordered data. -WEBP_EXTERN(uint8_t*) WebPDecodeBGR(const uint8_t* data, size_t data_size, - int* width, int* height); - - -// Decode WebP images pointed to by 'data' to Y'UV format(*). The pointer -// returned is the Y samples buffer. Upon return, *u and *v will point to -// the U and V chroma data. These U and V buffers need NOT be passed to -// WebPFree(), unlike the returned Y luma one. The dimension of the U and V -// planes are both (*width + 1) / 2 and (*height + 1)/ 2. -// Upon return, the Y buffer has a stride returned as '*stride', while U and V -// have a common stride returned as '*uv_stride'. -// Return NULL in case of error. -// (*) Also named Y'CbCr. See: http://en.wikipedia.org/wiki/YCbCr -WEBP_EXTERN(uint8_t*) WebPDecodeYUV(const uint8_t* data, size_t data_size, - int* width, int* height, - uint8_t** u, uint8_t** v, - int* stride, int* uv_stride); - -// Releases memory returned by the WebPDecode*() functions above. -WEBP_EXTERN(void) WebPFree(void* ptr); - -// These five functions are variants of the above ones, that decode the image -// directly into a pre-allocated buffer 'output_buffer'. The maximum storage -// available in this buffer is indicated by 'output_buffer_size'. If this -// storage is not sufficient (or an error occurred), NULL is returned. -// Otherwise, output_buffer is returned, for convenience. -// The parameter 'output_stride' specifies the distance (in bytes) -// between scanlines. Hence, output_buffer_size is expected to be at least -// output_stride x picture-height. -WEBP_EXTERN(uint8_t*) WebPDecodeRGBAInto( - const uint8_t* data, size_t data_size, - uint8_t* output_buffer, size_t output_buffer_size, int output_stride); -WEBP_EXTERN(uint8_t*) WebPDecodeARGBInto( - const uint8_t* data, size_t data_size, - uint8_t* output_buffer, size_t output_buffer_size, int output_stride); -WEBP_EXTERN(uint8_t*) WebPDecodeBGRAInto( - const uint8_t* data, size_t data_size, - uint8_t* output_buffer, size_t output_buffer_size, int output_stride); - -// RGB and BGR variants. Here too the transparency information, if present, -// will be dropped and ignored. -WEBP_EXTERN(uint8_t*) WebPDecodeRGBInto( - const uint8_t* data, size_t data_size, - uint8_t* output_buffer, size_t output_buffer_size, int output_stride); -WEBP_EXTERN(uint8_t*) WebPDecodeBGRInto( - const uint8_t* data, size_t data_size, - uint8_t* output_buffer, size_t output_buffer_size, int output_stride); - -// WebPDecodeYUVInto() is a variant of WebPDecodeYUV() that operates directly -// into pre-allocated luma/chroma plane buffers. This function requires the -// strides to be passed: one for the luma plane and one for each of the -// chroma ones. The size of each plane buffer is passed as 'luma_size', -// 'u_size' and 'v_size' respectively. -// Pointer to the luma plane ('*luma') is returned or NULL if an error occurred -// during decoding (or because some buffers were found to be too small). -WEBP_EXTERN(uint8_t*) WebPDecodeYUVInto( - const uint8_t* data, size_t data_size, - uint8_t* luma, size_t luma_size, int luma_stride, - uint8_t* u, size_t u_size, int u_stride, - uint8_t* v, size_t v_size, int v_stride); - -//------------------------------------------------------------------------------ -// Output colorspaces and buffer - -// Colorspaces -// Note: the naming describes the byte-ordering of packed samples in memory. -// For instance, MODE_BGRA relates to samples ordered as B,G,R,A,B,G,R,A,... -// Non-capital names (e.g.:MODE_Argb) relates to pre-multiplied RGB channels. -// RGBA-4444 and RGB-565 colorspaces are represented by following byte-order: -// RGBA-4444: [r3 r2 r1 r0 g3 g2 g1 g0], [b3 b2 b1 b0 a3 a2 a1 a0], ... -// RGB-565: [r4 r3 r2 r1 r0 g5 g4 g3], [g2 g1 g0 b4 b3 b2 b1 b0], ... -// In the case WEBP_SWAP_16BITS_CSP is defined, the bytes are swapped for -// these two modes: -// RGBA-4444: [b3 b2 b1 b0 a3 a2 a1 a0], [r3 r2 r1 r0 g3 g2 g1 g0], ... -// RGB-565: [g2 g1 g0 b4 b3 b2 b1 b0], [r4 r3 r2 r1 r0 g5 g4 g3], ... - -typedef enum WEBP_CSP_MODE { - MODE_RGB = 0, MODE_RGBA = 1, - MODE_BGR = 2, MODE_BGRA = 3, - MODE_ARGB = 4, MODE_RGBA_4444 = 5, - MODE_RGB_565 = 6, - // RGB-premultiplied transparent modes (alpha value is preserved) - MODE_rgbA = 7, - MODE_bgrA = 8, - MODE_Argb = 9, - MODE_rgbA_4444 = 10, - // YUV modes must come after RGB ones. - MODE_YUV = 11, MODE_YUVA = 12, // yuv 4:2:0 - MODE_LAST = 13 -} WEBP_CSP_MODE; - -// Some useful macros: -static WEBP_INLINE int WebPIsPremultipliedMode(WEBP_CSP_MODE mode) { - return (mode == MODE_rgbA || mode == MODE_bgrA || mode == MODE_Argb || - mode == MODE_rgbA_4444); -} - -static WEBP_INLINE int WebPIsAlphaMode(WEBP_CSP_MODE mode) { - return (mode == MODE_RGBA || mode == MODE_BGRA || mode == MODE_ARGB || - mode == MODE_RGBA_4444 || mode == MODE_YUVA || - WebPIsPremultipliedMode(mode)); -} - -static WEBP_INLINE int WebPIsRGBMode(WEBP_CSP_MODE mode) { - return (mode < MODE_YUV); -} - -//------------------------------------------------------------------------------ -// WebPDecBuffer: Generic structure for describing the output sample buffer. - -struct WebPRGBABuffer { // view as RGBA - uint8_t* rgba; // pointer to RGBA samples - int stride; // stride in bytes from one scanline to the next. - size_t size; // total size of the *rgba buffer. -}; - -struct WebPYUVABuffer { // view as YUVA - uint8_t* y, *u, *v, *a; // pointer to luma, chroma U/V, alpha samples - int y_stride; // luma stride - int u_stride, v_stride; // chroma strides - int a_stride; // alpha stride - size_t y_size; // luma plane size - size_t u_size, v_size; // chroma planes size - size_t a_size; // alpha-plane size -}; - -// Output buffer -struct WebPDecBuffer { - WEBP_CSP_MODE colorspace; // Colorspace. - int width, height; // Dimensions. - int is_external_memory; // If true, 'internal_memory' pointer is not used. - union { - WebPRGBABuffer RGBA; - WebPYUVABuffer YUVA; - } u; // Nameless union of buffer parameters. - uint32_t pad[4]; // padding for later use - - uint8_t* private_memory; // Internally allocated memory (only when - // is_external_memory is false). Should not be used - // externally, but accessed via the buffer union. -}; - -// Internal, version-checked, entry point -WEBP_EXTERN(int) WebPInitDecBufferInternal(WebPDecBuffer*, int); - -// Initialize the structure as empty. Must be called before any other use. -// Returns false in case of version mismatch -static WEBP_INLINE int WebPInitDecBuffer(WebPDecBuffer* buffer) { - return WebPInitDecBufferInternal(buffer, WEBP_DECODER_ABI_VERSION); -} - -// Free any memory associated with the buffer. Must always be called last. -// Note: doesn't free the 'buffer' structure itself. -WEBP_EXTERN(void) WebPFreeDecBuffer(WebPDecBuffer* buffer); - -//------------------------------------------------------------------------------ -// Enumeration of the status codes - -typedef enum VP8StatusCode { - VP8_STATUS_OK = 0, - VP8_STATUS_OUT_OF_MEMORY, - VP8_STATUS_INVALID_PARAM, - VP8_STATUS_BITSTREAM_ERROR, - VP8_STATUS_UNSUPPORTED_FEATURE, - VP8_STATUS_SUSPENDED, - VP8_STATUS_USER_ABORT, - VP8_STATUS_NOT_ENOUGH_DATA -} VP8StatusCode; - -//------------------------------------------------------------------------------ -// Incremental decoding -// -// This API allows streamlined decoding of partial data. -// Picture can be incrementally decoded as data become available thanks to the -// WebPIDecoder object. This object can be left in a SUSPENDED state if the -// picture is only partially decoded, pending additional input. -// Code example: -// -// WebPInitDecBuffer(&buffer); -// buffer.colorspace = mode; -// ... -// WebPIDecoder* idec = WebPINewDecoder(&buffer); -// while (has_more_data) { -// // ... (get additional data) -// status = WebPIAppend(idec, new_data, new_data_size); -// if (status != VP8_STATUS_SUSPENDED || -// break; -// } -// -// // The above call decodes the current available buffer. -// // Part of the image can now be refreshed by calling to -// // WebPIDecGetRGB()/WebPIDecGetYUVA() etc. -// } -// WebPIDelete(idec); - -// Creates a new incremental decoder with the supplied buffer parameter. -// This output_buffer can be passed NULL, in which case a default output buffer -// is used (with MODE_RGB). Otherwise, an internal reference to 'output_buffer' -// is kept, which means that the lifespan of 'output_buffer' must be larger than -// that of the returned WebPIDecoder object. -// The supplied 'output_buffer' content MUST NOT be changed between calls to -// WebPIAppend() or WebPIUpdate() unless 'output_buffer.is_external_memory' is -// set to 1. In such a case, it is allowed to modify the pointers, size and -// stride of output_buffer.u.RGBA or output_buffer.u.YUVA, provided they remain -// within valid bounds. -// All other fields of WebPDecBuffer MUST remain constant between calls. -// Returns NULL if the allocation failed. -WEBP_EXTERN(WebPIDecoder*) WebPINewDecoder(WebPDecBuffer* output_buffer); - -// This function allocates and initializes an incremental-decoder object, which -// will output the RGB/A samples specified by 'csp' into a preallocated -// buffer 'output_buffer'. The size of this buffer is at least -// 'output_buffer_size' and the stride (distance in bytes between two scanlines) -// is specified by 'output_stride'. -// Additionally, output_buffer can be passed NULL in which case the output -// buffer will be allocated automatically when the decoding starts. The -// colorspace 'csp' is taken into account for allocating this buffer. All other -// parameters are ignored. -// Returns NULL if the allocation failed, or if some parameters are invalid. -WEBP_EXTERN(WebPIDecoder*) WebPINewRGB( - WEBP_CSP_MODE csp, - uint8_t* output_buffer, size_t output_buffer_size, int output_stride); - -// This function allocates and initializes an incremental-decoder object, which -// will output the raw luma/chroma samples into a preallocated planes if -// supplied. The luma plane is specified by its pointer 'luma', its size -// 'luma_size' and its stride 'luma_stride'. Similarly, the chroma-u plane -// is specified by the 'u', 'u_size' and 'u_stride' parameters, and the chroma-v -// plane by 'v' and 'v_size'. And same for the alpha-plane. The 'a' pointer -// can be pass NULL in case one is not interested in the transparency plane. -// Conversely, 'luma' can be passed NULL if no preallocated planes are supplied. -// In this case, the output buffer will be automatically allocated (using -// MODE_YUVA) when decoding starts. All parameters are then ignored. -// Returns NULL if the allocation failed or if a parameter is invalid. -WEBP_EXTERN(WebPIDecoder*) WebPINewYUVA( - uint8_t* luma, size_t luma_size, int luma_stride, - uint8_t* u, size_t u_size, int u_stride, - uint8_t* v, size_t v_size, int v_stride, - uint8_t* a, size_t a_size, int a_stride); - -// Deprecated version of the above, without the alpha plane. -// Kept for backward compatibility. -WEBP_EXTERN(WebPIDecoder*) WebPINewYUV( - uint8_t* luma, size_t luma_size, int luma_stride, - uint8_t* u, size_t u_size, int u_stride, - uint8_t* v, size_t v_size, int v_stride); - -// Deletes the WebPIDecoder object and associated memory. Must always be called -// if WebPINewDecoder, WebPINewRGB or WebPINewYUV succeeded. -WEBP_EXTERN(void) WebPIDelete(WebPIDecoder* idec); - -// Copies and decodes the next available data. Returns VP8_STATUS_OK when -// the image is successfully decoded. Returns VP8_STATUS_SUSPENDED when more -// data is expected. Returns error in other cases. -WEBP_EXTERN(VP8StatusCode) WebPIAppend( - WebPIDecoder* idec, const uint8_t* data, size_t data_size); - -// A variant of the above function to be used when data buffer contains -// partial data from the beginning. In this case data buffer is not copied -// to the internal memory. -// Note that the value of the 'data' pointer can change between calls to -// WebPIUpdate, for instance when the data buffer is resized to fit larger data. -WEBP_EXTERN(VP8StatusCode) WebPIUpdate( - WebPIDecoder* idec, const uint8_t* data, size_t data_size); - -// Returns the RGB/A image decoded so far. Returns NULL if output params -// are not initialized yet. The RGB/A output type corresponds to the colorspace -// specified during call to WebPINewDecoder() or WebPINewRGB(). -// *last_y is the index of last decoded row in raster scan order. Some pointers -// (*last_y, *width etc.) can be NULL if corresponding information is not -// needed. -WEBP_EXTERN(uint8_t*) WebPIDecGetRGB( - const WebPIDecoder* idec, int* last_y, - int* width, int* height, int* stride); - -// Same as above function to get a YUVA image. Returns pointer to the luma -// plane or NULL in case of error. If there is no alpha information -// the alpha pointer '*a' will be returned NULL. -WEBP_EXTERN(uint8_t*) WebPIDecGetYUVA( - const WebPIDecoder* idec, int* last_y, - uint8_t** u, uint8_t** v, uint8_t** a, - int* width, int* height, int* stride, int* uv_stride, int* a_stride); - -// Deprecated alpha-less version of WebPIDecGetYUVA(): it will ignore the -// alpha information (if present). Kept for backward compatibility. -static WEBP_INLINE uint8_t* WebPIDecGetYUV( - const WebPIDecoder* idec, int* last_y, uint8_t** u, uint8_t** v, - int* width, int* height, int* stride, int* uv_stride) { - return WebPIDecGetYUVA(idec, last_y, u, v, NULL, width, height, - stride, uv_stride, NULL); -} - -// Generic call to retrieve information about the displayable area. -// If non NULL, the left/right/width/height pointers are filled with the visible -// rectangular area so far. -// Returns NULL in case the incremental decoder object is in an invalid state. -// Otherwise returns the pointer to the internal representation. This structure -// is read-only, tied to WebPIDecoder's lifespan and should not be modified. -WEBP_EXTERN(const WebPDecBuffer*) WebPIDecodedArea( - const WebPIDecoder* idec, int* left, int* top, int* width, int* height); - -//------------------------------------------------------------------------------ -// Advanced decoding parametrization -// -// Code sample for using the advanced decoding API -/* - // A) Init a configuration object - WebPDecoderConfig config; - CHECK(WebPInitDecoderConfig(&config)); - - // B) optional: retrieve the bitstream's features. - CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK); - - // C) Adjust 'config', if needed - config.no_fancy_upsampling = 1; - config.output.colorspace = MODE_BGRA; - // etc. - - // Note that you can also make config.output point to an externally - // supplied memory buffer, provided it's big enough to store the decoded - // picture. Otherwise, config.output will just be used to allocate memory - // and store the decoded picture. - - // D) Decode! - CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK); - - // E) Decoded image is now in config.output (and config.output.u.RGBA) - - // F) Reclaim memory allocated in config's object. It's safe to call - // this function even if the memory is external and wasn't allocated - // by WebPDecode(). - WebPFreeDecBuffer(&config.output); -*/ - -// Features gathered from the bitstream -struct WebPBitstreamFeatures { - int width; // Width in pixels, as read from the bitstream. - int height; // Height in pixels, as read from the bitstream. - int has_alpha; // True if the bitstream contains an alpha channel. - int has_animation; // True if the bitstream is an animation. - int format; // 0 = undefined (/mixed), 1 = lossy, 2 = lossless - - uint32_t pad[5]; // padding for later use -}; - -// Internal, version-checked, entry point -WEBP_EXTERN(VP8StatusCode) WebPGetFeaturesInternal( - const uint8_t*, size_t, WebPBitstreamFeatures*, int); - -// Retrieve features from the bitstream. The *features structure is filled -// with information gathered from the bitstream. -// Returns VP8_STATUS_OK when the features are successfully retrieved. Returns -// VP8_STATUS_NOT_ENOUGH_DATA when more data is needed to retrieve the -// features from headers. Returns error in other cases. -static WEBP_INLINE VP8StatusCode WebPGetFeatures( - const uint8_t* data, size_t data_size, - WebPBitstreamFeatures* features) { - return WebPGetFeaturesInternal(data, data_size, features, - WEBP_DECODER_ABI_VERSION); -} - -// Decoding options -struct WebPDecoderOptions { - int bypass_filtering; // if true, skip the in-loop filtering - int no_fancy_upsampling; // if true, use faster pointwise upsampler - int use_cropping; // if true, cropping is applied _first_ - int crop_left, crop_top; // top-left position for cropping. - // Will be snapped to even values. - int crop_width, crop_height; // dimension of the cropping area - int use_scaling; // if true, scaling is applied _afterward_ - int scaled_width, scaled_height; // final resolution - int use_threads; // if true, use multi-threaded decoding - int dithering_strength; // dithering strength (0=Off, 100=full) - int flip; // flip output vertically - int alpha_dithering_strength; // alpha dithering strength in [0..100] - - uint32_t pad[5]; // padding for later use -}; - -// Main object storing the configuration for advanced decoding. -struct WebPDecoderConfig { - WebPBitstreamFeatures input; // Immutable bitstream features (optional) - WebPDecBuffer output; // Output buffer (can point to external mem) - WebPDecoderOptions options; // Decoding options -}; - -// Internal, version-checked, entry point -WEBP_EXTERN(int) WebPInitDecoderConfigInternal(WebPDecoderConfig*, int); - -// Initialize the configuration as empty. This function must always be -// called first, unless WebPGetFeatures() is to be called. -// Returns false in case of mismatched version. -static WEBP_INLINE int WebPInitDecoderConfig(WebPDecoderConfig* config) { - return WebPInitDecoderConfigInternal(config, WEBP_DECODER_ABI_VERSION); -} - -// Instantiate a new incremental decoder object with the requested -// configuration. The bitstream can be passed using 'data' and 'data_size' -// parameter, in which case the features will be parsed and stored into -// config->input. Otherwise, 'data' can be NULL and no parsing will occur. -// Note that 'config' can be NULL too, in which case a default configuration -// is used. -// The return WebPIDecoder object must always be deleted calling WebPIDelete(). -// Returns NULL in case of error (and config->status will then reflect -// the error condition). -WEBP_EXTERN(WebPIDecoder*) WebPIDecode(const uint8_t* data, size_t data_size, - WebPDecoderConfig* config); - -// Non-incremental version. This version decodes the full data at once, taking -// 'config' into account. Returns decoding status (which should be VP8_STATUS_OK -// if the decoding was successful). -WEBP_EXTERN(VP8StatusCode) WebPDecode(const uint8_t* data, size_t data_size, - WebPDecoderConfig* config); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_WEBP_DECODE_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/webp/demux.h b/Example-Mac/Pods/libwebp/src/webp/demux.h deleted file mode 100644 index 454f6914..00000000 --- a/Example-Mac/Pods/libwebp/src/webp/demux.h +++ /dev/null @@ -1,358 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Demux API. -// Enables extraction of image and extended format data from WebP files. - -// Code Example: Demuxing WebP data to extract all the frames, ICC profile -// and EXIF/XMP metadata. -/* - WebPDemuxer* demux = WebPDemux(&webp_data); - - uint32_t width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH); - uint32_t height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT); - // ... (Get information about the features present in the WebP file). - uint32_t flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS); - - // ... (Iterate over all frames). - WebPIterator iter; - if (WebPDemuxGetFrame(demux, 1, &iter)) { - do { - // ... (Consume 'iter'; e.g. Decode 'iter.fragment' with WebPDecode(), - // ... and get other frame properties like width, height, offsets etc. - // ... see 'struct WebPIterator' below for more info). - } while (WebPDemuxNextFrame(&iter)); - WebPDemuxReleaseIterator(&iter); - } - - // ... (Extract metadata). - WebPChunkIterator chunk_iter; - if (flags & ICCP_FLAG) WebPDemuxGetChunk(demux, "ICCP", 1, &chunk_iter); - // ... (Consume the ICC profile in 'chunk_iter.chunk'). - WebPDemuxReleaseChunkIterator(&chunk_iter); - if (flags & EXIF_FLAG) WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter); - // ... (Consume the EXIF metadata in 'chunk_iter.chunk'). - WebPDemuxReleaseChunkIterator(&chunk_iter); - if (flags & XMP_FLAG) WebPDemuxGetChunk(demux, "XMP ", 1, &chunk_iter); - // ... (Consume the XMP metadata in 'chunk_iter.chunk'). - WebPDemuxReleaseChunkIterator(&chunk_iter); - WebPDemuxDelete(demux); -*/ - -#ifndef WEBP_WEBP_DEMUX_H_ -#define WEBP_WEBP_DEMUX_H_ - -#include "./decode.h" // for WEBP_CSP_MODE -#include "./mux_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define WEBP_DEMUX_ABI_VERSION 0x0107 // MAJOR(8b) + MINOR(8b) - -// Note: forward declaring enumerations is not allowed in (strict) C and C++, -// the types are left here for reference. -// typedef enum WebPDemuxState WebPDemuxState; -// typedef enum WebPFormatFeature WebPFormatFeature; -typedef struct WebPDemuxer WebPDemuxer; -typedef struct WebPIterator WebPIterator; -typedef struct WebPChunkIterator WebPChunkIterator; -typedef struct WebPAnimInfo WebPAnimInfo; -typedef struct WebPAnimDecoderOptions WebPAnimDecoderOptions; - -//------------------------------------------------------------------------------ - -// Returns the version number of the demux library, packed in hexadecimal using -// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507. -WEBP_EXTERN(int) WebPGetDemuxVersion(void); - -//------------------------------------------------------------------------------ -// Life of a Demux object - -typedef enum WebPDemuxState { - WEBP_DEMUX_PARSE_ERROR = -1, // An error occurred while parsing. - WEBP_DEMUX_PARSING_HEADER = 0, // Not enough data to parse full header. - WEBP_DEMUX_PARSED_HEADER = 1, // Header parsing complete, - // data may be available. - WEBP_DEMUX_DONE = 2 // Entire file has been parsed. -} WebPDemuxState; - -// Internal, version-checked, entry point -WEBP_EXTERN(WebPDemuxer*) WebPDemuxInternal( - const WebPData*, int, WebPDemuxState*, int); - -// Parses the full WebP file given by 'data'. For single images the WebP file -// header alone or the file header and the chunk header may be absent. -// Returns a WebPDemuxer object on successful parse, NULL otherwise. -static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) { - return WebPDemuxInternal(data, 0, NULL, WEBP_DEMUX_ABI_VERSION); -} - -// Parses the possibly incomplete WebP file given by 'data'. -// If 'state' is non-NULL it will be set to indicate the status of the demuxer. -// Returns NULL in case of error or if there isn't enough data to start parsing; -// and a WebPDemuxer object on successful parse. -// Note that WebPDemuxer keeps internal pointers to 'data' memory segment. -// If this data is volatile, the demuxer object should be deleted (by calling -// WebPDemuxDelete()) and WebPDemuxPartial() called again on the new data. -// This is usually an inexpensive operation. -static WEBP_INLINE WebPDemuxer* WebPDemuxPartial( - const WebPData* data, WebPDemuxState* state) { - return WebPDemuxInternal(data, 1, state, WEBP_DEMUX_ABI_VERSION); -} - -// Frees memory associated with 'dmux'. -WEBP_EXTERN(void) WebPDemuxDelete(WebPDemuxer* dmux); - -//------------------------------------------------------------------------------ -// Data/information extraction. - -typedef enum WebPFormatFeature { - WEBP_FF_FORMAT_FLAGS, // Extended format flags present in the 'VP8X' chunk. - WEBP_FF_CANVAS_WIDTH, - WEBP_FF_CANVAS_HEIGHT, - WEBP_FF_LOOP_COUNT, - WEBP_FF_BACKGROUND_COLOR, - WEBP_FF_FRAME_COUNT // Number of frames present in the demux object. - // In case of a partial demux, this is the number of - // frames seen so far, with the last frame possibly - // being partial. -} WebPFormatFeature; - -// Get the 'feature' value from the 'dmux'. -// NOTE: values are only valid if WebPDemux() was used or WebPDemuxPartial() -// returned a state > WEBP_DEMUX_PARSING_HEADER. -WEBP_EXTERN(uint32_t) WebPDemuxGetI( - const WebPDemuxer* dmux, WebPFormatFeature feature); - -//------------------------------------------------------------------------------ -// Frame iteration. - -struct WebPIterator { - int frame_num; - int num_frames; // equivalent to WEBP_FF_FRAME_COUNT. - int x_offset, y_offset; // offset relative to the canvas. - int width, height; // dimensions of this frame. - int duration; // display duration in milliseconds. - WebPMuxAnimDispose dispose_method; // dispose method for the frame. - int complete; // true if 'fragment' contains a full frame. partial images - // may still be decoded with the WebP incremental decoder. - WebPData fragment; // The frame given by 'frame_num'. Note for historical - // reasons this is called a fragment. - int has_alpha; // True if the frame contains transparency. - WebPMuxAnimBlend blend_method; // Blend operation for the frame. - - uint32_t pad[2]; // padding for later use. - void* private_; // for internal use only. -}; - -// Retrieves frame 'frame_number' from 'dmux'. -// 'iter->fragment' points to the frame on return from this function. -// Setting 'frame_number' equal to 0 will return the last frame of the image. -// Returns false if 'dmux' is NULL or frame 'frame_number' is not present. -// Call WebPDemuxReleaseIterator() when use of the iterator is complete. -// NOTE: 'dmux' must persist for the lifetime of 'iter'. -WEBP_EXTERN(int) WebPDemuxGetFrame( - const WebPDemuxer* dmux, int frame_number, WebPIterator* iter); - -// Sets 'iter->fragment' to point to the next ('iter->frame_num' + 1) or -// previous ('iter->frame_num' - 1) frame. These functions do not loop. -// Returns true on success, false otherwise. -WEBP_EXTERN(int) WebPDemuxNextFrame(WebPIterator* iter); -WEBP_EXTERN(int) WebPDemuxPrevFrame(WebPIterator* iter); - -// Releases any memory associated with 'iter'. -// Must be called before any subsequent calls to WebPDemuxGetChunk() on the same -// iter. Also, must be called before destroying the associated WebPDemuxer with -// WebPDemuxDelete(). -WEBP_EXTERN(void) WebPDemuxReleaseIterator(WebPIterator* iter); - -//------------------------------------------------------------------------------ -// Chunk iteration. - -struct WebPChunkIterator { - // The current and total number of chunks with the fourcc given to - // WebPDemuxGetChunk(). - int chunk_num; - int num_chunks; - WebPData chunk; // The payload of the chunk. - - uint32_t pad[6]; // padding for later use - void* private_; -}; - -// Retrieves the 'chunk_number' instance of the chunk with id 'fourcc' from -// 'dmux'. -// 'fourcc' is a character array containing the fourcc of the chunk to return, -// e.g., "ICCP", "XMP ", "EXIF", etc. -// Setting 'chunk_number' equal to 0 will return the last chunk in a set. -// Returns true if the chunk is found, false otherwise. Image related chunk -// payloads are accessed through WebPDemuxGetFrame() and related functions. -// Call WebPDemuxReleaseChunkIterator() when use of the iterator is complete. -// NOTE: 'dmux' must persist for the lifetime of the iterator. -WEBP_EXTERN(int) WebPDemuxGetChunk(const WebPDemuxer* dmux, - const char fourcc[4], int chunk_number, - WebPChunkIterator* iter); - -// Sets 'iter->chunk' to point to the next ('iter->chunk_num' + 1) or previous -// ('iter->chunk_num' - 1) chunk. These functions do not loop. -// Returns true on success, false otherwise. -WEBP_EXTERN(int) WebPDemuxNextChunk(WebPChunkIterator* iter); -WEBP_EXTERN(int) WebPDemuxPrevChunk(WebPChunkIterator* iter); - -// Releases any memory associated with 'iter'. -// Must be called before destroying the associated WebPDemuxer with -// WebPDemuxDelete(). -WEBP_EXTERN(void) WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter); - -//------------------------------------------------------------------------------ -// WebPAnimDecoder API -// -// This API allows decoding (possibly) animated WebP images. -// -// Code Example: -/* - WebPAnimDecoderOptions dec_options; - WebPAnimDecoderOptionsInit(&dec_options); - // Tune 'dec_options' as needed. - WebPAnimDecoder* dec = WebPAnimDecoderNew(webp_data, &dec_options); - WebPAnimInfo anim_info; - WebPAnimDecoderGetInfo(dec, &anim_info); - for (uint32_t i = 0; i < anim_info.loop_count; ++i) { - while (WebPAnimDecoderHasMoreFrames(dec)) { - uint8_t* buf; - int timestamp; - WebPAnimDecoderGetNext(dec, &buf, ×tamp); - // ... (Render 'buf' based on 'timestamp'). - // ... (Do NOT free 'buf', as it is owned by 'dec'). - } - WebPAnimDecoderReset(dec); - } - const WebPDemuxer* demuxer = WebPAnimDecoderGetDemuxer(dec); - // ... (Do something using 'demuxer'; e.g. get EXIF/XMP/ICC data). - WebPAnimDecoderDelete(dec); -*/ - -typedef struct WebPAnimDecoder WebPAnimDecoder; // Main opaque object. - -// Global options. -struct WebPAnimDecoderOptions { - // Output colorspace. Only the following modes are supported: - // MODE_RGBA, MODE_BGRA, MODE_rgbA and MODE_bgrA. - WEBP_CSP_MODE color_mode; - int use_threads; // If true, use multi-threaded decoding. - uint32_t padding[7]; // Padding for later use. -}; - -// Internal, version-checked, entry point. -WEBP_EXTERN(int) WebPAnimDecoderOptionsInitInternal( - WebPAnimDecoderOptions*, int); - -// Should always be called, to initialize a fresh WebPAnimDecoderOptions -// structure before modification. Returns false in case of version mismatch. -// WebPAnimDecoderOptionsInit() must have succeeded before using the -// 'dec_options' object. -static WEBP_INLINE int WebPAnimDecoderOptionsInit( - WebPAnimDecoderOptions* dec_options) { - return WebPAnimDecoderOptionsInitInternal(dec_options, - WEBP_DEMUX_ABI_VERSION); -} - -// Internal, version-checked, entry point. -WEBP_EXTERN(WebPAnimDecoder*) WebPAnimDecoderNewInternal( - const WebPData*, const WebPAnimDecoderOptions*, int); - -// Creates and initializes a WebPAnimDecoder object. -// Parameters: -// webp_data - (in) WebP bitstream. This should remain unchanged during the -// lifetime of the output WebPAnimDecoder object. -// dec_options - (in) decoding options. Can be passed NULL to choose -// reasonable defaults (in particular, color mode MODE_RGBA -// will be picked). -// Returns: -// A pointer to the newly created WebPAnimDecoder object, or NULL in case of -// parsing error, invalid option or memory error. -static WEBP_INLINE WebPAnimDecoder* WebPAnimDecoderNew( - const WebPData* webp_data, const WebPAnimDecoderOptions* dec_options) { - return WebPAnimDecoderNewInternal(webp_data, dec_options, - WEBP_DEMUX_ABI_VERSION); -} - -// Global information about the animation.. -struct WebPAnimInfo { - uint32_t canvas_width; - uint32_t canvas_height; - uint32_t loop_count; - uint32_t bgcolor; - uint32_t frame_count; - uint32_t pad[4]; // padding for later use -}; - -// Get global information about the animation. -// Parameters: -// dec - (in) decoder instance to get information from. -// info - (out) global information fetched from the animation. -// Returns: -// True on success. -WEBP_EXTERN(int) WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec, - WebPAnimInfo* info); - -// Fetch the next frame from 'dec' based on options supplied to -// WebPAnimDecoderNew(). This will be a fully reconstructed canvas of size -// 'canvas_width * 4 * canvas_height', and not just the frame sub-rectangle. The -// returned buffer 'buf' is valid only until the next call to -// WebPAnimDecoderGetNext(), WebPAnimDecoderReset() or WebPAnimDecoderDelete(). -// Parameters: -// dec - (in/out) decoder instance from which the next frame is to be fetched. -// buf - (out) decoded frame. -// timestamp - (out) timestamp of the frame in milliseconds. -// Returns: -// False if any of the arguments are NULL, or if there is a parsing or -// decoding error, or if there are no more frames. Otherwise, returns true. -WEBP_EXTERN(int) WebPAnimDecoderGetNext(WebPAnimDecoder* dec, - uint8_t** buf, int* timestamp); - -// Check if there are more frames left to decode. -// Parameters: -// dec - (in) decoder instance to be checked. -// Returns: -// True if 'dec' is not NULL and some frames are yet to be decoded. -// Otherwise, returns false. -WEBP_EXTERN(int) WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec); - -// Resets the WebPAnimDecoder object, so that next call to -// WebPAnimDecoderGetNext() will restart decoding from 1st frame. This would be -// helpful when all frames need to be decoded multiple times (e.g. -// info.loop_count times) without destroying and recreating the 'dec' object. -// Parameters: -// dec - (in/out) decoder instance to be reset -WEBP_EXTERN(void) WebPAnimDecoderReset(WebPAnimDecoder* dec); - -// Grab the internal demuxer object. -// Getting the demuxer object can be useful if one wants to use operations only -// available through demuxer; e.g. to get XMP/EXIF/ICC metadata. The returned -// demuxer object is owned by 'dec' and is valid only until the next call to -// WebPAnimDecoderDelete(). -// -// Parameters: -// dec - (in) decoder instance from which the demuxer object is to be fetched. -WEBP_EXTERN(const WebPDemuxer*) WebPAnimDecoderGetDemuxer( - const WebPAnimDecoder* dec); - -// Deletes the WebPAnimDecoder object. -// Parameters: -// dec - (in/out) decoder instance to be deleted -WEBP_EXTERN(void) WebPAnimDecoderDelete(WebPAnimDecoder* dec); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_WEBP_DEMUX_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/webp/encode.h b/Example-Mac/Pods/libwebp/src/webp/encode.h deleted file mode 100644 index c382ea76..00000000 --- a/Example-Mac/Pods/libwebp/src/webp/encode.h +++ /dev/null @@ -1,527 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// WebP encoder: main interface -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_WEBP_ENCODE_H_ -#define WEBP_WEBP_ENCODE_H_ - -#include "./types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define WEBP_ENCODER_ABI_VERSION 0x0209 // MAJOR(8b) + MINOR(8b) - -// Note: forward declaring enumerations is not allowed in (strict) C and C++, -// the types are left here for reference. -// typedef enum WebPImageHint WebPImageHint; -// typedef enum WebPEncCSP WebPEncCSP; -// typedef enum WebPPreset WebPPreset; -// typedef enum WebPEncodingError WebPEncodingError; -typedef struct WebPConfig WebPConfig; -typedef struct WebPPicture WebPPicture; // main structure for I/O -typedef struct WebPAuxStats WebPAuxStats; -typedef struct WebPMemoryWriter WebPMemoryWriter; - -// Return the encoder's version number, packed in hexadecimal using 8bits for -// each of major/minor/revision. E.g: v2.5.7 is 0x020507. -WEBP_EXTERN(int) WebPGetEncoderVersion(void); - -//------------------------------------------------------------------------------ -// One-stop-shop call! No questions asked: - -// Returns the size of the compressed data (pointed to by *output), or 0 if -// an error occurred. The compressed data must be released by the caller -// using the call 'WebPFree(*output)'. -// These functions compress using the lossy format, and the quality_factor -// can go from 0 (smaller output, lower quality) to 100 (best quality, -// larger output). -WEBP_EXTERN(size_t) WebPEncodeRGB(const uint8_t* rgb, - int width, int height, int stride, - float quality_factor, uint8_t** output); -WEBP_EXTERN(size_t) WebPEncodeBGR(const uint8_t* bgr, - int width, int height, int stride, - float quality_factor, uint8_t** output); -WEBP_EXTERN(size_t) WebPEncodeRGBA(const uint8_t* rgba, - int width, int height, int stride, - float quality_factor, uint8_t** output); -WEBP_EXTERN(size_t) WebPEncodeBGRA(const uint8_t* bgra, - int width, int height, int stride, - float quality_factor, uint8_t** output); - -// These functions are the equivalent of the above, but compressing in a -// lossless manner. Files are usually larger than lossy format, but will -// not suffer any compression loss. -WEBP_EXTERN(size_t) WebPEncodeLosslessRGB(const uint8_t* rgb, - int width, int height, int stride, - uint8_t** output); -WEBP_EXTERN(size_t) WebPEncodeLosslessBGR(const uint8_t* bgr, - int width, int height, int stride, - uint8_t** output); -WEBP_EXTERN(size_t) WebPEncodeLosslessRGBA(const uint8_t* rgba, - int width, int height, int stride, - uint8_t** output); -WEBP_EXTERN(size_t) WebPEncodeLosslessBGRA(const uint8_t* bgra, - int width, int height, int stride, - uint8_t** output); - -// Releases memory returned by the WebPEncode*() functions above. -WEBP_EXTERN(void) WebPFree(void* ptr); - -//------------------------------------------------------------------------------ -// Coding parameters - -// Image characteristics hint for the underlying encoder. -typedef enum WebPImageHint { - WEBP_HINT_DEFAULT = 0, // default preset. - WEBP_HINT_PICTURE, // digital picture, like portrait, inner shot - WEBP_HINT_PHOTO, // outdoor photograph, with natural lighting - WEBP_HINT_GRAPH, // Discrete tone image (graph, map-tile etc). - WEBP_HINT_LAST -} WebPImageHint; - -// Compression parameters. -struct WebPConfig { - int lossless; // Lossless encoding (0=lossy(default), 1=lossless). - float quality; // between 0 (smallest file) and 100 (biggest) - int method; // quality/speed trade-off (0=fast, 6=slower-better) - - WebPImageHint image_hint; // Hint for image type (lossless only for now). - - // Parameters related to lossy compression only: - int target_size; // if non-zero, set the desired target size in bytes. - // Takes precedence over the 'compression' parameter. - float target_PSNR; // if non-zero, specifies the minimal distortion to - // try to achieve. Takes precedence over target_size. - int segments; // maximum number of segments to use, in [1..4] - int sns_strength; // Spatial Noise Shaping. 0=off, 100=maximum. - int filter_strength; // range: [0 = off .. 100 = strongest] - int filter_sharpness; // range: [0 = off .. 7 = least sharp] - int filter_type; // filtering type: 0 = simple, 1 = strong (only used - // if filter_strength > 0 or autofilter > 0) - int autofilter; // Auto adjust filter's strength [0 = off, 1 = on] - int alpha_compression; // Algorithm for encoding the alpha plane (0 = none, - // 1 = compressed with WebP lossless). Default is 1. - int alpha_filtering; // Predictive filtering method for alpha plane. - // 0: none, 1: fast, 2: best. Default if 1. - int alpha_quality; // Between 0 (smallest size) and 100 (lossless). - // Default is 100. - int pass; // number of entropy-analysis passes (in [1..10]). - - int show_compressed; // if true, export the compressed picture back. - // In-loop filtering is not applied. - int preprocessing; // preprocessing filter: - // 0=none, 1=segment-smooth, 2=pseudo-random dithering - int partitions; // log2(number of token partitions) in [0..3]. Default - // is set to 0 for easier progressive decoding. - int partition_limit; // quality degradation allowed to fit the 512k limit - // on prediction modes coding (0: no degradation, - // 100: maximum possible degradation). - int emulate_jpeg_size; // If true, compression parameters will be remapped - // to better match the expected output size from - // JPEG compression. Generally, the output size will - // be similar but the degradation will be lower. - int thread_level; // If non-zero, try and use multi-threaded encoding. - int low_memory; // If set, reduce memory usage (but increase CPU use). - - int near_lossless; // Near lossless encoding [0 = off(default) .. 100]. - // This feature is experimental. - int exact; // if non-zero, preserve the exact RGB values under - // transparent area. Otherwise, discard this invisible - // RGB information for better compression. The default - // value is 0. - -#ifdef WEBP_EXPERIMENTAL_FEATURES - int delta_palettization; - uint32_t pad[2]; // padding for later use -#else - uint32_t pad[3]; // padding for later use -#endif // WEBP_EXPERIMENTAL_FEATURES -}; - -// Enumerate some predefined settings for WebPConfig, depending on the type -// of source picture. These presets are used when calling WebPConfigPreset(). -typedef enum WebPPreset { - WEBP_PRESET_DEFAULT = 0, // default preset. - WEBP_PRESET_PICTURE, // digital picture, like portrait, inner shot - WEBP_PRESET_PHOTO, // outdoor photograph, with natural lighting - WEBP_PRESET_DRAWING, // hand or line drawing, with high-contrast details - WEBP_PRESET_ICON, // small-sized colorful images - WEBP_PRESET_TEXT // text-like -} WebPPreset; - -// Internal, version-checked, entry point -WEBP_EXTERN(int) WebPConfigInitInternal(WebPConfig*, WebPPreset, float, int); - -// Should always be called, to initialize a fresh WebPConfig structure before -// modification. Returns false in case of version mismatch. WebPConfigInit() -// must have succeeded before using the 'config' object. -// Note that the default values are lossless=0 and quality=75. -static WEBP_INLINE int WebPConfigInit(WebPConfig* config) { - return WebPConfigInitInternal(config, WEBP_PRESET_DEFAULT, 75.f, - WEBP_ENCODER_ABI_VERSION); -} - -// This function will initialize the configuration according to a predefined -// set of parameters (referred to by 'preset') and a given quality factor. -// This function can be called as a replacement to WebPConfigInit(). Will -// return false in case of error. -static WEBP_INLINE int WebPConfigPreset(WebPConfig* config, - WebPPreset preset, float quality) { - return WebPConfigInitInternal(config, preset, quality, - WEBP_ENCODER_ABI_VERSION); -} - -// Activate the lossless compression mode with the desired efficiency level -// between 0 (fastest, lowest compression) and 9 (slower, best compression). -// A good default level is '6', providing a fair tradeoff between compression -// speed and final compressed size. -// This function will overwrite several fields from config: 'method', 'quality' -// and 'lossless'. Returns false in case of parameter error. -WEBP_EXTERN(int) WebPConfigLosslessPreset(WebPConfig* config, int level); - -// Returns true if 'config' is non-NULL and all configuration parameters are -// within their valid ranges. -WEBP_EXTERN(int) WebPValidateConfig(const WebPConfig* config); - -//------------------------------------------------------------------------------ -// Input / Output -// Structure for storing auxiliary statistics (mostly for lossy encoding). - -struct WebPAuxStats { - int coded_size; // final size - - float PSNR[5]; // peak-signal-to-noise ratio for Y/U/V/All/Alpha - int block_count[3]; // number of intra4/intra16/skipped macroblocks - int header_bytes[2]; // approximate number of bytes spent for header - // and mode-partition #0 - int residual_bytes[3][4]; // approximate number of bytes spent for - // DC/AC/uv coefficients for each (0..3) segments. - int segment_size[4]; // number of macroblocks in each segments - int segment_quant[4]; // quantizer values for each segments - int segment_level[4]; // filtering strength for each segments [0..63] - - int alpha_data_size; // size of the transparency data - int layer_data_size; // size of the enhancement layer data - - // lossless encoder statistics - uint32_t lossless_features; // bit0:predictor bit1:cross-color transform - // bit2:subtract-green bit3:color indexing - int histogram_bits; // number of precision bits of histogram - int transform_bits; // precision bits for transform - int cache_bits; // number of bits for color cache lookup - int palette_size; // number of color in palette, if used - int lossless_size; // final lossless size - int lossless_hdr_size; // lossless header (transform, huffman etc) size - int lossless_data_size; // lossless image data size - - uint32_t pad[2]; // padding for later use -}; - -// Signature for output function. Should return true if writing was successful. -// data/data_size is the segment of data to write, and 'picture' is for -// reference (and so one can make use of picture->custom_ptr). -typedef int (*WebPWriterFunction)(const uint8_t* data, size_t data_size, - const WebPPicture* picture); - -// WebPMemoryWrite: a special WebPWriterFunction that writes to memory using -// the following WebPMemoryWriter object (to be set as a custom_ptr). -struct WebPMemoryWriter { - uint8_t* mem; // final buffer (of size 'max_size', larger than 'size'). - size_t size; // final size - size_t max_size; // total capacity - uint32_t pad[1]; // padding for later use -}; - -// The following must be called first before any use. -WEBP_EXTERN(void) WebPMemoryWriterInit(WebPMemoryWriter* writer); - -// The following must be called to deallocate writer->mem memory. The 'writer' -// object itself is not deallocated. -WEBP_EXTERN(void) WebPMemoryWriterClear(WebPMemoryWriter* writer); -// The custom writer to be used with WebPMemoryWriter as custom_ptr. Upon -// completion, writer.mem and writer.size will hold the coded data. -// writer.mem must be freed by calling WebPMemoryWriterClear. -WEBP_EXTERN(int) WebPMemoryWrite(const uint8_t* data, size_t data_size, - const WebPPicture* picture); - -// Progress hook, called from time to time to report progress. It can return -// false to request an abort of the encoding process, or true otherwise if -// everything is OK. -typedef int (*WebPProgressHook)(int percent, const WebPPicture* picture); - -// Color spaces. -typedef enum WebPEncCSP { - // chroma sampling - WEBP_YUV420 = 0, // 4:2:0 - WEBP_YUV420A = 4, // alpha channel variant - WEBP_CSP_UV_MASK = 3, // bit-mask to get the UV sampling factors - WEBP_CSP_ALPHA_BIT = 4 // bit that is set if alpha is present -} WebPEncCSP; - -// Encoding error conditions. -typedef enum WebPEncodingError { - VP8_ENC_OK = 0, - VP8_ENC_ERROR_OUT_OF_MEMORY, // memory error allocating objects - VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY, // memory error while flushing bits - VP8_ENC_ERROR_NULL_PARAMETER, // a pointer parameter is NULL - VP8_ENC_ERROR_INVALID_CONFIGURATION, // configuration is invalid - VP8_ENC_ERROR_BAD_DIMENSION, // picture has invalid width/height - VP8_ENC_ERROR_PARTITION0_OVERFLOW, // partition is bigger than 512k - VP8_ENC_ERROR_PARTITION_OVERFLOW, // partition is bigger than 16M - VP8_ENC_ERROR_BAD_WRITE, // error while flushing bytes - VP8_ENC_ERROR_FILE_TOO_BIG, // file is bigger than 4G - VP8_ENC_ERROR_USER_ABORT, // abort request by user - VP8_ENC_ERROR_LAST // list terminator. always last. -} WebPEncodingError; - -// maximum width/height allowed (inclusive), in pixels -#define WEBP_MAX_DIMENSION 16383 - -// Main exchange structure (input samples, output bytes, statistics) -struct WebPPicture { - // INPUT - ////////////// - // Main flag for encoder selecting between ARGB or YUV input. - // It is recommended to use ARGB input (*argb, argb_stride) for lossless - // compression, and YUV input (*y, *u, *v, etc.) for lossy compression - // since these are the respective native colorspace for these formats. - int use_argb; - - // YUV input (mostly used for input to lossy compression) - WebPEncCSP colorspace; // colorspace: should be YUV420 for now (=Y'CbCr). - int width, height; // dimensions (less or equal to WEBP_MAX_DIMENSION) - uint8_t *y, *u, *v; // pointers to luma/chroma planes. - int y_stride, uv_stride; // luma/chroma strides. - uint8_t* a; // pointer to the alpha plane - int a_stride; // stride of the alpha plane - uint32_t pad1[2]; // padding for later use - - // ARGB input (mostly used for input to lossless compression) - uint32_t* argb; // Pointer to argb (32 bit) plane. - int argb_stride; // This is stride in pixels units, not bytes. - uint32_t pad2[3]; // padding for later use - - // OUTPUT - /////////////// - // Byte-emission hook, to store compressed bytes as they are ready. - WebPWriterFunction writer; // can be NULL - void* custom_ptr; // can be used by the writer. - - // map for extra information (only for lossy compression mode) - int extra_info_type; // 1: intra type, 2: segment, 3: quant - // 4: intra-16 prediction mode, - // 5: chroma prediction mode, - // 6: bit cost, 7: distortion - uint8_t* extra_info; // if not NULL, points to an array of size - // ((width + 15) / 16) * ((height + 15) / 16) that - // will be filled with a macroblock map, depending - // on extra_info_type. - - // STATS AND REPORTS - /////////////////////////// - // Pointer to side statistics (updated only if not NULL) - WebPAuxStats* stats; - - // Error code for the latest error encountered during encoding - WebPEncodingError error_code; - - // If not NULL, report progress during encoding. - WebPProgressHook progress_hook; - - void* user_data; // this field is free to be set to any value and - // used during callbacks (like progress-report e.g.). - - uint32_t pad3[3]; // padding for later use - - // Unused for now - uint8_t *pad4, *pad5; - uint32_t pad6[8]; // padding for later use - - // PRIVATE FIELDS - //////////////////// - void* memory_; // row chunk of memory for yuva planes - void* memory_argb_; // and for argb too. - void* pad7[2]; // padding for later use -}; - -// Internal, version-checked, entry point -WEBP_EXTERN(int) WebPPictureInitInternal(WebPPicture*, int); - -// Should always be called, to initialize the structure. Returns false in case -// of version mismatch. WebPPictureInit() must have succeeded before using the -// 'picture' object. -// Note that, by default, use_argb is false and colorspace is WEBP_YUV420. -static WEBP_INLINE int WebPPictureInit(WebPPicture* picture) { - return WebPPictureInitInternal(picture, WEBP_ENCODER_ABI_VERSION); -} - -//------------------------------------------------------------------------------ -// WebPPicture utils - -// Convenience allocation / deallocation based on picture->width/height: -// Allocate y/u/v buffers as per colorspace/width/height specification. -// Note! This function will free the previous buffer if needed. -// Returns false in case of memory error. -WEBP_EXTERN(int) WebPPictureAlloc(WebPPicture* picture); - -// Release the memory allocated by WebPPictureAlloc() or WebPPictureImport*(). -// Note that this function does _not_ free the memory used by the 'picture' -// object itself. -// Besides memory (which is reclaimed) all other fields of 'picture' are -// preserved. -WEBP_EXTERN(void) WebPPictureFree(WebPPicture* picture); - -// Copy the pixels of *src into *dst, using WebPPictureAlloc. Upon return, *dst -// will fully own the copied pixels (this is not a view). The 'dst' picture need -// not be initialized as its content is overwritten. -// Returns false in case of memory allocation error. -WEBP_EXTERN(int) WebPPictureCopy(const WebPPicture* src, WebPPicture* dst); - -// Compute PSNR, SSIM or LSIM distortion metric between two pictures. Results -// are in dB, stored in result[] in the Y/U/V/Alpha/All or B/G/R/A/All order. -// Returns false in case of error (src and ref don't have same dimension, ...) -// Warning: this function is rather CPU-intensive. -WEBP_EXTERN(int) WebPPictureDistortion( - const WebPPicture* src, const WebPPicture* ref, - int metric_type, // 0 = PSNR, 1 = SSIM, 2 = LSIM - float result[5]); - -// self-crops a picture to the rectangle defined by top/left/width/height. -// Returns false in case of memory allocation error, or if the rectangle is -// outside of the source picture. -// The rectangle for the view is defined by the top-left corner pixel -// coordinates (left, top) as well as its width and height. This rectangle -// must be fully be comprised inside the 'src' source picture. If the source -// picture uses the YUV420 colorspace, the top and left coordinates will be -// snapped to even values. -WEBP_EXTERN(int) WebPPictureCrop(WebPPicture* picture, - int left, int top, int width, int height); - -// Extracts a view from 'src' picture into 'dst'. The rectangle for the view -// is defined by the top-left corner pixel coordinates (left, top) as well -// as its width and height. This rectangle must be fully be comprised inside -// the 'src' source picture. If the source picture uses the YUV420 colorspace, -// the top and left coordinates will be snapped to even values. -// Picture 'src' must out-live 'dst' picture. Self-extraction of view is allowed -// ('src' equal to 'dst') as a mean of fast-cropping (but note that doing so, -// the original dimension will be lost). Picture 'dst' need not be initialized -// with WebPPictureInit() if it is different from 'src', since its content will -// be overwritten. -// Returns false in case of memory allocation error or invalid parameters. -WEBP_EXTERN(int) WebPPictureView(const WebPPicture* src, - int left, int top, int width, int height, - WebPPicture* dst); - -// Returns true if the 'picture' is actually a view and therefore does -// not own the memory for pixels. -WEBP_EXTERN(int) WebPPictureIsView(const WebPPicture* picture); - -// Rescale a picture to new dimension width x height. -// If either 'width' or 'height' (but not both) is 0 the corresponding -// dimension will be calculated preserving the aspect ratio. -// No gamma correction is applied. -// Returns false in case of error (invalid parameter or insufficient memory). -WEBP_EXTERN(int) WebPPictureRescale(WebPPicture* pic, int width, int height); - -// Colorspace conversion function to import RGB samples. -// Previous buffer will be free'd, if any. -// *rgb buffer should have a size of at least height * rgb_stride. -// Returns false in case of memory error. -WEBP_EXTERN(int) WebPPictureImportRGB( - WebPPicture* picture, const uint8_t* rgb, int rgb_stride); -// Same, but for RGBA buffer. -WEBP_EXTERN(int) WebPPictureImportRGBA( - WebPPicture* picture, const uint8_t* rgba, int rgba_stride); -// Same, but for RGBA buffer. Imports the RGB direct from the 32-bit format -// input buffer ignoring the alpha channel. Avoids needing to copy the data -// to a temporary 24-bit RGB buffer to import the RGB only. -WEBP_EXTERN(int) WebPPictureImportRGBX( - WebPPicture* picture, const uint8_t* rgbx, int rgbx_stride); - -// Variants of the above, but taking BGR(A|X) input. -WEBP_EXTERN(int) WebPPictureImportBGR( - WebPPicture* picture, const uint8_t* bgr, int bgr_stride); -WEBP_EXTERN(int) WebPPictureImportBGRA( - WebPPicture* picture, const uint8_t* bgra, int bgra_stride); -WEBP_EXTERN(int) WebPPictureImportBGRX( - WebPPicture* picture, const uint8_t* bgrx, int bgrx_stride); - -// Converts picture->argb data to the YUV420A format. The 'colorspace' -// parameter is deprecated and should be equal to WEBP_YUV420. -// Upon return, picture->use_argb is set to false. The presence of real -// non-opaque transparent values is detected, and 'colorspace' will be -// adjusted accordingly. Note that this method is lossy. -// Returns false in case of error. -WEBP_EXTERN(int) WebPPictureARGBToYUVA(WebPPicture* picture, - WebPEncCSP /*colorspace = WEBP_YUV420*/); - -// Same as WebPPictureARGBToYUVA(), but the conversion is done using -// pseudo-random dithering with a strength 'dithering' between -// 0.0 (no dithering) and 1.0 (maximum dithering). This is useful -// for photographic picture. -WEBP_EXTERN(int) WebPPictureARGBToYUVADithered( - WebPPicture* picture, WebPEncCSP colorspace, float dithering); - -// Performs 'smart' RGBA->YUVA420 downsampling and colorspace conversion. -// Downsampling is handled with extra care in case of color clipping. This -// method is roughly 2x slower than WebPPictureARGBToYUVA() but produces better -// YUV representation. -// Returns false in case of error. -WEBP_EXTERN(int) WebPPictureSmartARGBToYUVA(WebPPicture* picture); - -// Converts picture->yuv to picture->argb and sets picture->use_argb to true. -// The input format must be YUV_420 or YUV_420A. -// Note that the use of this method is discouraged if one has access to the -// raw ARGB samples, since using YUV420 is comparatively lossy. Also, the -// conversion from YUV420 to ARGB incurs a small loss too. -// Returns false in case of error. -WEBP_EXTERN(int) WebPPictureYUVAToARGB(WebPPicture* picture); - -// Helper function: given a width x height plane of RGBA or YUV(A) samples -// clean-up the YUV or RGB samples under fully transparent area, to help -// compressibility (no guarantee, though). -WEBP_EXTERN(void) WebPCleanupTransparentArea(WebPPicture* picture); - -// Scan the picture 'picture' for the presence of non fully opaque alpha values. -// Returns true in such case. Otherwise returns false (indicating that the -// alpha plane can be ignored altogether e.g.). -WEBP_EXTERN(int) WebPPictureHasTransparency(const WebPPicture* picture); - -// Remove the transparency information (if present) by blending the color with -// the background color 'background_rgb' (specified as 24bit RGB triplet). -// After this call, all alpha values are reset to 0xff. -WEBP_EXTERN(void) WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb); - -//------------------------------------------------------------------------------ -// Main call - -// Main encoding call, after config and picture have been initialized. -// 'picture' must be less than 16384x16384 in dimension (cf WEBP_MAX_DIMENSION), -// and the 'config' object must be a valid one. -// Returns false in case of error, true otherwise. -// In case of error, picture->error_code is updated accordingly. -// 'picture' can hold the source samples in both YUV(A) or ARGB input, depending -// on the value of 'picture->use_argb'. It is highly recommended to use -// the former for lossy encoding, and the latter for lossless encoding -// (when config.lossless is true). Automatic conversion from one format to -// another is provided but they both incur some loss. -WEBP_EXTERN(int) WebPEncode(const WebPConfig* config, WebPPicture* picture); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_WEBP_ENCODE_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/webp/extras.h b/Example-Mac/Pods/libwebp/src/webp/extras.h deleted file mode 100644 index 1c24be2e..00000000 --- a/Example-Mac/Pods/libwebp/src/webp/extras.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// - -#ifndef WEBP_WEBP_EXTRAS_H_ -#define WEBP_WEBP_EXTRAS_H_ - -#include "./types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "./encode.h" - -#define WEBP_EXTRAS_ABI_VERSION 0x0000 // MAJOR(8b) + MINOR(8b) - -//------------------------------------------------------------------------------ - -// Returns the version number of the extras library, packed in hexadecimal using -// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507. -WEBP_EXTERN(int) WebPGetExtrasVersion(void); - -//------------------------------------------------------------------------------ -// Ad-hoc colorspace importers. - -// Import luma sample (gray scale image) into 'picture'. The 'picture' -// width and height must be set prior to calling this function. -WEBP_EXTERN(int) WebPImportGray(const uint8_t* gray, WebPPicture* picture); - -// Import rgb sample in RGB565 packed format into 'picture'. The 'picture' -// width and height must be set prior to calling this function. -WEBP_EXTERN(int) WebPImportRGB565(const uint8_t* rgb565, WebPPicture* pic); - -// Import rgb sample in RGB4444 packed format into 'picture'. The 'picture' -// width and height must be set prior to calling this function. -WEBP_EXTERN(int) WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_WEBP_EXTRAS_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/webp/format_constants.h b/Example-Mac/Pods/libwebp/src/webp/format_constants.h deleted file mode 100644 index b6e78a64..00000000 --- a/Example-Mac/Pods/libwebp/src/webp/format_constants.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Internal header for constants related to WebP file format. -// -// Author: Urvang (urvang@google.com) - -#ifndef WEBP_WEBP_FORMAT_CONSTANTS_H_ -#define WEBP_WEBP_FORMAT_CONSTANTS_H_ - -// Create fourcc of the chunk from the chunk tag characters. -#define MKFOURCC(a, b, c, d) ((a) | (b) << 8 | (c) << 16 | (uint32_t)(d) << 24) - -// VP8 related constants. -#define VP8_SIGNATURE 0x9d012a // Signature in VP8 data. -#define VP8_MAX_PARTITION0_SIZE (1 << 19) // max size of mode partition -#define VP8_MAX_PARTITION_SIZE (1 << 24) // max size for token partition -#define VP8_FRAME_HEADER_SIZE 10 // Size of the frame header within VP8 data. - -// VP8L related constants. -#define VP8L_SIGNATURE_SIZE 1 // VP8L signature size. -#define VP8L_MAGIC_BYTE 0x2f // VP8L signature byte. -#define VP8L_IMAGE_SIZE_BITS 14 // Number of bits used to store - // width and height. -#define VP8L_VERSION_BITS 3 // 3 bits reserved for version. -#define VP8L_VERSION 0 // version 0 -#define VP8L_FRAME_HEADER_SIZE 5 // Size of the VP8L frame header. - -#define MAX_PALETTE_SIZE 256 -#define MAX_CACHE_BITS 11 -#define HUFFMAN_CODES_PER_META_CODE 5 -#define ARGB_BLACK 0xff000000 - -#define DEFAULT_CODE_LENGTH 8 -#define MAX_ALLOWED_CODE_LENGTH 15 - -#define NUM_LITERAL_CODES 256 -#define NUM_LENGTH_CODES 24 -#define NUM_DISTANCE_CODES 40 -#define CODE_LENGTH_CODES 19 - -#define MIN_HUFFMAN_BITS 2 // min number of Huffman bits -#define MAX_HUFFMAN_BITS 9 // max number of Huffman bits - -#define TRANSFORM_PRESENT 1 // The bit to be written when next data - // to be read is a transform. -#define NUM_TRANSFORMS 4 // Maximum number of allowed transform - // in a bitstream. -typedef enum { - PREDICTOR_TRANSFORM = 0, - CROSS_COLOR_TRANSFORM = 1, - SUBTRACT_GREEN = 2, - COLOR_INDEXING_TRANSFORM = 3 -} VP8LImageTransformType; - -// Alpha related constants. -#define ALPHA_HEADER_LEN 1 -#define ALPHA_NO_COMPRESSION 0 -#define ALPHA_LOSSLESS_COMPRESSION 1 -#define ALPHA_PREPROCESSED_LEVELS 1 - -// Mux related constants. -#define TAG_SIZE 4 // Size of a chunk tag (e.g. "VP8L"). -#define CHUNK_SIZE_BYTES 4 // Size needed to store chunk's size. -#define CHUNK_HEADER_SIZE 8 // Size of a chunk header. -#define RIFF_HEADER_SIZE 12 // Size of the RIFF header ("RIFFnnnnWEBP"). -#define ANMF_CHUNK_SIZE 16 // Size of an ANMF chunk. -#define ANIM_CHUNK_SIZE 6 // Size of an ANIM chunk. -#define FRGM_CHUNK_SIZE 6 // Size of a FRGM chunk. -#define VP8X_CHUNK_SIZE 10 // Size of a VP8X chunk. - -#define MAX_CANVAS_SIZE (1 << 24) // 24-bit max for VP8X width/height. -#define MAX_IMAGE_AREA (1ULL << 32) // 32-bit max for width x height. -#define MAX_LOOP_COUNT (1 << 16) // maximum value for loop-count -#define MAX_DURATION (1 << 24) // maximum duration -#define MAX_POSITION_OFFSET (1 << 24) // maximum frame/fragment x/y offset - -// Maximum chunk payload is such that adding the header and padding won't -// overflow a uint32_t. -#define MAX_CHUNK_PAYLOAD (~0U - CHUNK_HEADER_SIZE - 1) - -#endif /* WEBP_WEBP_FORMAT_CONSTANTS_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/webp/mux.h b/Example-Mac/Pods/libwebp/src/webp/mux.h deleted file mode 100644 index b72658c7..00000000 --- a/Example-Mac/Pods/libwebp/src/webp/mux.h +++ /dev/null @@ -1,530 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// RIFF container manipulation and encoding for WebP images. -// -// Authors: Urvang (urvang@google.com) -// Vikas (vikasa@google.com) - -#ifndef WEBP_WEBP_MUX_H_ -#define WEBP_WEBP_MUX_H_ - -#include "./mux_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define WEBP_MUX_ABI_VERSION 0x0106 // MAJOR(8b) + MINOR(8b) - -//------------------------------------------------------------------------------ -// Mux API -// -// This API allows manipulation of WebP container images containing features -// like color profile, metadata, animation and fragmented images. -// -// Code Example#1: Create a WebPMux object with image data, color profile and -// XMP metadata. -/* - int copy_data = 0; - WebPMux* mux = WebPMuxNew(); - // ... (Prepare image data). - WebPMuxSetImage(mux, &image, copy_data); - // ... (Prepare ICCP color profile data). - WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data); - // ... (Prepare XMP metadata). - WebPMuxSetChunk(mux, "XMP ", &xmp, copy_data); - // Get data from mux in WebP RIFF format. - WebPMuxAssemble(mux, &output_data); - WebPMuxDelete(mux); - // ... (Consume output_data; e.g. write output_data.bytes to file). - WebPDataClear(&output_data); -*/ - -// Code Example#2: Get image and color profile data from a WebP file. -/* - int copy_data = 0; - // ... (Read data from file). - WebPMux* mux = WebPMuxCreate(&data, copy_data); - WebPMuxGetFrame(mux, 1, &image); - // ... (Consume image; e.g. call WebPDecode() to decode the data). - WebPMuxGetChunk(mux, "ICCP", &icc_profile); - // ... (Consume icc_data). - WebPMuxDelete(mux); - free(data); -*/ - -// Note: forward declaring enumerations is not allowed in (strict) C and C++, -// the types are left here for reference. -// typedef enum WebPMuxError WebPMuxError; -// typedef enum WebPChunkId WebPChunkId; -typedef struct WebPMux WebPMux; // main opaque object. -typedef struct WebPMuxFrameInfo WebPMuxFrameInfo; -typedef struct WebPMuxAnimParams WebPMuxAnimParams; -typedef struct WebPAnimEncoderOptions WebPAnimEncoderOptions; - -// Error codes -typedef enum WebPMuxError { - WEBP_MUX_OK = 1, - WEBP_MUX_NOT_FOUND = 0, - WEBP_MUX_INVALID_ARGUMENT = -1, - WEBP_MUX_BAD_DATA = -2, - WEBP_MUX_MEMORY_ERROR = -3, - WEBP_MUX_NOT_ENOUGH_DATA = -4 -} WebPMuxError; - -// IDs for different types of chunks. -typedef enum WebPChunkId { - WEBP_CHUNK_VP8X, // VP8X - WEBP_CHUNK_ICCP, // ICCP - WEBP_CHUNK_ANIM, // ANIM - WEBP_CHUNK_ANMF, // ANMF - WEBP_CHUNK_FRGM, // FRGM - WEBP_CHUNK_ALPHA, // ALPH - WEBP_CHUNK_IMAGE, // VP8/VP8L - WEBP_CHUNK_EXIF, // EXIF - WEBP_CHUNK_XMP, // XMP - WEBP_CHUNK_UNKNOWN, // Other chunks. - WEBP_CHUNK_NIL -} WebPChunkId; - -//------------------------------------------------------------------------------ - -// Returns the version number of the mux library, packed in hexadecimal using -// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507. -WEBP_EXTERN(int) WebPGetMuxVersion(void); - -//------------------------------------------------------------------------------ -// Life of a Mux object - -// Internal, version-checked, entry point -WEBP_EXTERN(WebPMux*) WebPNewInternal(int); - -// Creates an empty mux object. -// Returns: -// A pointer to the newly created empty mux object. -// Or NULL in case of memory error. -static WEBP_INLINE WebPMux* WebPMuxNew(void) { - return WebPNewInternal(WEBP_MUX_ABI_VERSION); -} - -// Deletes the mux object. -// Parameters: -// mux - (in/out) object to be deleted -WEBP_EXTERN(void) WebPMuxDelete(WebPMux* mux); - -//------------------------------------------------------------------------------ -// Mux creation. - -// Internal, version-checked, entry point -WEBP_EXTERN(WebPMux*) WebPMuxCreateInternal(const WebPData*, int, int); - -// Creates a mux object from raw data given in WebP RIFF format. -// Parameters: -// bitstream - (in) the bitstream data in WebP RIFF format -// copy_data - (in) value 1 indicates given data WILL be copied to the mux -// object and value 0 indicates data will NOT be copied. -// Returns: -// A pointer to the mux object created from given data - on success. -// NULL - In case of invalid data or memory error. -static WEBP_INLINE WebPMux* WebPMuxCreate(const WebPData* bitstream, - int copy_data) { - return WebPMuxCreateInternal(bitstream, copy_data, WEBP_MUX_ABI_VERSION); -} - -//------------------------------------------------------------------------------ -// Non-image chunks. - -// Note: Only non-image related chunks should be managed through chunk APIs. -// (Image related chunks are: "ANMF", "FRGM", "VP8 ", "VP8L" and "ALPH"). -// To add, get and delete images, use WebPMuxSetImage(), WebPMuxPushFrame(), -// WebPMuxGetFrame() and WebPMuxDeleteFrame(). - -// Adds a chunk with id 'fourcc' and data 'chunk_data' in the mux object. -// Any existing chunk(s) with the same id will be removed. -// Parameters: -// mux - (in/out) object to which the chunk is to be added -// fourcc - (in) a character array containing the fourcc of the given chunk; -// e.g., "ICCP", "XMP ", "EXIF" etc. -// chunk_data - (in) the chunk data to be added -// copy_data - (in) value 1 indicates given data WILL be copied to the mux -// object and value 0 indicates data will NOT be copied. -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux, fourcc or chunk_data is NULL -// or if fourcc corresponds to an image chunk. -// WEBP_MUX_MEMORY_ERROR - on memory allocation error. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxSetChunk( - WebPMux* mux, const char fourcc[4], const WebPData* chunk_data, - int copy_data); - -// Gets a reference to the data of the chunk with id 'fourcc' in the mux object. -// The caller should NOT free the returned data. -// Parameters: -// mux - (in) object from which the chunk data is to be fetched -// fourcc - (in) a character array containing the fourcc of the chunk; -// e.g., "ICCP", "XMP ", "EXIF" etc. -// chunk_data - (out) returned chunk data -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux, fourcc or chunk_data is NULL -// or if fourcc corresponds to an image chunk. -// WEBP_MUX_NOT_FOUND - If mux does not contain a chunk with the given id. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxGetChunk( - const WebPMux* mux, const char fourcc[4], WebPData* chunk_data); - -// Deletes the chunk with the given 'fourcc' from the mux object. -// Parameters: -// mux - (in/out) object from which the chunk is to be deleted -// fourcc - (in) a character array containing the fourcc of the chunk; -// e.g., "ICCP", "XMP ", "EXIF" etc. -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux or fourcc is NULL -// or if fourcc corresponds to an image chunk. -// WEBP_MUX_NOT_FOUND - If mux does not contain a chunk with the given fourcc. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxDeleteChunk( - WebPMux* mux, const char fourcc[4]); - -//------------------------------------------------------------------------------ -// Images. - -// Encapsulates data about a single frame/fragment. -struct WebPMuxFrameInfo { - WebPData bitstream; // image data: can be a raw VP8/VP8L bitstream - // or a single-image WebP file. - int x_offset; // x-offset of the frame. - int y_offset; // y-offset of the frame. - int duration; // duration of the frame (in milliseconds). - - WebPChunkId id; // frame type: should be one of WEBP_CHUNK_ANMF, - // WEBP_CHUNK_FRGM or WEBP_CHUNK_IMAGE - WebPMuxAnimDispose dispose_method; // Disposal method for the frame. - WebPMuxAnimBlend blend_method; // Blend operation for the frame. - uint32_t pad[1]; // padding for later use -}; - -// Sets the (non-animated and non-fragmented) image in the mux object. -// Note: Any existing images (including frames/fragments) will be removed. -// Parameters: -// mux - (in/out) object in which the image is to be set -// bitstream - (in) can be a raw VP8/VP8L bitstream or a single-image -// WebP file (non-animated and non-fragmented) -// copy_data - (in) value 1 indicates given data WILL be copied to the mux -// object and value 0 indicates data will NOT be copied. -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL or bitstream is NULL. -// WEBP_MUX_MEMORY_ERROR - on memory allocation error. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxSetImage( - WebPMux* mux, const WebPData* bitstream, int copy_data); - -// Adds a frame at the end of the mux object. -// Notes: (1) frame.id should be one of WEBP_CHUNK_ANMF or WEBP_CHUNK_FRGM -// (2) For setting a non-animated non-fragmented image, use -// WebPMuxSetImage() instead. -// (3) Type of frame being pushed must be same as the frames in mux. -// (4) As WebP only supports even offsets, any odd offset will be snapped -// to an even location using: offset &= ~1 -// Parameters: -// mux - (in/out) object to which the frame is to be added -// frame - (in) frame data. -// copy_data - (in) value 1 indicates given data WILL be copied to the mux -// object and value 0 indicates data will NOT be copied. -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL -// or if content of 'frame' is invalid. -// WEBP_MUX_MEMORY_ERROR - on memory allocation error. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxPushFrame( - WebPMux* mux, const WebPMuxFrameInfo* frame, int copy_data); - -// Gets the nth frame from the mux object. -// The content of 'frame->bitstream' is allocated using malloc(), and NOT -// owned by the 'mux' object. It MUST be deallocated by the caller by calling -// WebPDataClear(). -// nth=0 has a special meaning - last position. -// Parameters: -// mux - (in) object from which the info is to be fetched -// nth - (in) index of the frame in the mux object -// frame - (out) data of the returned frame -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL. -// WEBP_MUX_NOT_FOUND - if there are less than nth frames in the mux object. -// WEBP_MUX_BAD_DATA - if nth frame chunk in mux is invalid. -// WEBP_MUX_MEMORY_ERROR - on memory allocation error. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxGetFrame( - const WebPMux* mux, uint32_t nth, WebPMuxFrameInfo* frame); - -// Deletes a frame from the mux object. -// nth=0 has a special meaning - last position. -// Parameters: -// mux - (in/out) object from which a frame is to be deleted -// nth - (in) The position from which the frame is to be deleted -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL. -// WEBP_MUX_NOT_FOUND - If there are less than nth frames in the mux object -// before deletion. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth); - -//------------------------------------------------------------------------------ -// Animation. - -// Animation parameters. -struct WebPMuxAnimParams { - uint32_t bgcolor; // Background color of the canvas stored (in MSB order) as: - // Bits 00 to 07: Alpha. - // Bits 08 to 15: Red. - // Bits 16 to 23: Green. - // Bits 24 to 31: Blue. - int loop_count; // Number of times to repeat the animation [0 = infinite]. -}; - -// Sets the animation parameters in the mux object. Any existing ANIM chunks -// will be removed. -// Parameters: -// mux - (in/out) object in which ANIM chunk is to be set/added -// params - (in) animation parameters. -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux or params is NULL. -// WEBP_MUX_MEMORY_ERROR - on memory allocation error. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxSetAnimationParams( - WebPMux* mux, const WebPMuxAnimParams* params); - -// Gets the animation parameters from the mux object. -// Parameters: -// mux - (in) object from which the animation parameters to be fetched -// params - (out) animation parameters extracted from the ANIM chunk -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux or params is NULL. -// WEBP_MUX_NOT_FOUND - if ANIM chunk is not present in mux object. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxGetAnimationParams( - const WebPMux* mux, WebPMuxAnimParams* params); - -//------------------------------------------------------------------------------ -// Misc Utilities. - -// Sets the canvas size for the mux object. The width and height can be -// specified explicitly or left as zero (0, 0). -// * When width and height are specified explicitly, then this frame bound is -// enforced during subsequent calls to WebPMuxAssemble() and an error is -// reported if any animated frame does not completely fit within the canvas. -// * When unspecified (0, 0), the constructed canvas will get the frame bounds -// from the bounding-box over all frames after calling WebPMuxAssemble(). -// Parameters: -// mux - (in) object to which the canvas size is to be set -// width - (in) canvas width -// height - (in) canvas height -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL; or -// width or height are invalid or out of bounds -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxSetCanvasSize(WebPMux* mux, - int width, int height); - -// Gets the canvas size from the mux object. -// Note: This method assumes that the VP8X chunk, if present, is up-to-date. -// That is, the mux object hasn't been modified since the last call to -// WebPMuxAssemble() or WebPMuxCreate(). -// Parameters: -// mux - (in) object from which the canvas size is to be fetched -// width - (out) canvas width -// height - (out) canvas height -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux, width or height is NULL. -// WEBP_MUX_BAD_DATA - if VP8X/VP8/VP8L chunk or canvas size is invalid. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxGetCanvasSize(const WebPMux* mux, - int* width, int* height); - -// Gets the feature flags from the mux object. -// Note: This method assumes that the VP8X chunk, if present, is up-to-date. -// That is, the mux object hasn't been modified since the last call to -// WebPMuxAssemble() or WebPMuxCreate(). -// Parameters: -// mux - (in) object from which the features are to be fetched -// flags - (out) the flags specifying which features are present in the -// mux object. This will be an OR of various flag values. -// Enum 'WebPFeatureFlags' can be used to test individual flag values. -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux or flags is NULL. -// WEBP_MUX_BAD_DATA - if VP8X/VP8/VP8L chunk or canvas size is invalid. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxGetFeatures(const WebPMux* mux, - uint32_t* flags); - -// Gets number of chunks with the given 'id' in the mux object. -// Parameters: -// mux - (in) object from which the info is to be fetched -// id - (in) chunk id specifying the type of chunk -// num_elements - (out) number of chunks with the given chunk id -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux, or num_elements is NULL. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxNumChunks(const WebPMux* mux, - WebPChunkId id, int* num_elements); - -// Assembles all chunks in WebP RIFF format and returns in 'assembled_data'. -// This function also validates the mux object. -// Note: The content of 'assembled_data' will be ignored and overwritten. -// Also, the content of 'assembled_data' is allocated using malloc(), and NOT -// owned by the 'mux' object. It MUST be deallocated by the caller by calling -// WebPDataClear(). It's always safe to call WebPDataClear() upon return, -// even in case of error. -// Parameters: -// mux - (in/out) object whose chunks are to be assembled -// assembled_data - (out) assembled WebP data -// Returns: -// WEBP_MUX_BAD_DATA - if mux object is invalid. -// WEBP_MUX_INVALID_ARGUMENT - if mux or assembled_data is NULL. -// WEBP_MUX_MEMORY_ERROR - on memory allocation error. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxAssemble(WebPMux* mux, - WebPData* assembled_data); - -//------------------------------------------------------------------------------ -// WebPAnimEncoder API -// -// This API allows encoding (possibly) animated WebP images. -// -// Code Example: -/* - WebPAnimEncoderOptions enc_options; - WebPAnimEncoderOptionsInit(&enc_options); - // Tune 'enc_options' as needed. - WebPAnimEncoder* enc = WebPAnimEncoderNew(width, height, &enc_options); - while() { - WebPConfig config; - WebPConfigInit(&config); - // Tune 'config' as needed. - WebPAnimEncoderAdd(enc, frame, timestamp_ms, &config); - } - WebPAnimEncoderAdd(enc, NULL, timestamp_ms, NULL); - WebPAnimEncoderAssemble(enc, webp_data); - WebPAnimEncoderDelete(enc); - // Write the 'webp_data' to a file, or re-mux it further. -*/ - -typedef struct WebPAnimEncoder WebPAnimEncoder; // Main opaque object. - -// Forward declarations. Defined in encode.h. -struct WebPPicture; -struct WebPConfig; - -// Global options. -struct WebPAnimEncoderOptions { - WebPMuxAnimParams anim_params; // Animation parameters. - int minimize_size; // If true, minimize the output size (slow). Implicitly - // disables key-frame insertion. - int kmin; - int kmax; // Minimum and maximum distance between consecutive key - // frames in the output. The library may insert some key - // frames as needed to satisfy this criteria. - // Note that these conditions should hold: kmax > kmin - // and kmin >= kmax / 2 + 1. Also, if kmin == 0, then - // key-frame insertion is disabled; and if kmax == 0, - // then all frames will be key-frames. - int allow_mixed; // If true, use mixed compression mode; may choose - // either lossy and lossless for each frame. - int verbose; // If true, print info and warning messages to stderr. - - uint32_t padding[4]; // Padding for later use. -}; - -// Internal, version-checked, entry point. -WEBP_EXTERN(int) WebPAnimEncoderOptionsInitInternal( - WebPAnimEncoderOptions*, int); - -// Should always be called, to initialize a fresh WebPAnimEncoderOptions -// structure before modification. Returns false in case of version mismatch. -// WebPAnimEncoderOptionsInit() must have succeeded before using the -// 'enc_options' object. -static WEBP_INLINE int WebPAnimEncoderOptionsInit( - WebPAnimEncoderOptions* enc_options) { - return WebPAnimEncoderOptionsInitInternal(enc_options, WEBP_MUX_ABI_VERSION); -} - -// Internal, version-checked, entry point. -WEBP_EXTERN(WebPAnimEncoder*) WebPAnimEncoderNewInternal( - int, int, const WebPAnimEncoderOptions*, int); - -// Creates and initializes a WebPAnimEncoder object. -// Parameters: -// width/height - (in) canvas width and height of the animation. -// enc_options - (in) encoding options; can be passed NULL to pick -// reasonable defaults. -// Returns: -// A pointer to the newly created WebPAnimEncoder object. -// Or NULL in case of memory error. -static WEBP_INLINE WebPAnimEncoder* WebPAnimEncoderNew( - int width, int height, const WebPAnimEncoderOptions* enc_options) { - return WebPAnimEncoderNewInternal(width, height, enc_options, - WEBP_MUX_ABI_VERSION); -} - -// Optimize the given frame for WebP, encode it and add it to the -// WebPAnimEncoder object. -// The last call to 'WebPAnimEncoderAdd' should be with frame = NULL, which -// indicates that no more frames are to be added. This call is also used to -// determine the duration of the last frame. -// Parameters: -// enc - (in/out) object to which the frame is to be added. -// frame - (in/out) frame data in ARGB or YUV(A) format. If it is in YUV(A) -// format, it will be converted to ARGB, which incurs a small loss. -// timestamp_ms - (in) timestamp of this frame in milliseconds. -// Duration of a frame would be calculated as -// "timestamp of next frame - timestamp of this frame". -// Hence, timestamps should be in non-decreasing order. -// config - (in) encoding options; can be passed NULL to pick -// reasonable defaults. -// Returns: -// On error, returns false and frame->error_code is set appropriately. -// Otherwise, returns true. -WEBP_EXTERN(int) WebPAnimEncoderAdd( - WebPAnimEncoder* enc, struct WebPPicture* frame, int timestamp_ms, - const struct WebPConfig* config); - -// Assemble all frames added so far into a WebP bitstream. -// This call should be preceded by a call to 'WebPAnimEncoderAdd' with -// frame = NULL; if not, the duration of the last frame will be internally -// estimated. -// Parameters: -// enc - (in/out) object from which the frames are to be assembled. -// webp_data - (out) generated WebP bitstream. -// Returns: -// True on success. -WEBP_EXTERN(int) WebPAnimEncoderAssemble(WebPAnimEncoder* enc, - WebPData* webp_data); - -// Get error string corresponding to the most recent call using 'enc'. The -// returned string is owned by 'enc' and is valid only until the next call to -// WebPAnimEncoderAdd() or WebPAnimEncoderAssemble() or WebPAnimEncoderDelete(). -// Parameters: -// enc - (in/out) object from which the error string is to be fetched. -// Returns: -// NULL if 'enc' is NULL. Otherwise, returns the error string if the last call -// to 'enc' had an error, or an empty string if the last call was a success. -WEBP_EXTERN(const char*) WebPAnimEncoderGetError(WebPAnimEncoder* enc); - -// Deletes the WebPAnimEncoder object. -// Parameters: -// enc - (in/out) object to be deleted -WEBP_EXTERN(void) WebPAnimEncoderDelete(WebPAnimEncoder* enc); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_WEBP_MUX_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/webp/mux_types.h b/Example-Mac/Pods/libwebp/src/webp/mux_types.h deleted file mode 100644 index c94043a3..00000000 --- a/Example-Mac/Pods/libwebp/src/webp/mux_types.h +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Data-types common to the mux and demux libraries. -// -// Author: Urvang (urvang@google.com) - -#ifndef WEBP_WEBP_MUX_TYPES_H_ -#define WEBP_WEBP_MUX_TYPES_H_ - -#include // free() -#include // memset() -#include "./types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Note: forward declaring enumerations is not allowed in (strict) C and C++, -// the types are left here for reference. -// typedef enum WebPFeatureFlags WebPFeatureFlags; -// typedef enum WebPMuxAnimDispose WebPMuxAnimDispose; -// typedef enum WebPMuxAnimBlend WebPMuxAnimBlend; -typedef struct WebPData WebPData; - -// VP8X Feature Flags. -typedef enum WebPFeatureFlags { - FRAGMENTS_FLAG = 0x00000001, - ANIMATION_FLAG = 0x00000002, - XMP_FLAG = 0x00000004, - EXIF_FLAG = 0x00000008, - ALPHA_FLAG = 0x00000010, - ICCP_FLAG = 0x00000020 -} WebPFeatureFlags; - -// Dispose method (animation only). Indicates how the area used by the current -// frame is to be treated before rendering the next frame on the canvas. -typedef enum WebPMuxAnimDispose { - WEBP_MUX_DISPOSE_NONE, // Do not dispose. - WEBP_MUX_DISPOSE_BACKGROUND // Dispose to background color. -} WebPMuxAnimDispose; - -// Blend operation (animation only). Indicates how transparent pixels of the -// current frame are blended with those of the previous canvas. -typedef enum WebPMuxAnimBlend { - WEBP_MUX_BLEND, // Blend. - WEBP_MUX_NO_BLEND // Do not blend. -} WebPMuxAnimBlend; - -// Data type used to describe 'raw' data, e.g., chunk data -// (ICC profile, metadata) and WebP compressed image data. -struct WebPData { - const uint8_t* bytes; - size_t size; -}; - -// Initializes the contents of the 'webp_data' object with default values. -static WEBP_INLINE void WebPDataInit(WebPData* webp_data) { - if (webp_data != NULL) { - memset(webp_data, 0, sizeof(*webp_data)); - } -} - -// Clears the contents of the 'webp_data' object by calling free(). Does not -// deallocate the object itself. -static WEBP_INLINE void WebPDataClear(WebPData* webp_data) { - if (webp_data != NULL) { - free((void*)webp_data->bytes); - WebPDataInit(webp_data); - } -} - -// Allocates necessary storage for 'dst' and copies the contents of 'src'. -// Returns true on success. -static WEBP_INLINE int WebPDataCopy(const WebPData* src, WebPData* dst) { - if (src == NULL || dst == NULL) return 0; - WebPDataInit(dst); - if (src->bytes != NULL && src->size != 0) { - dst->bytes = (uint8_t*)malloc(src->size); - if (dst->bytes == NULL) return 0; - memcpy((void*)dst->bytes, src->bytes, src->size); - dst->size = src->size; - } - return 1; -} - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_WEBP_MUX_TYPES_H_ */ diff --git a/Example-Mac/Pods/libwebp/src/webp/types.h b/Example-Mac/Pods/libwebp/src/webp/types.h deleted file mode 100644 index 98fff35a..00000000 --- a/Example-Mac/Pods/libwebp/src/webp/types.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Common types -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_WEBP_TYPES_H_ -#define WEBP_WEBP_TYPES_H_ - -#include // for size_t - -#ifndef _MSC_VER -#include -#if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \ - (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) -#define WEBP_INLINE inline -#else -#define WEBP_INLINE -#endif -#else -typedef signed char int8_t; -typedef unsigned char uint8_t; -typedef signed short int16_t; -typedef unsigned short uint16_t; -typedef signed int int32_t; -typedef unsigned int uint32_t; -typedef unsigned long long int uint64_t; -typedef long long int int64_t; -#define WEBP_INLINE __forceinline -#endif /* _MSC_VER */ - -#ifndef WEBP_EXTERN -// This explicitly marks library functions and allows for changing the -// signature for e.g., Windows DLL builds. -# if defined(__GNUC__) && __GNUC__ >= 4 -# define WEBP_EXTERN(type) extern __attribute__ ((visibility ("default"))) type -# else -# define WEBP_EXTERN(type) extern type -# endif /* __GNUC__ >= 4 */ -#endif /* WEBP_EXTERN */ - -// Macro to check ABI compatibility (same major revision number) -#define WEBP_ABI_IS_INCOMPATIBLE(a, b) (((a) >> 8) != ((b) >> 8)) - -#endif /* WEBP_WEBP_TYPES_H_ */ diff --git a/Example-Shared/Kitten.m b/Example-Shared/Kitten.m deleted file mode 100644 index 84981acd..00000000 --- a/Example-Shared/Kitten.m +++ /dev/null @@ -1,132 +0,0 @@ -// -// Kitten.m -// PINRemoteImage -// -// Created by Michael Schneider on 1/6/16. -// Copyright © 2016 mischneider. All rights reserved. -// - -#import "Kitten.h" - -#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED - -@interface NSValue (PINiOSMapping) -+ (NSValue *)valueWithCGSize:(CGSize)size; -- (CGSize)CGSizeValue; -@end - -@implementation NSValue (PINiOSMapping) - -+ (NSValue *)valueWithCGSize:(CGSize)size -{ - return [self valueWithSize:size]; -} - -- (CGSize)CGSizeValue -{ - return self.sizeValue; -} - -@end - -#endif - - -@implementation Kitten - -+ (void)fetchKittenForWidth:(CGFloat)width completion:(void (^)(NSArray *kittens))completion -{ - NSArray *kittenURLs = @[[NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/92/5d/5a/925d5ac74db0dcfabc238e1686e31d16.jpg"], - [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/ff/b3/ae/ffb3ae40533b7f9463cf1c04d7ab69d1.jpg"], - [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/e4/b7/7c/e4b77ca06e1d4a401b1a49d7fadd90d9.jpg"], - [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/46/e1/59/46e159d76b167ed9211d662f95e7bf6f.jpg"], - [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/7a/72/77/7a72779329942c06f888c148eb8d7e34.jpg"], - [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/60/21/8f/60218ff43257fb3b6d7c5b888f74a5bf.jpg"], - [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/90/e8/e4/90e8e47d53e71e0d97691dd13a5617fb.jpg"], - [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/96/ae/31/96ae31fbc52d96dd3308d2754a6ca37e.jpg"], - [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/9b/7b/99/9b7b99ff63be31bba8f9863724b3ebbc.jpg"], - [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/80/23/51/802351d953dd2a8b232d0da1c7ca6880.jpg"], - [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/f5/c4/f0/f5c4f04fa2686338dc3b08420d198484.jpg"], - [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/2b/06/4f/2b064f3e0af984a556ac94b251ff7060.jpg"], - [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/17/1f/c0/171fc02398143269d8a507a15563166a.jpg"], - [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/8a/35/33/8a35338bbf67c86a198ba2dd926edd82.jpg"], - [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/4d/6e/3c/4d6e3cf970031116c57486e85c2a4cab.jpg"], - [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/54/25/ee/5425eeccba78731cf7be70f0b8808bd2.jpg"], - [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/04/f1/3f/04f13fdb7580dcbe8c4d6b7d5a0a5ec2.jpg"], - [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/dc/16/4e/dc164ed33af9d899e5ed188e642f00e9.jpg"], - [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/c1/06/13/c106132936189b6cb654671f2a2183ed.jpg"], - [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/46/43/ed/4643eda4e1be4273721a76a370b90346.jpg"], - ]; - - NSArray *kittenSizes = @[[NSValue valueWithCGSize:CGSizeMake(503, 992)], - [NSValue valueWithCGSize:CGSizeMake(500, 337)], - [NSValue valueWithCGSize:CGSizeMake(522, 695)], - [NSValue valueWithCGSize:CGSizeMake(557, 749)], - [NSValue valueWithCGSize:CGSizeMake(710, 1069)], - [NSValue valueWithCGSize:CGSizeMake(522, 676)], - [NSValue valueWithCGSize:CGSizeMake(500, 688)], - [NSValue valueWithCGSize:CGSizeMake(377, 700)], - [NSValue valueWithCGSize:CGSizeMake(334, 494)], - [NSValue valueWithCGSize:CGSizeMake(625, 469)], - [NSValue valueWithCGSize:CGSizeMake(625, 833)], - [NSValue valueWithCGSize:CGSizeMake(625, 469)], - [NSValue valueWithCGSize:CGSizeMake(625, 469)], - [NSValue valueWithCGSize:CGSizeMake(625, 791)], - [NSValue valueWithCGSize:CGSizeMake(625, 833)], - [NSValue valueWithCGSize:CGSizeMake(605, 605)], - [NSValue valueWithCGSize:CGSizeMake(504, 750)], - [NSValue valueWithCGSize:CGSizeMake(500, 500)], - [NSValue valueWithCGSize:CGSizeMake(640, 640)], - [NSValue valueWithCGSize:CGSizeMake(500, 473)], - ]; - - dispatch_group_t group = dispatch_group_create(); - NSMutableArray *kittens = [[NSMutableArray alloc] init]; - - CGFloat scale = 1; -#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED - scale = [[UIScreen mainScreen] scale]; -#else - scale = [[NSScreen mainScreen] backingScaleFactor]; -#endif - dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - NSInteger count = 0; - for (NSInteger idx = 0; idx < 500; idx++) { - Kitten *kitten = [[Kitten alloc] init]; - CGFloat r = (rand() % 255) / 255.0f; - CGFloat g = (rand() % 255) / 255.0f; - CGFloat b = (rand() % 255) / 255.0f; -#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED - kitten.dominantColor = [UIColor colorWithRed:r green:g blue:b alpha:1.0f]; -#else - kitten.dominantColor = [NSColor colorWithRed:r green:g blue:b alpha:1.0f]; -#endif - - NSUInteger kittenIdx = rand() % 20; - - CGSize kittenSize = [kittenSizes[kittenIdx] CGSizeValue]; - NSInteger kittenSizeWidth = kittenSize.width; - NSInteger kittenSizeHeight = kittenSize.height; - - if (kittenSizeWidth > (width * scale)) { - kittenSizeHeight = ((width * scale) / kittenSizeWidth) * kittenSizeHeight; - kittenSizeWidth = (width * scale); - } - - kitten.imageURL = kittenURLs[kittenIdx]; - kitten.imageSize = CGSizeMake(kittenSizeWidth / scale, kittenSizeHeight / scale); - - dispatch_sync(dispatch_get_main_queue(), ^{ - [kittens addObject:kitten]; - }); - count++; - } - }); - dispatch_group_notify(group, dispatch_get_main_queue(), ^{ - if (completion) { - completion(kittens); - } - }); -} - -@end diff --git a/Example-tvOS/PINRemoteImage.tvOSExample.xcodeproj/project.pbxproj b/Example-tvOS/PINRemoteImage.tvOSExample.xcodeproj/project.pbxproj deleted file mode 100644 index c5da7c30..00000000 --- a/Example-tvOS/PINRemoteImage.tvOSExample.xcodeproj/project.pbxproj +++ /dev/null @@ -1,376 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 78699F481C668C8E0044C9E9 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78699F471C668C8E0044C9E9 /* AppDelegate.swift */; }; - 78699F4C1C668C8E0044C9E9 /* ProgressiveViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78699F4B1C668C8E0044C9E9 /* ProgressiveViewController.swift */; }; - 78699F4F1C668C8E0044C9E9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 78699F4D1C668C8E0044C9E9 /* Main.storyboard */; }; - 78699F511C668C8E0044C9E9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 78699F501C668C8E0044C9E9 /* Assets.xcassets */; }; - 78699F591C669AC70044C9E9 /* ProcessingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78699F581C669AC70044C9E9 /* ProcessingViewController.swift */; }; - 78699F5B1C66A5A90044C9E9 /* DegradedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78699F5A1C66A5A90044C9E9 /* DegradedViewController.swift */; }; - 78699F5D1C66A7E20044C9E9 /* CollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78699F5C1C66A7E20044C9E9 /* CollectionViewController.swift */; }; - 78699F5F1C66A8610044C9E9 /* CollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78699F5E1C66A8610044C9E9 /* CollectionViewCell.swift */; }; - 8711EE2CA5977BA3B86E1B62 /* Pods_PINRemoteImage_tvOSExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C82D54FC041E5BDD75901E15 /* Pods_PINRemoteImage_tvOSExample.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 093C3E4AE850337BCD0D2FE6 /* Pods-PINRemoteImage.tvOSExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PINRemoteImage.tvOSExample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample.debug.xcconfig"; sourceTree = ""; }; - 78699F441C668C8E0044C9E9 /* PINRemoteImage.tvOSExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PINRemoteImage.tvOSExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 78699F471C668C8E0044C9E9 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 78699F4B1C668C8E0044C9E9 /* ProgressiveViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressiveViewController.swift; sourceTree = ""; }; - 78699F4E1C668C8E0044C9E9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 78699F501C668C8E0044C9E9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 78699F521C668C8E0044C9E9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 78699F581C669AC70044C9E9 /* ProcessingViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProcessingViewController.swift; sourceTree = ""; }; - 78699F5A1C66A5A90044C9E9 /* DegradedViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DegradedViewController.swift; sourceTree = ""; }; - 78699F5C1C66A7E20044C9E9 /* CollectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionViewController.swift; sourceTree = ""; }; - 78699F5E1C66A8610044C9E9 /* CollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionViewCell.swift; sourceTree = ""; }; - AAF1AB8C026DF61369E568CC /* Pods-PINRemoteImage.tvOSExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PINRemoteImage.tvOSExample.release.xcconfig"; path = "Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample.release.xcconfig"; sourceTree = ""; }; - C82D54FC041E5BDD75901E15 /* Pods_PINRemoteImage_tvOSExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PINRemoteImage_tvOSExample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 78699F411C668C8E0044C9E9 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 8711EE2CA5977BA3B86E1B62 /* Pods_PINRemoteImage_tvOSExample.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 717A14585C13E19AFD257717 /* Frameworks */ = { - isa = PBXGroup; - children = ( - C82D54FC041E5BDD75901E15 /* Pods_PINRemoteImage_tvOSExample.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 78699F3B1C668C8E0044C9E9 = { - isa = PBXGroup; - children = ( - 78699F461C668C8E0044C9E9 /* PINRemoteImage.tvOSExample */, - 78699F451C668C8E0044C9E9 /* Products */, - 91B09A3FE05D54DA24016146 /* Pods */, - 717A14585C13E19AFD257717 /* Frameworks */, - ); - sourceTree = ""; - }; - 78699F451C668C8E0044C9E9 /* Products */ = { - isa = PBXGroup; - children = ( - 78699F441C668C8E0044C9E9 /* PINRemoteImage.tvOSExample.app */, - ); - name = Products; - sourceTree = ""; - }; - 78699F461C668C8E0044C9E9 /* PINRemoteImage.tvOSExample */ = { - isa = PBXGroup; - children = ( - 78699F501C668C8E0044C9E9 /* Assets.xcassets */, - 78699F521C668C8E0044C9E9 /* Info.plist */, - 78699F471C668C8E0044C9E9 /* AppDelegate.swift */, - 78699F4D1C668C8E0044C9E9 /* Main.storyboard */, - 78699F4B1C668C8E0044C9E9 /* ProgressiveViewController.swift */, - 78699F581C669AC70044C9E9 /* ProcessingViewController.swift */, - 78699F5A1C66A5A90044C9E9 /* DegradedViewController.swift */, - 78699F5C1C66A7E20044C9E9 /* CollectionViewController.swift */, - 78699F5E1C66A8610044C9E9 /* CollectionViewCell.swift */, - ); - path = PINRemoteImage.tvOSExample; - sourceTree = ""; - }; - 91B09A3FE05D54DA24016146 /* Pods */ = { - isa = PBXGroup; - children = ( - 093C3E4AE850337BCD0D2FE6 /* Pods-PINRemoteImage.tvOSExample.debug.xcconfig */, - AAF1AB8C026DF61369E568CC /* Pods-PINRemoteImage.tvOSExample.release.xcconfig */, - ); - name = Pods; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 78699F431C668C8E0044C9E9 /* PINRemoteImage.tvOSExample */ = { - isa = PBXNativeTarget; - buildConfigurationList = 78699F551C668C8E0044C9E9 /* Build configuration list for PBXNativeTarget "PINRemoteImage.tvOSExample" */; - buildPhases = ( - FA9E035135C48FB08841B4A3 /* Check Pods Manifest.lock */, - 78699F401C668C8E0044C9E9 /* Sources */, - 78699F411C668C8E0044C9E9 /* Frameworks */, - 78699F421C668C8E0044C9E9 /* Resources */, - 8B150830C60182EB93A19C74 /* Embed Pods Frameworks */, - CC3C0E4279D9CD7BF5C64E5D /* Copy Pods Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = PINRemoteImage.tvOSExample; - productName = PINRemoteImage.tvOSExample; - productReference = 78699F441C668C8E0044C9E9 /* PINRemoteImage.tvOSExample.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 78699F3C1C668C8E0044C9E9 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; - TargetAttributes = { - 78699F431C668C8E0044C9E9 = { - CreatedOnToolsVersion = 7.2.1; - }; - }; - }; - buildConfigurationList = 78699F3F1C668C8E0044C9E9 /* Build configuration list for PBXProject "PINRemoteImage.tvOSExample" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 78699F3B1C668C8E0044C9E9; - productRefGroup = 78699F451C668C8E0044C9E9 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 78699F431C668C8E0044C9E9 /* PINRemoteImage.tvOSExample */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 78699F421C668C8E0044C9E9 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 78699F511C668C8E0044C9E9 /* Assets.xcassets in Resources */, - 78699F4F1C668C8E0044C9E9 /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 8B150830C60182EB93A19C74 /* Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Embed Pods Frameworks"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - CC3C0E4279D9CD7BF5C64E5D /* Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - FA9E035135C48FB08841B4A3 /* Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Check Pods Manifest.lock"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 78699F401C668C8E0044C9E9 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 78699F5D1C66A7E20044C9E9 /* CollectionViewController.swift in Sources */, - 78699F4C1C668C8E0044C9E9 /* ProgressiveViewController.swift in Sources */, - 78699F591C669AC70044C9E9 /* ProcessingViewController.swift in Sources */, - 78699F5F1C66A8610044C9E9 /* CollectionViewCell.swift in Sources */, - 78699F481C668C8E0044C9E9 /* AppDelegate.swift in Sources */, - 78699F5B1C66A5A90044C9E9 /* DegradedViewController.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 78699F4D1C668C8E0044C9E9 /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 78699F4E1C668C8E0044C9E9 /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 78699F531C668C8E0044C9E9 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = appletvos; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 9.1; - }; - name = Debug; - }; - 78699F541C668C8E0044C9E9 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = appletvos; - TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 9.1; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 78699F561C668C8E0044C9E9 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 093C3E4AE850337BCD0D2FE6 /* Pods-PINRemoteImage.tvOSExample.debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - INFOPLIST_FILE = PINRemoteImage.tvOSExample/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.PINRemoteImage-tvOSExample"; - PRODUCT_NAME = "$(TARGET_NAME)"; - TVOS_DEPLOYMENT_TARGET = 9.0; - }; - name = Debug; - }; - 78699F571C668C8E0044C9E9 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = AAF1AB8C026DF61369E568CC /* Pods-PINRemoteImage.tvOSExample.release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - INFOPLIST_FILE = PINRemoteImage.tvOSExample/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.PINRemoteImage-tvOSExample"; - PRODUCT_NAME = "$(TARGET_NAME)"; - TVOS_DEPLOYMENT_TARGET = 9.0; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 78699F3F1C668C8E0044C9E9 /* Build configuration list for PBXProject "PINRemoteImage.tvOSExample" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 78699F531C668C8E0044C9E9 /* Debug */, - 78699F541C668C8E0044C9E9 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 78699F551C668C8E0044C9E9 /* Build configuration list for PBXNativeTarget "PINRemoteImage.tvOSExample" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 78699F561C668C8E0044C9E9 /* Debug */, - 78699F571C668C8E0044C9E9 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 78699F3C1C668C8E0044C9E9 /* Project object */; -} diff --git a/Example-tvOS/PINRemoteImage.tvOSExample.xcworkspace/contents.xcworkspacedata b/Example-tvOS/PINRemoteImage.tvOSExample.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 95c731b5..00000000 --- a/Example-tvOS/PINRemoteImage.tvOSExample.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/AppDelegate.swift b/Example-tvOS/PINRemoteImage.tvOSExample/AppDelegate.swift deleted file mode 100644 index b385bb63..00000000 --- a/Example-tvOS/PINRemoteImage.tvOSExample/AppDelegate.swift +++ /dev/null @@ -1,45 +0,0 @@ -// -// AppDelegate.swift -// PINRemoteImage.tvOSExample -// -// Created by Isaac Overacker on 2/6/16. -// -// - -import UIKit - -@UIApplicationMain -class AppDelegate: UIResponder, UIApplicationDelegate { - - var window: UIWindow? - - func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { - // Override point for customization after application launch. - return true - } - - func applicationWillResignActive(application: UIApplication) { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. - } - - func applicationDidEnterBackground(application: UIApplication) { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. - } - - func applicationWillEnterForeground(application: UIApplication) { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. - } - - func applicationDidBecomeActive(application: UIApplication) { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. - } - - func applicationWillTerminate(application: UIApplication) { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. - } - - -} - diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/Base.lproj/Main.storyboard b/Example-tvOS/PINRemoteImage.tvOSExample/Base.lproj/Main.storyboard deleted file mode 100644 index 86d55968..00000000 --- a/Example-tvOS/PINRemoteImage.tvOSExample/Base.lproj/Main.storyboard +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/CollectionViewController.swift b/Example-tvOS/PINRemoteImage.tvOSExample/CollectionViewController.swift deleted file mode 100644 index c9105dab..00000000 --- a/Example-tvOS/PINRemoteImage.tvOSExample/CollectionViewController.swift +++ /dev/null @@ -1,65 +0,0 @@ -// -// CollectionViewController.swift -// PINRemoteImage.tvOSExample -// -// Created by Isaac Overacker on 2/6/16. -// -// - -import UIKit -import PINRemoteImage - -private let reuseIdentifier = "Cell" - -class CollectionViewController: UICollectionViewController { - - let kittenURLs = [ - NSURL(string: "https://s-media-cache-ak0.pinimg.com/736x/92/5d/5a/925d5ac74db0dcfabc238e1686e31d16.jpg"), - NSURL(string: "https://s-media-cache-ak0.pinimg.com/736x/ff/b3/ae/ffb3ae40533b7f9463cf1c04d7ab69d1.jpg"), - NSURL(string: "https://s-media-cache-ak0.pinimg.com/736x/e4/b7/7c/e4b77ca06e1d4a401b1a49d7fadd90d9.jpg"), - NSURL(string: "https://s-media-cache-ak0.pinimg.com/736x/46/e1/59/46e159d76b167ed9211d662f95e7bf6f.jpg"), - NSURL(string: "https://s-media-cache-ak0.pinimg.com/736x/7a/72/77/7a72779329942c06f888c148eb8d7e34.jpg"), - NSURL(string: "https://s-media-cache-ak0.pinimg.com/736x/60/21/8f/60218ff43257fb3b6d7c5b888f74a5bf.jpg"), - NSURL(string: "https://s-media-cache-ak0.pinimg.com/736x/90/e8/e4/90e8e47d53e71e0d97691dd13a5617fb.jpg"), - NSURL(string: "https://s-media-cache-ak0.pinimg.com/736x/96/ae/31/96ae31fbc52d96dd3308d2754a6ca37e.jpg"), - NSURL(string: "https://s-media-cache-ak0.pinimg.com/736x/9b/7b/99/9b7b99ff63be31bba8f9863724b3ebbc.jpg"), - NSURL(string: "https://s-media-cache-ak0.pinimg.com/736x/80/23/51/802351d953dd2a8b232d0da1c7ca6880.jpg"), - NSURL(string: "https://s-media-cache-ak0.pinimg.com/736x/f5/c4/f0/f5c4f04fa2686338dc3b08420d198484.jpg"), - NSURL(string: "https://s-media-cache-ak0.pinimg.com/736x/2b/06/4f/2b064f3e0af984a556ac94b251ff7060.jpg"), - NSURL(string: "https://s-media-cache-ak0.pinimg.com/736x/17/1f/c0/171fc02398143269d8a507a15563166a.jpg"), - NSURL(string: "https://s-media-cache-ak0.pinimg.com/736x/8a/35/33/8a35338bbf67c86a198ba2dd926edd82.jpg"), - NSURL(string: "https://s-media-cache-ak0.pinimg.com/736x/4d/6e/3c/4d6e3cf970031116c57486e85c2a4cab.jpg"), - NSURL(string: "https://s-media-cache-ak0.pinimg.com/736x/54/25/ee/5425eeccba78731cf7be70f0b8808bd2.jpg"), - NSURL(string: "https://s-media-cache-ak0.pinimg.com/736x/04/f1/3f/04f13fdb7580dcbe8c4d6b7d5a0a5ec2.jpg"), - NSURL(string: "https://s-media-cache-ak0.pinimg.com/736x/dc/16/4e/dc164ed33af9d899e5ed188e642f00e9.jpg"), - NSURL(string: "https://s-media-cache-ak0.pinimg.com/736x/c1/06/13/c106132936189b6cb654671f2a2183ed.jpg"), - NSURL(string: "https://s-media-cache-ak0.pinimg.com/736x/46/43/ed/4643eda4e1be4273721a76a370b90346.jpg") - ] - - override func viewDidLoad() { - super.viewDidLoad() - } - - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. - } - - // MARK: UICollectionViewDataSource - - override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int { - return 1 - } - - - override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return kittenURLs.count - } - - override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { - let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! CollectionViewCell - cell.imageView.pin_setImageFromURL(kittenURLs[indexPath.row]) - return cell - } - -} diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/DegradedViewController.swift b/Example-tvOS/PINRemoteImage.tvOSExample/DegradedViewController.swift deleted file mode 100644 index 91d8f115..00000000 --- a/Example-tvOS/PINRemoteImage.tvOSExample/DegradedViewController.swift +++ /dev/null @@ -1,35 +0,0 @@ -// -// DegradedViewController.swift -// PINRemoteImage.tvOSExample -// -// Created by Isaac Overacker on 2/6/16. -// -// - -import UIKit -import PINRemoteImage - -class DegradedViewController: UIViewController { - - @IBOutlet weak var imageView: UIImageView! - - override func viewDidLoad() { - super.viewDidLoad() - PINRemoteImageManager.sharedImageManager().setShouldUpgradeLowQualityImages(true, completion: nil) - } - - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. - } - - override func viewWillAppear(animated: Bool) { - super.viewWillAppear(animated) - - imageView.pin_setImageFromURLs([ - NSURL(string: "https://placekitten.com/101/101")!, - NSURL(string: "https://placekitten.com/401/401")!, - NSURL(string: "https://placekitten.com/801/801")! - ]) - } -} diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/ProcessingViewController.swift b/Example-tvOS/PINRemoteImage.tvOSExample/ProcessingViewController.swift deleted file mode 100644 index ecd82d21..00000000 --- a/Example-tvOS/PINRemoteImage.tvOSExample/ProcessingViewController.swift +++ /dev/null @@ -1,77 +0,0 @@ -// -// ProcessingViewController.swift -// PINRemoteImage.tvOSExample -// -// Created by Isaac Overacker on 2/6/16. -// -// - -import UIKit -import PINRemoteImage - -class ProcessingViewController: UIViewController { - - @IBOutlet weak var imageView: UIImageView! - - override func viewDidLoad() { - super.viewDidLoad() - } - - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. - } - - override func viewWillAppear(animated: Bool) { - super.viewWillAppear(animated) - - if let url = NSURL(string: "https://s-media-cache-ak0.pinimg.com/1200x/2e/0c/c5/2e0cc5d86e7b7cd42af225c29f21c37f.jpg") { - imageView.pin_setImageFromURL(url, - processorKey: "rounded", - processor: { (result, cost) -> UIImage? in - if let image = result.image { - let radius = CGFloat(7.0) - let targetSize = CGSize(width: 200, height: 300) - let imageRect = CGRect(x: 0, y: 0, width: targetSize.width, height: targetSize.height) - UIGraphicsBeginImageContext(imageRect.size) - let bezierPath = UIBezierPath(roundedRect: imageRect, cornerRadius: radius) - bezierPath.addClip() - - let widthMultiplier = CGFloat(targetSize.width / image.size.width) - let heightMultiplier = CGFloat(targetSize.height / image.size.height) - let sizeMultiplier = max(widthMultiplier, heightMultiplier) - - var drawRect = CGRect(x: 0, y: 0, width: image.size.width * sizeMultiplier, height: image.size.height * sizeMultiplier) - if CGRectGetMaxX(drawRect) > CGRectGetMaxX(imageRect) { - drawRect.origin.x -= (CGRectGetMaxX(drawRect) - CGRectGetMaxX(imageRect)) / 2.0; - } - if CGRectGetMaxY(drawRect) > CGRectGetMaxY(imageRect) { - drawRect.origin.y -= (CGRectGetMaxY(drawRect) - CGRectGetMaxY(imageRect)) / 2.0; - } - - image.drawInRect(drawRect) - - UIColor.redColor().setStroke() - bezierPath.lineWidth = 5.0 - bezierPath.stroke() - - let ctx = UIGraphicsGetCurrentContext(); - CGContextSetBlendMode(ctx, .Overlay); - CGContextSetAlpha(ctx, 0.5); - - if let logo = UIImage(named: "white-pinterest-logo") { - CGContextScaleCTM(ctx, 1.0, -1.0); - CGContextTranslateCTM(ctx, 0.0, -drawRect.size.height); - CGContextDrawImage(ctx, CGRect(x: 0, y: 0, width: logo.size.width, height: logo.size.height), logo.CGImage); - } - - let processedImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return processedImage; - } - - return nil - }) - } - } -} diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/ProgressiveViewController.swift b/Example-tvOS/PINRemoteImage.tvOSExample/ProgressiveViewController.swift deleted file mode 100644 index ebf6b775..00000000 --- a/Example-tvOS/PINRemoteImage.tvOSExample/ProgressiveViewController.swift +++ /dev/null @@ -1,50 +0,0 @@ -// -// ProgressiveViewController.swift -// PINRemoteImage.tvOSExample -// -// Created by Isaac Overacker on 2/6/16. -// -// - -import UIKit -import PINRemoteImage - -class ProgressiveViewController: UIViewController { - - @IBOutlet weak var imageView: UIImageView! - - override func viewDidLoad() { - super.viewDidLoad() - imageView.pin_updateWithProgress = true - } - - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. - } - - override func viewDidAppear(animated: Bool) { - super.viewDidAppear(animated) - - if let url = NSURL(string: "https://s-media-cache-ak0.pinimg.com/1200x/2e/0c/c5/2e0cc5d86e7b7cd42af225c29f21c37f.jpg") { - PINRemoteImageManager.sharedImageManager().setProgressThresholds([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9], completion: nil) - - imageView.pin_setImageFromURL(url) - - var progress = [UIImage]() - PINRemoteImageManager.sharedImageManager().downloadImageWithURL(url, - options: .DownloadOptionsNone, - progressImage: { result in - if let image = result.image { - progress.append(image) - } - }, completion: { result in - if let image = result.image { - progress.append(image) - } - }) - } - } - -} - diff --git a/Example-tvOS/Podfile b/Example-tvOS/Podfile deleted file mode 100644 index 63931d51..00000000 --- a/Example-tvOS/Podfile +++ /dev/null @@ -1,5 +0,0 @@ -use_frameworks! - -target 'PINRemoteImage.tvOSExample', :exclusive => true do - pod "PINRemoteImage/iOS", :path => "../" -end diff --git a/Example-tvOS/Podfile.lock b/Example-tvOS/Podfile.lock deleted file mode 100644 index f7c801ef..00000000 --- a/Example-tvOS/Podfile.lock +++ /dev/null @@ -1,19 +0,0 @@ -PODS: - - PINCache (2.2.2) - - PINRemoteImage/Core (3.0.0-beta): - - PINCache (>= 2.1) - - PINRemoteImage/iOS (3.0.0-beta): - - PINRemoteImage/Core - -DEPENDENCIES: - - PINRemoteImage/iOS (from `../`) - -EXTERNAL SOURCES: - PINRemoteImage: - :path: ../ - -SPEC CHECKSUMS: - PINCache: 078426d356ab95ef875e9e62e5c35a2ea3333c28 - PINRemoteImage: 43b7123d7cc96a8394b3c6afaa20101679e6d463 - -COCOAPODS: 0.39.0 diff --git a/Example-tvOS/Pods/Headers/Private/PINCache/Nullability.h b/Example-tvOS/Pods/Headers/Private/PINCache/Nullability.h deleted file mode 120000 index b90c434a..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINCache/Nullability.h +++ /dev/null @@ -1 +0,0 @@ -../../../PINCache/PINCache/Nullability.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINCache/PINCache.h b/Example-tvOS/Pods/Headers/Private/PINCache/PINCache.h deleted file mode 120000 index 149e0bb6..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINCache/PINCache.h +++ /dev/null @@ -1 +0,0 @@ -../../../PINCache/PINCache/PINCache.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINCache/PINDiskCache.h b/Example-tvOS/Pods/Headers/Private/PINCache/PINDiskCache.h deleted file mode 120000 index c5206f89..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINCache/PINDiskCache.h +++ /dev/null @@ -1 +0,0 @@ -../../../PINCache/PINCache/PINDiskCache.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINCache/PINMemoryCache.h b/Example-tvOS/Pods/Headers/Private/PINCache/PINMemoryCache.h deleted file mode 120000 index c1b9753b..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINCache/PINMemoryCache.h +++ /dev/null @@ -1 +0,0 @@ -../../../PINCache/PINCache/PINMemoryCache.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/NSData+ImageDetectors.h b/Example-tvOS/Pods/Headers/Private/PINRemoteImage/NSData+ImageDetectors.h deleted file mode 120000 index 8d98e1a4..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/NSData+ImageDetectors.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Categories/NSData+ImageDetectors.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINAlternateRepresentationProvider.h b/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINAlternateRepresentationProvider.h deleted file mode 120000 index ce662f35..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINAlternateRepresentationProvider.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINAlternateRepresentationProvider.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINAnimatedImage.h b/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINAnimatedImage.h deleted file mode 120000 index 4ad10fe3..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINAnimatedImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINAnimatedImage.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINAnimatedImageManager.h b/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINAnimatedImageManager.h deleted file mode 120000 index c9139ffe..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINAnimatedImageManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINAnimatedImageManager.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINButton+PINRemoteImage.h b/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINButton+PINRemoteImage.h deleted file mode 120000 index 0ed989a1..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINButton+PINRemoteImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Image Categories/PINButton+PINRemoteImage.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINDataTaskOperation.h b/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINDataTaskOperation.h deleted file mode 120000 index 6ebb4a80..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINDataTaskOperation.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINDataTaskOperation.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINImage+DecodedImage.h b/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINImage+DecodedImage.h deleted file mode 120000 index 96d0ec62..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINImage+DecodedImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Categories/PINImage+DecodedImage.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINImage+WebP.h b/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINImage+WebP.h deleted file mode 120000 index 6d484bc7..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINImage+WebP.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Categories/PINImage+WebP.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINImageView+PINRemoteImage.h b/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINImageView+PINRemoteImage.h deleted file mode 120000 index a94e8f7c..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINImageView+PINRemoteImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Image Categories/PINImageView+PINRemoteImage.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINProgressiveImage.h b/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINProgressiveImage.h deleted file mode 120000 index 03e8769f..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINProgressiveImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINProgressiveImage.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImage.h b/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImage.h deleted file mode 120000 index 64ec7893..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImage.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageCallbacks.h b/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageCallbacks.h deleted file mode 120000 index 790720bb..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageCallbacks.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageCallbacks.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageCategoryManager.h b/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageCategoryManager.h deleted file mode 120000 index cba384e6..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageCategoryManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageCategoryManager.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageDownloadTask.h b/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageDownloadTask.h deleted file mode 120000 index e492464a..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageDownloadTask.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageDownloadTask.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageMacros.h b/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageMacros.h deleted file mode 120000 index 5c9588e9..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageMacros.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageMacros.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageManager.h b/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageManager.h deleted file mode 120000 index d0e9703d..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageManager.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageManagerResult.h b/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageManagerResult.h deleted file mode 120000 index b719636b..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageManagerResult.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageManagerResult.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageMemoryContainer.h b/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageMemoryContainer.h deleted file mode 120000 index 8e2c8de9..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageMemoryContainer.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageMemoryContainer.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageProcessorTask.h b/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageProcessorTask.h deleted file mode 120000 index 89c8a48b..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageProcessorTask.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageProcessorTask.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageTask.h b/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageTask.h deleted file mode 120000 index 8379dfef..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteImageTask.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageTask.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteLock.h b/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteLock.h deleted file mode 120000 index 1712bbd3..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINRemoteLock.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteLock.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINURLSessionManager.h b/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINURLSessionManager.h deleted file mode 120000 index ad2ce3c8..00000000 --- a/Example-tvOS/Pods/Headers/Private/PINRemoteImage/PINURLSessionManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINURLSessionManager.h \ No newline at end of file diff --git a/Example-tvOS/Pods/Local Podspecs/PINRemoteImage.podspec.json b/Example-tvOS/Pods/Local Podspecs/PINRemoteImage.podspec.json deleted file mode 100644 index 138e4ba2..00000000 --- a/Example-tvOS/Pods/Local Podspecs/PINRemoteImage.podspec.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "name": "PINRemoteImage", - "version": "3.0.0-beta", - "summary": "A thread safe, performant, feature rich image fetcher", - "homepage": "https://github.com/pinterest/PINRemoteImage", - "license": "Apache 2.0", - "authors": { - "Garrett Moon": "garrett@pinterest.com" - }, - "source": { - "git": "https://github.com/pinterest/PINRemoteImage.git", - "tag": "3.0.0-beta" - }, - "social_media_url": "https://twitter.com/garrettmoon", - "platforms": { - "ios": "6.0", - "tvos": "9.0" - }, - "requires_arc": true, - "default_subspecs": "FLAnimatedImage", - "subspecs": [ - { - "name": "Core", - "platforms": { - "ios": "6.0", - "tvos": "9.0", - "osx": "10.8" - }, - "source_files": "Pod/Classes/**/*.{h,m}", - "exclude_files": [ - "Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.h", - "Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.m" - ], - "public_header_files": "Pod/Classes/**/*.h", - "frameworks": [ - "ImageIO", - "Accelerate" - ], - "dependencies": { - "PINCache": [ - ">=2.1" - ] - } - }, - { - "name": "iOS", - "platforms": { - "ios": "6.0", - "tvos": "9.0" - }, - "dependencies": { - "PINRemoteImage/Core": [ - - ] - }, - "frameworks": "UIKit" - }, - { - "name": "OSX", - "platforms": { - "osx": "10.8" - }, - "dependencies": { - "PINRemoteImage/Core": [ - - ] - }, - "frameworks": [ - "Cocoa", - "CoreServices" - ] - }, - { - "name": "FLAnimatedImage", - "platforms": "ios", - "dependencies": { - "PINRemoteImage/Core": [ - - ], - "FLAnimatedImage": [ - ">= 1.0" - ] - }, - "source_files": [ - "Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.h", - "Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.m" - ] - }, - { - "name": "WebP", - "xcconfig": { - "GCC_PREPROCESSOR_DEFINITIONS": "$(inherited) PIN_WEBP=1" - }, - "dependencies": { - "PINRemoteImage/Core": [ - - ], - "libwebp": [ - - ] - } - } - ] -} diff --git a/Example-tvOS/Pods/Manifest.lock b/Example-tvOS/Pods/Manifest.lock deleted file mode 100644 index f7c801ef..00000000 --- a/Example-tvOS/Pods/Manifest.lock +++ /dev/null @@ -1,19 +0,0 @@ -PODS: - - PINCache (2.2.2) - - PINRemoteImage/Core (3.0.0-beta): - - PINCache (>= 2.1) - - PINRemoteImage/iOS (3.0.0-beta): - - PINRemoteImage/Core - -DEPENDENCIES: - - PINRemoteImage/iOS (from `../`) - -EXTERNAL SOURCES: - PINRemoteImage: - :path: ../ - -SPEC CHECKSUMS: - PINCache: 078426d356ab95ef875e9e62e5c35a2ea3333c28 - PINRemoteImage: 43b7123d7cc96a8394b3c6afaa20101679e6d463 - -COCOAPODS: 0.39.0 diff --git a/Example-tvOS/Pods/PINCache/LICENSE.txt b/Example-tvOS/Pods/PINCache/LICENSE.txt deleted file mode 100644 index 3af296ea..00000000 --- a/Example-tvOS/Pods/PINCache/LICENSE.txt +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [2013] [Tumblr, Inc.] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/Example-tvOS/Pods/PINCache/PINCache/Nullability.h b/Example-tvOS/Pods/PINCache/PINCache/Nullability.h deleted file mode 100644 index 437a16f3..00000000 --- a/Example-tvOS/Pods/PINCache/PINCache/Nullability.h +++ /dev/null @@ -1,20 +0,0 @@ -// PINCache is a modified version of TMCache -// Modifications by Garrett Moon -// Copyright (c) 2015 Pinterest. All rights reserved. - -#ifndef PINCache_nullability_h -#define PINCache_nullability_h - -#if !__has_feature(nullability) -#define NS_ASSUME_NONNULL_BEGIN -#define NS_ASSUME_NONNULL_END -#define nullable -#define nonnull -#define null_unspecified -#define null_resettable -#define __nullable -#define __nonnull -#define __null_unspecified -#endif - -#endif diff --git a/Example-tvOS/Pods/PINCache/PINCache/PINCache.h b/Example-tvOS/Pods/PINCache/PINCache/PINCache.h deleted file mode 100644 index 9af2d18d..00000000 --- a/Example-tvOS/Pods/PINCache/PINCache/PINCache.h +++ /dev/null @@ -1,203 +0,0 @@ -// PINCache is a modified version of TMCache -// Modifications by Garrett Moon -// Copyright (c) 2015 Pinterest. All rights reserved. - -#import - -#import "PINDiskCache.h" -#import "PINMemoryCache.h" - -NS_ASSUME_NONNULL_BEGIN - -@class PINCache; - -/** - A callback block which provides only the cache as an argument - */ - -typedef void (^PINCacheBlock)(PINCache *cache); - -/** - A callback block which provides the cache, key and object as arguments - */ - -typedef void (^PINCacheObjectBlock)(PINCache *cache, NSString *key, id __nullable object); - -/** - `PINCache` is a thread safe key/value store designed for persisting temporary objects that are expensive to - reproduce, such as downloaded data or the results of slow processing. It is comprised of two self-similar - stores, one in memory () and one on disk (). - - `PINCache` itself actually does very little; its main function is providing a front end for a common use case: - a small, fast memory cache that asynchronously persists itself to a large, slow disk cache. When objects are - removed from the memory cache in response to an "apocalyptic" event they remain in the disk cache and are - repopulated in memory the next time they are accessed. `PINCache` also does the tedious work of creating a - dispatch group to wait for both caches to finish their operations without blocking each other. - - The parallel caches are accessible as public properties ( and ) and can be manipulated - separately if necessary. See the docs for and for more details. - - @warning when using in extension or watch extension, define PIN_APP_EXTENSIONS=1 - */ - -@interface PINCache : NSObject - -#pragma mark - -/// @name Core - -/** - The name of this cache, used to create the and also appearing in stack traces. - */ -@property (readonly) NSString *name; - -/** - A concurrent queue on which blocks passed to the asynchronous access methods are run. - */ -@property (readonly) dispatch_queue_t concurrentQueue; - -/** - Synchronously retrieves the total byte count of the on the shared disk queue. - */ -@property (readonly) NSUInteger diskByteCount; - -/** - The underlying disk cache, see for additional configuration and trimming options. - */ -@property (readonly) PINDiskCache *diskCache; - -/** - The underlying memory cache, see for additional configuration and trimming options. - */ -@property (readonly) PINMemoryCache *memoryCache; - -#pragma mark - -/// @name Initialization - -/** - A shared cache. - - @result The shared singleton cache instance. - */ -+ (instancetype)sharedCache; - -- (instancetype)init NS_UNAVAILABLE; - -/** - Multiple instances with the same name are allowed and can safely access - the same data on disk thanks to the magic of seriality. Also used to create the . - - @see name - @param name The name of the cache. - @result A new cache with the specified name. - */ -- (instancetype)initWithName:(NSString *)name; - -/** - Multiple instances with the same name are allowed and can safely access - the same data on disk thanks to the magic of seriality. Also used to create the . - - @see name - @param name The name of the cache. - @param rootPath The path of the cache on disk. - @result A new cache with the specified name. - */ -- (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath NS_DESIGNATED_INITIALIZER; - -#pragma mark - -/// @name Asynchronous Methods - -/** - Retrieves the object for the specified key. This method returns immediately and executes the passed - block after the object is available, potentially in parallel with other blocks on the . - - @param key The key associated with the requested object. - @param block A block to be executed concurrently when the object is available. - */ -- (void)objectForKey:(NSString *)key block:(PINCacheObjectBlock)block; - -/** - Stores an object in the cache for the specified key. This method returns immediately and executes the - passed block after the object has been stored, potentially in parallel with other blocks on the . - - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - @param block A block to be executed concurrently after the object has been stored, or nil. - */ -- (void)setObject:(id )object forKey:(NSString *)key block:(nullable PINCacheObjectBlock)block; - -/** - Removes the object for the specified key. This method returns immediately and executes the passed - block after the object has been removed, potentially in parallel with other blocks on the . - - @param key The key associated with the object to be removed. - @param block A block to be executed concurrently after the object has been removed, or nil. - */ -- (void)removeObjectForKey:(NSString *)key block:(nullable PINCacheObjectBlock)block; - -/** - Removes all objects from the cache that have not been used since the specified date. This method returns immediately and - executes the passed block after the cache has been trimmed, potentially in parallel with other blocks on the . - - @param date Objects that haven't been accessed since this date are removed from the cache. - @param block A block to be executed concurrently after the cache has been trimmed, or nil. - */ -- (void)trimToDate:(NSDate *)date block:(nullable PINCacheBlock)block; - -/** - Removes all objects from the cache.This method returns immediately and executes the passed block after the - cache has been cleared, potentially in parallel with other blocks on the . - - @param block A block to be executed concurrently after the cache has been cleared, or nil. - */ -- (void)removeAllObjects:(nullable PINCacheBlock)block; - -#pragma mark - -/// @name Synchronous Methods - -/** - Retrieves the object for the specified key. This method blocks the calling thread until the object is available. - Uses a semaphore to achieve synchronicity on the disk cache. - - @see objectForKey:block: - @param key The key associated with the object. - @result The object for the specified key. - */ -- (__nullable id)objectForKey:(NSString *)key; - -/** - Stores an object in the cache for the specified key. This method blocks the calling thread until the object has been set. - Uses a semaphore to achieve synchronicity on the disk cache. - - @see setObject:forKey:block: - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - */ -- (void)setObject:(id )object forKey:(NSString *)key; - -/** - Removes the object for the specified key. This method blocks the calling thread until the object - has been removed. - Uses a semaphore to achieve synchronicity on the disk cache. - - @param key The key associated with the object to be removed. - */ -- (void)removeObjectForKey:(NSString *)key; - -/** - Removes all objects from the cache that have not been used since the specified date. - This method blocks the calling thread until the cache has been trimmed. - Uses a semaphore to achieve synchronicity on the disk cache. - - @param date Objects that haven't been accessed since this date are removed from the cache. - */ -- (void)trimToDate:(NSDate *)date; - -/** - Removes all objects from the cache. This method blocks the calling thread until the cache has been cleared. - Uses a semaphore to achieve synchronicity on the disk cache. - */ -- (void)removeAllObjects; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example-tvOS/Pods/PINCache/PINCache/PINCache.m b/Example-tvOS/Pods/PINCache/PINCache/PINCache.m deleted file mode 100644 index 53cdcd6c..00000000 --- a/Example-tvOS/Pods/PINCache/PINCache/PINCache.m +++ /dev/null @@ -1,359 +0,0 @@ -// PINCache is a modified version of PINCache -// Modifications by Garrett Moon -// Copyright (c) 2015 Pinterest. All rights reserved. - -#import "PINCache.h" - -static NSString * const PINCachePrefix = @"com.pinterest.PINCache"; -static NSString * const PINCacheSharedName = @"PINCacheShared"; - -@interface PINCache () -#if OS_OBJECT_USE_OBJC -@property (strong, nonatomic) dispatch_queue_t concurrentQueue; -#else -@property (assign, nonatomic) dispatch_queue_t concurrentQueue; -#endif -@end - -@implementation PINCache - -#pragma mark - Initialization - - -#if !OS_OBJECT_USE_OBJC -- (void)dealloc -{ - dispatch_release(_concurrentQueue); - _concurrentQueue = nil; -} -#endif - -- (instancetype)init -{ - @throw [NSException exceptionWithName:@"Must initialize with a name" reason:@"PINCache must be initialized with a name. Call initWithName: instead." userInfo:nil]; - return [self initWithName:@""]; -} - -- (instancetype)initWithName:(NSString *)name -{ - return [self initWithName:name rootPath:[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]]; -} - -- (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath -{ - if (!name) - return nil; - - if (self = [super init]) { - _name = [name copy]; - - NSString *queueName = [[NSString alloc] initWithFormat:@"%@.%p", PINCachePrefix, self]; - _concurrentQueue = dispatch_queue_create([[NSString stringWithFormat:@"%@ Asynchronous Queue", queueName] UTF8String], DISPATCH_QUEUE_CONCURRENT); - - _diskCache = [[PINDiskCache alloc] initWithName:_name rootPath:rootPath]; - _memoryCache = [[PINMemoryCache alloc] init]; - } - return self; -} - -- (NSString *)description -{ - return [[NSString alloc] initWithFormat:@"%@.%@.%p", PINCachePrefix, _name, self]; -} - -+ (instancetype)sharedCache -{ - static id cache; - static dispatch_once_t predicate; - - dispatch_once(&predicate, ^{ - cache = [[self alloc] initWithName:PINCacheSharedName]; - }); - - return cache; -} - -#pragma mark - Public Asynchronous Methods - - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wshadow" - -- (void)objectForKey:(NSString *)key block:(PINCacheObjectBlock)block -{ - if (!key || !block) - return; - - __weak PINCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - __weak PINCache *weakSelf = strongSelf; - - [strongSelf->_memoryCache objectForKey:key block:^(PINMemoryCache *memoryCache, NSString *memoryCacheKey, id memoryCacheObject) { - PINCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - if (memoryCacheObject) { - [strongSelf->_diskCache fileURLForKey:memoryCacheKey block:^(PINDiskCache *diskCache, NSString *diskCacheKey, id diskCacheObject, NSURL *fileURL) { - // update the access time on disk - }]; - - __weak PINCache *weakSelf = strongSelf; - - dispatch_async(strongSelf->_concurrentQueue, ^{ - PINCache *strongSelf = weakSelf; - if (strongSelf) - block(strongSelf, memoryCacheKey, memoryCacheObject); - }); - } else { - __weak PINCache *weakSelf = strongSelf; - - [strongSelf->_diskCache objectForKey:memoryCacheKey block:^(PINDiskCache *diskCache, NSString *diskCacheKey, id diskCacheObject, NSURL *fileURL) { - PINCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf->_memoryCache setObject:diskCacheObject forKey:diskCacheKey block:nil]; - - __weak PINCache *weakSelf = strongSelf; - - dispatch_async(strongSelf->_concurrentQueue, ^{ - PINCache *strongSelf = weakSelf; - if (strongSelf) - block(strongSelf, diskCacheKey, diskCacheObject); - }); - }]; - } - }]; - }); -} - -#pragma clang diagnostic pop - -- (void)setObject:(id )object forKey:(NSString *)key block:(PINCacheObjectBlock)block -{ - if (!key || !object) - return; - - dispatch_group_t group = nil; - PINMemoryCacheObjectBlock memBlock = nil; - PINDiskCacheObjectBlock diskBlock = nil; - - if (block) { - group = dispatch_group_create(); - dispatch_group_enter(group); - dispatch_group_enter(group); - - memBlock = ^(PINMemoryCache *memoryCache, NSString *memoryCacheKey, id memoryCacheObject) { - dispatch_group_leave(group); - }; - - diskBlock = ^(PINDiskCache *diskCache, NSString *diskCacheKey, id memoryCacheObject, NSURL *memoryCacheFileURL) { - dispatch_group_leave(group); - }; - } - - [_memoryCache setObject:object forKey:key block:memBlock]; - [_diskCache setObject:object forKey:key block:diskBlock]; - - if (group) { - __weak PINCache *weakSelf = self; - dispatch_group_notify(group, _concurrentQueue, ^{ - PINCache *strongSelf = weakSelf; - if (strongSelf) - block(strongSelf, key, object); - }); - -#if !OS_OBJECT_USE_OBJC - dispatch_release(group); -#endif - } -} - -- (void)removeObjectForKey:(NSString *)key block:(PINCacheObjectBlock)block -{ - if (!key) - return; - - dispatch_group_t group = nil; - PINMemoryCacheObjectBlock memBlock = nil; - PINDiskCacheObjectBlock diskBlock = nil; - - if (block) { - group = dispatch_group_create(); - dispatch_group_enter(group); - dispatch_group_enter(group); - - memBlock = ^(PINMemoryCache *memoryCache, NSString *memoryCacheKey, id memoryCacheObject) { - dispatch_group_leave(group); - }; - - diskBlock = ^(PINDiskCache *diskCache, NSString *diskCacheKey, id memoryCacheObject, NSURL *memoryCacheFileURL) { - dispatch_group_leave(group); - }; - } - - [_memoryCache removeObjectForKey:key block:memBlock]; - [_diskCache removeObjectForKey:key block:diskBlock]; - - if (group) { - __weak PINCache *weakSelf = self; - dispatch_group_notify(group, _concurrentQueue, ^{ - PINCache *strongSelf = weakSelf; - if (strongSelf) - block(strongSelf, key, nil); - }); - -#if !OS_OBJECT_USE_OBJC - dispatch_release(group); -#endif - } -} - -- (void)removeAllObjects:(PINCacheBlock)block -{ - dispatch_group_t group = nil; - PINMemoryCacheBlock memBlock = nil; - PINDiskCacheBlock diskBlock = nil; - - if (block) { - group = dispatch_group_create(); - dispatch_group_enter(group); - dispatch_group_enter(group); - - memBlock = ^(PINMemoryCache *cache) { - dispatch_group_leave(group); - }; - - diskBlock = ^(PINDiskCache *cache) { - dispatch_group_leave(group); - }; - } - - [_memoryCache removeAllObjects:memBlock]; - [_diskCache removeAllObjects:diskBlock]; - - if (group) { - __weak PINCache *weakSelf = self; - dispatch_group_notify(group, _concurrentQueue, ^{ - PINCache *strongSelf = weakSelf; - if (strongSelf) - block(strongSelf); - }); - -#if !OS_OBJECT_USE_OBJC - dispatch_release(group); -#endif - } -} - -- (void)trimToDate:(NSDate *)date block:(PINCacheBlock)block -{ - if (!date) - return; - - dispatch_group_t group = nil; - PINMemoryCacheBlock memBlock = nil; - PINDiskCacheBlock diskBlock = nil; - - if (block) { - group = dispatch_group_create(); - dispatch_group_enter(group); - dispatch_group_enter(group); - - memBlock = ^(PINMemoryCache *cache) { - dispatch_group_leave(group); - }; - - diskBlock = ^(PINDiskCache *cache) { - dispatch_group_leave(group); - }; - } - - [_memoryCache trimToDate:date block:memBlock]; - [_diskCache trimToDate:date block:diskBlock]; - - if (group) { - __weak PINCache *weakSelf = self; - dispatch_group_notify(group, _concurrentQueue, ^{ - PINCache *strongSelf = weakSelf; - if (strongSelf) - block(strongSelf); - }); - -#if !OS_OBJECT_USE_OBJC - dispatch_release(group); -#endif - } -} - -#pragma mark - Public Synchronous Accessors - - -- (NSUInteger)diskByteCount -{ - __block NSUInteger byteCount = 0; - - [_diskCache synchronouslyLockFileAccessWhileExecutingBlock:^(PINDiskCache *diskCache) { - byteCount = diskCache.byteCount; - }]; - - return byteCount; -} - -- (__nullable id)objectForKey:(NSString *)key -{ - if (!key) - return nil; - - __block id object = nil; - - object = [_memoryCache objectForKey:key]; - - if (object) { - // update the access time on disk - [_diskCache fileURLForKey:key block:NULL]; - } else { - object = [_diskCache objectForKey:key]; - [_memoryCache setObject:object forKey:key]; - } - - return object; -} - -- (void)setObject:(id )object forKey:(NSString *)key -{ - if (!key || !object) - return; - - [_memoryCache setObject:object forKey:key]; - [_diskCache setObject:object forKey:key]; -} - -- (void)removeObjectForKey:(NSString *)key -{ - if (!key) - return; - - [_memoryCache removeObjectForKey:key]; - [_diskCache removeObjectForKey:key]; -} - -- (void)trimToDate:(NSDate *)date -{ - if (!date) - return; - - [_memoryCache trimToDate:date]; - [_diskCache trimToDate:date]; -} - -- (void)removeAllObjects -{ - [_memoryCache removeAllObjects]; - [_diskCache removeAllObjects]; -} - -@end diff --git a/Example-tvOS/Pods/PINCache/PINCache/PINDiskCache.h b/Example-tvOS/Pods/PINCache/PINCache/PINDiskCache.h deleted file mode 100644 index 8f2da086..00000000 --- a/Example-tvOS/Pods/PINCache/PINCache/PINDiskCache.h +++ /dev/null @@ -1,373 +0,0 @@ -// PINCache is a modified version of TMCache -// Modifications by Garrett Moon -// Copyright (c) 2015 Pinterest. All rights reserved. - -#import -#import "Nullability.h" - -NS_ASSUME_NONNULL_BEGIN - -@class PINDiskCache; - -/** - A callback block which provides only the cache as an argument - */ - -typedef void (^PINDiskCacheBlock)(PINDiskCache *cache); - -/** - A callback block which provides the cache, key and object as arguments - */ - -typedef void (^PINDiskCacheObjectBlock)(PINDiskCache *cache, NSString *key, id __nullable object, NSURL * __nullable fileURL); - -/** - `PINDiskCache` is a thread safe key/value store backed by the file system. It accepts any object conforming - to the `NSCoding` protocol, which includes the basic Foundation data types and collection classes and also - many UIKit classes, notably `UIImage`. All work is performed on a serial queue shared by all instances in - the app, and archiving is handled by `NSKeyedArchiver`. This is a particular advantage for `UIImage` because - it skips `UIImagePNGRepresentation()` and retains information like scale and orientation. - - The designated initializer for `PINDiskCache` is . The string is used to create a directory - under Library/Caches that scopes disk access for this instance. Multiple instances with the same name are *not* - allowed as they would conflict with each other. - - Unless otherwise noted, all properties and methods are safe to access from any thread at any time. All blocks - will cause the queue to wait, making it safe to access and manipulate the actual cache files on disk for the - duration of the block. - - Because this cache is bound by disk I/O it can be much slower than , although values stored in - `PINDiskCache` persist after application relaunch. Using is recommended over using `PINDiskCache` - by itself, as it adds a fast layer of additional memory caching while still writing to disk. - - All access to the cache is dated so the that the least-used objects can be trimmed first. Setting an optional - will trigger a GCD timer to periodically to trim the cache with . - */ - -@interface PINDiskCache : NSObject - - - -#pragma mark - -/// @name Core - -/** - The name of this cache, used to create a directory under Library/Caches and also appearing in stack traces. - */ -@property (readonly) NSString *name; - -/** - The URL of the directory used by this cache, usually `Library/Caches/com.pinterest.PINDiskCache.(name)` - - @warning Do not interact with files under this URL except in or - . - */ -@property (readonly) NSURL *cacheURL; - -/** - The total number of bytes used on disk, as reported by `NSURLTotalFileAllocatedSizeKey`. - - @warning This property should only be read from a call to or - its asynchronous equivolent - - For example: - - // some background thread - - __block NSUInteger byteCount = 0; - - [_diskCache synchronouslyLockFileAccessWhileExecutingBlock:^(PINDiskCache *diskCache) { - byteCount = diskCache.byteCount; - }]; - */ -@property (readonly) NSUInteger byteCount; - -/** - The maximum number of bytes allowed on disk. This value is checked every time an object is set, if the written - size exceeds the limit a trim call is queued. Defaults to `0.0`, meaning no practical limit. - - */ -@property (assign) NSUInteger byteLimit; - -/** - The maximum number of seconds an object is allowed to exist in the cache. Setting this to a value - greater than `0.0` will start a recurring GCD timer with the same period that calls . - Setting it back to `0.0` will stop the timer. Defaults to `0.0`, meaning no limit. - - */ -@property (assign) NSTimeInterval ageLimit; - -/** - If ttlCache is YES, the cache behaves like a ttlCache. This means that once an object enters the - cache, it only lives as long as self.ageLimit. This has the following implications: - - Accessing an object in the cache does not extend that object's lifetime in the cache - - When attempting to access an object in the cache that has lived longer than self.ageLimit, - the cache will behave as if the object does not exist - - */ -@property (nonatomic, assign, getter=isTTLCache) BOOL ttlCache; - -#pragma mark - -/// @name Event Blocks - -/** - A block to be executed just before an object is added to the cache. The queue waits during execution. - */ -@property (copy) PINDiskCacheObjectBlock __nullable willAddObjectBlock; - -/** - A block to be executed just before an object is removed from the cache. The queue waits during execution. - */ -@property (copy) PINDiskCacheObjectBlock __nullable willRemoveObjectBlock; - -/** - A block to be executed just before all objects are removed from the cache as a result of . - The queue waits during execution. - */ -@property (copy) PINDiskCacheBlock __nullable willRemoveAllObjectsBlock; - -/** - A block to be executed just after an object is added to the cache. The queue waits during execution. - */ -@property (copy) PINDiskCacheObjectBlock __nullable didAddObjectBlock; - -/** - A block to be executed just after an object is removed from the cache. The queue waits during execution. - */ -@property (copy) PINDiskCacheObjectBlock __nullable didRemoveObjectBlock; - -/** - A block to be executed just after all objects are removed from the cache as a result of . - The queue waits during execution. - */ -@property (copy) PINDiskCacheBlock __nullable didRemoveAllObjectsBlock; - -#pragma mark - -/// @name Initialization - -/** - A shared cache. - - @result The shared singleton cache instance. - */ -+ (instancetype)sharedCache; - -/** - Empties the trash with `DISPATCH_QUEUE_PRIORITY_BACKGROUND`. Does not use lock. - */ -+ (void)emptyTrash; - -- (instancetype)init NS_UNAVAILABLE; - -/** - Multiple instances with the same name are allowed and can safely access - the same data on disk thanks to the magic of seriality. - - @see name - @param name The name of the cache. - @result A new cache with the specified name. - */ -- (instancetype)initWithName:(NSString *)name; - -/** - The designated initializer. Multiple instances with the same name are allowed and can safely access - the same data on disk thanks to the magic of seriality. - - @see name - @param name The name of the cache. - @param rootPath The path of the cache. - @result A new cache with the specified name. - */ -- (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath NS_DESIGNATED_INITIALIZER; - -#pragma mark - -/// @name Asynchronous Methods -/** - Locks access to ivars and allows safe interaction with files on disk. This method returns immediately. - - @warning Calling synchronous methods on the diskCache inside this block will likely cause a deadlock. - - @param block A block to be executed when a lock is available. - */ -- (void)lockFileAccessWhileExecutingBlock:(nullable PINDiskCacheBlock)block; - -/** - Retrieves the object for the specified key. This method returns immediately and executes the passed - block as soon as the object is available. - - @warning The fileURL is only valid for the duration of this block, do not use it after the block ends. - - @param key The key associated with the requested object. - @param block A block to be executed serially when the object is available. - */ -- (void)objectForKey:(NSString *)key block:(nullable PINDiskCacheObjectBlock)block; - -/** - Retrieves the fileURL for the specified key without actually reading the data from disk. This method - returns immediately and executes the passed block as soon as the object is available. - - @warning Access is protected for the duration of the block, but to maintain safe disk access do not - access this fileURL after the block has ended. - - @param key The key associated with the requested object. - @param block A block to be executed serially when the file URL is available. - */ -- (void)fileURLForKey:(nullable NSString *)key block:(nullable PINDiskCacheObjectBlock)block; - -/** - Stores an object in the cache for the specified key. This method returns immediately and executes the - passed block as soon as the object has been stored. - - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - @param block A block to be executed serially after the object has been stored, or nil. - */ -- (void)setObject:(id )object forKey:(NSString *)key block:(nullable PINDiskCacheObjectBlock)block; - -/** - Removes the object for the specified key. This method returns immediately and executes the passed block - as soon as the object has been removed. - - @param key The key associated with the object to be removed. - @param block A block to be executed serially after the object has been removed, or nil. - */ -- (void)removeObjectForKey:(NSString *)key block:(nullable PINDiskCacheObjectBlock)block; - -/** - Removes all objects from the cache that have not been used since the specified date. - This method returns immediately and executes the passed block as soon as the cache has been trimmed. - - @param date Objects that haven't been accessed since this date are removed from the cache. - @param block A block to be executed serially after the cache has been trimmed, or nil. - */ -- (void)trimToDate:(NSDate *)date block:(nullable PINDiskCacheBlock)block; - -/** - Removes objects from the cache, largest first, until the cache is equal to or smaller than the specified byteCount. - This method returns immediately and executes the passed block as soon as the cache has been trimmed. - - @param byteCount The cache will be trimmed equal to or smaller than this size. - @param block A block to be executed serially after the cache has been trimmed, or nil. - */ -- (void)trimToSize:(NSUInteger)byteCount block:(nullable PINDiskCacheBlock)block; - -/** - Removes objects from the cache, ordered by date (least recently used first), until the cache is equal to or smaller - than the specified byteCount. This method returns immediately and executes the passed block as soon as the cache has - been trimmed. - - @param byteCount The cache will be trimmed equal to or smaller than this size. - @param block A block to be executed serially after the cache has been trimmed, or nil. - */ -- (void)trimToSizeByDate:(NSUInteger)byteCount block:(nullable PINDiskCacheBlock)block; - -/** - Removes all objects from the cache. This method returns immediately and executes the passed block as soon as the - cache has been cleared. - - @param block A block to be executed serially after the cache has been cleared, or nil. - */ -- (void)removeAllObjects:(nullable PINDiskCacheBlock)block; - -/** - Loops through all objects in the cache (reads and writes are suspended during the enumeration). Data is not actually - read from disk, the `object` parameter of the block will be `nil` but the `fileURL` will be available. - This method returns immediately. - - @param block A block to be executed for every object in the cache. - @param completionBlock An optional block to be executed after the enumeration is complete. - */ -- (void)enumerateObjectsWithBlock:(PINDiskCacheObjectBlock)block completionBlock:(nullable PINDiskCacheBlock)completionBlock; - -#pragma mark - -/// @name Synchronous Methods - -/** - Locks access to ivars and allows safe interaction with files on disk. This method only returns once the block - has been run. - - @warning Calling synchronous methods on the diskCache inside this block will likely cause a deadlock. - - @param block A block to be executed when a lock is available. - */ -- (void)synchronouslyLockFileAccessWhileExecutingBlock:(nullable PINDiskCacheBlock)block; - -/** - Retrieves the object for the specified key. This method blocks the calling thread until the - object is available. - - @see objectForKey:block: - @param key The key associated with the object. - @result The object for the specified key. - */ -- (__nullable id )objectForKey:(NSString *)key; - -/** - Retrieves the file URL for the specified key. This method blocks the calling thread until the - url is available. Do not use this URL anywhere except with . This method probably - shouldn't even exist, just use the asynchronous one. - - @see fileURLForKey:block: - @param key The key associated with the object. - @result The file URL for the specified key. - */ -- (NSURL *)fileURLForKey:(nullable NSString *)key; - -/** - Stores an object in the cache for the specified key. This method blocks the calling thread until - the object has been stored. - - @see setObject:forKey:block: - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - */ -- (void)setObject:(id )object forKey:(NSString *)key; - -/** - Removes the object for the specified key. This method blocks the calling thread until the object - has been removed. - - @param key The key associated with the object to be removed. - */ -- (void)removeObjectForKey:(NSString *)key; - -/** - Removes all objects from the cache that have not been used since the specified date. - This method blocks the calling thread until the cache has been trimmed. - @param date Objects that haven't been accessed since this date are removed from the cache. - */ -- (void)trimToDate:(nullable NSDate *)date; - -/** - Removes objects from the cache, largest first, until the cache is equal to or smaller than the - specified byteCount. This method blocks the calling thread until the cache has been trimmed. - - @param byteCount The cache will be trimmed equal to or smaller than this size. - */ -- (void)trimToSize:(NSUInteger)byteCount; - -/** - Removes objects from the cache, ordered by date (least recently used first), until the cache is equal to or - smaller than the specified byteCount. This method blocks the calling thread until the cache has been trimmed. - @param byteCount The cache will be trimmed equal to or smaller than this size. - */ -- (void)trimToSizeByDate:(NSUInteger)byteCount; - -/** - Removes all objects from the cache. This method blocks the calling thread until the cache has been cleared. - */ -- (void)removeAllObjects; - -/** - Loops through all objects in the cache (reads and writes are suspended during the enumeration). Data is not actually - read from disk, the `object` parameter of the block will be `nil` but the `fileURL` will be available. - This method blocks the calling thread until all objects have been enumerated. - @param block A block to be executed for every object in the cache. - @warning Do not call this method within the event blocks (, etc.) - Instead use the asynchronous version, . - */ -- (void)enumerateObjectsWithBlock:(nullable PINDiskCacheObjectBlock)block; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example-tvOS/Pods/PINCache/PINCache/PINDiskCache.m b/Example-tvOS/Pods/PINCache/PINCache/PINDiskCache.m deleted file mode 100644 index 3755abbb..00000000 --- a/Example-tvOS/Pods/PINCache/PINCache/PINDiskCache.m +++ /dev/null @@ -1,1171 +0,0 @@ -// PINCache is a modified version of TMCache -// Modifications by Garrett Moon -// Copyright (c) 2015 Pinterest. All rights reserved. - -#import "PINDiskCache.h" - -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 -#import -#endif - -#define PINDiskCacheError(error) if (error) { NSLog(@"%@ (%d) ERROR: %@", \ -[[NSString stringWithUTF8String:__FILE__] lastPathComponent], \ -__LINE__, [error localizedDescription]); } - -static NSString * const PINDiskCachePrefix = @"com.pinterest.PINDiskCache"; -static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared"; - -@interface PINBackgroundTask : NSObject -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 && !TARGET_OS_WATCH -@property (atomic, assign) UIBackgroundTaskIdentifier taskID; -#endif -+ (instancetype)start; -- (void)end; -@end - -@interface PINDiskCache () - -@property (assign) NSUInteger byteCount; -@property (strong, nonatomic) NSURL *cacheURL; -#if OS_OBJECT_USE_OBJC -@property (strong, nonatomic) dispatch_queue_t asyncQueue; -@property (strong, nonatomic) dispatch_semaphore_t lockSemaphore; -#else -@property (assign, nonatomic) dispatch_queue_t asyncQueue; -@property (assign, nonatomic) dispatch_semaphore_t lockSemaphore; -#endif -@property (strong, nonatomic) NSMutableDictionary *dates; -@property (strong, nonatomic) NSMutableDictionary *sizes; -@end - -@implementation PINDiskCache - -@synthesize willAddObjectBlock = _willAddObjectBlock; -@synthesize willRemoveObjectBlock = _willRemoveObjectBlock; -@synthesize willRemoveAllObjectsBlock = _willRemoveAllObjectsBlock; -@synthesize didAddObjectBlock = _didAddObjectBlock; -@synthesize didRemoveObjectBlock = _didRemoveObjectBlock; -@synthesize didRemoveAllObjectsBlock = _didRemoveAllObjectsBlock; -@synthesize byteLimit = _byteLimit; -@synthesize ageLimit = _ageLimit; -@synthesize ttlCache = _ttlCache; - -#pragma mark - Initialization - - -- (void)dealloc -{ -#if !OS_OBJECT_USE_OBJC - dispatch_release(_lockSemaphore); - dispatch_release(_asyncQueue); - _asyncQueue = nil; -#endif -} - -- (instancetype)init -{ - @throw [NSException exceptionWithName:@"Must initialize with a name" reason:@"PINDiskCache must be initialized with a name. Call initWithName: instead." userInfo:nil]; - return [self initWithName:@""]; -} - -- (instancetype)initWithName:(NSString *)name -{ - return [self initWithName:name rootPath:[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0]]; -} - -- (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath -{ - if (!name) - return nil; - - if (self = [super init]) { - _name = [name copy]; - _asyncQueue = dispatch_queue_create([[NSString stringWithFormat:@"%@ Asynchronous Queue", PINDiskCachePrefix] UTF8String], DISPATCH_QUEUE_CONCURRENT); - _lockSemaphore = dispatch_semaphore_create(1); - _willAddObjectBlock = nil; - _willRemoveObjectBlock = nil; - _willRemoveAllObjectsBlock = nil; - _didAddObjectBlock = nil; - _didRemoveObjectBlock = nil; - _didRemoveAllObjectsBlock = nil; - - _byteCount = 0; - _byteLimit = 0; - _ageLimit = 0.0; - - _dates = [[NSMutableDictionary alloc] init]; - _sizes = [[NSMutableDictionary alloc] init]; - - NSString *pathComponent = [[NSString alloc] initWithFormat:@"%@.%@", PINDiskCachePrefix, _name]; - _cacheURL = [NSURL fileURLWithPathComponents:@[ rootPath, pathComponent ]]; - - //we don't want to do anything without setting up the disk cache, but we also don't want to block init, it can take a while to initialize - //this is only safe because we use a dispatch_semaphore as a lock. If we switch to an NSLock or posix locks, this will *no longer be safe*. - [self lock]; - dispatch_async(_asyncQueue, ^{ - [self createCacheDirectory]; - [self initializeDiskProperties]; - - [self unlock]; - }); - } - return self; -} - -- (NSString *)description -{ - return [[NSString alloc] initWithFormat:@"%@.%@.%p", PINDiskCachePrefix, _name, self]; -} - -+ (instancetype)sharedCache -{ - static id cache; - static dispatch_once_t predicate; - - dispatch_once(&predicate, ^{ - cache = [[self alloc] initWithName:PINDiskCacheSharedName]; - }); - - return cache; -} - -#pragma mark - Private Methods - - -- (NSURL *)encodedFileURLForKey:(NSString *)key -{ - if (![key length]) - return nil; - - return [_cacheURL URLByAppendingPathComponent:[self encodedString:key]]; -} - -- (NSString *)keyForEncodedFileURL:(NSURL *)url -{ - NSString *fileName = [url lastPathComponent]; - if (!fileName) - return nil; - - return [self decodedString:fileName]; -} - -- (NSString *)encodedString:(NSString *)string -{ - if (![string length]) { - return @""; - } - - if ([string respondsToSelector:@selector(stringByAddingPercentEncodingWithAllowedCharacters:)]) { - return [string stringByAddingPercentEncodingWithAllowedCharacters:[[NSCharacterSet characterSetWithCharactersInString:@".:/%"] invertedSet]]; - } - else { - CFStringRef static const charsToEscape = CFSTR(".:/%"); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - CFStringRef escapedString = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, - (__bridge CFStringRef)string, - NULL, - charsToEscape, - kCFStringEncodingUTF8); -#pragma clang diagnostic pop - return (__bridge_transfer NSString *)escapedString; - } -} - -- (NSString *)decodedString:(NSString *)string -{ - if (![string length]) { - return @""; - } - - if ([string respondsToSelector:@selector(stringByRemovingPercentEncoding)]) { - return [string stringByRemovingPercentEncoding]; - } - else { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - CFStringRef unescapedString = CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault, - (__bridge CFStringRef)string, - CFSTR(""), - kCFStringEncodingUTF8); -#pragma clang diagnostic pop - return (__bridge_transfer NSString *)unescapedString; - } -} - -#pragma mark - Private Trash Methods - - -+ (dispatch_queue_t)sharedTrashQueue -{ - static dispatch_queue_t trashQueue; - static dispatch_once_t predicate; - - dispatch_once(&predicate, ^{ - NSString *queueName = [[NSString alloc] initWithFormat:@"%@.trash", PINDiskCachePrefix]; - trashQueue = dispatch_queue_create([queueName UTF8String], DISPATCH_QUEUE_SERIAL); - dispatch_set_target_queue(trashQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)); - }); - - return trashQueue; -} - -+ (NSURL *)sharedTrashURL -{ - static NSURL *sharedTrashURL; - static dispatch_once_t predicate; - - dispatch_once(&predicate, ^{ - sharedTrashURL = [[[NSURL alloc] initFileURLWithPath:NSTemporaryDirectory()] URLByAppendingPathComponent:PINDiskCachePrefix isDirectory:YES]; - - if (![[NSFileManager defaultManager] fileExistsAtPath:[sharedTrashURL path]]) { - NSError *error = nil; - [[NSFileManager defaultManager] createDirectoryAtURL:sharedTrashURL - withIntermediateDirectories:YES - attributes:nil - error:&error]; - PINDiskCacheError(error); - } - }); - - return sharedTrashURL; -} - -+(BOOL)moveItemAtURLToTrash:(NSURL *)itemURL -{ - if (![[NSFileManager defaultManager] fileExistsAtPath:[itemURL path]]) - return NO; - - NSError *error = nil; - NSString *uniqueString = [[NSProcessInfo processInfo] globallyUniqueString]; - NSURL *uniqueTrashURL = [[PINDiskCache sharedTrashURL] URLByAppendingPathComponent:uniqueString]; - BOOL moved = [[NSFileManager defaultManager] moveItemAtURL:itemURL toURL:uniqueTrashURL error:&error]; - PINDiskCacheError(error); - return moved; -} - -+ (void)emptyTrash -{ - PINBackgroundTask *task = [PINBackgroundTask start]; - - dispatch_async([self sharedTrashQueue], ^{ - NSError *searchTrashedItemsError = nil; - NSArray *trashedItems = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:[self sharedTrashURL] - includingPropertiesForKeys:nil - options:0 - error:&searchTrashedItemsError]; - PINDiskCacheError(searchTrashedItemsError); - - for (NSURL *trashedItemURL in trashedItems) { - NSError *removeTrashedItemError = nil; - [[NSFileManager defaultManager] removeItemAtURL:trashedItemURL error:&removeTrashedItemError]; - PINDiskCacheError(removeTrashedItemError); - } - - [task end]; - }); -} - -#pragma mark - Private Queue Methods - - -- (BOOL)createCacheDirectory -{ - if ([[NSFileManager defaultManager] fileExistsAtPath:[_cacheURL path]]) - return NO; - - NSError *error = nil; - BOOL success = [[NSFileManager defaultManager] createDirectoryAtURL:_cacheURL - withIntermediateDirectories:YES - attributes:nil - error:&error]; - PINDiskCacheError(error); - - return success; -} - -- (void)initializeDiskProperties -{ - NSUInteger byteCount = 0; - NSArray *keys = @[ NSURLContentModificationDateKey, NSURLTotalFileAllocatedSizeKey ]; - - NSError *error = nil; - NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:_cacheURL - includingPropertiesForKeys:keys - options:NSDirectoryEnumerationSkipsHiddenFiles - error:&error]; - PINDiskCacheError(error); - - for (NSURL *fileURL in files) { - NSString *key = [self keyForEncodedFileURL:fileURL]; - - error = nil; - NSDictionary *dictionary = [fileURL resourceValuesForKeys:keys error:&error]; - PINDiskCacheError(error); - - NSDate *date = [dictionary objectForKey:NSURLContentModificationDateKey]; - if (date && key) - [_dates setObject:date forKey:key]; - - NSNumber *fileSize = [dictionary objectForKey:NSURLTotalFileAllocatedSizeKey]; - if (fileSize) { - [_sizes setObject:fileSize forKey:key]; - byteCount += [fileSize unsignedIntegerValue]; - } - } - - if (byteCount > 0) - self.byteCount = byteCount; // atomic -} - -- (BOOL)setFileModificationDate:(NSDate *)date forURL:(NSURL *)fileURL -{ - if (!date || !fileURL) { - return NO; - } - - NSError *error = nil; - BOOL success = [[NSFileManager defaultManager] setAttributes:@{ NSFileModificationDate: date } - ofItemAtPath:[fileURL path] - error:&error]; - PINDiskCacheError(error); - - if (success) { - NSString *key = [self keyForEncodedFileURL:fileURL]; - if (key) { - [_dates setObject:date forKey:key]; - } - } - - return success; -} - -- (BOOL)removeFileAndExecuteBlocksForKey:(NSString *)key -{ - NSURL *fileURL = [self encodedFileURLForKey:key]; - if (!fileURL || ![[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]]) - return NO; - - if (_willRemoveObjectBlock) - _willRemoveObjectBlock(self, key, nil, fileURL); - - BOOL trashed = [PINDiskCache moveItemAtURLToTrash:fileURL]; - if (!trashed) - return NO; - - [PINDiskCache emptyTrash]; - - NSNumber *byteSize = [_sizes objectForKey:key]; - if (byteSize) - self.byteCount = _byteCount - [byteSize unsignedIntegerValue]; // atomic - - [_sizes removeObjectForKey:key]; - [_dates removeObjectForKey:key]; - - if (_didRemoveObjectBlock) - _didRemoveObjectBlock(self, key, nil, fileURL); - - return YES; -} - -- (void)trimDiskToSize:(NSUInteger)trimByteCount -{ - if (_byteCount <= trimByteCount) - return; - - NSArray *keysSortedBySize = [_sizes keysSortedByValueUsingSelector:@selector(compare:)]; - - for (NSString *key in [keysSortedBySize reverseObjectEnumerator]) { // largest objects first - [self removeFileAndExecuteBlocksForKey:key]; - - if (_byteCount <= trimByteCount) - break; - } -} - -- (void)trimDiskToSizeByDate:(NSUInteger)trimByteCount -{ - if (_byteCount <= trimByteCount) - return; - - NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)]; - - for (NSString *key in keysSortedByDate) { // oldest objects first - [self removeFileAndExecuteBlocksForKey:key]; - - if (_byteCount <= trimByteCount) - break; - } -} - -- (void)trimDiskToDate:(NSDate *)trimDate -{ - NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)]; - - for (NSString *key in keysSortedByDate) { // oldest files first - NSDate *accessDate = [_dates objectForKey:key]; - if (!accessDate) - continue; - - if ([accessDate compare:trimDate] == NSOrderedAscending) { // older than trim date - [self removeFileAndExecuteBlocksForKey:key]; - } else { - break; - } - } -} - -- (void)trimToAgeLimitRecursively -{ - [self lock]; - NSTimeInterval ageLimit = _ageLimit; - [self unlock]; - if (ageLimit == 0.0) - return; - - [self lock]; - NSDate *date = [[NSDate alloc] initWithTimeIntervalSinceNow:-ageLimit]; - [self trimDiskToDate:date]; - [self unlock]; - - __weak PINDiskCache *weakSelf = self; - - dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_ageLimit * NSEC_PER_SEC)); - dispatch_after(time, _asyncQueue, ^(void) { - PINDiskCache *strongSelf = weakSelf; - [strongSelf trimToAgeLimitRecursively]; - }); -} - -#pragma mark - Public Asynchronous Methods - - -- (void)lockFileAccessWhileExecutingBlock:(void(^)(PINDiskCache *diskCache))block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (block) { - [strongSelf lock]; - block(strongSelf); - [strongSelf unlock]; - } - }); -} - -- (void)objectForKey:(NSString *)key block:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - NSURL *fileURL = nil; - id object = [strongSelf objectForKey:key fileURL:&fileURL]; - - if (block) { - [strongSelf lock]; - block(strongSelf, key, object, fileURL); - [strongSelf unlock]; - } - }); -} - -- (void)fileURLForKey:(NSString *)key block:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - NSURL *fileURL = [strongSelf fileURLForKey:key]; - - if (block) { - [strongSelf lock]; - block(strongSelf, key, nil, fileURL); - [strongSelf unlock]; - } - }); -} - -- (void)setObject:(id )object forKey:(NSString *)key block:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - NSURL *fileURL = nil; - [strongSelf setObject:object forKey:key fileURL:&fileURL]; - - if (block) { - [strongSelf lock]; - block(strongSelf, key, object, fileURL); - [strongSelf unlock]; - } - }); -} - -- (void)removeObjectForKey:(NSString *)key block:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - NSURL *fileURL = nil; - [strongSelf removeObjectForKey:key fileURL:&fileURL]; - - if (block) { - [strongSelf lock]; - block(strongSelf, key, nil, fileURL); - [strongSelf unlock]; - } - }); -} - -- (void)trimToSize:(NSUInteger)trimByteCount block:(PINDiskCacheBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - [strongSelf trimToSize:trimByteCount]; - - if (block) { - [strongSelf lock]; - block(strongSelf); - [strongSelf unlock]; - } - }); -} - -- (void)trimToDate:(NSDate *)trimDate block:(PINDiskCacheBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - [strongSelf trimToDate:trimDate]; - - if (block) { - [strongSelf lock]; - block(strongSelf); - [strongSelf unlock]; - } - }); -} - -- (void)trimToSizeByDate:(NSUInteger)trimByteCount block:(PINDiskCacheBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - [strongSelf trimToSizeByDate:trimByteCount]; - - if (block) { - [strongSelf lock]; - block(strongSelf); - [strongSelf unlock]; - } - }); -} - -- (void)removeAllObjects:(PINDiskCacheBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - [strongSelf removeAllObjects]; - - if (block) { - [strongSelf lock]; - block(strongSelf); - [strongSelf unlock]; - } - }); -} - -- (void)enumerateObjectsWithBlock:(PINDiskCacheObjectBlock)block completionBlock:(PINDiskCacheBlock)completionBlock -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - [strongSelf enumerateObjectsWithBlock:block]; - - if (completionBlock) { - [self lock]; - completionBlock(strongSelf); - [self unlock]; - } - }); -} - -#pragma mark - Public Synchronous Methods - - -- (void)synchronouslyLockFileAccessWhileExecutingBlock:(void(^)(PINDiskCache *diskCache))block -{ - if (block) { - [self lock]; - block(self); - [self unlock]; - } -} - -- (__nullable id)objectForKey:(NSString *)key -{ - return [self objectForKey:key fileURL:nil]; -} - -- (__nullable id )objectForKey:(NSString *)key fileURL:(NSURL **)outFileURL -{ - NSDate *now = [[NSDate alloc] init]; - - if (!key) - return nil; - - id object = nil; - NSURL *fileURL = nil; - - [self lock]; - fileURL = [self encodedFileURLForKey:key]; - object = nil; - - if ([[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]] && - // If the cache should behave like a TTL cache, then only fetch the object if there's a valid ageLimit and the object is still alive - (!self->_ttlCache || self->_ageLimit <= 0 || fabs([[_dates objectForKey:key] timeIntervalSinceDate:now]) < self->_ageLimit)) { - @try { - object = [NSKeyedUnarchiver unarchiveObjectWithFile:[fileURL path]]; - } - @catch (NSException *exception) { - NSError *error = nil; - [[NSFileManager defaultManager] removeItemAtPath:[fileURL path] error:&error]; - PINDiskCacheError(error); - } - if (!self->_ttlCache) { - [self setFileModificationDate:now forURL:fileURL]; - } - } - [self unlock]; - - if (outFileURL) { - *outFileURL = fileURL; - } - - return object; -} - -- (NSURL *)fileURLForKey:(NSString *)key -{ - NSDate *now = [[NSDate alloc] init]; - - if (!key) - return nil; - - NSURL *fileURL = nil; - - [self lock]; - fileURL = [self encodedFileURLForKey:key]; - - if ([[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]]) { - // Don't update the file modification time, if self is a ttlCache - if (!self->_ttlCache) { - [self setFileModificationDate:now forURL:fileURL]; - } - } else { - fileURL = nil; - } - [self unlock]; - return fileURL; -} - -- (void)setObject:(id )object forKey:(NSString *)key -{ - [self setObject:object forKey:key fileURL:nil]; -} - -- (void)setObject:(id )object forKey:(NSString *)key fileURL:(NSURL **)outFileURL -{ - NSDate *now = [[NSDate alloc] init]; - - if (!key || !object) - return; - - PINBackgroundTask *task = [PINBackgroundTask start]; - - NSURL *fileURL = nil; - - [self lock]; - fileURL = [self encodedFileURLForKey:key]; - - if (self->_willAddObjectBlock) - self->_willAddObjectBlock(self, key, object, fileURL); - - BOOL written = [NSKeyedArchiver archiveRootObject:object toFile:[fileURL path]]; - - if (written) { - [self setFileModificationDate:now forURL:fileURL]; - - NSError *error = nil; - NSDictionary *values = [fileURL resourceValuesForKeys:@[ NSURLTotalFileAllocatedSizeKey ] error:&error]; - PINDiskCacheError(error); - - NSNumber *diskFileSize = [values objectForKey:NSURLTotalFileAllocatedSizeKey]; - if (diskFileSize) { - NSNumber *prevDiskFileSize = [self->_sizes objectForKey:key]; - if (prevDiskFileSize) { - self.byteCount = self->_byteCount - [prevDiskFileSize unsignedIntegerValue]; - } - [self->_sizes setObject:diskFileSize forKey:key]; - self.byteCount = self->_byteCount + [diskFileSize unsignedIntegerValue]; // atomic - } - - if (self->_byteLimit > 0 && self->_byteCount > self->_byteLimit) - [self trimToSizeByDate:self->_byteLimit block:nil]; - } else { - fileURL = nil; - } - - if (self->_didAddObjectBlock) - self->_didAddObjectBlock(self, key, object, written ? fileURL : nil); - [self unlock]; - - if (outFileURL) { - *outFileURL = fileURL; - } - - [task end]; -} - -- (void)removeObjectForKey:(NSString *)key -{ - [self removeObjectForKey:key fileURL:nil]; -} - -- (void)removeObjectForKey:(NSString *)key fileURL:(NSURL **)outFileURL -{ - if (!key) - return; - - PINBackgroundTask *task = [PINBackgroundTask start]; - - NSURL *fileURL = nil; - - [self lock]; - fileURL = [self encodedFileURLForKey:key]; - [self removeFileAndExecuteBlocksForKey:key]; - [self unlock]; - - [task end]; - - if (outFileURL) { - *outFileURL = fileURL; - } -} - -- (void)trimToSize:(NSUInteger)trimByteCount -{ - if (trimByteCount == 0) { - [self removeAllObjects]; - return; - } - - PINBackgroundTask *task = [PINBackgroundTask start]; - - [self lock]; - [self trimDiskToSize:trimByteCount]; - [self unlock]; - - [task end]; -} - -- (void)trimToDate:(NSDate *)trimDate -{ - if (!trimDate) - return; - - if ([trimDate isEqualToDate:[NSDate distantPast]]) { - [self removeAllObjects]; - return; - } - - PINBackgroundTask *task = [PINBackgroundTask start]; - - [self lock]; - [self trimDiskToDate:trimDate]; - [self unlock]; - - [task end]; -} - -- (void)trimToSizeByDate:(NSUInteger)trimByteCount -{ - if (trimByteCount == 0) { - [self removeAllObjects]; - return; - } - - PINBackgroundTask *task = [PINBackgroundTask start]; - - [self lock]; - [self trimDiskToSizeByDate:trimByteCount]; - [self unlock]; - - [task end]; -} - -- (void)removeAllObjects -{ - PINBackgroundTask *task = [PINBackgroundTask start]; - - [self lock]; - if (self->_willRemoveAllObjectsBlock) - self->_willRemoveAllObjectsBlock(self); - - [PINDiskCache moveItemAtURLToTrash:self->_cacheURL]; - [PINDiskCache emptyTrash]; - - [self createCacheDirectory]; - - [self->_dates removeAllObjects]; - [self->_sizes removeAllObjects]; - self.byteCount = 0; // atomic - - if (self->_didRemoveAllObjectsBlock) - self->_didRemoveAllObjectsBlock(self); - [self unlock]; - - [task end]; -} - -- (void)enumerateObjectsWithBlock:(PINDiskCacheObjectBlock)block -{ - if (!block) - return; - - PINBackgroundTask *task = [PINBackgroundTask start]; - - [self lock]; - NSDate *now = [NSDate date]; - NSArray *keysSortedByDate = [self->_dates keysSortedByValueUsingSelector:@selector(compare:)]; - - for (NSString *key in keysSortedByDate) { - NSURL *fileURL = [self encodedFileURLForKey:key]; - // If the cache should behave like a TTL cache, then only fetch the object if there's a valid ageLimit and the object is still alive - if (!self->_ttlCache || self->_ageLimit <= 0 || fabs([[_dates objectForKey:key] timeIntervalSinceDate:now]) < self->_ageLimit) { - block(self, key, nil, fileURL); - } - } - [self unlock]; - - [task end]; -} - -#pragma mark - Public Thread Safe Accessors - - -- (PINDiskCacheObjectBlock)willAddObjectBlock -{ - PINDiskCacheObjectBlock block = nil; - - [self lock]; - block = _willAddObjectBlock; - [self unlock]; - - return block; -} - -- (void)setWillAddObjectBlock:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - [strongSelf lock]; - strongSelf->_willAddObjectBlock = [block copy]; - [strongSelf unlock]; - }); -} - -- (PINDiskCacheObjectBlock)willRemoveObjectBlock -{ - PINDiskCacheObjectBlock block = nil; - - [self lock]; - block = _willRemoveObjectBlock; - [self unlock]; - - return block; -} - -- (void)setWillRemoveObjectBlock:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_willRemoveObjectBlock = [block copy]; - [strongSelf unlock]; - }); -} - -- (PINDiskCacheBlock)willRemoveAllObjectsBlock -{ - PINDiskCacheBlock block = nil; - - [self lock]; - block = _willRemoveAllObjectsBlock; - [self unlock]; - - return block; -} - -- (void)setWillRemoveAllObjectsBlock:(PINDiskCacheBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_willRemoveAllObjectsBlock = [block copy]; - [strongSelf unlock]; - }); -} - -- (PINDiskCacheObjectBlock)didAddObjectBlock -{ - PINDiskCacheObjectBlock block = nil; - - [self lock]; - block = _didAddObjectBlock; - [self unlock]; - - return block; -} - -- (void)setDidAddObjectBlock:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_didAddObjectBlock = [block copy]; - [strongSelf unlock]; - }); -} - -- (PINDiskCacheObjectBlock)didRemoveObjectBlock -{ - PINDiskCacheObjectBlock block = nil; - - [self lock]; - block = _didRemoveObjectBlock; - [self unlock]; - - return block; -} - -- (void)setDidRemoveObjectBlock:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_didRemoveObjectBlock = [block copy]; - [strongSelf unlock]; - }); -} - -- (PINDiskCacheBlock)didRemoveAllObjectsBlock -{ - PINDiskCacheBlock block = nil; - - [self lock]; - block = _didRemoveAllObjectsBlock; - [self unlock]; - - return block; -} - -- (void)setDidRemoveAllObjectsBlock:(PINDiskCacheBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_didRemoveAllObjectsBlock = [block copy]; - [strongSelf unlock]; - }); -} - -- (NSUInteger)byteLimit -{ - NSUInteger byteLimit; - - [self lock]; - byteLimit = _byteLimit; - [self unlock]; - - return byteLimit; -} - -- (void)setByteLimit:(NSUInteger)byteLimit -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_byteLimit = byteLimit; - - if (byteLimit > 0) - [strongSelf trimDiskToSizeByDate:byteLimit]; - [strongSelf unlock]; - }); -} - -- (NSTimeInterval)ageLimit -{ - NSTimeInterval ageLimit; - - [self lock]; - ageLimit = _ageLimit; - [self unlock]; - - return ageLimit; -} - -- (void)setAgeLimit:(NSTimeInterval)ageLimit -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_ageLimit = ageLimit; - [strongSelf unlock]; - - [strongSelf trimToAgeLimitRecursively]; - }); -} - -- (BOOL)isTTLCache { - BOOL isTTLCache; - - [self lock]; - isTTLCache = _ttlCache; - [self unlock]; - - return isTTLCache; -} - -- (void)setTtlCache:(BOOL)ttlCache { - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_ttlCache = ttlCache; - [strongSelf unlock]; - }); -} - -- (void)lock -{ - dispatch_semaphore_wait(_lockSemaphore, DISPATCH_TIME_FOREVER); -} - -- (void)unlock -{ - dispatch_semaphore_signal(_lockSemaphore); -} - -@end - -@implementation PINBackgroundTask - -+ (BOOL)isAppExtension { - - static BOOL isExtension; - static dispatch_once_t onceToken; - - dispatch_once(&onceToken, ^{ - NSDictionary *extensionDictionary = [[NSBundle mainBundle] infoDictionary][@"NSExtension"]; - isExtension = [extensionDictionary isKindOfClass:[NSDictionary class]]; - }); - - return isExtension; -} - -- (instancetype)init -{ - if (self = [super init]) { -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 && !TARGET_OS_WATCH - _taskID = UIBackgroundTaskInvalid; -#endif - } - return self; -} - -+ (instancetype)start -{ - PINBackgroundTask *task = nil; - -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 && !TARGET_OS_WATCH - if ([self.class isAppExtension]) { - return task; - } - - task = [[self alloc] init]; - - UIApplication *sharedApplication = [UIApplication performSelector:@selector(sharedApplication)]; - task.taskID = [sharedApplication beginBackgroundTaskWithExpirationHandler:^{ - UIBackgroundTaskIdentifier taskID = task.taskID; - task.taskID = UIBackgroundTaskInvalid; - [sharedApplication endBackgroundTask:taskID]; - }]; -#endif - - return task; -} - -- (void)end -{ -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 && !TARGET_OS_WATCH - if ([self.class isAppExtension]) { - return; - } - - UIBackgroundTaskIdentifier taskID = self.taskID; - self.taskID = UIBackgroundTaskInvalid; - - UIApplication *sharedApplication = [UIApplication performSelector:@selector(sharedApplication)]; - [sharedApplication endBackgroundTask:taskID]; -#endif -} - -@end diff --git a/Example-tvOS/Pods/PINCache/PINCache/PINMemoryCache.h b/Example-tvOS/Pods/PINCache/PINCache/PINMemoryCache.h deleted file mode 100644 index f0b244c0..00000000 --- a/Example-tvOS/Pods/PINCache/PINCache/PINMemoryCache.h +++ /dev/null @@ -1,334 +0,0 @@ -// PINCache is a modified version of TMCache -// Modifications by Garrett Moon -// Copyright (c) 2015 Pinterest. All rights reserved. - -#import -#import "Nullability.h" - -NS_ASSUME_NONNULL_BEGIN - -@class PINMemoryCache; - -/** - A callback block which provides only the cache as an argument - */ - -typedef void (^PINMemoryCacheBlock)(PINMemoryCache *cache); - -/** - A callback block which provides the cache, key and object as arguments - */ -typedef void (^PINMemoryCacheObjectBlock)(PINMemoryCache *cache, NSString *key, id __nullable object); - -/** - `PINMemoryCache` is a fast, thread safe key/value store similar to `NSCache`. On iOS it will clear itself - automatically to reduce memory usage when the app receives a memory warning or goes into the background. - - Access is natively synchronous. Asynchronous variations are provided. Every asynchronous method accepts a - callback block that runs on a concurrent , with cache reads and writes protected by an semaphore. - - All access to the cache is dated so the that the least-used objects can be trimmed first. Setting an - optional will trigger a GCD timer to periodically to trim the cache to that age. - - Objects can optionally be set with a "cost", which could be a byte count or any other meaningful integer. - Setting a will automatically keep the cache below that value with . - - Values will not persist after application relaunch or returning from the background. See for - a memory cache backed by a disk cache. - */ - -@interface PINMemoryCache : NSObject - -#pragma mark - -/// @name Core - -/** - A concurrent queue on which all callbacks are called. It is exposed here so that it can be set to - target some other queue, such as a global concurrent queue with a priority other than the default. - */ -@property (readonly) dispatch_queue_t concurrentQueue; - -/** - The total accumulated cost. - */ -@property (readonly) NSUInteger totalCost; - -/** - The maximum cost allowed to accumulate before objects begin to be removed with . - */ -@property (assign) NSUInteger costLimit; - -/** - The maximum number of seconds an object is allowed to exist in the cache. Setting this to a value - greater than `0.0` will start a recurring GCD timer with the same period that calls . - Setting it back to `0.0` will stop the timer. Defaults to `0.0`. - */ -@property (assign) NSTimeInterval ageLimit; - -/** - If ttlCache is YES, the cache behaves like a ttlCache. This means that once an object enters the - cache, it only lives as long as self.ageLimit. This has the following implications: - - Accessing an object in the cache does not extend that object's lifetime in the cache - - When attempting to access an object in the cache that has lived longer than self.ageLimit, - the cache will behave as if the object does not exist - - */ -@property (nonatomic, assign, getter=isTTLCache) BOOL ttlCache; - -/** - When `YES` on iOS the cache will remove all objects when the app receives a memory warning. - Defaults to `YES`. - */ -@property (assign) BOOL removeAllObjectsOnMemoryWarning; - -/** - When `YES` on iOS the cache will remove all objects when the app enters the background. - Defaults to `YES`. - */ -@property (assign) BOOL removeAllObjectsOnEnteringBackground; - -#pragma mark - -/// @name Event Blocks - -/** - A block to be executed just before an object is added to the cache. This block will be excuted within - a lock, i.e. all reads and writes are suspended for the duration of the block. - Calling synchronous methods on the cache within this callback will likely cause a deadlock. - */ -@property (copy) PINMemoryCacheObjectBlock __nullable willAddObjectBlock; - -/** - A block to be executed just before an object is removed from the cache. This block will be excuted - within a lock, i.e. all reads and writes are suspended for the duration of the block. - Calling synchronous methods on the cache within this callback will likely cause a deadlock. - */ -@property (copy) PINMemoryCacheObjectBlock __nullable willRemoveObjectBlock; - -/** - A block to be executed just before all objects are removed from the cache as a result of . - This block will be excuted within a lock, i.e. all reads and writes are suspended for the duration of the block. - Calling synchronous methods on the cache within this callback will likely cause a deadlock. - */ -@property (copy) PINMemoryCacheBlock __nullable willRemoveAllObjectsBlock; - -/** - A block to be executed just after an object is added to the cache. This block will be excuted within - a lock, i.e. all reads and writes are suspended for the duration of the block. - Calling synchronous methods on the cache within this callback will likely cause a deadlock. - */ -@property (copy) PINMemoryCacheObjectBlock __nullable didAddObjectBlock; - -/** - A block to be executed just after an object is removed from the cache. This block will be excuted - within a lock, i.e. all reads and writes are suspended for the duration of the block. - Calling synchronous methods on the cache within this callback will likely cause a deadlock. - */ -@property (copy) PINMemoryCacheObjectBlock __nullable didRemoveObjectBlock; - -/** - A block to be executed just after all objects are removed from the cache as a result of . - This block will be excuted within a lock, i.e. all reads and writes are suspended for the duration of the block. - Calling synchronous methods on the cache within this callback will likely cause a deadlock. - */ -@property (copy) PINMemoryCacheBlock __nullable didRemoveAllObjectsBlock; - -/** - A block to be executed upon receiving a memory warning (iOS only) potentially in parallel with other blocks on the . - This block will be executed regardless of the value of . Defaults to `nil`. - */ -@property (copy) PINMemoryCacheBlock __nullable didReceiveMemoryWarningBlock; - -/** - A block to be executed when the app enters the background (iOS only) potentially in parallel with other blocks on the . - This block will be executed regardless of the value of . Defaults to `nil`. - */ -@property (copy) PINMemoryCacheBlock __nullable didEnterBackgroundBlock; - -#pragma mark - -/// @name Shared Cache - -/** - A shared cache. - - @result The shared singleton cache instance. - */ -+ (instancetype)sharedCache; - -#pragma mark - -/// @name Asynchronous Methods - -/** - Retrieves the object for the specified key. This method returns immediately and executes the passed - block after the object is available, potentially in parallel with other blocks on the . - - @param key The key associated with the requested object. - @param block A block to be executed concurrently when the object is available. - */ -- (void)objectForKey:(NSString *)key block:(nullable PINMemoryCacheObjectBlock)block; - -/** - Stores an object in the cache for the specified key. This method returns immediately and executes the - passed block after the object has been stored, potentially in parallel with other blocks on the . - - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - @param block A block to be executed concurrently after the object has been stored, or nil. - */ -- (void)setObject:(id)object forKey:(NSString *)key block:(nullable PINMemoryCacheObjectBlock)block; - -/** - Stores an object in the cache for the specified key and the specified cost. If the cost causes the total - to go over the the cache is trimmed (oldest objects first). This method returns immediately - and executes the passed block after the object has been stored, potentially in parallel with other blocks - on the . - - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - @param cost An amount to add to the . - @param block A block to be executed concurrently after the object has been stored, or nil. - */ -- (void)setObject:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost block:(nullable PINMemoryCacheObjectBlock)block; - -/** - Removes the object for the specified key. This method returns immediately and executes the passed - block after the object has been removed, potentially in parallel with other blocks on the . - - @param key The key associated with the object to be removed. - @param block A block to be executed concurrently after the object has been removed, or nil. - */ -- (void)removeObjectForKey:(NSString *)key block:(nullable PINMemoryCacheObjectBlock)block; - -/** - Removes all objects from the cache that have not been used since the specified date. - This method returns immediately and executes the passed block after the cache has been trimmed, - potentially in parallel with other blocks on the . - - @param date Objects that haven't been accessed since this date are removed from the cache. - @param block A block to be executed concurrently after the cache has been trimmed, or nil. - */ -- (void)trimToDate:(NSDate *)date block:(nullable PINMemoryCacheBlock)block; - -/** - Removes objects from the cache, costliest objects first, until the is below the specified - value. This method returns immediately and executes the passed block after the cache has been trimmed, - potentially in parallel with other blocks on the . - - @param cost The total accumulation allowed to remain after the cache has been trimmed. - @param block A block to be executed concurrently after the cache has been trimmed, or nil. - */ -- (void)trimToCost:(NSUInteger)cost block:(nullable PINMemoryCacheBlock)block; - -/** - Removes objects from the cache, ordered by date (least recently used first), until the is below - the specified value. This method returns immediately and executes the passed block after the cache has been - trimmed, potentially in parallel with other blocks on the . - - @param cost The total accumulation allowed to remain after the cache has been trimmed. - @param block A block to be executed concurrently after the cache has been trimmed, or nil. - */ -- (void)trimToCostByDate:(NSUInteger)cost block:(nullable PINMemoryCacheBlock)block; - -/** - Removes all objects from the cache. This method returns immediately and executes the passed block after - the cache has been cleared, potentially in parallel with other blocks on the . - - @param block A block to be executed concurrently after the cache has been cleared, or nil. - */ -- (void)removeAllObjects:(nullable PINMemoryCacheBlock)block; - -/** - Loops through all objects in the cache with reads and writes suspended. Calling serial methods which - write to the cache inside block may be unsafe and may result in a deadlock. This method returns immediately. - - @param block A block to be executed for every object in the cache. - @param completionBlock An optional block to be executed concurrently when the enumeration is complete. - */ -- (void)enumerateObjectsWithBlock:(PINMemoryCacheObjectBlock)block completionBlock:(nullable PINMemoryCacheBlock)completionBlock; - -#pragma mark - -/// @name Synchronous Methods - -/** - Retrieves the object for the specified key. This method blocks the calling thread until the - object is available. - - @see objectForKey:block: - @param key The key associated with the object. - @result The object for the specified key. - */ -- (__nullable id)objectForKey:(nullable NSString *)key; - -/** - Stores an object in the cache for the specified key. This method blocks the calling thread until the object - has been set. - - @see setObject:forKey:block: - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - */ -- (void)setObject:(id)object forKey:(NSString *)key; - -/** - Stores an object in the cache for the specified key and the specified cost. If the cost causes the total - to go over the the cache is trimmed (oldest objects first). This method blocks the calling thread - until the object has been stored. - - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - @param cost An amount to add to the . - */ -- (void)setObject:(nullable id)object forKey:(nullable NSString *)key withCost:(NSUInteger)cost; - -/** - Removes the object for the specified key. This method blocks the calling thread until the object - has been removed. - - @param key The key associated with the object to be removed. - */ -- (void)removeObjectForKey:(nullable NSString *)key; - -/** - Removes all objects from the cache that have not been used since the specified date. - This method blocks the calling thread until the cache has been trimmed. - - @param date Objects that haven't been accessed since this date are removed from the cache. - */ -- (void)trimToDate:(nullable NSDate *)date; - -/** - Removes objects from the cache, costliest objects first, until the is below the specified - value. This method blocks the calling thread until the cache has been trimmed. - - @param cost The total accumulation allowed to remain after the cache has been trimmed. - */ -- (void)trimToCost:(NSUInteger)cost; - -/** - Removes objects from the cache, ordered by date (least recently used first), until the is below - the specified value. This method blocks the calling thread until the cache has been trimmed. - - @param cost The total accumulation allowed to remain after the cache has been trimmed. - */ -- (void)trimToCostByDate:(NSUInteger)cost; - -/** - Removes all objects from the cache. This method blocks the calling thread until the cache has been cleared. - */ -- (void)removeAllObjects; - -/** - Loops through all objects in the cache within a memory lock (reads and writes are suspended during the enumeration). - This method blocks the calling thread until all objects have been enumerated. - Calling synchronous methods on the cache within this callback will likely cause a deadlock. - - @param block A block to be executed for every object in the cache. - - @warning Do not call this method within the event blocks (, etc.) - Instead use the asynchronous version, . - - */ -- (void)enumerateObjectsWithBlock:(nullable PINMemoryCacheObjectBlock)block; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example-tvOS/Pods/PINCache/PINCache/PINMemoryCache.m b/Example-tvOS/Pods/PINCache/PINCache/PINMemoryCache.m deleted file mode 100644 index 63ea2acf..00000000 --- a/Example-tvOS/Pods/PINCache/PINCache/PINMemoryCache.m +++ /dev/null @@ -1,716 +0,0 @@ -// PINCache is a modified version of TMCache -// Modifications by Garrett Moon -// Copyright (c) 2015 Pinterest. All rights reserved. - -#import "PINMemoryCache.h" - -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 -#import -#endif - -static NSString * const PINMemoryCachePrefix = @"com.pinterest.PINMemoryCache"; - -@interface PINMemoryCache () -#if OS_OBJECT_USE_OBJC -@property (strong, nonatomic) dispatch_queue_t concurrentQueue; -@property (strong, nonatomic) dispatch_semaphore_t lockSemaphore; -#else -@property (assign, nonatomic) dispatch_queue_t concurrentQueue; -@property (assign, nonatomic) dispatch_semaphore_t lockSemaphore; -#endif -@property (strong, nonatomic) NSMutableDictionary *dictionary; -@property (strong, nonatomic) NSMutableDictionary *dates; -@property (strong, nonatomic) NSMutableDictionary *costs; -@end - -@implementation PINMemoryCache - -@synthesize ageLimit = _ageLimit; -@synthesize costLimit = _costLimit; -@synthesize totalCost = _totalCost; -@synthesize ttlCache = _ttlCache; -@synthesize willAddObjectBlock = _willAddObjectBlock; -@synthesize willRemoveObjectBlock = _willRemoveObjectBlock; -@synthesize willRemoveAllObjectsBlock = _willRemoveAllObjectsBlock; -@synthesize didAddObjectBlock = _didAddObjectBlock; -@synthesize didRemoveObjectBlock = _didRemoveObjectBlock; -@synthesize didRemoveAllObjectsBlock = _didRemoveAllObjectsBlock; -@synthesize didReceiveMemoryWarningBlock = _didReceiveMemoryWarningBlock; -@synthesize didEnterBackgroundBlock = _didEnterBackgroundBlock; - -#pragma mark - Initialization - - -- (void)dealloc -{ - [[NSNotificationCenter defaultCenter] removeObserver:self]; - - #if !OS_OBJECT_USE_OBJC - dispatch_release(_concurrentQueue); - dispatch_release(_lockSemaphore); - _concurrentQueue = nil; - #endif -} - -- (instancetype)init -{ - if (self = [super init]) { - _lockSemaphore = dispatch_semaphore_create(1); - NSString *queueName = [[NSString alloc] initWithFormat:@"%@.%p", PINMemoryCachePrefix, self]; - _concurrentQueue = dispatch_queue_create([queueName UTF8String], DISPATCH_QUEUE_CONCURRENT); - - _dictionary = [[NSMutableDictionary alloc] init]; - _dates = [[NSMutableDictionary alloc] init]; - _costs = [[NSMutableDictionary alloc] init]; - - _willAddObjectBlock = nil; - _willRemoveObjectBlock = nil; - _willRemoveAllObjectsBlock = nil; - - _didAddObjectBlock = nil; - _didRemoveObjectBlock = nil; - _didRemoveAllObjectsBlock = nil; - - _didReceiveMemoryWarningBlock = nil; - _didEnterBackgroundBlock = nil; - - _ageLimit = 0.0; - _costLimit = 0; - _totalCost = 0; - - _removeAllObjectsOnMemoryWarning = YES; - _removeAllObjectsOnEnteringBackground = YES; - -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 && !TARGET_OS_WATCH - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(didReceiveEnterBackgroundNotification:) - name:UIApplicationDidEnterBackgroundNotification - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(didReceiveMemoryWarningNotification:) - name:UIApplicationDidReceiveMemoryWarningNotification - object:nil]; - -#endif - } - return self; -} - -+ (instancetype)sharedCache -{ - static id cache; - static dispatch_once_t predicate; - - dispatch_once(&predicate, ^{ - cache = [[self alloc] init]; - }); - - return cache; -} - -#pragma mark - Private Methods - - -- (void)didReceiveMemoryWarningNotification:(NSNotification *)notification { - if (self.removeAllObjectsOnMemoryWarning) - [self removeAllObjects:nil]; - - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - if (!strongSelf) { - return; - } - - [strongSelf lock]; - PINMemoryCacheBlock didReceiveMemoryWarningBlock = strongSelf->_didReceiveMemoryWarningBlock; - [strongSelf unlock]; - - if (didReceiveMemoryWarningBlock) - didReceiveMemoryWarningBlock(strongSelf); - }); -} - -- (void)didReceiveEnterBackgroundNotification:(NSNotification *)notification -{ - if (self.removeAllObjectsOnEnteringBackground) - [self removeAllObjects:nil]; - - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - if (!strongSelf) { - return; - } - - [strongSelf lock]; - PINMemoryCacheBlock didEnterBackgroundBlock = strongSelf->_didEnterBackgroundBlock; - [strongSelf unlock]; - - if (didEnterBackgroundBlock) - didEnterBackgroundBlock(strongSelf); - }); -} - -- (void)removeObjectAndExecuteBlocksForKey:(NSString *)key -{ - [self lock]; - id object = _dictionary[key]; - NSNumber *cost = _costs[key]; - PINMemoryCacheObjectBlock willRemoveObjectBlock = _willRemoveObjectBlock; - PINMemoryCacheObjectBlock didRemoveObjectBlock = _didRemoveObjectBlock; - [self unlock]; - - if (willRemoveObjectBlock) - willRemoveObjectBlock(self, key, object); - - [self lock]; - if (cost) - _totalCost -= [cost unsignedIntegerValue]; - - [_dictionary removeObjectForKey:key]; - [_dates removeObjectForKey:key]; - [_costs removeObjectForKey:key]; - [self unlock]; - - if (didRemoveObjectBlock) - didRemoveObjectBlock(self, key, nil); -} - -- (void)trimMemoryToDate:(NSDate *)trimDate -{ - [self lock]; - NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)]; - NSDictionary *dates = [_dates copy]; - [self unlock]; - - for (NSString *key in keysSortedByDate) { // oldest objects first - NSDate *accessDate = dates[key]; - if (!accessDate) - continue; - - if ([accessDate compare:trimDate] == NSOrderedAscending) { // older than trim date - [self removeObjectAndExecuteBlocksForKey:key]; - } else { - break; - } - } -} - -- (void)trimToCostLimit:(NSUInteger)limit -{ - NSUInteger totalCost = 0; - - [self lock]; - totalCost = _totalCost; - NSArray *keysSortedByCost = [_costs keysSortedByValueUsingSelector:@selector(compare:)]; - [self unlock]; - - if (totalCost <= limit) { - return; - } - - for (NSString *key in [keysSortedByCost reverseObjectEnumerator]) { // costliest objects first - [self removeObjectAndExecuteBlocksForKey:key]; - - [self lock]; - totalCost = _totalCost; - [self unlock]; - - if (totalCost <= limit) - break; - } -} - -- (void)trimToCostLimitByDate:(NSUInteger)limit -{ - NSUInteger totalCost = 0; - - [self lock]; - totalCost = _totalCost; - NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)]; - [self unlock]; - - if (totalCost <= limit) - return; - - for (NSString *key in keysSortedByDate) { // oldest objects first - [self removeObjectAndExecuteBlocksForKey:key]; - - [self lock]; - totalCost = _totalCost; - [self unlock]; - if (totalCost <= limit) - break; - } -} - -- (void)trimToAgeLimitRecursively -{ - [self lock]; - NSTimeInterval ageLimit = _ageLimit; - [self unlock]; - - if (ageLimit == 0.0) - return; - - NSDate *date = [[NSDate alloc] initWithTimeIntervalSinceNow:-ageLimit]; - - [self trimMemoryToDate:date]; - - __weak PINMemoryCache *weakSelf = self; - - dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(ageLimit * NSEC_PER_SEC)); - dispatch_after(time, _concurrentQueue, ^(void){ - PINMemoryCache *strongSelf = weakSelf; - - [strongSelf trimToAgeLimitRecursively]; - }); -} - -#pragma mark - Public Asynchronous Methods - - -- (void)objectForKey:(NSString *)key block:(PINMemoryCacheObjectBlock)block -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - id object = [strongSelf objectForKey:key]; - - if (block) - block(strongSelf, key, object); - }); -} - -- (void)setObject:(id)object forKey:(NSString *)key block:(PINMemoryCacheObjectBlock)block -{ - [self setObject:object forKey:key withCost:0 block:block]; -} - -- (void)setObject:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost block:(PINMemoryCacheObjectBlock)block -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - [strongSelf setObject:object forKey:key withCost:cost]; - - if (block) - block(strongSelf, key, object); - }); -} - -- (void)removeObjectForKey:(NSString *)key block:(PINMemoryCacheObjectBlock)block -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - [strongSelf removeObjectForKey:key]; - - if (block) - block(strongSelf, key, nil); - }); -} - -- (void)trimToDate:(NSDate *)trimDate block:(PINMemoryCacheBlock)block -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - [strongSelf trimToDate:trimDate]; - - if (block) - block(strongSelf); - }); -} - -- (void)trimToCost:(NSUInteger)cost block:(PINMemoryCacheBlock)block -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - [strongSelf trimToCost:cost]; - - if (block) - block(strongSelf); - }); -} - -- (void)trimToCostByDate:(NSUInteger)cost block:(PINMemoryCacheBlock)block -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - [strongSelf trimToCostByDate:cost]; - - if (block) - block(strongSelf); - }); -} - -- (void)removeAllObjects:(PINMemoryCacheBlock)block -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - [strongSelf removeAllObjects]; - - if (block) - block(strongSelf); - }); -} - -- (void)enumerateObjectsWithBlock:(PINMemoryCacheObjectBlock)block completionBlock:(PINMemoryCacheBlock)completionBlock -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - [strongSelf enumerateObjectsWithBlock:block]; - - if (completionBlock) - completionBlock(strongSelf); - }); -} - -#pragma mark - Public Synchronous Methods - - -- (__nullable id)objectForKey:(NSString *)key -{ - if (!key) - return nil; - - NSDate *now = [[NSDate alloc] init]; - [self lock]; - id object = nil; - // If the cache should behave like a TTL cache, then only fetch the object if there's a valid ageLimit and the object is still alive - if (!self->_ttlCache || self->_ageLimit <= 0 || fabs([[_dates objectForKey:key] timeIntervalSinceDate:now]) < self->_ageLimit) { - object = _dictionary[key]; - } - [self unlock]; - - if (object) { - [self lock]; - _dates[key] = now; - [self unlock]; - } - - return object; -} - -- (void)setObject:(id)object forKey:(NSString *)key -{ - [self setObject:object forKey:key withCost:0]; -} - -- (void)setObject:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost -{ - if (!key || !object) - return; - - [self lock]; - PINMemoryCacheObjectBlock willAddObjectBlock = _willAddObjectBlock; - PINMemoryCacheObjectBlock didAddObjectBlock = _didAddObjectBlock; - NSUInteger costLimit = _costLimit; - [self unlock]; - - if (willAddObjectBlock) - willAddObjectBlock(self, key, object); - - [self lock]; - _dictionary[key] = object; - _dates[key] = [[NSDate alloc] init]; - _costs[key] = @(cost); - - _totalCost += cost; - [self unlock]; - - if (didAddObjectBlock) - didAddObjectBlock(self, key, object); - - if (costLimit > 0) - [self trimToCostByDate:costLimit]; -} - -- (void)removeObjectForKey:(NSString *)key -{ - if (!key) - return; - - [self removeObjectAndExecuteBlocksForKey:key]; -} - -- (void)trimToDate:(NSDate *)trimDate -{ - if (!trimDate) - return; - - if ([trimDate isEqualToDate:[NSDate distantPast]]) { - [self removeAllObjects]; - return; - } - - [self trimMemoryToDate:trimDate]; -} - -- (void)trimToCost:(NSUInteger)cost -{ - [self trimToCostLimit:cost]; -} - -- (void)trimToCostByDate:(NSUInteger)cost -{ - [self trimToCostLimitByDate:cost]; -} - -- (void)removeAllObjects -{ - [self lock]; - PINMemoryCacheBlock willRemoveAllObjectsBlock = _willRemoveAllObjectsBlock; - PINMemoryCacheBlock didRemoveAllObjectsBlock = _didRemoveAllObjectsBlock; - [self unlock]; - - if (willRemoveAllObjectsBlock) - willRemoveAllObjectsBlock(self); - - [self lock]; - [_dictionary removeAllObjects]; - [_dates removeAllObjects]; - [_costs removeAllObjects]; - - _totalCost = 0; - [self unlock]; - - if (didRemoveAllObjectsBlock) - didRemoveAllObjectsBlock(self); - -} - -- (void)enumerateObjectsWithBlock:(PINMemoryCacheObjectBlock)block -{ - if (!block) - return; - - [self lock]; - NSDate *now = [[NSDate alloc] init]; - NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)]; - - for (NSString *key in keysSortedByDate) { - // If the cache should behave like a TTL cache, then only fetch the object if there's a valid ageLimit and the object is still alive - if (!self->_ttlCache || self->_ageLimit <= 0 || fabs([[_dates objectForKey:key] timeIntervalSinceDate:now]) < self->_ageLimit) { - block(self, key, _dictionary[key]); - } - } - [self unlock]; -} - -#pragma mark - Public Thread Safe Accessors - - -- (PINMemoryCacheObjectBlock)willAddObjectBlock -{ - [self lock]; - PINMemoryCacheObjectBlock block = _willAddObjectBlock; - [self unlock]; - - return block; -} - -- (void)setWillAddObjectBlock:(PINMemoryCacheObjectBlock)block -{ - [self lock]; - _willAddObjectBlock = [block copy]; - [self unlock]; -} - -- (PINMemoryCacheObjectBlock)willRemoveObjectBlock -{ - [self lock]; - PINMemoryCacheObjectBlock block = _willRemoveObjectBlock; - [self unlock]; - - return block; -} - -- (void)setWillRemoveObjectBlock:(PINMemoryCacheObjectBlock)block -{ - [self lock]; - _willRemoveObjectBlock = [block copy]; - [self unlock]; -} - -- (PINMemoryCacheBlock)willRemoveAllObjectsBlock -{ - [self lock]; - PINMemoryCacheBlock block = _willRemoveAllObjectsBlock; - [self unlock]; - - return block; -} - -- (void)setWillRemoveAllObjectsBlock:(PINMemoryCacheBlock)block -{ - [self lock]; - _willRemoveAllObjectsBlock = [block copy]; - [self unlock]; -} - -- (PINMemoryCacheObjectBlock)didAddObjectBlock -{ - [self lock]; - PINMemoryCacheObjectBlock block = _didAddObjectBlock; - [self unlock]; - - return block; -} - -- (void)setDidAddObjectBlock:(PINMemoryCacheObjectBlock)block -{ - [self lock]; - _didAddObjectBlock = [block copy]; - [self unlock]; -} - -- (PINMemoryCacheObjectBlock)didRemoveObjectBlock -{ - [self lock]; - PINMemoryCacheObjectBlock block = _didRemoveObjectBlock; - [self unlock]; - - return block; -} - -- (void)setDidRemoveObjectBlock:(PINMemoryCacheObjectBlock)block -{ - [self lock]; - _didRemoveObjectBlock = [block copy]; - [self unlock]; -} - -- (PINMemoryCacheBlock)didRemoveAllObjectsBlock -{ - [self lock]; - PINMemoryCacheBlock block = _didRemoveAllObjectsBlock; - [self unlock]; - - return block; -} - -- (void)setDidRemoveAllObjectsBlock:(PINMemoryCacheBlock)block -{ - [self lock]; - _didRemoveAllObjectsBlock = [block copy]; - [self unlock]; -} - -- (PINMemoryCacheBlock)didReceiveMemoryWarningBlock -{ - [self lock]; - PINMemoryCacheBlock block = _didReceiveMemoryWarningBlock; - [self unlock]; - - return block; -} - -- (void)setDidReceiveMemoryWarningBlock:(PINMemoryCacheBlock)block -{ - [self lock]; - _didReceiveMemoryWarningBlock = [block copy]; - [self unlock]; -} - -- (PINMemoryCacheBlock)didEnterBackgroundBlock -{ - [self lock]; - PINMemoryCacheBlock block = _didEnterBackgroundBlock; - [self unlock]; - - return block; -} - -- (void)setDidEnterBackgroundBlock:(PINMemoryCacheBlock)block -{ - [self lock]; - _didEnterBackgroundBlock = [block copy]; - [self unlock]; -} - -- (NSTimeInterval)ageLimit -{ - [self lock]; - NSTimeInterval ageLimit = _ageLimit; - [self unlock]; - - return ageLimit; -} - -- (void)setAgeLimit:(NSTimeInterval)ageLimit -{ - [self lock]; - _ageLimit = ageLimit; - [self unlock]; - - [self trimToAgeLimitRecursively]; -} - -- (NSUInteger)costLimit -{ - [self lock]; - NSUInteger costLimit = _costLimit; - [self unlock]; - - return costLimit; -} - -- (void)setCostLimit:(NSUInteger)costLimit -{ - [self lock]; - _costLimit = costLimit; - [self unlock]; - - if (costLimit > 0) - [self trimToCostLimitByDate:costLimit]; -} - -- (NSUInteger)totalCost -{ - [self lock]; - NSUInteger cost = _totalCost; - [self unlock]; - - return cost; -} - -- (BOOL)isTTLCache { - BOOL isTTLCache; - - [self lock]; - isTTLCache = _ttlCache; - [self unlock]; - - return isTTLCache; -} - -- (void)setTtlCache:(BOOL)ttlCache { - [self lock]; - _ttlCache = ttlCache; - [self unlock]; -} - - -- (void)lock -{ - dispatch_semaphore_wait(_lockSemaphore, DISPATCH_TIME_FOREVER); -} - -- (void)unlock -{ - dispatch_semaphore_signal(_lockSemaphore); -} - -@end diff --git a/Example-tvOS/Pods/PINCache/README.md b/Example-tvOS/Pods/PINCache/README.md deleted file mode 100644 index 071f1ea5..00000000 --- a/Example-tvOS/Pods/PINCache/README.md +++ /dev/null @@ -1,75 +0,0 @@ -# PINCache - -[![CocoaPods](https://img.shields.io/cocoapods/v/PINCache.svg)](http://cocoadocs.org/docsets/PINCache/) -[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) - -## Fast, non-deadlocking parallel object cache for iOS and OS X. - -[PINCache](PINCache/PINCache.h) is a fork of [TMCache](https://github.com/tumblr/TMCache) re-architected to fix issues with deadlocking caused by heavy use. It is a key/value store designed for persisting temporary objects that are expensive to reproduce, such as downloaded data or the results of slow processing. It is comprised of two self-similar stores, one in memory ([PINMemoryCache](PINCache/PINMemoryCache.h)) and one on disk ([PINDiskCache](PINCache/PINDiskCache.h)), all backed by GCD and safe to access from multiple threads simultaneously. On iOS, `PINMemoryCache` will clear itself when the app receives a memory warning or goes into the background. Objects stored in `PINDiskCache` remain until you trim the cache yourself, either manually or by setting a byte or age limit. - -`PINCache` and `PINDiskCache` accept any object conforming to [NSCoding](https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Protocols/NSCoding_Protocol/Reference/Reference.html). Put things in like this: - -```objective-c -UIImage *img = [[UIImage alloc] initWithData:data scale:[[UIScreen mainScreen] scale]]; -[[PINCache sharedCache] setObject:img forKey:@"image" block:nil]; // returns immediately -``` - -Get them back out like this: - -```objective-c -[[PINCache sharedCache] objectForKey:@"image" - block:^(PINCache *cache, NSString *key, id object) { - UIImage *image = (UIImage *)object; - NSLog(@"image scale: %f", image.scale); - }]; -``` - -Both `PINMemoryCache` and PINDiskCache use locks to protect reads and writes. `PINCache` coordinates them so that objects added to memory are available immediately to other threads while being written to disk safely in the background. Both caches are public properties of `PINCache`, so it's easy to manipulate one or the other separately if necessary. - -Collections work too. Thanks to the magic of `NSKeyedArchiver`, objects repeated in a collection only occupy the space of one on disk: - -```objective-c -NSArray *images = @[ image, image, image ]; -[[PINCache sharedCache] setObject:images forKey:@"images"]; -NSLog(@"3 for the price of 1: %d", [[[PINCache sharedCache] diskCache] byteCount]); -``` - -## Installation - -### Manually - -[Download the latest tag](https://github.com/pinterest/PINCache/tags) and drag the `PINCache` folder into your Xcode project. - -Install the docs by double clicking the `.docset` file under `docs/`, or view them online at [cocoadocs.org](http://cocoadocs.org/docsets/PINCache/) - -### Git Submodule - - git submodule add https://github.com/pinterest/PINCache.git - git submodule update --init - -### CocoaPods - -Add [PINCache](http://cocoapods.org/?q=name%3APINCache) to your `Podfile` and run `pod install`. - -### Carthage - -Add the following line to your `Cartfile` and run `carthage update --platform ios`. Then follow [this instruction of Carthage](https://github.com/carthage/carthage#adding-frameworks-to-unit-tests-or-a-framework) to embed the framework. - -```github "pinterest/PINCache"``` - -## Requirements - -__PINCache__ requires iOS 5.0 or OS X 10.7 and greater. - -## Contact - -[Garrett Moon](mailto:garrett@pinterest.com) - -## License - -Copyright 2013 Tumblr, Inc. -Copyright 2015 Pinterest, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. [See the License](LICENSE.txt) for the specific language governing permissions and limitations under the License. diff --git a/Example-tvOS/Pods/Pods.xcodeproj/project.pbxproj b/Example-tvOS/Pods/Pods.xcodeproj/project.pbxproj deleted file mode 100644 index 7c4ee564..00000000 --- a/Example-tvOS/Pods/Pods.xcodeproj/project.pbxproj +++ /dev/null @@ -1,2875 +0,0 @@ - - - - - archiveVersion - 1 - classes - - objectVersion - 46 - objects - - 0082AEACF5E3322DFEF02C48C8DDD57B - - fileRef - 96129D0431AC9EBB5A3EB622E06343C2 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 00B3B9C4991C1B0C85AE5DED6A4D2C62 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINImageView+PINRemoteImage.m - sourceTree - <group> - - 02BC488232D79DA1645047BC5F173D0C - - fileRef - 9A36FE6EEC065E0AAAA97654BF17C86F - isa - PBXBuildFile - - 0BBEB7022039F54EC4DBF7D0C4223002 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - PINDiskCache.m - path - PINCache/PINDiskCache.m - sourceTree - <group> - - 0C8E36CBE8E5106F618C090EA4C37794 - - explicitFileType - wrapper.framework - includeInIndex - 0 - isa - PBXFileReference - name - PINRemoteImage.framework - path - PINRemoteImage.framework - sourceTree - BUILT_PRODUCTS_DIR - - 0F70C2136FE8DCAE781C0DC943EE1489 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINImage+DecodedImage.h - sourceTree - <group> - - 1178C76713EE167389861F46BD78DCB2 - - explicitFileType - wrapper.framework - includeInIndex - 0 - isa - PBXFileReference - name - Pods_PINRemoteImage_tvOSExample.framework - path - Pods_PINRemoteImage_tvOSExample.framework - sourceTree - BUILT_PRODUCTS_DIR - - 127D34DDD6B2EBDB21320DAFA69F5569 - - children - - ECA9EB61856A198FCF0CD44378D46A33 - C9BDC32461F9F491F2084482A1ADDA75 - 47EAB010D0162435502AAA1E0DCE15C7 - 4B33168A4464405200A140C9BE9DCC79 - 4CCA89E5ED6C29B6145C96552EFD662D - 496DA6296490B6AA094CF40F2A832F42 - E24E18A9273179786E74EAAC66C4ABEF - B7FA0CEC568A035CF973D073D73D463C - 707F53B90179791451EF529A17E0FC45 - FCAAC8B180208DB99B60EB0723F31ACA - 82E4DC69C030B87D8C9A2F6DDDF2C442 - DD40E593D553A3ED22C4F980EE15F4A8 - 37B64DE05DBF4030618C6AE560690C13 - A96ACCCB76069F3D169B711F3C7F74BE - 7F07F9AD5C2C3165B22D1C0863D7107B - 9E20F0DD4F1090630B45A784E0ADBCC7 - 5F98474E7839C137BF0762939DA7B196 - A7F7337182D2B02EAB6406E8CC4962CA - 56EF7F4A6DB4E32B8463A3582EA7B845 - 8F60525815DE0C04797BA90A0B9C7892 - F1218F0F65D2299CF3D3D9CCC326831B - 1DF16FA3CAE18FECB90F83CACB619DC8 - 1C8FCFF85251DF7E9B81F44BE263767D - 8D4F47E8907BDE089E9078E7458D1C08 - 8998AF7A79DFB285AB0D8ECEEA602770 - 8E02B62C237A68B609303071D5ED4923 - 67388068077038F8E54B92C705BC2126 - DDB1568A71DF397312B3C52FF1D9FD65 - 261708701B67E47D265FB45379463B9C - 7356CBACF954E3FBAC433547FB5E1BC7 - 648E69B8D0C8109E82EE8528D42557B4 - 4FA12EEDD7E879A2E0EE9E4EB0D5BD5B - 4E610CA07D24A0CB37105E722C9D6CE1 - 98EA53B5C45941E27F9BDB90AF84083D - - isa - PBXGroup - name - Classes - path - Classes - sourceTree - <group> - - 12C7B0DD52FED6F5E64C87A78220CE63 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - NSData+ImageDetectors.h - sourceTree - <group> - - 1C8FCFF85251DF7E9B81F44BE263767D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINRemoteImageMemoryContainer.h - sourceTree - <group> - - 1DF16FA3CAE18FECB90F83CACB619DC8 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINRemoteImageManagerResult.m - sourceTree - <group> - - 1E466E748220A0BE2FB7A2D5953CAF2C - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.plist.xml - path - Info.plist - sourceTree - <group> - - 261708701B67E47D265FB45379463B9C - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINRemoteLock.h - sourceTree - <group> - - 279A9F8BE8E95B5EC2187584CE97DD74 - - fileRef - 9E20F0DD4F1090630B45A784E0ADBCC7 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 2C29CE313795DE4CFF398C1D71394C7D - - buildActionMask - 2147483647 - files - - EB1579102405BDD7C1574308EC467AA1 - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 2D8E8EC45A3A1A1D94AE762CB5028504 - - buildConfigurations - - 61E9C960176A58563D21517D299990A4 - C332B185519D08E2641ECF2E00474E29 - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - 31761D7D4756260666C1444A39EA491C - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - Pods-PINRemoteImage.tvOSExample-PINCache-dummy.m - sourceTree - <group> - - 33C74D5E256EE1D948B7A836039CEEB9 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINImageView+PINRemoteImage.h - sourceTree - <group> - - 3437B95AA2CBE7490149EEFA83978A7B - - buildConfigurations - - 47DCACFE9EA08FFC1086F3F5D8082B50 - 896F6415029D158822134FEC217A3EEC - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - 346F53C38695BBB2F87EE155141F9D96 - - isa - PBXFileReference - lastKnownFileType - wrapper.framework - name - Foundation.framework - path - Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/System/Library/Frameworks/Foundation.framework - sourceTree - DEVELOPER_DIR - - 366A9C137237118C71B9615F2A8CDA28 - - isa - PBXFileReference - lastKnownFileType - wrapper.framework - name - ImageIO.framework - path - Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/System/Library/Frameworks/ImageIO.framework - sourceTree - DEVELOPER_DIR - - 36AE58D4844DFD26151C6A1803C91C55 - - children - - ED38D82EF154E02E73484E0DE01C9DE6 - 6E4B34927F601D8E1138FDAA17909E5F - BAC33ACD79895192DBE3CFC2E8FE044E - 31761D7D4756260666C1444A39EA491C - 7B2FF995DE107406E1B42A2EACC61AB7 - 5A002565FAB8E473E1D62EF38FBEF8E9 - - isa - PBXGroup - name - Support Files - path - ../Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache - sourceTree - <group> - - 378CB9C04F32ACE5AEFF45752FFD439A - - children - - 5494200DC3AAB386529CE8F470E9E21D - F31EC5948759058807C5B0298D21A6DC - F4F85C3A97C5DA45547C0F195192BD7E - F4DBD6B7FC84ADB109BD7E87A9B3B3B1 - 3E9EA84A849BD2DCE6B6372A7209B76E - 6B2C3B18326AFCA937340FD7A91687E5 - 90554EAEB5A49F2B4507524353FE96F8 - 9720749F9C88E2E81B1AEE11AF25D76E - AE807D4E0267B44EFBD262551F35164B - 5F2D5E87B882076993986791F6F82246 - - isa - PBXGroup - name - Pods-PINRemoteImage.tvOSExample - path - Target Support Files/Pods-PINRemoteImage.tvOSExample - sourceTree - <group> - - 379087D543E17F80A72501752D5A4EB3 - - fileRef - FCAAC8B180208DB99B60EB0723F31ACA - isa - PBXBuildFile - - 37B64DE05DBF4030618C6AE560690C13 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINRemoteImageCallbacks.m - sourceTree - <group> - - 3818FFD59B9280FAAE8521513DC6C260 - - buildActionMask - 2147483647 - files - - 8AA404D33E867092DC602FDBE54A1F1F - - isa - PBXHeadersBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 3B7A7F0FA776A6203BE8A75456AEDCA1 - - fileRef - 33C74D5E256EE1D948B7A836039CEEB9 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 3C169D649A289B19A36B233A50094217 - - fileRef - 8F60525815DE0C04797BA90A0B9C7892 - isa - PBXBuildFile - - 3D8A1536DF1F57D95589FE810B7A58DD - - isa - PBXTargetDependency - name - Pods-PINRemoteImage.tvOSExample-PINCache - target - F89BEFD0A7CC0797936BF229DC2BD11E - targetProxy - 644283B8A312162A25737CF6AD946A0E - - 3E9EA84A849BD2DCE6B6372A7209B76E - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - Pods-PINRemoteImage.tvOSExample-dummy.m - sourceTree - <group> - - 3EEDAD248C9290F719B75F73D7ABBC45 - - fileRef - 707F53B90179791451EF529A17E0FC45 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 4537EA7ED274CC0D5EC24EFCBD3AFD3E - - fileRef - 8998AF7A79DFB285AB0D8ECEEA602770 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 46389BE87B3F40F6233B39E15FC0AE33 - - fileRef - 3E9EA84A849BD2DCE6B6372A7209B76E - isa - PBXBuildFile - - 4757E3B49DFEF69A852EE4540D987A7C - - fileRef - 648E69B8D0C8109E82EE8528D42557B4 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 47DCACFE9EA08FFC1086F3F5D8082B50 - - baseConfigurationReference - AE807D4E0267B44EFBD262551F35164B - buildSettings - - CURRENT_PROJECT_VERSION - 1 - DEFINES_MODULE - YES - DYLIB_COMPATIBILITY_VERSION - 1 - DYLIB_CURRENT_VERSION - 1 - DYLIB_INSTALL_NAME_BASE - @rpath - ENABLE_STRICT_OBJC_MSGSEND - YES - INFOPLIST_FILE - Target Support Files/Pods-PINRemoteImage.tvOSExample/Info.plist - INSTALL_PATH - $(LOCAL_LIBRARY_DIR)/Frameworks - MACH_O_TYPE - staticlib - MODULEMAP_FILE - Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample.modulemap - MTL_ENABLE_DEBUG_INFO - YES - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PODS_ROOT - $(SRCROOT) - PRODUCT_NAME - Pods_PINRemoteImage_tvOSExample - SDKROOT - appletvos - SKIP_INSTALL - YES - TVOS_DEPLOYMENT_TARGET - 9.0 - VERSIONING_SYSTEM - apple-generic - VERSION_INFO_PREFIX - - - isa - XCBuildConfiguration - name - Debug - - 47EAB010D0162435502AAA1E0DCE15C7 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINAnimatedImage.h - sourceTree - <group> - - 496DA6296490B6AA094CF40F2A832F42 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINAnimatedImageManager.m - sourceTree - <group> - - 49EABB78EFDA4E09FEADB95FDAF15937 - - fileRef - 8E02B62C237A68B609303071D5ED4923 - isa - PBXBuildFile - - 4B33168A4464405200A140C9BE9DCC79 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINAnimatedImage.m - sourceTree - <group> - - 4B9D83F8EB0CB74E9CC103C2CC7CC136 - - fileRef - DDB1568A71DF397312B3C52FF1D9FD65 - isa - PBXBuildFile - - 4CB34F8CA1A2C97F74DBD4BABB62B2F8 - - buildActionMask - 2147483647 - files - - D196AB8E0FD8CC50F9D009F6C0D875CE - 574814B226CD5EE7FD088D4FCF68E159 - D6A2B0364AD71E09EE8FC70CD65273CD - 55904766F880176085D1AE0157B3942C - AFF6089EAA682853F510658FAC82F236 - 69FF3730C23BC8D5EAEF69A2BBE1CF30 - 97393D9D0069759262A188831D786D0D - 0082AEACF5E3322DFEF02C48C8DDD57B - 3B7A7F0FA776A6203BE8A75456AEDCA1 - 3EEDAD248C9290F719B75F73D7ABBC45 - 72C43DD1844E893A6846D7D9A657C2C1 - 9F97F42B69BA94B06F726D804A642205 - 53E0314E196CD19F29EB6D45FB7E9969 - 279A9F8BE8E95B5EC2187584CE97DD74 - A3EC838691A5E5500346B77B1A0753FF - DF4323BDDAC40C8B0D78D2BDEA14C23E - 8945807D4AE8F1472BBB6CEA6DC0CA1E - 8E9AE5247BB319DB36A311785F11CA2F - 4537EA7ED274CC0D5EC24EFCBD3AFD3E - 4F19FC7DA55ED8F097DE1059250F881D - 69715DD80B23A84EF14DB4DCBF932D25 - 4757E3B49DFEF69A852EE4540D987A7C - 826290B2ECFAE65811A4A3044F2C3F81 - - isa - PBXHeadersBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 4CCA89E5ED6C29B6145C96552EFD662D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINAnimatedImageManager.h - sourceTree - <group> - - 4E610CA07D24A0CB37105E722C9D6CE1 - - children - - 12C7B0DD52FED6F5E64C87A78220CE63 - F4F8BAF4CCE2B8DBF69C12172BB463BD - 0F70C2136FE8DCAE781C0DC943EE1489 - A7BC165895AD244CAB04788807EF333D - 96129D0431AC9EBB5A3EB622E06343C2 - 583C5ECB1CDF1C5FDD36E4A2CFC2DD03 - - isa - PBXGroup - name - Categories - path - Categories - sourceTree - <group> - - 4F19FC7DA55ED8F097DE1059250F881D - - fileRef - 67388068077038F8E54B92C705BC2126 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 4F3090D1A95E67E0CB96FD93F97C948C - - isa - PBXTargetDependency - name - Pods-PINRemoteImage.tvOSExample-PINRemoteImage - target - C7507E3FAB7C1052089CA5564CF81E70 - targetProxy - E12660042648FB5A145EF4DA2A6D7EB0 - - 4FA12EEDD7E879A2E0EE9E4EB0D5BD5B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINURLSessionManager.m - sourceTree - <group> - - 51A52926B51BFCD8546D8C98E3ECFC76 - - includeInIndex - 1 - isa - PBXFileReference - path - Pods-PINRemoteImage.tvOSExample-PINRemoteImage.modulemap - sourceTree - <group> - - 51DAA8DDAB0D8413B4EF7ED602F6F3BB - - children - - 378CB9C04F32ACE5AEFF45752FFD439A - - isa - PBXGroup - name - Targets Support Files - sourceTree - <group> - - 53E0314E196CD19F29EB6D45FB7E9969 - - fileRef - A96ACCCB76069F3D169B711F3C7F74BE - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 547C46A697CBBA6BF9D73E6ADC44F788 - - buildActionMask - 2147483647 - files - - F760DCF9BE83B2E335AFE09E85AD8AB5 - 65B2A4295D29FF4ED45CA5E584EC121D - ADB3285C96A8EBAD74ED646751A7B80A - CD8ED95DDF988E5FBA349E3AF62D0322 - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 5494200DC3AAB386529CE8F470E9E21D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.plist.xml - path - Info.plist - sourceTree - <group> - - 55904766F880176085D1AE0157B3942C - - fileRef - 4CCA89E5ED6C29B6145C96552EFD662D - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 56EF7F4A6DB4E32B8463A3582EA7B845 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINRemoteImageManager.h - sourceTree - <group> - - 574814B226CD5EE7FD088D4FCF68E159 - - fileRef - ECA9EB61856A198FCF0CD44378D46A33 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 5808499DF2CC1B545E029A99AD1904D3 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - PINCache.h - path - PINCache/PINCache.h - sourceTree - <group> - - 583C5ECB1CDF1C5FDD36E4A2CFC2DD03 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINImage+WebP.m - sourceTree - <group> - - 59258540AAE6EEDC46AEED7FBEEBD06A - - fileRef - 7F07F9AD5C2C3165B22D1C0863D7107B - isa - PBXBuildFile - - 5A002565FAB8E473E1D62EF38FBEF8E9 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - Pods-PINRemoteImage.tvOSExample-PINCache-umbrella.h - sourceTree - <group> - - 5DC2658D3440262A60A15BB24827915C - - fileRef - 5808499DF2CC1B545E029A99AD1904D3 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 5EBE1397EB2A8EE606852B58D88396C1 - - baseConfigurationReference - D080E63FD8ADB53B3D48D443AE972630 - buildSettings - - CURRENT_PROJECT_VERSION - 1 - DEFINES_MODULE - YES - DYLIB_COMPATIBILITY_VERSION - 1 - DYLIB_CURRENT_VERSION - 1 - DYLIB_INSTALL_NAME_BASE - @rpath - ENABLE_STRICT_OBJC_MSGSEND - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Pods-PINRemoteImage.tvOSExample-PINRemoteImage-prefix.pch - INFOPLIST_FILE - Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Info.plist - INSTALL_PATH - $(LOCAL_LIBRARY_DIR)/Frameworks - MODULEMAP_FILE - Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Pods-PINRemoteImage.tvOSExample-PINRemoteImage.modulemap - MTL_ENABLE_DEBUG_INFO - YES - PRODUCT_NAME - PINRemoteImage - SDKROOT - appletvos - SKIP_INSTALL - YES - TVOS_DEPLOYMENT_TARGET - 9.0 - VERSIONING_SYSTEM - apple-generic - VERSION_INFO_PREFIX - - - isa - XCBuildConfiguration - name - Debug - - 5F0D33FAFA4106D8E53CBBF1C3C5FA62 - - fileRef - 8B329BA18F22952E6640CA35AF511745 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 5F2D5E87B882076993986791F6F82246 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-PINRemoteImage.tvOSExample.release.xcconfig - sourceTree - <group> - - 5F98474E7839C137BF0762939DA7B196 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINRemoteImageDownloadTask.m - sourceTree - <group> - - 608C4A215B8CB9193748366E074C95EF - - children - - BF5F40786E5253179ECE505B730A39F9 - A00C17E2E2F5AD6FB731C2307218BD0F - - isa - PBXGroup - name - PINRemoteImage - path - ../.. - sourceTree - <group> - - 61E9C960176A58563D21517D299990A4 - - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - CLANG_CXX_LANGUAGE_STANDARD - gnu++0x - CLANG_CXX_LIBRARY - libc++ - CLANG_ENABLE_MODULES - YES - CLANG_ENABLE_OBJC_ARC - YES - CLANG_WARN_BOOL_CONVERSION - YES - CLANG_WARN_CONSTANT_CONVERSION - YES - CLANG_WARN_DIRECT_OBJC_ISA_USAGE - YES - CLANG_WARN_EMPTY_BODY - YES - CLANG_WARN_ENUM_CONVERSION - YES - CLANG_WARN_INT_CONVERSION - YES - CLANG_WARN_OBJC_ROOT_CLASS - YES - CLANG_WARN_UNREACHABLE_CODE - YES - CLANG_WARN__DUPLICATE_METHOD_MATCH - YES - COPY_PHASE_STRIP - NO - GCC_C_LANGUAGE_STANDARD - gnu99 - GCC_DYNAMIC_NO_PIC - NO - GCC_OPTIMIZATION_LEVEL - 0 - GCC_PREPROCESSOR_DEFINITIONS - - DEBUG=1 - $(inherited) - - GCC_SYMBOLS_PRIVATE_EXTERN - NO - GCC_WARN_64_TO_32_BIT_CONVERSION - YES - GCC_WARN_ABOUT_RETURN_TYPE - YES - GCC_WARN_UNDECLARED_SELECTOR - YES - GCC_WARN_UNINITIALIZED_AUTOS - YES - GCC_WARN_UNUSED_FUNCTION - YES - GCC_WARN_UNUSED_VARIABLE - YES - ONLY_ACTIVE_ARCH - YES - STRIP_INSTALLED_PRODUCT - NO - SYMROOT - ${SRCROOT}/../build - TVOS_DEPLOYMENT_TARGET - 9.0 - - isa - XCBuildConfiguration - name - Debug - - 62C6E8BCD332F363DCAE6DC90C390BB6 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINButton+PINRemoteImage.m - sourceTree - <group> - - 644283B8A312162A25737CF6AD946A0E - - containerPortal - D41D8CD98F00B204E9800998ECF8427E - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - F89BEFD0A7CC0797936BF229DC2BD11E - remoteInfo - Pods-PINRemoteImage.tvOSExample-PINCache - - 648E69B8D0C8109E82EE8528D42557B4 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINURLSessionManager.h - sourceTree - <group> - - 65B2A4295D29FF4ED45CA5E584EC121D - - fileRef - 0BBEB7022039F54EC4DBF7D0C4223002 - isa - PBXBuildFile - - 67388068077038F8E54B92C705BC2126 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINRemoteImageTask.h - sourceTree - <group> - - 688E4DCFB0E1FBEC8C8C73126305AA1C - - fileRef - 83497A28502289FBCA5F4064F09288A1 - isa - PBXBuildFile - - 69715DD80B23A84EF14DB4DCBF932D25 - - fileRef - 261708701B67E47D265FB45379463B9C - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 69FF3730C23BC8D5EAEF69A2BBE1CF30 - - fileRef - E24E18A9273179786E74EAAC66C4ABEF - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 6B2C3B18326AFCA937340FD7A91687E5 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.script.sh - path - Pods-PINRemoteImage.tvOSExample-frameworks.sh - sourceTree - <group> - - 6E4B34927F601D8E1138FDAA17909E5F - - includeInIndex - 1 - isa - PBXFileReference - path - Pods-PINRemoteImage.tvOSExample-PINCache.modulemap - sourceTree - <group> - - 6ED8D732E24A899406122627347B0FBE - - buildActionMask - 2147483647 - files - - 688E4DCFB0E1FBEC8C8C73126305AA1C - 7AA70721CA1DB7C21C541D5820B91C6D - CC5300DDBAFE181F696E5CCC2BA5AC48 - BCF184031BE6B519E8F9CBBBFC3C7801 - 76E1340731E93FF556CF8FF370337F3A - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 707F53B90179791451EF529A17E0FC45 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINProgressiveImage.h - sourceTree - <group> - - 711D52235B0BC670BE93BBC6EDF6DBD6 - - isa - PBXFileReference - lastKnownFileType - wrapper.framework - name - UIKit.framework - path - Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/System/Library/Frameworks/UIKit.framework - sourceTree - DEVELOPER_DIR - - 72C43DD1844E893A6846D7D9A657C2C1 - - fileRef - 82E4DC69C030B87D8C9A2F6DDDF2C442 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 7356CBACF954E3FBAC433547FB5E1BC7 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINRemoteLock.m - sourceTree - <group> - - 73D7A8B04476983D46AF2B6E6DF4541E - - fileRef - 37B64DE05DBF4030618C6AE560690C13 - isa - PBXBuildFile - - 75E22CF6A644F1A0279B17A2EBEFE9DC - - fileRef - 7356CBACF954E3FBAC433547FB5E1BC7 - isa - PBXBuildFile - - 76E1340731E93FF556CF8FF370337F3A - - fileRef - 711D52235B0BC670BE93BBC6EDF6DBD6 - isa - PBXBuildFile - - 7A0B379E1F4CA0B5215A71D71E307C51 - - fileRef - D091968E2C5439A8A6D9A229875CE9D3 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 7AA70721CA1DB7C21C541D5820B91C6D - - fileRef - 346F53C38695BBB2F87EE155141F9D96 - isa - PBXBuildFile - - 7B2FF995DE107406E1B42A2EACC61AB7 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - Pods-PINRemoteImage.tvOSExample-PINCache-prefix.pch - sourceTree - <group> - - 7CB8884E962B78001674FA638ACA87F4 - - fileRef - 1DF16FA3CAE18FECB90F83CACB619DC8 - isa - PBXBuildFile - - 7DB346D0F39D3F0E887471402A8071AB - - children - - BA6428E9F66FD5A23C0A2E06ED26CD2F - B1A11A7DE699B711ECE8F5987072C1D1 - B4C1B817EFFB094B26E198EF7B35892E - E07713D6BECC3D3DF7750BC32A6D3A01 - 8AE0A6730B7EAB6872C87B0594ABC3A5 - 51DAA8DDAB0D8413B4EF7ED602F6F3BB - - isa - PBXGroup - sourceTree - <group> - - 7F07F9AD5C2C3165B22D1C0863D7107B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINRemoteImageCategoryManager.m - sourceTree - <group> - - 7F762BC83B1C5131ACFA008AB85652DE - - buildActionMask - 2147483647 - files - - 46389BE87B3F40F6233B39E15FC0AE33 - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 80ABAE9276F576F4445D49D36CBB9419 - - fileRef - 8D4F47E8907BDE089E9078E7458D1C08 - isa - PBXBuildFile - - 826290B2ECFAE65811A4A3044F2C3F81 - - fileRef - EA420579FAB9AC17343639D1A27613F2 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 82E4DC69C030B87D8C9A2F6DDDF2C442 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINRemoteImage.h - sourceTree - <group> - - 83497A28502289FBCA5F4064F09288A1 - - isa - PBXFileReference - lastKnownFileType - wrapper.framework - name - Accelerate.framework - path - Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/System/Library/Frameworks/Accelerate.framework - sourceTree - DEVELOPER_DIR - - 8945807D4AE8F1472BBB6CEA6DC0CA1E - - fileRef - F1218F0F65D2299CF3D3D9CCC326831B - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 896F6415029D158822134FEC217A3EEC - - baseConfigurationReference - 5F2D5E87B882076993986791F6F82246 - buildSettings - - CURRENT_PROJECT_VERSION - 1 - DEFINES_MODULE - YES - DYLIB_COMPATIBILITY_VERSION - 1 - DYLIB_CURRENT_VERSION - 1 - DYLIB_INSTALL_NAME_BASE - @rpath - ENABLE_STRICT_OBJC_MSGSEND - YES - INFOPLIST_FILE - Target Support Files/Pods-PINRemoteImage.tvOSExample/Info.plist - INSTALL_PATH - $(LOCAL_LIBRARY_DIR)/Frameworks - MACH_O_TYPE - staticlib - MODULEMAP_FILE - Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample.modulemap - MTL_ENABLE_DEBUG_INFO - NO - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PODS_ROOT - $(SRCROOT) - PRODUCT_NAME - Pods_PINRemoteImage_tvOSExample - SDKROOT - appletvos - SKIP_INSTALL - YES - TVOS_DEPLOYMENT_TARGET - 9.0 - VERSIONING_SYSTEM - apple-generic - VERSION_INFO_PREFIX - - - isa - XCBuildConfiguration - name - Release - - 8998AF7A79DFB285AB0D8ECEEA602770 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINRemoteImageProcessorTask.h - sourceTree - <group> - - 8AA404D33E867092DC602FDBE54A1F1F - - fileRef - 9720749F9C88E2E81B1AEE11AF25D76E - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 8AE0A6730B7EAB6872C87B0594ABC3A5 - - children - - 9B71428B31BD826E391AB6F7278306F4 - 0C8E36CBE8E5106F618C090EA4C37794 - 1178C76713EE167389861F46BD78DCB2 - - isa - PBXGroup - name - Products - sourceTree - <group> - - 8AFDBC0DF3E6109D63FA1DA4705ADE63 - - baseConfigurationReference - BAC33ACD79895192DBE3CFC2E8FE044E - buildSettings - - CURRENT_PROJECT_VERSION - 1 - DEFINES_MODULE - YES - DYLIB_COMPATIBILITY_VERSION - 1 - DYLIB_CURRENT_VERSION - 1 - DYLIB_INSTALL_NAME_BASE - @rpath - ENABLE_STRICT_OBJC_MSGSEND - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Pods-PINRemoteImage.tvOSExample-PINCache-prefix.pch - INFOPLIST_FILE - Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Info.plist - INSTALL_PATH - $(LOCAL_LIBRARY_DIR)/Frameworks - MODULEMAP_FILE - Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Pods-PINRemoteImage.tvOSExample-PINCache.modulemap - MTL_ENABLE_DEBUG_INFO - NO - PRODUCT_NAME - PINCache - SDKROOT - appletvos - SKIP_INSTALL - YES - TVOS_DEPLOYMENT_TARGET - 9.0 - VERSIONING_SYSTEM - apple-generic - VERSION_INFO_PREFIX - - - isa - XCBuildConfiguration - name - Release - - 8B329BA18F22952E6640CA35AF511745 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - PINDiskCache.h - path - PINCache/PINDiskCache.h - sourceTree - <group> - - 8D4F47E8907BDE089E9078E7458D1C08 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINRemoteImageMemoryContainer.m - sourceTree - <group> - - 8E02B62C237A68B609303071D5ED4923 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINRemoteImageProcessorTask.m - sourceTree - <group> - - 8E3441FDF30DA81A599A5A21C2195447 - - fileRef - 62C6E8BCD332F363DCAE6DC90C390BB6 - isa - PBXBuildFile - - 8E9AE5247BB319DB36A311785F11CA2F - - fileRef - 1C8FCFF85251DF7E9B81F44BE263767D - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 8F60525815DE0C04797BA90A0B9C7892 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINRemoteImageManager.m - sourceTree - <group> - - 90554EAEB5A49F2B4507524353FE96F8 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.script.sh - path - Pods-PINRemoteImage.tvOSExample-resources.sh - sourceTree - <group> - - 93190F961637DCF561F0D1253E5E8CCF - - fileRef - C9BDC32461F9F491F2084482A1ADDA75 - isa - PBXBuildFile - - 94116D38CD2C91AE7D1A38E4DEBB0053 - - buildActionMask - 2147483647 - files - - D715B9247688E89783CE6B7F2CEE4944 - 93190F961637DCF561F0D1253E5E8CCF - BAE89168DD44937C544D3B5F2B30D390 - A862B93549C776A0660CB03DF7DD0EBC - 8E3441FDF30DA81A599A5A21C2195447 - F4A44019573E493AF7DCB60F18837773 - A74E5C839B77427A85DC5884D321A13D - F24A713F2B0A107A3085336D8D5AF73C - DC486D410F8ADEC2F2ABBE81DFEB3D48 - 379087D543E17F80A72501752D5A4EB3 - 73D7A8B04476983D46AF2B6E6DF4541E - 59258540AAE6EEDC46AEED7FBEEBD06A - DE061E53A342F1638D189628A50FE5A2 - 3C169D649A289B19A36B233A50094217 - 7CB8884E962B78001674FA638ACA87F4 - 80ABAE9276F576F4445D49D36CBB9419 - 49EABB78EFDA4E09FEADB95FDAF15937 - 4B9D83F8EB0CB74E9CC103C2CC7CC136 - 75E22CF6A644F1A0279B17A2EBEFE9DC - F8B2B0EC0D0ED9AF9CA430F2EC544174 - 02BC488232D79DA1645047BC5F173D0C - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 96129D0431AC9EBB5A3EB622E06343C2 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINImage+WebP.h - sourceTree - <group> - - 9720749F9C88E2E81B1AEE11AF25D76E - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - Pods-PINRemoteImage.tvOSExample-umbrella.h - sourceTree - <group> - - 97393D9D0069759262A188831D786D0D - - fileRef - 0F70C2136FE8DCAE781C0DC943EE1489 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - 98EA53B5C45941E27F9BDB90AF84083D - - children - - B19E66CDD39166FE5929891098D6BC5B - 62C6E8BCD332F363DCAE6DC90C390BB6 - 33C74D5E256EE1D948B7A836039CEEB9 - 00B3B9C4991C1B0C85AE5DED6A4D2C62 - - isa - PBXGroup - name - Image Categories - path - Image Categories - sourceTree - <group> - - 9A36FE6EEC065E0AAAA97654BF17C86F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - Pods-PINRemoteImage.tvOSExample-PINRemoteImage-dummy.m - sourceTree - <group> - - 9AE3724762891369254F21276752FBBC - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - PINMemoryCache.m - path - PINCache/PINMemoryCache.m - sourceTree - <group> - - 9B71428B31BD826E391AB6F7278306F4 - - explicitFileType - wrapper.framework - includeInIndex - 0 - isa - PBXFileReference - name - PINCache.framework - path - PINCache.framework - sourceTree - BUILT_PRODUCTS_DIR - - 9E20F0DD4F1090630B45A784E0ADBCC7 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINRemoteImageDownloadTask.h - sourceTree - <group> - - 9F97F42B69BA94B06F726D804A642205 - - fileRef - DD40E593D553A3ED22C4F980EE15F4A8 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - A00C17E2E2F5AD6FB731C2307218BD0F - - children - - 1E466E748220A0BE2FB7A2D5953CAF2C - 51A52926B51BFCD8546D8C98E3ECFC76 - D080E63FD8ADB53B3D48D443AE972630 - 9A36FE6EEC065E0AAAA97654BF17C86F - EC6F7D27F854F4B0C0A88A29F8DC0733 - EA420579FAB9AC17343639D1A27613F2 - - isa - PBXGroup - name - Support Files - path - Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage - sourceTree - <group> - - A3EC838691A5E5500346B77B1A0753FF - - fileRef - A7F7337182D2B02EAB6406E8CC4962CA - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - A74E5C839B77427A85DC5884D321A13D - - fileRef - A7BC165895AD244CAB04788807EF333D - isa - PBXBuildFile - - A757C70880A429751B87C3E57D8846C8 - - children - - 127D34DDD6B2EBDB21320DAFA69F5569 - - isa - PBXGroup - name - Pod - path - Pod - sourceTree - <group> - - A7BC165895AD244CAB04788807EF333D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINImage+DecodedImage.m - sourceTree - <group> - - A7F7337182D2B02EAB6406E8CC4962CA - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINRemoteImageMacros.h - sourceTree - <group> - - A862B93549C776A0660CB03DF7DD0EBC - - fileRef - 496DA6296490B6AA094CF40F2A832F42 - isa - PBXBuildFile - - A96ACCCB76069F3D169B711F3C7F74BE - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINRemoteImageCategoryManager.h - sourceTree - <group> - - AB8E2873E6E57D6D9850230DD0AEEAB8 - - buildActionMask - 2147483647 - files - - ECEEA30C3816B8CBE8F2F1AA33EE4F93 - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - ABC5760AB3D111384234E5071464BC51 - - containerPortal - D41D8CD98F00B204E9800998ECF8427E - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - F89BEFD0A7CC0797936BF229DC2BD11E - remoteInfo - Pods-PINRemoteImage.tvOSExample-PINCache - - ADB3285C96A8EBAD74ED646751A7B80A - - fileRef - 9AE3724762891369254F21276752FBBC - isa - PBXBuildFile - - AE807D4E0267B44EFBD262551F35164B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-PINRemoteImage.tvOSExample.debug.xcconfig - sourceTree - <group> - - AFF6089EAA682853F510658FAC82F236 - - fileRef - B19E66CDD39166FE5929891098D6BC5B - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - B19E66CDD39166FE5929891098D6BC5B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINButton+PINRemoteImage.h - sourceTree - <group> - - B1A11A7DE699B711ECE8F5987072C1D1 - - children - - 608C4A215B8CB9193748366E074C95EF - - isa - PBXGroup - name - Development Pods - sourceTree - <group> - - B4C1B817EFFB094B26E198EF7B35892E - - children - - DB6A961AE322AD9C22D2248A11231A61 - D7DC5CC930AA686F52A1468564725997 - - isa - PBXGroup - name - Frameworks - sourceTree - <group> - - B7FA0CEC568A035CF973D073D73D463C - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINDataTaskOperation.m - sourceTree - <group> - - BA6428E9F66FD5A23C0A2E06ED26CD2F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text - name - Podfile - path - ../Podfile - sourceTree - SOURCE_ROOT - xcLanguageSpecificationIdentifier - xcode.lang.ruby - - BAC33ACD79895192DBE3CFC2E8FE044E - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-PINRemoteImage.tvOSExample-PINCache.xcconfig - sourceTree - <group> - - BAE89168DD44937C544D3B5F2B30D390 - - fileRef - 4B33168A4464405200A140C9BE9DCC79 - isa - PBXBuildFile - - BC3756BCBD0E953A1C8BDAFCBF34514F - - isa - PBXTargetDependency - name - Pods-PINRemoteImage.tvOSExample-PINCache - target - F89BEFD0A7CC0797936BF229DC2BD11E - targetProxy - ABC5760AB3D111384234E5071464BC51 - - BCF184031BE6B519E8F9CBBBFC3C7801 - - fileRef - DB6A961AE322AD9C22D2248A11231A61 - isa - PBXBuildFile - - BF5F40786E5253179ECE505B730A39F9 - - children - - A757C70880A429751B87C3E57D8846C8 - - isa - PBXGroup - name - Core - sourceTree - <group> - - C332B185519D08E2641ECF2E00474E29 - - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - CLANG_CXX_LANGUAGE_STANDARD - gnu++0x - CLANG_CXX_LIBRARY - libc++ - CLANG_ENABLE_MODULES - YES - CLANG_ENABLE_OBJC_ARC - YES - CLANG_WARN_BOOL_CONVERSION - YES - CLANG_WARN_CONSTANT_CONVERSION - YES - CLANG_WARN_DIRECT_OBJC_ISA_USAGE - YES - CLANG_WARN_EMPTY_BODY - YES - CLANG_WARN_ENUM_CONVERSION - YES - CLANG_WARN_INT_CONVERSION - YES - CLANG_WARN_OBJC_ROOT_CLASS - YES - CLANG_WARN_UNREACHABLE_CODE - YES - CLANG_WARN__DUPLICATE_METHOD_MATCH - YES - COPY_PHASE_STRIP - YES - ENABLE_NS_ASSERTIONS - NO - GCC_C_LANGUAGE_STANDARD - gnu99 - GCC_PREPROCESSOR_DEFINITIONS - - RELEASE=1 - - GCC_WARN_64_TO_32_BIT_CONVERSION - YES - GCC_WARN_ABOUT_RETURN_TYPE - YES - GCC_WARN_UNDECLARED_SELECTOR - YES - GCC_WARN_UNINITIALIZED_AUTOS - YES - GCC_WARN_UNUSED_FUNCTION - YES - GCC_WARN_UNUSED_VARIABLE - YES - STRIP_INSTALLED_PRODUCT - NO - SYMROOT - ${SRCROOT}/../build - TVOS_DEPLOYMENT_TARGET - 9.0 - VALIDATE_PRODUCT - YES - - isa - XCBuildConfiguration - name - Release - - C5E5C0425DC9294D0FD3E17FE51AF611 - - fileRef - 5A002565FAB8E473E1D62EF38FBEF8E9 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - C7507E3FAB7C1052089CA5564CF81E70 - - buildConfigurationList - D7F4169D190690FAB44FE2B1FE464B0C - buildPhases - - 94116D38CD2C91AE7D1A38E4DEBB0053 - 6ED8D732E24A899406122627347B0FBE - 4CB34F8CA1A2C97F74DBD4BABB62B2F8 - - buildRules - - dependencies - - 3D8A1536DF1F57D95589FE810B7A58DD - - isa - PBXNativeTarget - name - Pods-PINRemoteImage.tvOSExample-PINRemoteImage - productName - Pods-PINRemoteImage.tvOSExample-PINRemoteImage - productReference - 0C8E36CBE8E5106F618C090EA4C37794 - productType - com.apple.product-type.framework - - C9BDC32461F9F491F2084482A1ADDA75 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINAlternateRepresentationProvider.m - sourceTree - <group> - - CC5300DDBAFE181F696E5CCC2BA5AC48 - - fileRef - 366A9C137237118C71B9615F2A8CDA28 - isa - PBXBuildFile - - CD8ED95DDF988E5FBA349E3AF62D0322 - - fileRef - 31761D7D4756260666C1444A39EA491C - isa - PBXBuildFile - - D080E63FD8ADB53B3D48D443AE972630 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-PINRemoteImage.tvOSExample-PINRemoteImage.xcconfig - sourceTree - <group> - - D091968E2C5439A8A6D9A229875CE9D3 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - PINMemoryCache.h - path - PINCache/PINMemoryCache.h - sourceTree - <group> - - D196AB8E0FD8CC50F9D009F6C0D875CE - - fileRef - 12C7B0DD52FED6F5E64C87A78220CE63 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - D41D8CD98F00B204E9800998ECF8427E - - attributes - - LastSwiftUpdateCheck - 0700 - LastUpgradeCheck - 0700 - - buildConfigurationList - 2D8E8EC45A3A1A1D94AE762CB5028504 - compatibilityVersion - Xcode 3.2 - developmentRegion - English - hasScannedForEncodings - 0 - isa - PBXProject - knownRegions - - en - - mainGroup - 7DB346D0F39D3F0E887471402A8071AB - productRefGroup - 8AE0A6730B7EAB6872C87B0594ABC3A5 - projectDirPath - - projectReferences - - projectRoot - - targets - - F5EE8E8AEECACB6458F5B67E4D5F309B - F89BEFD0A7CC0797936BF229DC2BD11E - C7507E3FAB7C1052089CA5564CF81E70 - - - D6A2B0364AD71E09EE8FC70CD65273CD - - fileRef - 47EAB010D0162435502AAA1E0DCE15C7 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - D715B9247688E89783CE6B7F2CEE4944 - - fileRef - F4F8BAF4CCE2B8DBF69C12172BB463BD - isa - PBXBuildFile - - D7DC5CC930AA686F52A1468564725997 - - children - - 83497A28502289FBCA5F4064F09288A1 - 346F53C38695BBB2F87EE155141F9D96 - 366A9C137237118C71B9615F2A8CDA28 - 711D52235B0BC670BE93BBC6EDF6DBD6 - - isa - PBXGroup - name - tvOS - sourceTree - <group> - - D7F4169D190690FAB44FE2B1FE464B0C - - buildConfigurations - - 5EBE1397EB2A8EE606852B58D88396C1 - EBBEACFAAD48ED6D1120D0C90F08E916 - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - D887531676F31D8E99401003F41BD541 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - Nullability.h - path - PINCache/Nullability.h - sourceTree - <group> - - D8BBA19A80E9E07E57ED0A9305810A6A - - baseConfigurationReference - BAC33ACD79895192DBE3CFC2E8FE044E - buildSettings - - CURRENT_PROJECT_VERSION - 1 - DEFINES_MODULE - YES - DYLIB_COMPATIBILITY_VERSION - 1 - DYLIB_CURRENT_VERSION - 1 - DYLIB_INSTALL_NAME_BASE - @rpath - ENABLE_STRICT_OBJC_MSGSEND - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Pods-PINRemoteImage.tvOSExample-PINCache-prefix.pch - INFOPLIST_FILE - Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Info.plist - INSTALL_PATH - $(LOCAL_LIBRARY_DIR)/Frameworks - MODULEMAP_FILE - Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Pods-PINRemoteImage.tvOSExample-PINCache.modulemap - MTL_ENABLE_DEBUG_INFO - YES - PRODUCT_NAME - PINCache - SDKROOT - appletvos - SKIP_INSTALL - YES - TVOS_DEPLOYMENT_TARGET - 9.0 - VERSIONING_SYSTEM - apple-generic - VERSION_INFO_PREFIX - - - isa - XCBuildConfiguration - name - Debug - - DB6A961AE322AD9C22D2248A11231A61 - - explicitFileType - wrapper.framework - includeInIndex - 0 - isa - PBXFileReference - path - PINCache.framework - sourceTree - BUILT_PRODUCTS_DIR - - DC486D410F8ADEC2F2ABBE81DFEB3D48 - - fileRef - 00B3B9C4991C1B0C85AE5DED6A4D2C62 - isa - PBXBuildFile - - DCB7C9EC537AB3427EDDE8F278C6A767 - - fileRef - D887531676F31D8E99401003F41BD541 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - DD40E593D553A3ED22C4F980EE15F4A8 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINRemoteImageCallbacks.h - sourceTree - <group> - - DDB1568A71DF397312B3C52FF1D9FD65 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINRemoteImageTask.m - sourceTree - <group> - - DE061E53A342F1638D189628A50FE5A2 - - fileRef - 5F98474E7839C137BF0762939DA7B196 - isa - PBXBuildFile - - DF4323BDDAC40C8B0D78D2BDEA14C23E - - fileRef - 56EF7F4A6DB4E32B8463A3582EA7B845 - isa - PBXBuildFile - settings - - ATTRIBUTES - - Public - - - - E07713D6BECC3D3DF7750BC32A6D3A01 - - children - - EDF0F514284F9C89DDD2308CFA152269 - - isa - PBXGroup - name - Pods - sourceTree - <group> - - E12660042648FB5A145EF4DA2A6D7EB0 - - containerPortal - D41D8CD98F00B204E9800998ECF8427E - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - C7507E3FAB7C1052089CA5564CF81E70 - remoteInfo - Pods-PINRemoteImage.tvOSExample-PINRemoteImage - - E24E18A9273179786E74EAAC66C4ABEF - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINDataTaskOperation.h - sourceTree - <group> - - E2B9114EACB748E5D082C54669916963 - - buildActionMask - 2147483647 - files - - DCB7C9EC537AB3427EDDE8F278C6A767 - 5DC2658D3440262A60A15BB24827915C - 5F0D33FAFA4106D8E53CBBF1C3C5FA62 - 7A0B379E1F4CA0B5215A71D71E307C51 - C5E5C0425DC9294D0FD3E17FE51AF611 - - isa - PBXHeadersBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - EA420579FAB9AC17343639D1A27613F2 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - Pods-PINRemoteImage.tvOSExample-PINRemoteImage-umbrella.h - sourceTree - <group> - - EB1579102405BDD7C1574308EC467AA1 - - fileRef - 346F53C38695BBB2F87EE155141F9D96 - isa - PBXBuildFile - - EBBEACFAAD48ED6D1120D0C90F08E916 - - baseConfigurationReference - D080E63FD8ADB53B3D48D443AE972630 - buildSettings - - CURRENT_PROJECT_VERSION - 1 - DEFINES_MODULE - YES - DYLIB_COMPATIBILITY_VERSION - 1 - DYLIB_CURRENT_VERSION - 1 - DYLIB_INSTALL_NAME_BASE - @rpath - ENABLE_STRICT_OBJC_MSGSEND - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Pods-PINRemoteImage.tvOSExample-PINRemoteImage-prefix.pch - INFOPLIST_FILE - Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Info.plist - INSTALL_PATH - $(LOCAL_LIBRARY_DIR)/Frameworks - MODULEMAP_FILE - Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Pods-PINRemoteImage.tvOSExample-PINRemoteImage.modulemap - MTL_ENABLE_DEBUG_INFO - NO - PRODUCT_NAME - PINRemoteImage - SDKROOT - appletvos - SKIP_INSTALL - YES - TVOS_DEPLOYMENT_TARGET - 9.0 - VERSIONING_SYSTEM - apple-generic - VERSION_INFO_PREFIX - - - isa - XCBuildConfiguration - name - Release - - EC6F7D27F854F4B0C0A88A29F8DC0733 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - Pods-PINRemoteImage.tvOSExample-PINRemoteImage-prefix.pch - sourceTree - <group> - - ECA9EB61856A198FCF0CD44378D46A33 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINAlternateRepresentationProvider.h - sourceTree - <group> - - ECEEA30C3816B8CBE8F2F1AA33EE4F93 - - fileRef - 346F53C38695BBB2F87EE155141F9D96 - isa - PBXBuildFile - - ED38D82EF154E02E73484E0DE01C9DE6 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.plist.xml - path - Info.plist - sourceTree - <group> - - EDF0F514284F9C89DDD2308CFA152269 - - children - - D887531676F31D8E99401003F41BD541 - 5808499DF2CC1B545E029A99AD1904D3 - F638725E08D320BFEEE38B493278338B - 8B329BA18F22952E6640CA35AF511745 - 0BBEB7022039F54EC4DBF7D0C4223002 - D091968E2C5439A8A6D9A229875CE9D3 - 9AE3724762891369254F21276752FBBC - 36AE58D4844DFD26151C6A1803C91C55 - - isa - PBXGroup - name - PINCache - path - PINCache - sourceTree - <group> - - F1218F0F65D2299CF3D3D9CCC326831B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - PINRemoteImageManagerResult.h - sourceTree - <group> - - F24A713F2B0A107A3085336D8D5AF73C - - fileRef - 583C5ECB1CDF1C5FDD36E4A2CFC2DD03 - isa - PBXBuildFile - - F31EC5948759058807C5B0298D21A6DC - - includeInIndex - 1 - isa - PBXFileReference - path - Pods-PINRemoteImage.tvOSExample.modulemap - sourceTree - <group> - - F3A1FB86303BC0591CB47FF00876044B - - buildConfigurations - - D8BBA19A80E9E07E57ED0A9305810A6A - 8AFDBC0DF3E6109D63FA1DA4705ADE63 - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - F4A44019573E493AF7DCB60F18837773 - - fileRef - B7FA0CEC568A035CF973D073D73D463C - isa - PBXBuildFile - - F4DBD6B7FC84ADB109BD7E87A9B3B3B1 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.plist.xml - path - Pods-PINRemoteImage.tvOSExample-acknowledgements.plist - sourceTree - <group> - - F4F85C3A97C5DA45547C0F195192BD7E - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text - path - Pods-PINRemoteImage.tvOSExample-acknowledgements.markdown - sourceTree - <group> - - F4F8BAF4CCE2B8DBF69C12172BB463BD - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - NSData+ImageDetectors.m - sourceTree - <group> - - F5EE8E8AEECACB6458F5B67E4D5F309B - - buildConfigurationList - 3437B95AA2CBE7490149EEFA83978A7B - buildPhases - - 7F762BC83B1C5131ACFA008AB85652DE - AB8E2873E6E57D6D9850230DD0AEEAB8 - 3818FFD59B9280FAAE8521513DC6C260 - - buildRules - - dependencies - - BC3756BCBD0E953A1C8BDAFCBF34514F - 4F3090D1A95E67E0CB96FD93F97C948C - - isa - PBXNativeTarget - name - Pods-PINRemoteImage.tvOSExample - productName - Pods-PINRemoteImage.tvOSExample - productReference - 1178C76713EE167389861F46BD78DCB2 - productType - com.apple.product-type.framework - - F638725E08D320BFEEE38B493278338B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - PINCache.m - path - PINCache/PINCache.m - sourceTree - <group> - - F760DCF9BE83B2E335AFE09E85AD8AB5 - - fileRef - F638725E08D320BFEEE38B493278338B - isa - PBXBuildFile - - F89BEFD0A7CC0797936BF229DC2BD11E - - buildConfigurationList - F3A1FB86303BC0591CB47FF00876044B - buildPhases - - 547C46A697CBBA6BF9D73E6ADC44F788 - 2C29CE313795DE4CFF398C1D71394C7D - E2B9114EACB748E5D082C54669916963 - - buildRules - - dependencies - - isa - PBXNativeTarget - name - Pods-PINRemoteImage.tvOSExample-PINCache - productName - Pods-PINRemoteImage.tvOSExample-PINCache - productReference - 9B71428B31BD826E391AB6F7278306F4 - productType - com.apple.product-type.framework - - F8B2B0EC0D0ED9AF9CA430F2EC544174 - - fileRef - 4FA12EEDD7E879A2E0EE9E4EB0D5BD5B - isa - PBXBuildFile - - FCAAC8B180208DB99B60EB0723F31ACA - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - PINProgressiveImage.m - sourceTree - <group> - - - rootObject - D41D8CD98F00B204E9800998ECF8427E - - diff --git a/Example-tvOS/Pods/Pods.xcodeproj/xcshareddata/xcschemes/PINRemoteImage.xcscheme b/Example-tvOS/Pods/Pods.xcodeproj/xcshareddata/xcschemes/PINRemoteImage.xcscheme deleted file mode 100644 index de4d8b44..00000000 --- a/Example-tvOS/Pods/Pods.xcodeproj/xcshareddata/xcschemes/PINRemoteImage.xcscheme +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Example-tvOS/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-PINRemoteImage.tvOSExample-PINRemoteImage.xcscheme b/Example-tvOS/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-PINRemoteImage.tvOSExample-PINRemoteImage.xcscheme deleted file mode 100644 index 99f5efc8..00000000 --- a/Example-tvOS/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-PINRemoteImage.tvOSExample-PINRemoteImage.xcscheme +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Info.plist b/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Info.plist deleted file mode 100644 index 260aa73d..00000000 --- a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Info.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIdentifier - org.cocoapods.${PRODUCT_NAME:rfc1034identifier} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - FMWK - CFBundleShortVersionString - 2.2.2 - CFBundleSignature - ???? - CFBundleVersion - ${CURRENT_PROJECT_VERSION} - NSPrincipalClass - - - diff --git a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Pods-PINRemoteImage.tvOSExample-PINCache-dummy.m b/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Pods-PINRemoteImage.tvOSExample-PINCache-dummy.m deleted file mode 100644 index 8958ee3d..00000000 --- a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Pods-PINRemoteImage.tvOSExample-PINCache-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Pods_PINRemoteImage_tvOSExample_PINCache : NSObject -@end -@implementation PodsDummy_Pods_PINRemoteImage_tvOSExample_PINCache -@end diff --git a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Pods-PINRemoteImage.tvOSExample-PINCache-prefix.pch b/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Pods-PINRemoteImage.tvOSExample-PINCache-prefix.pch deleted file mode 100644 index 5e15de4f..00000000 --- a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Pods-PINRemoteImage.tvOSExample-PINCache-prefix.pch +++ /dev/null @@ -1,7 +0,0 @@ -#ifdef __OBJC__ -#import -#endif - -#ifndef TARGET_OS_WATCH - #define TARGET_OS_WATCH 0 -#endif diff --git a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Pods-PINRemoteImage.tvOSExample-PINCache-umbrella.h b/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Pods-PINRemoteImage.tvOSExample-PINCache-umbrella.h deleted file mode 100644 index 05d1f87f..00000000 --- a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Pods-PINRemoteImage.tvOSExample-PINCache-umbrella.h +++ /dev/null @@ -1,10 +0,0 @@ -#import - -#import "Nullability.h" -#import "PINCache.h" -#import "PINDiskCache.h" -#import "PINMemoryCache.h" - -FOUNDATION_EXPORT double PINCacheVersionNumber; -FOUNDATION_EXPORT const unsigned char PINCacheVersionString[]; - diff --git a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Pods-PINRemoteImage.tvOSExample-PINCache.modulemap b/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Pods-PINRemoteImage.tvOSExample-PINCache.modulemap deleted file mode 100644 index 8cb80d14..00000000 --- a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Pods-PINRemoteImage.tvOSExample-PINCache.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -framework module PINCache { - umbrella header "Pods-PINRemoteImage.tvOSExample-PINCache-umbrella.h" - - export * - module * { export * } -} diff --git a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Pods-PINRemoteImage.tvOSExample-PINCache.xcconfig b/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Pods-PINRemoteImage.tvOSExample-PINCache.xcconfig deleted file mode 100644 index 219cc389..00000000 --- a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINCache/Pods-PINRemoteImage.tvOSExample-PINCache.xcconfig +++ /dev/null @@ -1,8 +0,0 @@ -CONFIGURATION_BUILD_DIR = $PODS_FRAMEWORK_BUILD_PATH -FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_FRAMEWORK_BUILD_PATH" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/PINCache" "${PODS_ROOT}/Headers/Public" -OTHER_LDFLAGS = -framework "Foundation" -PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-PINRemoteImage.tvOSExample -PODS_ROOT = ${SRCROOT} -SKIP_INSTALL = YES \ No newline at end of file diff --git a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Info.plist b/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Info.plist deleted file mode 100644 index 7dbd65be..00000000 --- a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Info.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIdentifier - org.cocoapods.${PRODUCT_NAME:rfc1034identifier} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - FMWK - CFBundleShortVersionString - 3.0.0-beta - CFBundleSignature - ???? - CFBundleVersion - ${CURRENT_PROJECT_VERSION} - NSPrincipalClass - - - diff --git a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Pods-PINRemoteImage.tvOSExample-PINRemoteImage-dummy.m b/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Pods-PINRemoteImage.tvOSExample-PINRemoteImage-dummy.m deleted file mode 100644 index aa497b05..00000000 --- a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Pods-PINRemoteImage.tvOSExample-PINRemoteImage-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Pods_PINRemoteImage_tvOSExample_PINRemoteImage : NSObject -@end -@implementation PodsDummy_Pods_PINRemoteImage_tvOSExample_PINRemoteImage -@end diff --git a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Pods-PINRemoteImage.tvOSExample-PINRemoteImage-prefix.pch b/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Pods-PINRemoteImage.tvOSExample-PINRemoteImage-prefix.pch deleted file mode 100644 index aa992a4a..00000000 --- a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Pods-PINRemoteImage.tvOSExample-PINRemoteImage-prefix.pch +++ /dev/null @@ -1,4 +0,0 @@ -#ifdef __OBJC__ -#import -#endif - diff --git a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Pods-PINRemoteImage.tvOSExample-PINRemoteImage-umbrella.h b/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Pods-PINRemoteImage.tvOSExample-PINRemoteImage-umbrella.h deleted file mode 100644 index 5a1deda2..00000000 --- a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Pods-PINRemoteImage.tvOSExample-PINRemoteImage-umbrella.h +++ /dev/null @@ -1,28 +0,0 @@ -#import - -#import "NSData+ImageDetectors.h" -#import "PINImage+DecodedImage.h" -#import "PINImage+WebP.h" -#import "PINButton+PINRemoteImage.h" -#import "PINImageView+PINRemoteImage.h" -#import "PINAlternateRepresentationProvider.h" -#import "PINAnimatedImage.h" -#import "PINAnimatedImageManager.h" -#import "PINDataTaskOperation.h" -#import "PINProgressiveImage.h" -#import "PINRemoteImage.h" -#import "PINRemoteImageCallbacks.h" -#import "PINRemoteImageCategoryManager.h" -#import "PINRemoteImageDownloadTask.h" -#import "PINRemoteImageMacros.h" -#import "PINRemoteImageManager.h" -#import "PINRemoteImageManagerResult.h" -#import "PINRemoteImageMemoryContainer.h" -#import "PINRemoteImageProcessorTask.h" -#import "PINRemoteImageTask.h" -#import "PINRemoteLock.h" -#import "PINURLSessionManager.h" - -FOUNDATION_EXPORT double PINRemoteImageVersionNumber; -FOUNDATION_EXPORT const unsigned char PINRemoteImageVersionString[]; - diff --git a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Pods-PINRemoteImage.tvOSExample-PINRemoteImage.modulemap b/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Pods-PINRemoteImage.tvOSExample-PINRemoteImage.modulemap deleted file mode 100644 index 3699bf2b..00000000 --- a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Pods-PINRemoteImage.tvOSExample-PINRemoteImage.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -framework module PINRemoteImage { - umbrella header "Pods-PINRemoteImage.tvOSExample-PINRemoteImage-umbrella.h" - - export * - module * { export * } -} diff --git a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Pods-PINRemoteImage.tvOSExample-PINRemoteImage.xcconfig b/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Pods-PINRemoteImage.tvOSExample-PINRemoteImage.xcconfig deleted file mode 100644 index 22276831..00000000 --- a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample-PINRemoteImage/Pods-PINRemoteImage.tvOSExample-PINRemoteImage.xcconfig +++ /dev/null @@ -1,8 +0,0 @@ -CONFIGURATION_BUILD_DIR = $PODS_FRAMEWORK_BUILD_PATH -FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_FRAMEWORK_BUILD_PATH" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/PINRemoteImage" "${PODS_ROOT}/Headers/Public" -OTHER_LDFLAGS = -framework "Accelerate" -framework "ImageIO" -framework "UIKit" -PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-PINRemoteImage.tvOSExample -PODS_ROOT = ${SRCROOT} -SKIP_INSTALL = YES \ No newline at end of file diff --git a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Info.plist b/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Info.plist deleted file mode 100644 index 69745425..00000000 --- a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Info.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIdentifier - org.cocoapods.${PRODUCT_NAME:rfc1034identifier} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0.0 - CFBundleSignature - ???? - CFBundleVersion - ${CURRENT_PROJECT_VERSION} - NSPrincipalClass - - - diff --git a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample-acknowledgements.markdown b/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample-acknowledgements.markdown deleted file mode 100644 index b3b1f31a..00000000 --- a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample-acknowledgements.markdown +++ /dev/null @@ -1,225 +0,0 @@ -# Acknowledgements -This application makes use of the following third party libraries: - -## PINCache - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [2013] [Tumblr, Inc.] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - -## PINRemoteImage - -Copyright (c) 2015-2016 Pinterest, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -Generated by CocoaPods - http://cocoapods.org diff --git a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample-acknowledgements.plist b/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample-acknowledgements.plist deleted file mode 100644 index bae42535..00000000 --- a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample-acknowledgements.plist +++ /dev/null @@ -1,259 +0,0 @@ - - - - - PreferenceSpecifiers - - - FooterText - This application makes use of the following third party libraries: - Title - Acknowledgements - Type - PSGroupSpecifier - - - FooterText - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [2013] [Tumblr, Inc.] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - Title - PINCache - Type - PSGroupSpecifier - - - FooterText - Copyright (c) 2015-2016 Pinterest, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - Title - PINRemoteImage - Type - PSGroupSpecifier - - - FooterText - Generated by CocoaPods - http://cocoapods.org - Title - - Type - PSGroupSpecifier - - - StringsTable - Acknowledgements - Title - Acknowledgements - - diff --git a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample-dummy.m b/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample-dummy.m deleted file mode 100644 index 8f1bf6c5..00000000 --- a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Pods_PINRemoteImage_tvOSExample : NSObject -@end -@implementation PodsDummy_Pods_PINRemoteImage_tvOSExample -@end diff --git a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample-frameworks.sh b/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample-frameworks.sh deleted file mode 100755 index 96d372a2..00000000 --- a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample-frameworks.sh +++ /dev/null @@ -1,93 +0,0 @@ -#!/bin/sh -set -e - -echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" -mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - -SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" - -install_framework() -{ - if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then - local source="${BUILT_PRODUCTS_DIR}/$1" - elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then - local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" - elif [ -r "$1" ]; then - local source="$1" - fi - - local destination="${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - - if [ -L "${source}" ]; then - echo "Symlinked..." - source="$(readlink "${source}")" - fi - - # use filter instead of exclude so missing patterns dont' throw errors - echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" - rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" - - local basename - basename="$(basename -s .framework "$1")" - binary="${destination}/${basename}.framework/${basename}" - if ! [ -r "$binary" ]; then - binary="${destination}/${basename}" - fi - - # Strip invalid architectures so "fat" simulator / device frameworks work on device - if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then - strip_invalid_archs "$binary" - fi - - # Resign the code if required by the build settings to avoid unstable apps - code_sign_if_enabled "${destination}/$(basename "$1")" - - # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. - if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then - local swift_runtime_libs - swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) - for lib in $swift_runtime_libs; do - echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" - rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" - code_sign_if_enabled "${destination}/${lib}" - done - fi -} - -# Signs a framework with the provided identity -code_sign_if_enabled() { - if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then - # Use the current code_sign_identitiy - echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" - echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements \"$1\"" - /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements "$1" - fi -} - -# Strip invalid architectures -strip_invalid_archs() { - binary="$1" - # Get architectures for current file - archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" - stripped="" - for arch in $archs; do - if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then - # Strip non-valid architectures in-place - lipo -remove "$arch" -output "$binary" "$binary" || exit 1 - stripped="$stripped $arch" - fi - done - if [[ "$stripped" ]]; then - echo "Stripped $binary of architectures:$stripped" - fi -} - - -if [[ "$CONFIGURATION" == "Debug" ]]; then - install_framework "Pods-PINRemoteImage.tvOSExample/PINCache.framework" - install_framework "Pods-PINRemoteImage.tvOSExample/PINRemoteImage.framework" -fi -if [[ "$CONFIGURATION" == "Release" ]]; then - install_framework "Pods-PINRemoteImage.tvOSExample/PINCache.framework" - install_framework "Pods-PINRemoteImage.tvOSExample/PINRemoteImage.framework" -fi diff --git a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample-resources.sh b/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample-resources.sh deleted file mode 100755 index 16774fb4..00000000 --- a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample-resources.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/bin/sh -set -e - -mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" - -RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt -> "$RESOURCES_TO_COPY" - -XCASSET_FILES=() - -realpath() { - DIRECTORY="$(cd "${1%/*}" && pwd)" - FILENAME="${1##*/}" - echo "$DIRECTORY/$FILENAME" -} - -install_resource() -{ - case $1 in - *.storyboard) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}" - ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" - ;; - *.xib) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}" - ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" - ;; - *.framework) - echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - ;; - *.xcdatamodel) - echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\"" - xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom" - ;; - *.xcdatamodeld) - echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\"" - xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd" - ;; - *.xcmappingmodel) - echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\"" - xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm" - ;; - *.xcassets) - ABSOLUTE_XCASSET_FILE=$(realpath "${PODS_ROOT}/$1") - XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") - ;; - /*) - echo "$1" - echo "$1" >> "$RESOURCES_TO_COPY" - ;; - *) - echo "${PODS_ROOT}/$1" - echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY" - ;; - esac -} - -mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then - mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" - rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -fi -rm -f "$RESOURCES_TO_COPY" - -if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] -then - case "${TARGETED_DEVICE_FAMILY}" in - 1,2) - TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" - ;; - 1) - TARGET_DEVICE_ARGS="--target-device iphone" - ;; - 2) - TARGET_DEVICE_ARGS="--target-device ipad" - ;; - *) - TARGET_DEVICE_ARGS="--target-device mac" - ;; - esac - - # Find all other xcassets (this unfortunately includes those of path pods and other targets). - OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) - while read line; do - if [[ $line != "`realpath $PODS_ROOT`*" ]]; then - XCASSET_FILES+=("$line") - fi - done <<<"$OTHER_XCASSETS" - - printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -fi diff --git a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample-umbrella.h b/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample-umbrella.h deleted file mode 100644 index 5b2d6e90..00000000 --- a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample-umbrella.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - - -FOUNDATION_EXPORT double Pods_PINRemoteImage_tvOSExampleVersionNumber; -FOUNDATION_EXPORT const unsigned char Pods_PINRemoteImage_tvOSExampleVersionString[]; - diff --git a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample.debug.xcconfig b/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample.debug.xcconfig deleted file mode 100644 index 463169cf..00000000 --- a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample.debug.xcconfig +++ /dev/null @@ -1,7 +0,0 @@ -FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_FRAMEWORK_BUILD_PATH" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -OTHER_CFLAGS = $(inherited) -iquote "$PODS_FRAMEWORK_BUILD_PATH/PINCache.framework/Headers" -iquote "$PODS_FRAMEWORK_BUILD_PATH/PINRemoteImage.framework/Headers" -OTHER_LDFLAGS = $(inherited) -framework "PINCache" -framework "PINRemoteImage" -PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-PINRemoteImage.tvOSExample -PODS_ROOT = ${SRCROOT}/Pods \ No newline at end of file diff --git a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample.modulemap b/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample.modulemap deleted file mode 100644 index 71e4b3fa..00000000 --- a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -framework module Pods_PINRemoteImage_tvOSExample { - umbrella header "Pods-PINRemoteImage.tvOSExample-umbrella.h" - - export * - module * { export * } -} diff --git a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample.release.xcconfig b/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample.release.xcconfig deleted file mode 100644 index 463169cf..00000000 --- a/Example-tvOS/Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample.release.xcconfig +++ /dev/null @@ -1,7 +0,0 @@ -FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_FRAMEWORK_BUILD_PATH" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -OTHER_CFLAGS = $(inherited) -iquote "$PODS_FRAMEWORK_BUILD_PATH/PINCache.framework/Headers" -iquote "$PODS_FRAMEWORK_BUILD_PATH/PINRemoteImage.framework/Headers" -OTHER_LDFLAGS = $(inherited) -framework "PINCache" -framework "PINRemoteImage" -PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-PINRemoteImage.tvOSExample -PODS_ROOT = ${SRCROOT}/Pods \ No newline at end of file diff --git a/Example/PINRemoteImage Tests/Info.plist b/Example/PINRemoteImage Tests/Info.plist deleted file mode 100644 index 15082b8e..00000000 --- a/Example/PINRemoteImage Tests/Info.plist +++ /dev/null @@ -1,31 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - NSExceptionAllowsInsecureHTTPLoads - - - - diff --git a/Example/PINRemoteImage Tests/PINRemoteImage_Tests.m b/Example/PINRemoteImage Tests/PINRemoteImage_Tests.m deleted file mode 100644 index d2e3c027..00000000 --- a/Example/PINRemoteImage Tests/PINRemoteImage_Tests.m +++ /dev/null @@ -1,931 +0,0 @@ -// -// PINRemoteImage_Tests.m -// PINRemoteImage Tests -// -// Created by Garrett Moon on 11/6/14. -// Copyright (c) 2014 Garrett Moon. All rights reserved. -// - -#import -#import -#import -#import -#import -#import -#import - -#if USE_FLANIMATED_IMAGE -#import -#endif - -static inline BOOL PINImageAlphaInfoIsOpaque(CGImageAlphaInfo info) { - switch (info) { - case kCGImageAlphaNone: - case kCGImageAlphaNoneSkipLast: - case kCGImageAlphaNoneSkipFirst: - return YES; - default: - return NO; - } -} - -#if DEBUG -@interface PINRemoteImageManager () - -@property (nonatomic, strong) PINURLSessionManager *sessionManager; -@property (nonatomic, readonly) NSUInteger totalDownloads; - -- (float)currentBytesPerSecond; -- (void)addTaskBPS:(float)bytesPerSecond endDate:(NSDate *)endDate; -- (void)setCurrentBytesPerSecond:(float)currentBPS; - -@end - -@interface PINURLSessionManager () - -@property (nonatomic, strong) NSURLSession *session; - -@end -#endif - -@interface PINRemoteImage_Tests : XCTestCase - -@property (nonatomic, strong) PINRemoteImageManager *imageManager; -@property (nonatomic, strong) NSData *data; -@property (nonatomic, strong) NSURLSessionTask *task; -@property (nonatomic, strong) NSError *error; - -@end - -@implementation PINRemoteImage_Tests - -- (NSTimeInterval)timeoutTimeInterval { - return 10.0; -} - -- (dispatch_time_t)timeoutWithInterval:(NSTimeInterval)interval { - return dispatch_time(DISPATCH_TIME_NOW, (int64_t)(interval * NSEC_PER_SEC)); -} - -- (dispatch_time_t)timeout { - return [self timeoutWithInterval:[self timeoutTimeInterval]]; -} - -- (NSURL *)GIFURL -{ - return [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/originals/90/f5/77/90f577fc6abcd24f9a5f9f55b2d7482b.jpg"]; -} - -- (NSURL *)emptyURL -{ - return [NSURL URLWithString:@""]; -} - -- (NSURL *)fourZeroFourURL -{ - return [NSURL URLWithString:@"https://www.pinterest.com/404/"]; -} - -- (NSURL *)headersURL -{ - return [NSURL URLWithString:@"https://httpbin.org/headers"]; -} - -- (NSURL *)JPEGURL_Small -{ - return [NSURL URLWithString:@"https://media-cache-ec0.pinimg.com/345x/1b/bc/c2/1bbcc264683171eb3815292d2f546e92.jpg"]; -} - -- (NSURL *)JPEGURL_Medium -{ - return [NSURL URLWithString:@"https://media-cache-ec0.pinimg.com/600x/1b/bc/c2/1bbcc264683171eb3815292d2f546e92.jpg"]; -} - -- (NSURL *)JPEGURL_Large -{ - return [NSURL URLWithString:@"https://media-cache-ec0.pinimg.com/750x/1b/bc/c2/1bbcc264683171eb3815292d2f546e92.jpg"]; -} - -- (NSURL *)JPEGURL -{ - return [self JPEGURL_Medium]; -} - -- (NSURL *)BASE64URL -{ - return [NSURL URLWithString:@"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD///+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4Ug9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC"]; -} - -- (NSURL *)transparentPNGURL -{ - return [NSURL URLWithString:@"https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png"]; -} - -- (NSURL *)nonTransparentWebPURL -{ - return [NSURL URLWithString:@"https://www.gstatic.com/webp/gallery/5.webp"]; -} - -- (NSURL *)transparentWebPURL -{ - return [NSURL URLWithString:@"https://www.gstatic.com/webp/gallery3/4_webp_ll.webp"]; -} - -- (NSURL *)veryLongURL -{ - return [NSURL URLWithString:@"https://placekitten.com/g/200/300?longarg=helloMomHowAreYouDoing.IamFineJustMovedToLiveWithANiceChapWeTravelTogetherInHisBlueBoxThroughSpaceAndTimeMaybeYouveMetHimAlready.YesterdayWeMetACultureOfPeopleWithTentaclesWhoSingWithAVeryCelestialVoice.SoGood.SeeYouSoon.MaybeYesterday.WhoKnows.XOXO"]; -} - -#pragma mark - - -- (void)didReceiveData:(NSData *)data forTask:(NSURLSessionTask *)task -{ - self.data = data; - self.task = task; -} - -- (void)didCompleteTask:(NSURLSessionTask *)task withError:(NSError *)error -{ - self.task = task; - self.error = error; -} - -- (void)setUp -{ - [super setUp]; - // Put setup code here. This method is called before the invocation of each test method in the class. - self.imageManager = [[PINRemoteImageManager alloc] init]; -} - -- (void)tearDown -{ - // Put teardown code here. This method is called after the invocation of each test method in the class. - //clear disk cache - [self.imageManager.cache removeAllCachedObjects]; - self.imageManager = nil; - [super tearDown]; -} - -#if USE_FLANIMATED_IMAGE -- (void)testGIFDownload -{ - XCTestExpectation *expectation = [self expectationWithDescription:@"Download animatedImage"]; - [self.imageManager downloadImageWithURL:[self GIFURL] - options:PINRemoteImageManagerDownloadOptionsNone - completion:^(PINRemoteImageManagerResult *result) - { - UIImage *outImage = result.image; - id outAnimatedImage = result.alternativeRepresentation; - - XCTAssert(outAnimatedImage && [outAnimatedImage isKindOfClass:[FLAnimatedImage class]], @"Failed downloading animatedImage or animatedImage is not an FLAnimatedImage."); - XCTAssert(outImage == nil, @"Image is not nil."); - - [expectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; -} -#endif - -- (void)testInitWithNilConfiguration -{ - self.imageManager = [[PINRemoteImageManager alloc] initWithSessionConfiguration:nil]; - XCTAssertNotNil(self.imageManager.sessionManager.session.configuration); -} - -- (void)testInitWithConfiguration -{ - NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; - configuration.HTTPAdditionalHeaders = @{ @"Authorization" : @"Pinterest 123456" }; - self.imageManager = [[PINRemoteImageManager alloc] initWithSessionConfiguration:configuration]; - XCTAssert([self.imageManager.sessionManager.session.configuration.HTTPAdditionalHeaders isEqualToDictionary:@{ @"Authorization" : @"Pinterest 123456" }]); -} - -- (void)testCustomHeaderIsAddedToImageRequests -{ - XCTestExpectation *expectation = [self expectationWithDescription:@"Custom header was added to image request"]; - NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; - configuration.HTTPAdditionalHeaders = @{ @"X-Custom-Header" : @"Custom Header Value" }; - self.imageManager = [[PINRemoteImageManager alloc] initWithSessionConfiguration:configuration]; - self.imageManager.sessionManager.delegate = self; - [self.imageManager downloadImageWithURL:[self headersURL] - options:PINRemoteImageManagerDownloadOptionsNone - completion:^(PINRemoteImageManagerResult *result) - { - NSDictionary *headers = [[NSJSONSerialization JSONObjectWithData:self.data options:NSJSONReadingMutableContainers error:nil] valueForKey:@"headers"]; - - XCTAssert([headers[@"X-Custom-Header"] isEqualToString:@"Custom Header Value"]); - - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; -} - -- (void)testSkipFLAnimatedImageDownload -{ - XCTestExpectation *expectation = [self expectationWithDescription:@"Download animated image"]; - [self.imageManager downloadImageWithURL:[self GIFURL] - options:PINRemoteImageManagerDisallowAlternateRepresentations - completion:^(PINRemoteImageManagerResult *result) - { - UIImage *outImage = result.image; - id outAnimatedImage = result.alternativeRepresentation; - - XCTAssert(outImage && [outImage isKindOfClass:[UIImage class]], @"Failed downloading image or image is not a UIImage."); - XCTAssert(outAnimatedImage == nil, @"Animated image is not nil."); - - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; -} - -- (void)testJPEGDownload -{ - XCTestExpectation *expectation = [self expectationWithDescription:@"Downloading JPEG image"]; - [self.imageManager downloadImageWithURL:[self JPEGURL] - options:PINRemoteImageManagerDownloadOptionsNone - completion:^(PINRemoteImageManagerResult *result) - { - UIImage *outImage = result.image; - id outAnimatedImage = result.alternativeRepresentation; - - XCTAssert(outImage && [outImage isKindOfClass:[UIImage class]], @"Failed downloading image or image is not a UIImage."); - XCTAssert(outAnimatedImage == nil, @"Animated image is not nil."); - - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; -} - -- (void)testBase64 -{ - XCTestExpectation *expectation = [self expectationWithDescription:@"Decoding base64 image"]; - [self.imageManager downloadImageWithURL:[self BASE64URL] - options:PINRemoteImageManagerDownloadOptionsNone - completion:^(PINRemoteImageManagerResult *result) - { - UIImage *outImage = result.image; - FLAnimatedImage *outAnimatedImage = result.alternativeRepresentation; - - XCTAssert(outImage && [outImage isKindOfClass:[UIImage class]], @"Failed downloading image or image is not a UIImage."); - XCTAssert(CGSizeEqualToSize(outImage.size, CGSizeMake(16,16)), @"Failed decoding image, image size is wrong."); - XCTAssert(outAnimatedImage == nil, @"Animated image is not nil."); - - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; -} - -- (void)testErrorOnNilURLDownload -{ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wnonnull" - XCTestExpectation *expectation = [self expectationWithDescription:@"Error on nil image url download"]; - [self.imageManager downloadImageWithURL:nil - options:PINRemoteImageManagerDownloadOptionsNone - completion:^(PINRemoteImageManagerResult *result) -#pragma clang diagnostic pop - { - NSError *outError = result.error; - - XCTAssert([outError.domain isEqualToString:NSURLErrorDomain]); - XCTAssert(outError.code == NSURLErrorUnsupportedURL); - XCTAssert([outError.localizedDescription isEqualToString:@"unsupported URL"]); - - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; -} - -- (void)testErrorOnEmptyURLDownload -{ - XCTestExpectation *expectation = [self expectationWithDescription:@"Error on empty image url download"]; - [self.imageManager downloadImageWithURL:[self emptyURL] - options:PINRemoteImageManagerDownloadOptionsNone - completion:^(PINRemoteImageManagerResult *result) - { - NSError *outError = result.error; - - XCTAssert([outError.domain isEqualToString:NSURLErrorDomain]); - XCTAssert(outError.code == NSURLErrorUnsupportedURL); - // iOS8 (and presumably 10.10) returns NSURLErrorUnsupportedURL which means the HTTP NSURLProtocol does not accept it - NSArray *validErrorMessages = @[ @"unsupported URL", @"The operation couldn’t be completed. (NSURLErrorDomain error -1002.)"]; - XCTAssert([validErrorMessages containsObject:outError.localizedDescription], @"%@", outError.localizedDescription); - - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; -} - -- (void)testErrorOn404Response -{ - XCTestExpectation *expectation = [self expectationWithDescription:@"Error on 404 response"]; - [self.imageManager downloadImageWithURL:[self fourZeroFourURL] - options:PINRemoteImageManagerDownloadOptionsNone - completion:^(PINRemoteImageManagerResult *result) - { - NSError *outError = result.error; - - XCTAssert([outError.domain isEqualToString:PINURLErrorDomain]); - XCTAssert(outError.code == 404); - - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; -} - -- (void)testDecoding -{ - dispatch_group_t group = dispatch_group_create(); - __block UIImage *outImageDecoded = nil; - __block UIImage *outImageEncoded = nil; - PINRemoteImageManager *encodedManager = [[PINRemoteImageManager alloc] init]; - - dispatch_group_enter(group); - [self.imageManager downloadImageWithURL:[self JPEGURL] - options:PINRemoteImageManagerDownloadOptionsNone - completion:^(PINRemoteImageManagerResult *result) - { - outImageDecoded = result.image; - dispatch_group_leave(group); - }]; - - dispatch_group_wait(group, DISPATCH_TIME_FOREVER); - - dispatch_group_enter(group); - [encodedManager downloadImageWithURL:[self JPEGURL] - options:PINRemoteImageManagerDownloadOptionsSkipDecode - completion:^(PINRemoteImageManagerResult *result) - { - outImageEncoded = result.image; - dispatch_group_leave(group); - }]; - - dispatch_group_wait(group, DISPATCH_TIME_FOREVER); - - CFTimeInterval before = CACurrentMediaTime(); - [self drawImage:outImageEncoded]; - CFTimeInterval after = CACurrentMediaTime(); - CFTimeInterval encodedDrawTime = after - before; - - before = CACurrentMediaTime(); - [self drawImage:outImageDecoded]; - after = CACurrentMediaTime(); - CFTimeInterval decodedDrawTime = after - before; - - XCTAssert(outImageEncoded && [outImageEncoded isKindOfClass:[UIImage class]], @"Failed downloading image or image is not a UIImage."); - XCTAssert(outImageDecoded && [outImageDecoded isKindOfClass:[UIImage class]], @"Failed downloading image or image is not a UIImage."); - XCTAssert(encodedDrawTime / decodedDrawTime > 2, @"Drawing decoded image should be much faster"); -} - -- (void)drawImage:(UIImage *)image -{ - UIGraphicsBeginImageContext(image.size); - - [image drawAtPoint:CGPointZero]; - - UIGraphicsEndImageContext(); -} - -- (void)waitForImageWithURLToBeCached:(NSURL *)URL -{ - NSString *key = [self.imageManager cacheKeyForURL:URL processorKey:nil]; - for (NSUInteger idx = 0; idx < 100; idx++) { - if ([[self.imageManager cache] objectExistsInCacheForKey:key]) { - break; - } - if (idx == 99) { - XCTAssert(NO, @"image never set to cache."); - } - usleep(50000); - } -} - -- (void)testTransparentWebPDownload -{ - XCTestExpectation *expectation = [self expectationWithDescription:@"Download transparent WebP image"]; - [self.imageManager downloadImageWithURL:[self transparentWebPURL] - options:PINRemoteImageManagerDownloadOptionsNone - completion:^(PINRemoteImageManagerResult *result) - { - XCTAssert(result.error == nil, @"error is non-nil: %@", result.error); - - UIImage *outImage = result.image; - id outAnimatedImage = result.alternativeRepresentation; - - XCTAssert(outImage && [outImage isKindOfClass:[UIImage class]], @"Failed downloading image or image is not a UIImage."); - - CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(outImage.CGImage); - BOOL opaque = alphaInfo == kCGImageAlphaNone || alphaInfo == kCGImageAlphaNoneSkipFirst || alphaInfo == kCGImageAlphaNoneSkipLast; - - XCTAssert(opaque == NO, @"transparent WebP image is opaque."); - XCTAssert(outAnimatedImage == nil, @"Animated image is not nil."); - - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; -} - -- (void)testNonTransparentWebPDownload -{ - XCTestExpectation *expectation = [self expectationWithDescription:@"Download non transparent WebP image"]; - [self.imageManager downloadImageWithURL:[self nonTransparentWebPURL] - options:PINRemoteImageManagerDownloadOptionsNone - completion:^(PINRemoteImageManagerResult *result) - { - UIImage *outImage = result.image; - id outAnimatedImage = result.alternativeRepresentation; - - XCTAssert(outImage && [outImage isKindOfClass:[UIImage class]], @"Failed downloading image or image is not a UIImage."); - - CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(outImage.CGImage); - BOOL opaque = alphaInfo == kCGImageAlphaNone || alphaInfo == kCGImageAlphaNoneSkipFirst || alphaInfo == kCGImageAlphaNoneSkipLast; - - XCTAssert(opaque == YES, @"non transparent WebP image is not opaque."); - XCTAssert(outAnimatedImage == nil, @"Animated image is not nil."); - - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; -} - -- (void)testPrefetchImage -{ - id key = [self.imageManager cacheKeyForURL:[self JPEGURL] processorKey:nil]; - - id object = [[self.imageManager cache] objectFromMemoryCacheForKey:key]; - XCTAssert(object == nil, @"image should not be in cache"); - - [self.imageManager prefetchImageWithURL:[self JPEGURL]]; - sleep([self timeoutTimeInterval]); - - object = [[self.imageManager cache] objectFromMemoryCacheForKey:key]; - XCTAssert(object, @"image was not prefetched or was not stored in cache"); -} - -- (void)testUIImageView -{ - XCTestExpectation *imageSetExpectation = [self expectationWithDescription:@"imageView did not have image set"]; - UIImageView *imageView = [[UIImageView alloc] init]; - __weak UIImageView *weakImageView = imageView; - [imageView pin_setImageFromURL:[self JPEGURL] - completion:^(PINRemoteImageManagerResult *result) - { - if (weakImageView.image) - [imageSetExpectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; -} - -#if USE_FLANIMATED_IMAGE -- (void)testFLAnimatedImageView -{ - XCTestExpectation *imageSetExpectation = [self expectationWithDescription:@"animatedImageView did not have animated image set"]; - FLAnimatedImageView *imageView = [[FLAnimatedImageView alloc] init]; - __weak FLAnimatedImageView *weakImageView = imageView; - [imageView pin_setImageFromURL:[self GIFURL] - completion:^(PINRemoteImageManagerResult *result) - { - if (weakImageView.animatedImage) - [imageSetExpectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; -} -#endif - -- (void)testEarlyReturn -{ - XCTestExpectation *expectation = [self expectationWithDescription:@"Download JPEG image"]; - [self.imageManager downloadImageWithURL:[self JPEGURL] completion:^(PINRemoteImageManagerResult *result) { - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; - - // callback can occur *before* image is stored in cache this is an optimization to avoid waiting on the cache to write. - // So, wait until it's actually in the cache. - [self waitForImageWithURLToBeCached:[self JPEGURL]]; - - __block UIImage *image = nil; - [self.imageManager downloadImageWithURL:[self JPEGURL] completion:^(PINRemoteImageManagerResult *result) { - image = result.image; - }]; - XCTAssert(image != nil, @"image callback did not occur synchronously."); -} - -#if USE_FLANIMATED_IMAGE -- (void)testload -{ - srand([[NSDate date] timeIntervalSince1970]); - dispatch_group_t group = dispatch_group_create(); - __block NSInteger count = 0; - const NSInteger numIntervals = 10000; - NSLock *countLock = [[NSLock alloc] init]; - for (NSUInteger idx = 0; idx < numIntervals; idx++) { - dispatch_group_enter(group); - NSURL *url = nil; - if (rand() % 2 == 0) { - url = [self JPEGURL]; - } else { - url = [self GIFURL]; - } - [self.imageManager downloadImageWithURL:url - options:PINRemoteImageManagerDownloadOptionsNone - completion:^(PINRemoteImageManagerResult *result) - { - [countLock lock]; - count++; - XCTAssert(count <= numIntervals, @"callback called too many times"); - [countLock unlock]; - XCTAssert((result.image && !result.alternativeRepresentation) || (result.alternativeRepresentation && !result.image), @"image or alternativeRepresentation not downloaded"); - if (rand() % 2) { - [[self.imageManager cache] removeCachedObjectForKey:[self.imageManager cacheKeyForURL:url processorKey:nil]]; - } - dispatch_group_leave(group); - }]; - } - XCTAssert(dispatch_group_wait(group, [self timeoutWithInterval:100]) == 0, @"Group timed out."); -} -#endif - -- (void)testInvalidObject -{ - NSString * const kPINRemoteImageDiskCacheName = @"PINRemoteImageManagerCache"; - NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]; - - PINDiskCache *tempDiskCache = [[PINDiskCache alloc] initWithName:kPINRemoteImageDiskCacheName rootPath:cachePath serializer:^NSData * _Nonnull(id _Nonnull object) { - return [NSKeyedArchiver archivedDataWithRootObject:object]; - } deserializer:^id _Nonnull(NSData * _Nonnull data) { - return [NSKeyedUnarchiver unarchiveObjectWithData:data]; - } fileExtension:nil]; - - [tempDiskCache setObject:@"invalid" forKey:[self.imageManager cacheKeyForURL:[self JPEGURL] processorKey:nil]]; - - XCTestExpectation *expectation = [self expectationWithDescription:@"Download JPEG image"]; - [self.imageManager downloadImageWithURL:[self JPEGURL] completion:^(PINRemoteImageManagerResult *result) { - UIImage *image = result.image; - - XCTAssert([image isKindOfClass:[UIImage class]], @"image should be UIImage"); - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; - -} - -- (void)testProcessingLoad -{ - dispatch_group_t group = dispatch_group_create(); - - __block UIImage *image = nil; - const NSUInteger numIntervals = 1000; - __block NSInteger processCount = 0; - __block UIImage *processedImage = nil; - NSLock *processCountLock = [[NSLock alloc] init]; - for (NSUInteger idx = 0; idx < numIntervals; idx++) { - dispatch_group_enter(group); - [self.imageManager downloadImageWithURL:[self JPEGURL] options:PINRemoteImageManagerDownloadOptionsNone - processorKey:@"process" - processor:^UIImage *(PINRemoteImageManagerResult *result, NSUInteger *cost) - { - [processCountLock lock]; - processCount++; - [processCountLock unlock]; - - UIImage *inputImage = result.image; - XCTAssert(inputImage, @"no input image"); - UIGraphicsBeginImageContextWithOptions(inputImage.size, NO, 0); - CGContextRef context = UIGraphicsGetCurrentContext(); - - CGRect destRect = CGRectMake(0, 0, inputImage.size.width, inputImage.size.height); - [[UIColor clearColor] set]; - CGContextFillRect(context, destRect); - - CGRect pathRect = CGRectMake(0, 0, inputImage.size.width, inputImage.size.height); - UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:pathRect - cornerRadius:MIN(inputImage.size.width, inputImage.size.height) / 2.0]; - CGContextAddPath(context, path.CGPath); - CGContextClosePath(context); - CGContextClip(context); - - [inputImage drawInRect:CGRectMake(0, 0, inputImage.size.width, inputImage.size.height)]; - - UIImage *roundedImage = nil; - roundedImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - processedImage = roundedImage; - - return roundedImage; - } - completion:^(PINRemoteImageManagerResult *result) - { - image = result.image; - XCTAssert([image isKindOfClass:[UIImage class]] && image == processedImage, @"result image is not a UIImage"); - dispatch_group_leave(group); - }]; - } - - XCTAssert(dispatch_group_wait(group, [self timeout]) == 0, @"Group timed out."); - - XCTAssert(processCount <= 1, @"image processed too many times"); - XCTAssert([image isKindOfClass:[UIImage class]], @"result image is not a UIImage"); -} - -- (void)testNumberDownloads -{ - dispatch_group_t group = dispatch_group_create(); - - __block UIImage *image = nil; - const NSUInteger numIntervals = 1000; - - for (NSUInteger idx = 0; idx < numIntervals; idx++) { - dispatch_group_enter(group); - [self.imageManager downloadImageWithURL:[self JPEGURL] completion:^(PINRemoteImageManagerResult *result) { - XCTAssert([result.image isKindOfClass:[UIImage class]], @"result image is not a UIImage"); - image = result.image; - dispatch_group_leave(group); - }]; - } - - XCTAssert(dispatch_group_wait(group, [self timeout]) == 0, @"Group timed out."); - - XCTAssert(self.imageManager.totalDownloads <= 1, @"image downloaded too many times"); - XCTAssert([image isKindOfClass:[UIImage class]], @"result image is not a UIImage"); -} - -- (BOOL)isFloat:(float)one equalToFloat:(float)two -{ - if (fabsf(one - two) < FLT_EPSILON) { - return YES; - } - return NO; -} - -- (void)testBytesPerSecond -{ - XCTestExpectation *finishExpectation = [self expectationWithDescription:@"Finished testing off the main thread."]; - //currentBytesPerSecond is not public, should not be called on the main queue - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - XCTAssert([self.imageManager currentBytesPerSecond] == -1, @"Without any tasks added, should be -1"); - [self.imageManager addTaskBPS:100 endDate:[NSDate dateWithTimeIntervalSinceNow:-61]]; - XCTAssert([self.imageManager currentBytesPerSecond] == -1, @"With only old task, should be -1"); - [self.imageManager addTaskBPS:100 endDate:[NSDate date]]; - XCTAssert([self isFloat:[self.imageManager currentBytesPerSecond] equalToFloat:100.0f], @"One task should be same as added task"); - [self.imageManager addTaskBPS:50 endDate:[NSDate dateWithTimeIntervalSinceNow:-30]]; - XCTAssert([self isFloat:[self.imageManager currentBytesPerSecond] equalToFloat:75.0f], @"Two tasks should be average of both tasks"); - [self.imageManager addTaskBPS:100 endDate:[NSDate dateWithTimeIntervalSinceNow:-61]]; - XCTAssert([self isFloat:[self.imageManager currentBytesPerSecond] equalToFloat:75.0f], @"Old task shouldn't be counted"); - [self.imageManager addTaskBPS:50 endDate:[NSDate date]]; - [self.imageManager addTaskBPS:50 endDate:[NSDate date]]; - [self.imageManager addTaskBPS:50 endDate:[NSDate date]]; - [self.imageManager addTaskBPS:50 endDate:[NSDate date]]; - [self.imageManager addTaskBPS:50 endDate:[NSDate date]]; - XCTAssert([self isFloat:[self.imageManager currentBytesPerSecond] equalToFloat:50.0f], @"Only last 5 tasks should be used"); - [finishExpectation fulfill]; - }); - [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; -} - -- (void)testQOS -{ - dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); - [self.imageManager setHighQualityBPSThreshold:10 completion:^{ - dispatch_semaphore_signal(semaphore); - }]; - XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); - - [self.imageManager setLowQualityBPSThreshold:5 completion:^{ - dispatch_semaphore_signal(semaphore); - }]; - XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); - - [self.imageManager setShouldUpgradeLowQualityImages:NO completion:^{ - dispatch_semaphore_signal(semaphore); - }]; - XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); - __block UIImage *image; - [self.imageManager downloadImageWithURLs:@[[self JPEGURL_Small], [self JPEGURL_Medium], [self JPEGURL_Large]] - options:PINRemoteImageManagerDownloadOptionsNone - progressImage:nil - completion:^(PINRemoteImageManagerResult *result) - { - image = result.image; - XCTAssert(image.size.width == 750, @"Large image should be downloaded. result.image: %@, result.error: %@", result.image, result.error); - dispatch_semaphore_signal(semaphore); - }]; - XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); - - // callback can occur *before* image is stored in cache this is an optimization to avoid waiting on the cache to write. - // So, wait until it's actually in the cache. - [self waitForImageWithURLToBeCached:[self JPEGURL_Large]]; - - [self.imageManager setCurrentBytesPerSecond:5]; - [self.imageManager downloadImageWithURLs:@[[self JPEGURL_Small], [self JPEGURL_Medium], [self JPEGURL_Large]] - options:PINRemoteImageManagerDownloadOptionsNone - progressImage:nil - completion:^(PINRemoteImageManagerResult *result) - { - image = result.image; - XCTAssert(image.size.width == 750, @"Large image should be found in cache"); - dispatch_semaphore_signal(semaphore); - }]; - XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); - - [self.imageManager.cache removeAllCachedObjects]; - [self.imageManager downloadImageWithURLs:@[[self JPEGURL_Small], [self JPEGURL_Medium], [self JPEGURL_Large]] - options:PINRemoteImageManagerDownloadOptionsNone - progressImage:nil - completion:^(PINRemoteImageManagerResult *result) - { - image = result.image; - XCTAssert(image.size.width == 345, @"Small image should be downloaded at low bps"); - dispatch_semaphore_signal(semaphore); - }]; - XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); - - [self waitForImageWithURLToBeCached:[self JPEGURL_Small]]; - - [self.imageManager setCurrentBytesPerSecond:100]; - [self.imageManager downloadImageWithURLs:@[[self JPEGURL_Small], [self JPEGURL_Medium], [self JPEGURL_Large]] - options:PINRemoteImageManagerDownloadOptionsNone - progressImage:nil - completion:^(PINRemoteImageManagerResult *result) - { - image = result.image; - XCTAssert(image.size.width == 345, @"Small image should be found in cache"); - dispatch_semaphore_signal(semaphore); - }]; - XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); - - [self.imageManager setShouldUpgradeLowQualityImages:YES completion:^{ - dispatch_semaphore_signal(semaphore); - }]; - XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); - - [self.imageManager setCurrentBytesPerSecond:7]; - [self.imageManager downloadImageWithURLs:@[[self JPEGURL_Small], [self JPEGURL_Medium], [self JPEGURL_Large]] - options:PINRemoteImageManagerDownloadOptionsNone - progressImage:nil - completion:^(PINRemoteImageManagerResult *result) - { - image = result.image; - XCTAssert(image.size.width == 600, @"Medium image should be now downloaded"); - dispatch_semaphore_signal(semaphore); - }]; - XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); - - //small image should have been removed from cache - NSString *key = [self.imageManager cacheKeyForURL:[self JPEGURL_Small] processorKey:nil]; - for (NSUInteger idx = 0; idx < 100; idx++) { - if ([[self.imageManager cache] objectFromMemoryCacheForKey:key] == nil) { - break; - } - sleep(50); - } - XCTAssert( - [[self.imageManager cache] objectFromMemoryCacheForKey:[self.imageManager cacheKeyForURL:[self JPEGURL_Small] processorKey:nil]] == nil, @"Small image should have been removed from cache"); - - [self.imageManager.cache removeAllCachedObjects]; - [self.imageManager setShouldUpgradeLowQualityImages:NO completion:^{ - dispatch_semaphore_signal(semaphore); - }]; - XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); - - [self.imageManager setCurrentBytesPerSecond:7]; - [self.imageManager downloadImageWithURLs:@[[self JPEGURL_Small], [self JPEGURL_Large]] - options:PINRemoteImageManagerDownloadOptionsNone - progressImage:nil - completion:^(PINRemoteImageManagerResult *result) - { - image = result.image; - XCTAssert(image.size.width == 345, @"Small image should be now downloaded"); - dispatch_semaphore_signal(semaphore); - }]; - XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); -} - -- (void)testAuthentication -{ - XCTestExpectation *expectation = [self expectationWithDescription:@"Authentification challenge was called"]; - - [self.imageManager setAuthenticationChallenge:^(NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, PINRemoteImageManagerAuthenticationChallengeCompletionHandler aHandler) { - aHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); - [expectation fulfill]; - }]; - - [self.imageManager downloadImageWithURL:[NSURL URLWithString:@"https://media-cache-ec0.pinimg.com/600x/1b/bc/c2/1bbcc264683171eb3815292d2f546e92.jpg"] - options:PINRemoteImageManagerDownloadOptionsNone - completion:nil]; - - [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; -} - -- (void)testDiskCacheOnLongURLs -{ - XCTestExpectation *expectation = [self expectationWithDescription:@"Image is available in the disk cache"]; - id cache = self.imageManager.cache; - NSURL *longURL = [self veryLongURL]; - NSString *key = [self.imageManager cacheKeyForURL:longURL processorKey:nil]; - [self.imageManager downloadImageWithURL:longURL - options:PINRemoteImageManagerDownloadOptionsNone - completion:^(PINRemoteImageManagerResult *result) - { - XCTAssertNotNil(result.image, @"Image should not be nil"); - id diskCachedObj = [cache objectFromDiskCacheForKey:key]; - XCTAssertNotNil(diskCachedObj); - [expectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; -} - -- (void)testLongCacheKeyCreationPerformance -{ - [self measureBlock:^{ - NSURL *longURL = [self veryLongURL]; - for (NSUInteger i = 0; i < 10000; i++) { - __unused NSString *key = [self.imageManager cacheKeyForURL:longURL processorKey:nil]; - } - }]; -} - -- (void)testDefaultCacheKeyCreationPerformance -{ - [self measureBlock:^{ - NSURL *defaultURL = [self JPEGURL]; - for (NSUInteger i = 0; i < 10000; i++) { - __unused NSString *key = [self.imageManager cacheKeyForURL:defaultURL processorKey:nil]; - } - }]; -} - -- (void)testThatNondecodedJPEGImageHasNoAlpha -{ - XCTestExpectation *expectation = [self expectationWithDescription:@"Downloading JPEG image"]; - [self.imageManager downloadImageWithURL:[self JPEGURL] - options:PINRemoteImageManagerDownloadOptionsSkipDecode - completion:^(PINRemoteImageManagerResult *result) - { - UIImage *outImage = result.image; - - XCTAssert(outImage && [outImage isKindOfClass:[UIImage class]], @"Failed downloading image or image is not a UIImage."); - XCTAssert(PINImageAlphaInfoIsOpaque(CGImageGetAlphaInfo(outImage.CGImage)), @"Opaque image has an alpha channel."); - - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; -} - -- (void)testThatDecodedJPEGImageHasNoAlpha -{ - XCTestExpectation *expectation = [self expectationWithDescription:@"Downloading JPEG image"]; - [self.imageManager downloadImageWithURL:[self JPEGURL] - options:PINRemoteImageManagerDownloadOptionsNone - completion:^(PINRemoteImageManagerResult *result) - { - UIImage *outImage = result.image; - - XCTAssert(outImage && [outImage isKindOfClass:[UIImage class]], @"Failed downloading image or image is not a UIImage."); - XCTAssert(PINImageAlphaInfoIsOpaque(CGImageGetAlphaInfo(outImage.CGImage)), @"Opaque image has an alpha channel."); - - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; -} - - -- (void)testThatNondecodedTransparentPNGImageHasAlpha -{ - XCTestExpectation *expectation = [self expectationWithDescription:@"Downloading PNG image"]; - [self.imageManager downloadImageWithURL:[self transparentPNGURL] - options:PINRemoteImageManagerDownloadOptionsSkipDecode - completion:^(PINRemoteImageManagerResult *result) - { - UIImage *outImage = result.image; - - XCTAssert(outImage && [outImage isKindOfClass:[UIImage class]], @"Failed downloading image or image is not a UIImage."); - XCTAssertFalse(PINImageAlphaInfoIsOpaque(CGImageGetAlphaInfo(outImage.CGImage)), @"Transparent image has no alpha."); - - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; -} - -- (void)testThatDecodedTransparentPNGImageHasAlpha -{ - XCTestExpectation *expectation = [self expectationWithDescription:@"Downloading PNG image"]; - [self.imageManager downloadImageWithURL:[self transparentPNGURL] - options:PINRemoteImageManagerDownloadOptionsNone - completion:^(PINRemoteImageManagerResult *result) - { - UIImage *outImage = result.image; - - XCTAssert(outImage && [outImage isKindOfClass:[UIImage class]], @"Failed downloading image or image is not a UIImage."); - XCTAssertFalse(PINImageAlphaInfoIsOpaque(CGImageGetAlphaInfo(outImage.CGImage)), @"Transparent image has no alpha."); - - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; -} - -@end diff --git a/Example/PINRemoteImage.xcodeproj/project.pbxproj b/Example/PINRemoteImage.xcodeproj/project.pbxproj deleted file mode 100644 index 6d27e9d8..00000000 --- a/Example/PINRemoteImage.xcodeproj/project.pbxproj +++ /dev/null @@ -1,649 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; - 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58F195388D20070C39A /* CoreGraphics.framework */; }; - 6003F592195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; - 6003F598195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F596195388D20070C39A /* InfoPlist.strings */; }; - 6003F59A195388D20070C39A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F599195388D20070C39A /* main.m */; }; - 6003F59E195388D20070C39A /* PINAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F59D195388D20070C39A /* PINAppDelegate.m */; }; - 6003F5A1195388D20070C39A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6003F59F195388D20070C39A /* Main.storyboard */; }; - 6003F5A7195388D20070C39A /* PINViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5A6195388D20070C39A /* PINViewController.m */; }; - 6003F5A9195388D20070C39A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5A8195388D20070C39A /* Images.xcassets */; }; - 682C52611B584DD300B3B813 /* ProcessingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 682C52601B584DD300B3B813 /* ProcessingViewController.m */; }; - 682C52671B58515D00B3B813 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 682C52661B58515D00B3B813 /* Media.xcassets */; }; - 682D3F7BAE8A92A5E46F046B /* libPods-PINRemoteImage Tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A85B7779305DF163437777D /* libPods-PINRemoteImage Tests.a */; }; - 68B385081B557116004EB26F /* WebPViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 68B385071B557116004EB26F /* WebPViewController.m */; }; - 68B3850B1B5572BF004EB26F /* ProgressiveViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 68B3850A1B5572BF004EB26F /* ProgressiveViewController.m */; }; - 68B3850E1B5577D4004EB26F /* DegradedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 68B3850D1B5577D4004EB26F /* DegradedViewController.m */; }; - 68B5CDF21A0BEC8C00A4BAAC /* PINRemoteImage_Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 68B5CDF11A0BEC8C00A4BAAC /* PINRemoteImage_Tests.m */; }; - 9D9328E51C3D4CC200E1F1D3 /* Kitten.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9328E41C3D4CC200E1F1D3 /* Kitten.m */; }; - D2712A480BA078E050EA2B3B /* libPods-PINRemoteImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CC3DC6E2AB62C575AEB6C8B /* libPods-PINRemoteImage.a */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 68B5CDF31A0BEC8C00A4BAAC /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 6003F582195388D10070C39A /* Project object */; - proxyType = 1; - remoteGlobalIDString = 6003F589195388D20070C39A; - remoteInfo = PIRemoteImage; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 063FF605A6CC8884BB10EE35 /* Pods-PINRemoteImage Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PINRemoteImage Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests.debug.xcconfig"; sourceTree = ""; }; - 1CC3DC6E2AB62C575AEB6C8B /* libPods-PINRemoteImage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PINRemoteImage.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 25CF9DB8CF954119BAA63004 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; - 5A85B7779305DF163437777D /* libPods-PINRemoteImage Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PINRemoteImage Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 6003F58A195388D20070C39A /* PINRemoteImage.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PINRemoteImage.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - 6003F591195388D20070C39A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 6003F595195388D20070C39A /* PINRemoteImage-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "PINRemoteImage-Info.plist"; sourceTree = ""; }; - 6003F597195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 6003F599195388D20070C39A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6003F59B195388D20070C39A /* PINRemoteImage-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PINRemoteImage-Prefix.pch"; sourceTree = ""; }; - 6003F59C195388D20070C39A /* PINAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PINAppDelegate.h; sourceTree = ""; }; - 6003F59D195388D20070C39A /* PINAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PINAppDelegate.m; sourceTree = ""; }; - 6003F5A0195388D20070C39A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6003F5A5195388D20070C39A /* PINViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PINViewController.h; sourceTree = ""; }; - 6003F5A6195388D20070C39A /* PINViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PINViewController.m; sourceTree = ""; }; - 6003F5A8195388D20070C39A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6003F5AF195388D20070C39A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; - 6008DA13D004B38845BA74EC /* Pods-PINRemoteImage Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PINRemoteImage Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests.release.xcconfig"; sourceTree = ""; }; - 682C525F1B584DD300B3B813 /* ProcessingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessingViewController.h; sourceTree = ""; }; - 682C52601B584DD300B3B813 /* ProcessingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProcessingViewController.m; sourceTree = ""; }; - 682C52661B58515D00B3B813 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Media.xcassets; path = PINRemoteImage/Media.xcassets; sourceTree = SOURCE_ROOT; }; - 68B385061B557116004EB26F /* WebPViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPViewController.h; sourceTree = ""; }; - 68B385071B557116004EB26F /* WebPViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebPViewController.m; sourceTree = ""; }; - 68B385091B5572BF004EB26F /* ProgressiveViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProgressiveViewController.h; sourceTree = ""; }; - 68B3850A1B5572BF004EB26F /* ProgressiveViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProgressiveViewController.m; sourceTree = ""; }; - 68B3850C1B5577D4004EB26F /* DegradedViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DegradedViewController.h; sourceTree = ""; }; - 68B3850D1B5577D4004EB26F /* DegradedViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DegradedViewController.m; sourceTree = ""; }; - 68B5CDED1A0BEC8C00A4BAAC /* PINRemoteImage Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "PINRemoteImage Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - 68B5CDF01A0BEC8C00A4BAAC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 68B5CDF11A0BEC8C00A4BAAC /* PINRemoteImage_Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImage_Tests.m; sourceTree = ""; }; - 8D571FD9970F7A64A2B80EE0 /* Pods-PINRemoteImage.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PINRemoteImage.release.xcconfig"; path = "Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage.release.xcconfig"; sourceTree = ""; }; - 95043F8A31505C02E51C4D2F /* Pods-PINRemoteImage.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PINRemoteImage.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage.debug.xcconfig"; sourceTree = ""; }; - 9D9328E31C3D4CC200E1F1D3 /* Kitten.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Kitten.h; path = "../../Example-Shared/Kitten.h"; sourceTree = ""; }; - 9D9328E41C3D4CC200E1F1D3 /* Kitten.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Kitten.m; path = "../../Example-Shared/Kitten.m"; sourceTree = ""; }; - A5DEC9B706184109844D57E2 /* PINRemoteImage.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = PINRemoteImage.podspec; path = ../PINRemoteImage.podspec; sourceTree = ""; }; - E2B84DF860DF48B5B22537B6 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6003F587195388D20070C39A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */, - 6003F592195388D20070C39A /* UIKit.framework in Frameworks */, - 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */, - D2712A480BA078E050EA2B3B /* libPods-PINRemoteImage.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 68B5CDEA1A0BEC8C00A4BAAC /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 682D3F7BAE8A92A5E46F046B /* libPods-PINRemoteImage Tests.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6003F581195388D10070C39A = { - isa = PBXGroup; - children = ( - 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */, - 6003F593195388D20070C39A /* PINRemoteImage */, - 68B5CDEE1A0BEC8C00A4BAAC /* PINRemoteImage Tests */, - 6003F58C195388D20070C39A /* Frameworks */, - 6003F58B195388D20070C39A /* Products */, - F5A6BFF7672C3055495CF245 /* Pods */, - ); - sourceTree = ""; - }; - 6003F58B195388D20070C39A /* Products */ = { - isa = PBXGroup; - children = ( - 6003F58A195388D20070C39A /* PINRemoteImage.app */, - 68B5CDED1A0BEC8C00A4BAAC /* PINRemoteImage Tests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 6003F58C195388D20070C39A /* Frameworks */ = { - isa = PBXGroup; - children = ( - 6003F58D195388D20070C39A /* Foundation.framework */, - 6003F58F195388D20070C39A /* CoreGraphics.framework */, - 6003F591195388D20070C39A /* UIKit.framework */, - 6003F5AF195388D20070C39A /* XCTest.framework */, - 1CC3DC6E2AB62C575AEB6C8B /* libPods-PINRemoteImage.a */, - 5A85B7779305DF163437777D /* libPods-PINRemoteImage Tests.a */, - ); - name = Frameworks; - sourceTree = ""; - }; - 6003F593195388D20070C39A /* PINRemoteImage */ = { - isa = PBXGroup; - children = ( - 9D9328E31C3D4CC200E1F1D3 /* Kitten.h */, - 9D9328E41C3D4CC200E1F1D3 /* Kitten.m */, - 6003F59C195388D20070C39A /* PINAppDelegate.h */, - 6003F59D195388D20070C39A /* PINAppDelegate.m */, - 6003F59F195388D20070C39A /* Main.storyboard */, - 6003F5A5195388D20070C39A /* PINViewController.h */, - 6003F5A6195388D20070C39A /* PINViewController.m */, - 6003F5A8195388D20070C39A /* Images.xcassets */, - 6003F594195388D20070C39A /* Supporting Files */, - 68B385061B557116004EB26F /* WebPViewController.h */, - 68B385071B557116004EB26F /* WebPViewController.m */, - 68B385091B5572BF004EB26F /* ProgressiveViewController.h */, - 68B3850A1B5572BF004EB26F /* ProgressiveViewController.m */, - 68B3850C1B5577D4004EB26F /* DegradedViewController.h */, - 68B3850D1B5577D4004EB26F /* DegradedViewController.m */, - 682C525F1B584DD300B3B813 /* ProcessingViewController.h */, - 682C52601B584DD300B3B813 /* ProcessingViewController.m */, - ); - path = PINRemoteImage; - sourceTree = ""; - }; - 6003F594195388D20070C39A /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 682C52661B58515D00B3B813 /* Media.xcassets */, - 6003F595195388D20070C39A /* PINRemoteImage-Info.plist */, - 6003F596195388D20070C39A /* InfoPlist.strings */, - 6003F599195388D20070C39A /* main.m */, - 6003F59B195388D20070C39A /* PINRemoteImage-Prefix.pch */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */ = { - isa = PBXGroup; - children = ( - A5DEC9B706184109844D57E2 /* PINRemoteImage.podspec */, - E2B84DF860DF48B5B22537B6 /* README.md */, - 25CF9DB8CF954119BAA63004 /* LICENSE */, - ); - name = "Podspec Metadata"; - sourceTree = ""; - }; - 68B5CDEE1A0BEC8C00A4BAAC /* PINRemoteImage Tests */ = { - isa = PBXGroup; - children = ( - 68B5CDF11A0BEC8C00A4BAAC /* PINRemoteImage_Tests.m */, - 68B5CDEF1A0BEC8C00A4BAAC /* Supporting Files */, - ); - path = "PINRemoteImage Tests"; - sourceTree = ""; - }; - 68B5CDEF1A0BEC8C00A4BAAC /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 68B5CDF01A0BEC8C00A4BAAC /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - F5A6BFF7672C3055495CF245 /* Pods */ = { - isa = PBXGroup; - children = ( - 95043F8A31505C02E51C4D2F /* Pods-PINRemoteImage.debug.xcconfig */, - 8D571FD9970F7A64A2B80EE0 /* Pods-PINRemoteImage.release.xcconfig */, - 063FF605A6CC8884BB10EE35 /* Pods-PINRemoteImage Tests.debug.xcconfig */, - 6008DA13D004B38845BA74EC /* Pods-PINRemoteImage Tests.release.xcconfig */, - ); - name = Pods; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6003F589195388D20070C39A /* PINRemoteImage */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "PINRemoteImage" */; - buildPhases = ( - D2E4FE25FDCE1E36A864F521 /* 📦 Check Pods Manifest.lock */, - 6003F586195388D20070C39A /* Sources */, - 6003F587195388D20070C39A /* Frameworks */, - 6003F588195388D20070C39A /* Resources */, - C29CD064817F94933C01A33C /* 📦 Embed Pods Frameworks */, - 5ADDA7CAEE4CC5113BCD55A4 /* 📦 Copy Pods Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = PINRemoteImage; - productName = PIRemoteImage; - productReference = 6003F58A195388D20070C39A /* PINRemoteImage.app */; - productType = "com.apple.product-type.application"; - }; - 68B5CDEC1A0BEC8C00A4BAAC /* PINRemoteImage Tests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 68B5CDF71A0BEC8C00A4BAAC /* Build configuration list for PBXNativeTarget "PINRemoteImage Tests" */; - buildPhases = ( - 7606B5F1EB3AB1B014CB163A /* 📦 Check Pods Manifest.lock */, - 68B5CDE91A0BEC8C00A4BAAC /* Sources */, - 68B5CDEA1A0BEC8C00A4BAAC /* Frameworks */, - 68B5CDEB1A0BEC8C00A4BAAC /* Resources */, - 47F0DF319C400B267A1F2C75 /* 📦 Embed Pods Frameworks */, - 748F831FA73D7004D52EA52B /* 📦 Copy Pods Resources */, - ); - buildRules = ( - ); - dependencies = ( - 68B5CDF41A0BEC8C00A4BAAC /* PBXTargetDependency */, - ); - name = "PINRemoteImage Tests"; - productName = "PIRemoteImage Tests"; - productReference = 68B5CDED1A0BEC8C00A4BAAC /* PINRemoteImage Tests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6003F582195388D10070C39A /* Project object */ = { - isa = PBXProject; - attributes = { - CLASSPREFIX = PI; - LastUpgradeCheck = 0730; - ORGANIZATIONNAME = "Garrett Moon"; - TargetAttributes = { - 68B5CDEC1A0BEC8C00A4BAAC = { - CreatedOnToolsVersion = 6.1; - TestTargetID = 6003F589195388D20070C39A; - }; - }; - }; - buildConfigurationList = 6003F585195388D10070C39A /* Build configuration list for PBXProject "PINRemoteImage" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6003F581195388D10070C39A; - productRefGroup = 6003F58B195388D20070C39A /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6003F589195388D20070C39A /* PINRemoteImage */, - 68B5CDEC1A0BEC8C00A4BAAC /* PINRemoteImage Tests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6003F588195388D20070C39A /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 682C52671B58515D00B3B813 /* Media.xcassets in Resources */, - 6003F5A9195388D20070C39A /* Images.xcassets in Resources */, - 6003F5A1195388D20070C39A /* Main.storyboard in Resources */, - 6003F598195388D20070C39A /* InfoPlist.strings in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 68B5CDEB1A0BEC8C00A4BAAC /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 47F0DF319C400B267A1F2C75 /* 📦 Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "📦 Embed Pods Frameworks"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - 5ADDA7CAEE4CC5113BCD55A4 /* 📦 Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "📦 Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - 748F831FA73D7004D52EA52B /* 📦 Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "📦 Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - 7606B5F1EB3AB1B014CB163A /* 📦 Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "📦 Check Pods Manifest.lock"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; - showEnvVarsInLog = 0; - }; - C29CD064817F94933C01A33C /* 📦 Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "📦 Embed Pods Frameworks"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - D2E4FE25FDCE1E36A864F521 /* 📦 Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "📦 Check Pods Manifest.lock"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6003F586195388D20070C39A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 68B385081B557116004EB26F /* WebPViewController.m in Sources */, - 68B3850B1B5572BF004EB26F /* ProgressiveViewController.m in Sources */, - 9D9328E51C3D4CC200E1F1D3 /* Kitten.m in Sources */, - 6003F59E195388D20070C39A /* PINAppDelegate.m in Sources */, - 682C52611B584DD300B3B813 /* ProcessingViewController.m in Sources */, - 6003F5A7195388D20070C39A /* PINViewController.m in Sources */, - 68B3850E1B5577D4004EB26F /* DegradedViewController.m in Sources */, - 6003F59A195388D20070C39A /* main.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 68B5CDE91A0BEC8C00A4BAAC /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 68B5CDF21A0BEC8C00A4BAAC /* PINRemoteImage_Tests.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 68B5CDF41A0BEC8C00A4BAAC /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 6003F589195388D20070C39A /* PINRemoteImage */; - targetProxy = 68B5CDF31A0BEC8C00A4BAAC /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 6003F596195388D20070C39A /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 6003F597195388D20070C39A /* en */, - ); - name = InfoPlist.strings; - sourceTree = ""; - }; - 6003F59F195388D20070C39A /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6003F5A0195388D20070C39A /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6003F5BD195388D20070C39A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6003F5BE195388D20070C39A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6003F5C0195388D20070C39A /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 95043F8A31505C02E51C4D2F /* Pods-PINRemoteImage.debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "PINRemoteImage/PINRemoteImage-Prefix.pch"; - INFOPLIST_FILE = "PINRemoteImage/PINRemoteImage-Info.plist"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - WRAPPER_EXTENSION = app; - }; - name = Debug; - }; - 6003F5C1195388D20070C39A /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 8D571FD9970F7A64A2B80EE0 /* Pods-PINRemoteImage.release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "PINRemoteImage/PINRemoteImage-Prefix.pch"; - INFOPLIST_FILE = "PINRemoteImage/PINRemoteImage-Info.plist"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - WRAPPER_EXTENSION = app; - }; - name = Release; - }; - 68B5CDF51A0BEC8C00A4BAAC /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 063FF605A6CC8884BB10EE35 /* Pods-PINRemoteImage Tests.debug.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CLANG_WARN_UNREACHABLE_CODE = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - INFOPLIST_FILE = "PINRemoteImage Tests/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_BUNDLE_IDENTIFIER = "Pinterest.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PINRemoteImage.app/PINRemoteImage"; - }; - name = Debug; - }; - 68B5CDF61A0BEC8C00A4BAAC /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 6008DA13D004B38845BA74EC /* Pods-PINRemoteImage Tests.release.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CLANG_WARN_UNREACHABLE_CODE = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); - INFOPLIST_FILE = "PINRemoteImage Tests/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_BUNDLE_IDENTIFIER = "Pinterest.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PINRemoteImage.app/PINRemoteImage"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6003F585195388D10070C39A /* Build configuration list for PBXProject "PINRemoteImage" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6003F5BD195388D20070C39A /* Debug */, - 6003F5BE195388D20070C39A /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "PINRemoteImage" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6003F5C0195388D20070C39A /* Debug */, - 6003F5C1195388D20070C39A /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 68B5CDF71A0BEC8C00A4BAAC /* Build configuration list for PBXNativeTarget "PINRemoteImage Tests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 68B5CDF51A0BEC8C00A4BAAC /* Debug */, - 68B5CDF61A0BEC8C00A4BAAC /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6003F582195388D10070C39A /* Project object */; -} diff --git a/Example/PINRemoteImage.xcodeproj/xcshareddata/xcschemes/PINRemoteImage.xcscheme b/Example/PINRemoteImage.xcodeproj/xcshareddata/xcschemes/PINRemoteImage.xcscheme deleted file mode 100644 index 44bd0e73..00000000 --- a/Example/PINRemoteImage.xcodeproj/xcshareddata/xcschemes/PINRemoteImage.xcscheme +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Example/PINRemoteImage.xcworkspace/contents.xcworkspacedata b/Example/PINRemoteImage.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 4d95871b..00000000 --- a/Example/PINRemoteImage.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/Example/PINRemoteImage.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Example/PINRemoteImage.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index 08de0be8..00000000 --- a/Example/PINRemoteImage.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded - - - diff --git a/Example/PINRemoteImage/Base.lproj/Main.storyboard b/Example/PINRemoteImage/Base.lproj/Main.storyboard deleted file mode 100644 index 9380e064..00000000 --- a/Example/PINRemoteImage/Base.lproj/Main.storyboard +++ /dev/null @@ -1,207 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Example/PINRemoteImage/Images.xcassets/AppIcon.appiconset/Contents.json b/Example/PINRemoteImage/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index eeea76c2..00000000 --- a/Example/PINRemoteImage/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "83.5x83.5", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Example/PINRemoteImage/PINRemoteImage-Prefix.pch b/Example/PINRemoteImage/PINRemoteImage-Prefix.pch deleted file mode 100644 index 82a2bb45..00000000 --- a/Example/PINRemoteImage/PINRemoteImage-Prefix.pch +++ /dev/null @@ -1,16 +0,0 @@ -// -// Prefix header -// -// The contents of this file are implicitly included at the beginning of every source file. -// - -#import - -#ifndef __IPHONE_5_0 -#warning "This project uses features only available in iOS SDK 5.0 and later." -#endif - -#ifdef __OBJC__ - #import - #import -#endif diff --git a/Example/PINRemoteImage/ProcessingViewController.m b/Example/PINRemoteImage/ProcessingViewController.m deleted file mode 100644 index ccb24801..00000000 --- a/Example/PINRemoteImage/ProcessingViewController.m +++ /dev/null @@ -1,88 +0,0 @@ -// -// ProcessingViewController.m -// PINRemoteImage -// -// Created by Garrett Moon on 7/16/15. -// Copyright (c) 2015 Garrett Moon. All rights reserved. -// - -#import "ProcessingViewController.h" - -#import - -@interface ProcessingViewController () - -@end - -@implementation ProcessingViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - // Do any additional setup after loading the view. -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. -} - -- (void)viewWillAppear:(BOOL)animated -{ - [super viewWillAppear:animated]; - - [self.imageView pin_setImageFromURL:[NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/5b/c6/c5/5bc6c5387ff6f104fd642f2b375efba3.jpg"] processorKey:@"rounded" processor:^UIImage *(PINRemoteImageManagerResult *result, NSUInteger *cost) - { - UIImage *image = result.image; - CGFloat radius = 7.0f; - CGSize targetSize = CGSizeMake(200, 300); - CGRect imageRect = CGRectMake(0, 0, targetSize.width, targetSize.height); - UIGraphicsBeginImageContext(imageRect.size); - UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:imageRect cornerRadius:radius]; - [bezierPath addClip]; - - CGFloat widthMultiplier = targetSize.width / image.size.width; - CGFloat heightMultiplier = targetSize.height / image.size.height; - CGFloat sizeMultiplier = MAX(widthMultiplier, heightMultiplier); - - CGRect drawRect = CGRectMake(0, 0, image.size.width * sizeMultiplier, image.size.height * sizeMultiplier); - if (CGRectGetMaxX(drawRect) > CGRectGetMaxX(imageRect)) { - drawRect.origin.x -= (CGRectGetMaxX(drawRect) - CGRectGetMaxX(imageRect)) / 2.0; - } - if (CGRectGetMaxY(drawRect) > CGRectGetMaxY(imageRect)) { - drawRect.origin.y -= (CGRectGetMaxY(drawRect) - CGRectGetMaxY(imageRect)) / 2.0; - } - - [image drawInRect:drawRect]; - - [[UIColor redColor] setStroke]; - [bezierPath setLineWidth:5.0]; - [bezierPath stroke]; - - CGContextRef ctx = UIGraphicsGetCurrentContext(); - CGContextSetBlendMode(ctx, kCGBlendModeOverlay); - CGContextSetAlpha(ctx, 0.5); - - UIImage *logo = [UIImage imageNamed:@"white-pinterest-logo"]; - CGContextScaleCTM(ctx, 1.0, -1.0); - CGContextTranslateCTM(ctx, 0.0, -drawRect.size.height); - CGContextDrawImage(ctx, CGRectMake(90, 10, logo.size.width, logo.size.height), [logo CGImage]); - - UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return processedImage; - }]; -} - -/* -#pragma mark - Navigation - -// In a storyboard-based application, you will often want to do a little preparation before navigation -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - // Get the new view controller using [segue destinationViewController]. - // Pass the selected object to the new view controller. -} -*/ - -@end diff --git a/Example/PINRemoteImage/ProgressiveViewController.m b/Example/PINRemoteImage/ProgressiveViewController.m deleted file mode 100644 index c5327cd3..00000000 --- a/Example/PINRemoteImage/ProgressiveViewController.m +++ /dev/null @@ -1,69 +0,0 @@ -// -// ProgressiveViewController.m -// PINRemoteImage -// -// Created by Garrett Moon on 7/14/15. -// Copyright (c) 2015 Garrett Moon. All rights reserved. -// - -#import "ProgressiveViewController.h" - -#import -#import - - -@interface ProgressiveViewController () - -@end - -@implementation ProgressiveViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - // MUST BE SET ON IMAGE VIEW TO GET PROGRESS UPDATES! - self.imageView.pin_updateWithProgress = YES; - // Do any additional setup after loading the view. -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. -} - -- (void)viewWillAppear:(BOOL)animated -{ - [super viewWillAppear:animated]; - self.imageView.image = nil; -} - -- (void)viewDidAppear:(BOOL)animated -{ - [super viewDidAppear:animated]; - NSURL *progressiveURL = [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/1200x/2e/0c/c5/2e0cc5d86e7b7cd42af225c29f21c37f.jpg"]; - [[PINRemoteImageManager sharedImageManager] setProgressThresholds:@[@(0.1), @(0.2), @(0.3), @(0.4), @(0.5), @(0.6), @(0.7), @(0.8), @(0.9)] completion:nil]; - [[[PINRemoteImageManager sharedImageManager] cache] removeCachedObjectForKey:[[PINRemoteImageManager sharedImageManager] cacheKeyForURL:progressiveURL processorKey:nil]]; - [self.imageView pin_setImageFromURL:progressiveURL]; - - NSMutableArray *progress = [[NSMutableArray alloc] init]; - [[PINRemoteImageManager sharedImageManager] - downloadImageWithURL:progressiveURL - options:PINRemoteImageManagerDownloadOptionsNone progressImage:^(PINRemoteImageManagerResult *result) { - [progress addObject:result.image]; - } completion:^(PINRemoteImageManagerResult *result) { - [progress addObject:result.image]; - }]; -} - -/* -#pragma mark - Navigation - -// In a storyboard-based application, you will often want to do a little preparation before navigation -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - // Get the new view controller using [segue destinationViewController]. - // Pass the selected object to the new view controller. -} -*/ - -@end diff --git a/Example/PINRemoteImage/WebPViewController.m b/Example/PINRemoteImage/WebPViewController.m deleted file mode 100644 index 1f056a3b..00000000 --- a/Example/PINRemoteImage/WebPViewController.m +++ /dev/null @@ -1,47 +0,0 @@ -// -// WebPViewController.m -// PINRemoteImage -// -// Created by Garrett Moon on 7/14/15. -// Copyright (c) 2015 Garrett Moon. All rights reserved. -// - -#import "WebPViewController.h" - -#import - -@interface WebPViewController () - -@end - -@implementation WebPViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - // Do any additional setup after loading the view. -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. -} - -- (void)viewDidAppear:(BOOL)animated -{ - [super viewDidAppear:animated]; - [self.imageView pin_setImageFromURL:[NSURL URLWithString:@"https://github.com/samdutton/simpl/blob/master/picturetype/kittens.webp?raw=true"]]; -} - -/* -#pragma mark - Navigation - -// In a storyboard-based application, you will often want to do a little preparation before navigation -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - // Get the new view controller using [segue destinationViewController]. - // Pass the selected object to the new view controller. -} -*/ - -@end diff --git a/Example/Podfile b/Example/Podfile deleted file mode 100644 index 63db68bf..00000000 --- a/Example/Podfile +++ /dev/null @@ -1,14 +0,0 @@ -xcodeproj 'PINRemoteImage.xcodeproj' - -def shared_pods - pod "PINRemoteImage", :path => "../" - pod "PINRemoteImage/WebP", :path => "../" -end - -target 'PINRemoteImage' do - shared_pods -end - -target 'PINRemoteImage Tests' do - shared_pods -end diff --git a/Example/Podfile.lock b/Example/Podfile.lock deleted file mode 100644 index 0ae2967b..00000000 --- a/Example/Podfile.lock +++ /dev/null @@ -1,58 +0,0 @@ -PODS: - - FLAnimatedImage (1.0.12) - - libwebp (0.5.0): - - libwebp/core (= 0.5.0) - - libwebp/dec (= 0.5.0) - - libwebp/demux (= 0.5.0) - - libwebp/dsp (= 0.5.0) - - libwebp/enc (= 0.5.0) - - libwebp/mux (= 0.5.0) - - libwebp/utils (= 0.5.0) - - libwebp/webp (= 0.5.0) - - libwebp/core (0.5.0): - - libwebp/webp - - libwebp/dec (0.5.0): - - libwebp/core - - libwebp/demux (0.5.0): - - libwebp/core - - libwebp/dsp (0.5.0): - - libwebp/core - - libwebp/enc (0.5.0): - - libwebp/core - - libwebp/mux (0.5.0): - - libwebp/core - - libwebp/utils (0.5.0): - - libwebp/core - - libwebp/webp (0.5.0) - - PINCache (3.0.1-beta) - - PINRemoteImage (3.0.0-beta.3): - - PINRemoteImage/FLAnimatedImage (= 3.0.0-beta.3) - - PINRemoteImage/PINCache (= 3.0.0-beta.3) - - PINRemoteImage/Core (3.0.0-beta.3) - - PINRemoteImage/FLAnimatedImage (3.0.0-beta.3): - - FLAnimatedImage (>= 1.0) - - PINRemoteImage/Core - - PINRemoteImage/PINCache (3.0.0-beta.3): - - PINCache (>= 3.0.1-beta) - - PINRemoteImage/Core - - PINRemoteImage/WebP (3.0.0-beta.3): - - libwebp - - PINRemoteImage/Core - -DEPENDENCIES: - - PINRemoteImage (from `../`) - - PINRemoteImage/WebP (from `../`) - -EXTERNAL SOURCES: - PINRemoteImage: - :path: ../ - -SPEC CHECKSUMS: - FLAnimatedImage: 4a0b56255d9b05f18b6dd7ee06871be5d3b89e31 - libwebp: 68ba2001ba6806ee52837ebd77a551a0b6567e4e - PINCache: 6911fe422a633e18b3d3ddf2bd4f0e55e36e2892 - PINRemoteImage: 909c740cc2878fa6b45a3cc093b87d8195a7e0fa - -PODFILE CHECKSUM: a64f6dc82868b26747c10e6c5e963d51a1ba55ba - -COCOAPODS: 1.0.0 diff --git a/Example/Pods/FLAnimatedImage/FLAnimatedImage/FLAnimatedImage.h b/Example/Pods/FLAnimatedImage/FLAnimatedImage/FLAnimatedImage.h deleted file mode 100644 index f056c3b9..00000000 --- a/Example/Pods/FLAnimatedImage/FLAnimatedImage/FLAnimatedImage.h +++ /dev/null @@ -1,84 +0,0 @@ -// -// FLAnimatedImage.h -// Flipboard -// -// Created by Raphael Schaad on 7/8/13. -// Copyright (c) 2013-2015 Flipboard. All rights reserved. -// - - -#import - -// Allow user classes conveniently just importing one header. -#import "FLAnimatedImageView.h" - - -#ifndef NS_DESIGNATED_INITIALIZER - #if __has_attribute(objc_designated_initializer) - #define NS_DESIGNATED_INITIALIZER __attribute((objc_designated_initializer)) - #else - #define NS_DESIGNATED_INITIALIZER - #endif -#endif - -extern const NSTimeInterval kFLAnimatedImageDelayTimeIntervalMinimum; - -// -// An `FLAnimatedImage`'s job is to deliver frames in a highly performant way and works in conjunction with `FLAnimatedImageView`. -// It subclasses `NSObject` and not `UIImage` because it's only an "image" in the sense that a sea lion is a lion. -// It tries to intelligently choose the frame cache size depending on the image and memory situation with the goal to lower CPU usage for smaller ones, lower memory usage for larger ones and always deliver frames for high performant play-back. -// Note: `posterImage`, `size`, `loopCount`, `delayTimes` and `frameCount` don't change after successful initialization. -// -@interface FLAnimatedImage : NSObject - -@property (nonatomic, strong, readonly) UIImage *posterImage; // Guaranteed to be loaded; usually equivalent to `-imageLazilyCachedAtIndex:0` -@property (nonatomic, assign, readonly) CGSize size; // The `.posterImage`'s `.size` - -@property (nonatomic, assign, readonly) NSUInteger loopCount; // 0 means repeating the animation indefinitely -@property (nonatomic, strong, readonly) NSDictionary *delayTimesForIndexes; // Of type `NSTimeInterval` boxed in `NSNumber`s -@property (nonatomic, assign, readonly) NSUInteger frameCount; // Number of valid frames; equal to `[.delayTimes count]` - -@property (nonatomic, assign, readonly) NSUInteger frameCacheSizeCurrent; // Current size of intelligently chosen buffer window; can range in the interval [1..frameCount] -@property (nonatomic, assign) NSUInteger frameCacheSizeMax; // Allow to cap the cache size; 0 means no specific limit (default) - -// Intended to be called from main thread synchronously; will return immediately. -// If the result isn't cached, will return `nil`; the caller should then pause playback, not increment frame counter and keep polling. -// After an initial loading time, depending on `frameCacheSize`, frames should be available immediately from the cache. -- (UIImage *)imageLazilyCachedAtIndex:(NSUInteger)index; - -// Pass either a `UIImage` or an `FLAnimatedImage` and get back its size -+ (CGSize)sizeForImage:(id)image; - -// On success, the initializers return an `FLAnimatedImage` with all fields initialized, on failure they return `nil` and an error will be logged. -- (instancetype)initWithAnimatedGIFData:(NSData *)data; -// Pass 0 for optimalFrameCacheSize to get the default, predrawing is enabled by default. -- (instancetype)initWithAnimatedGIFData:(NSData *)data optimalFrameCacheSize:(NSUInteger)optimalFrameCacheSize predrawingEnabled:(BOOL)isPredrawingEnabled NS_DESIGNATED_INITIALIZER; -+ (instancetype)animatedImageWithGIFData:(NSData *)data; - -@property (nonatomic, strong, readonly) NSData *data; // The data the receiver was initialized with; read-only - -@end - -typedef NS_ENUM(NSUInteger, FLLogLevel) { - FLLogLevelNone = 0, - FLLogLevelError, - FLLogLevelWarn, - FLLogLevelInfo, - FLLogLevelDebug, - FLLogLevelVerbose -}; - -@interface FLAnimatedImage (Logging) - -+ (void)setLogBlock:(void (^)(NSString *logString, FLLogLevel logLevel))logBlock logLevel:(FLLogLevel)logLevel; -+ (void)logStringFromBlock:(NSString *(^)(void))stringBlock withLevel:(FLLogLevel)level; - -@end - -#define FLLog(logLevel, format, ...) [FLAnimatedImage logStringFromBlock:^NSString *{ return [NSString stringWithFormat:(format), ## __VA_ARGS__]; } withLevel:(logLevel)] - -@interface FLWeakProxy : NSProxy - -+ (instancetype)weakProxyForObject:(id)targetObject; - -@end diff --git a/Example/Pods/FLAnimatedImage/FLAnimatedImage/FLAnimatedImage.m b/Example/Pods/FLAnimatedImage/FLAnimatedImage/FLAnimatedImage.m deleted file mode 100755 index 3fdddc96..00000000 --- a/Example/Pods/FLAnimatedImage/FLAnimatedImage/FLAnimatedImage.m +++ /dev/null @@ -1,816 +0,0 @@ -// -// FLAnimatedImage.m -// Flipboard -// -// Created by Raphael Schaad on 7/8/13. -// Copyright (c) 2013-2015 Flipboard. All rights reserved. -// - - -#import "FLAnimatedImage.h" -#import -#import - - -// From vm_param.h, define for iOS 8.0 or higher to build on device. -#ifndef BYTE_SIZE - #define BYTE_SIZE 8 // byte size in bits -#endif - -#define MEGABYTE (1024 * 1024) - -// This is how the fastest browsers do it as per 2012: http://nullsleep.tumblr.com/post/16524517190/animated-gif-minimum-frame-delay-browser-compatibility -const NSTimeInterval kFLAnimatedImageDelayTimeIntervalMinimum = 0.02; - -// An animated image's data size (dimensions * frameCount) category; its value is the max allowed memory (in MB). -// E.g.: A 100x200px GIF with 30 frames is ~2.3MB in our pixel format and would fall into the `FLAnimatedImageDataSizeCategoryAll` category. -typedef NS_ENUM(NSUInteger, FLAnimatedImageDataSizeCategory) { - FLAnimatedImageDataSizeCategoryAll = 10, // All frames permanently in memory (be nice to the CPU) - FLAnimatedImageDataSizeCategoryDefault = 75, // A frame cache of default size in memory (usually real-time performance and keeping low memory profile) - FLAnimatedImageDataSizeCategoryOnDemand = 250, // Only keep one frame at the time in memory (easier on memory, slowest performance) - FLAnimatedImageDataSizeCategoryUnsupported // Even for one frame too large, computer says no. -}; - -typedef NS_ENUM(NSUInteger, FLAnimatedImageFrameCacheSize) { - FLAnimatedImageFrameCacheSizeNoLimit = 0, // 0 means no specific limit - FLAnimatedImageFrameCacheSizeLowMemory = 1, // The minimum frame cache size; this will produce frames on-demand. - FLAnimatedImageFrameCacheSizeGrowAfterMemoryWarning = 2, // If we can produce the frames faster than we consume, one frame ahead will already result in a stutter-free playback. - FLAnimatedImageFrameCacheSizeDefault = 5 // Build up a comfy buffer window to cope with CPU hiccups etc. -}; - - -#if defined(DEBUG) && DEBUG -@protocol FLAnimatedImageDebugDelegate -@optional -- (void)debug_animatedImage:(FLAnimatedImage *)animatedImage didUpdateCachedFrames:(NSIndexSet *)indexesOfFramesInCache; -- (void)debug_animatedImage:(FLAnimatedImage *)animatedImage didRequestCachedFrame:(NSUInteger)index; -- (CGFloat)debug_animatedImagePredrawingSlowdownFactor:(FLAnimatedImage *)animatedImage; -@end -#endif - - -@interface FLAnimatedImage () - -@property (nonatomic, assign, readonly) NSUInteger frameCacheSizeOptimal; // The optimal number of frames to cache based on image size & number of frames; never changes -@property (nonatomic, assign, readonly, getter=isPredrawingEnabled) BOOL predrawingEnabled; // Enables predrawing of images to improve performance. -@property (nonatomic, assign) NSUInteger frameCacheSizeMaxInternal; // Allow to cap the cache size e.g. when memory warnings occur; 0 means no specific limit (default) -@property (nonatomic, assign) NSUInteger requestedFrameIndex; // Most recently requested frame index -@property (nonatomic, assign, readonly) NSUInteger posterImageFrameIndex; // Index of non-purgable poster image; never changes -@property (nonatomic, strong, readonly) NSMutableDictionary *cachedFramesForIndexes; -@property (nonatomic, strong, readonly) NSMutableIndexSet *cachedFrameIndexes; // Indexes of cached frames -@property (nonatomic, strong, readonly) NSMutableIndexSet *requestedFrameIndexes; // Indexes of frames that are currently produced in the background -@property (nonatomic, strong, readonly) NSIndexSet *allFramesIndexSet; // Default index set with the full range of indexes; never changes -@property (nonatomic, assign) NSUInteger memoryWarningCount; -@property (nonatomic, strong, readonly) dispatch_queue_t serialQueue; -@property (nonatomic, strong, readonly) __attribute__((NSObject)) CGImageSourceRef imageSource; - -// The weak proxy is used to break retain cycles with delayed actions from memory warnings. -// We are lying about the actual type here to gain static type checking and eliminate casts. -// The actual type of the object is `FLWeakProxy`. -@property (nonatomic, strong, readonly) FLAnimatedImage *weakProxy; - -#if defined(DEBUG) && DEBUG -@property (nonatomic, weak) id debug_delegate; -#endif - -@end - - -// For custom dispatching of memory warnings to avoid deallocation races since NSNotificationCenter doesn't retain objects it is notifying. -static NSHashTable *allAnimatedImagesWeak; - -@implementation FLAnimatedImage - -#pragma mark - Accessors -#pragma mark Public - -// This is the definite value the frame cache needs to size itself to. -- (NSUInteger)frameCacheSizeCurrent -{ - NSUInteger frameCacheSizeCurrent = self.frameCacheSizeOptimal; - - // If set, respect the caps. - if (self.frameCacheSizeMax > FLAnimatedImageFrameCacheSizeNoLimit) { - frameCacheSizeCurrent = MIN(frameCacheSizeCurrent, self.frameCacheSizeMax); - } - - if (self.frameCacheSizeMaxInternal > FLAnimatedImageFrameCacheSizeNoLimit) { - frameCacheSizeCurrent = MIN(frameCacheSizeCurrent, self.frameCacheSizeMaxInternal); - } - - return frameCacheSizeCurrent; -} - - -- (void)setFrameCacheSizeMax:(NSUInteger)frameCacheSizeMax -{ - if (_frameCacheSizeMax != frameCacheSizeMax) { - - // Remember whether the new cap will cause the current cache size to shrink; then we'll make sure to purge from the cache if needed. - BOOL willFrameCacheSizeShrink = (frameCacheSizeMax < self.frameCacheSizeCurrent); - - // Update the value - _frameCacheSizeMax = frameCacheSizeMax; - - if (willFrameCacheSizeShrink) { - [self purgeFrameCacheIfNeeded]; - } - } -} - - -#pragma mark Private - -- (void)setFrameCacheSizeMaxInternal:(NSUInteger)frameCacheSizeMaxInternal -{ - if (_frameCacheSizeMaxInternal != frameCacheSizeMaxInternal) { - - // Remember whether the new cap will cause the current cache size to shrink; then we'll make sure to purge from the cache if needed. - BOOL willFrameCacheSizeShrink = (frameCacheSizeMaxInternal < self.frameCacheSizeCurrent); - - // Update the value - _frameCacheSizeMaxInternal = frameCacheSizeMaxInternal; - - if (willFrameCacheSizeShrink) { - [self purgeFrameCacheIfNeeded]; - } - } -} - - -#pragma mark - Life Cycle - -+ (void)initialize -{ - if (self == [FLAnimatedImage class]) { - // UIKit memory warning notification handler shared by all of the instances - allAnimatedImagesWeak = [NSHashTable weakObjectsHashTable]; - - [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidReceiveMemoryWarningNotification object:nil queue:nil usingBlock:^(NSNotification *note) { - // UIKit notifications are posted on the main thread. didReceiveMemoryWarning: is expecting the main run loop, and we don't lock on allAnimatedImagesWeak - NSAssert([NSThread isMainThread], @"Received memory warning on non-main thread"); - // Get a strong reference to all of the images. If an instance is returned in this array, it is still live and has not entered dealloc. - // Note that FLAnimatedImages can be created on any thread, so the hash table must be locked. - NSArray *images = nil; - @synchronized(allAnimatedImagesWeak) { - images = [[allAnimatedImagesWeak allObjects] copy]; - } - // Now issue notifications to all of the images while holding a strong reference to them - [images makeObjectsPerformSelector:@selector(didReceiveMemoryWarning:) withObject:note]; - }]; - } -} - - -- (instancetype)init -{ - FLAnimatedImage *animatedImage = [self initWithAnimatedGIFData:nil]; - if (!animatedImage) { - FLLog(FLLogLevelError, @"Use `-initWithAnimatedGIFData:` and supply the animated GIF data as an argument to initialize an object of type `FLAnimatedImage`."); - } - return animatedImage; -} - - -- (instancetype)initWithAnimatedGIFData:(NSData *)data -{ - return [self initWithAnimatedGIFData:data optimalFrameCacheSize:0 predrawingEnabled:YES]; -} - -- (instancetype)initWithAnimatedGIFData:(NSData *)data optimalFrameCacheSize:(NSUInteger)optimalFrameCacheSize predrawingEnabled:(BOOL)isPredrawingEnabled -{ - // Early return if no data supplied! - BOOL hasData = ([data length] > 0); - if (!hasData) { - FLLog(FLLogLevelError, @"No animated GIF data supplied."); - return nil; - } - - self = [super init]; - if (self) { - // Do one-time initializations of `readonly` properties directly to ivar to prevent implicit actions and avoid need for private `readwrite` property overrides. - - // Keep a strong reference to `data` and expose it read-only publicly. - // However, we will use the `_imageSource` as handler to the image data throughout our life cycle. - _data = data; - _predrawingEnabled = isPredrawingEnabled; - - // Initialize internal data structures - _cachedFramesForIndexes = [[NSMutableDictionary alloc] init]; - _cachedFrameIndexes = [[NSMutableIndexSet alloc] init]; - _requestedFrameIndexes = [[NSMutableIndexSet alloc] init]; - - // Note: We could leverage `CGImageSourceCreateWithURL` too to add a second initializer `-initWithAnimatedGIFContentsOfURL:`. - _imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, - (__bridge CFDictionaryRef)@{(NSString *)kCGImageSourceShouldCache: @NO}); - // Early return on failure! - if (!_imageSource) { - FLLog(FLLogLevelError, @"Failed to `CGImageSourceCreateWithData` for animated GIF data %@", data); - return nil; - } - - // Early return if not GIF! - CFStringRef imageSourceContainerType = CGImageSourceGetType(_imageSource); - BOOL isGIFData = UTTypeConformsTo(imageSourceContainerType, kUTTypeGIF); - if (!isGIFData) { - FLLog(FLLogLevelError, @"Supplied data is of type %@ and doesn't seem to be GIF data %@", imageSourceContainerType, data); - return nil; - } - - // Get `LoopCount` - // Note: 0 means repeating the animation indefinitely. - // Image properties example: - // { - // FileSize = 314446; - // "{GIF}" = { - // HasGlobalColorMap = 1; - // LoopCount = 0; - // }; - // } - NSDictionary *imageProperties = (__bridge_transfer NSDictionary *)CGImageSourceCopyProperties(_imageSource, NULL); - _loopCount = [[[imageProperties objectForKey:(id)kCGImagePropertyGIFDictionary] objectForKey:(id)kCGImagePropertyGIFLoopCount] unsignedIntegerValue]; - - // Iterate through frame images - size_t imageCount = CGImageSourceGetCount(_imageSource); - NSUInteger skippedFrameCount = 0; - NSMutableDictionary *delayTimesForIndexesMutable = [NSMutableDictionary dictionaryWithCapacity:imageCount]; - for (size_t i = 0; i < imageCount; i++) { - @autoreleasepool { - CGImageRef frameImageRef = CGImageSourceCreateImageAtIndex(_imageSource, i, NULL); - if (frameImageRef) { - UIImage *frameImage = [UIImage imageWithCGImage:frameImageRef]; - // Check for valid `frameImage` before parsing its properties as frames can be corrupted (and `frameImage` even `nil` when `frameImageRef` was valid). - if (frameImage) { - // Set poster image - if (!self.posterImage) { - _posterImage = frameImage; - // Set its size to proxy our size. - _size = _posterImage.size; - // Remember index of poster image so we never purge it; also add it to the cache. - _posterImageFrameIndex = i; - [self.cachedFramesForIndexes setObject:self.posterImage forKey:@(self.posterImageFrameIndex)]; - [self.cachedFrameIndexes addIndex:self.posterImageFrameIndex]; - } - - // Get `DelayTime` - // Note: It's not in (1/100) of a second like still falsely described in the documentation as per iOS 8 (rdar://19507384) but in seconds stored as `kCFNumberFloat32Type`. - // Frame properties example: - // { - // ColorModel = RGB; - // Depth = 8; - // PixelHeight = 960; - // PixelWidth = 640; - // "{GIF}" = { - // DelayTime = "0.4"; - // UnclampedDelayTime = "0.4"; - // }; - // } - - NSDictionary *frameProperties = (__bridge_transfer NSDictionary *)CGImageSourceCopyPropertiesAtIndex(_imageSource, i, NULL); - NSDictionary *framePropertiesGIF = [frameProperties objectForKey:(id)kCGImagePropertyGIFDictionary]; - - // Try to use the unclamped delay time; fall back to the normal delay time. - NSNumber *delayTime = [framePropertiesGIF objectForKey:(id)kCGImagePropertyGIFUnclampedDelayTime]; - if (!delayTime) { - delayTime = [framePropertiesGIF objectForKey:(id)kCGImagePropertyGIFDelayTime]; - } - // If we don't get a delay time from the properties, fall back to `kDelayTimeIntervalDefault` or carry over the preceding frame's value. - const NSTimeInterval kDelayTimeIntervalDefault = 0.1; - if (!delayTime) { - if (i == 0) { - FLLog(FLLogLevelInfo, @"Falling back to default delay time for first frame %@ because none found in GIF properties %@", frameImage, frameProperties); - delayTime = @(kDelayTimeIntervalDefault); - } else { - FLLog(FLLogLevelInfo, @"Falling back to preceding delay time for frame %zu %@ because none found in GIF properties %@", i, frameImage, frameProperties); - delayTime = delayTimesForIndexesMutable[@(i - 1)]; - } - } - // Support frame delays as low as `kFLAnimatedImageDelayTimeIntervalMinimum`, with anything below being rounded up to `kDelayTimeIntervalDefault` for legacy compatibility. - // To support the minimum even when rounding errors occur, use an epsilon when comparing. We downcast to float because that's what we get for delayTime from ImageIO. - if ([delayTime floatValue] < ((float)kFLAnimatedImageDelayTimeIntervalMinimum - FLT_EPSILON)) { - FLLog(FLLogLevelInfo, @"Rounding frame %zu's `delayTime` from %f up to default %f (minimum supported: %f).", i, [delayTime floatValue], kDelayTimeIntervalDefault, kFLAnimatedImageDelayTimeIntervalMinimum); - delayTime = @(kDelayTimeIntervalDefault); - } - delayTimesForIndexesMutable[@(i)] = delayTime; - } else { - skippedFrameCount++; - FLLog(FLLogLevelInfo, @"Dropping frame %zu because valid `CGImageRef` %@ did result in `nil`-`UIImage`.", i, frameImageRef); - } - CFRelease(frameImageRef); - } else { - skippedFrameCount++; - FLLog(FLLogLevelInfo, @"Dropping frame %zu because failed to `CGImageSourceCreateImageAtIndex` with image source %@", i, _imageSource); - } - } - } - _delayTimesForIndexes = [delayTimesForIndexesMutable copy]; - _frameCount = imageCount; - - if (self.frameCount == 0) { - FLLog(FLLogLevelInfo, @"Failed to create any valid frames for GIF with properties %@", imageProperties); - return nil; - } else if (self.frameCount == 1) { - // Warn when we only have a single frame but return a valid GIF. - FLLog(FLLogLevelInfo, @"Created valid GIF but with only a single frame. Image properties: %@", imageProperties); - } else { - // We have multiple frames, rock on! - } - - // If no value is provided, select a default based on the GIF. - if (optimalFrameCacheSize == 0) { - // Calculate the optimal frame cache size: try choosing a larger buffer window depending on the predicted image size. - // It's only dependent on the image size & number of frames and never changes. - CGFloat animatedImageDataSize = CGImageGetBytesPerRow(self.posterImage.CGImage) * self.size.height * (self.frameCount - skippedFrameCount) / MEGABYTE; - if (animatedImageDataSize <= FLAnimatedImageDataSizeCategoryAll) { - _frameCacheSizeOptimal = self.frameCount; - } else if (animatedImageDataSize <= FLAnimatedImageDataSizeCategoryDefault) { - // This value doesn't depend on device memory much because if we're not keeping all frames in memory we will always be decoding 1 frame up ahead per 1 frame that gets played and at this point we might as well just keep a small buffer just large enough to keep from running out of frames. - _frameCacheSizeOptimal = FLAnimatedImageFrameCacheSizeDefault; - } else { - // The predicted size exceeds the limits to build up a cache and we go into low memory mode from the beginning. - _frameCacheSizeOptimal = FLAnimatedImageFrameCacheSizeLowMemory; - } - } else { - // Use the provided value. - _frameCacheSizeOptimal = optimalFrameCacheSize; - } - // In any case, cap the optimal cache size at the frame count. - _frameCacheSizeOptimal = MIN(_frameCacheSizeOptimal, self.frameCount); - - // Convenience/minor performance optimization; keep an index set handy with the full range to return in `-frameIndexesToCache`. - _allFramesIndexSet = [[NSIndexSet alloc] initWithIndexesInRange:NSMakeRange(0, self.frameCount)]; - - // See the property declarations for descriptions. - _weakProxy = (id)[FLWeakProxy weakProxyForObject:self]; - - // Register this instance in the weak table for memory notifications. The NSHashTable will clean up after itself when we're gone. - // Note that FLAnimatedImages can be created on any thread, so the hash table must be locked. - @synchronized(allAnimatedImagesWeak) { - [allAnimatedImagesWeak addObject:self]; - } - } - return self; -} - - -+ (instancetype)animatedImageWithGIFData:(NSData *)data -{ - FLAnimatedImage *animatedImage = [[FLAnimatedImage alloc] initWithAnimatedGIFData:data]; - return animatedImage; -} - - -- (void)dealloc -{ - if (_weakProxy) { - [NSObject cancelPreviousPerformRequestsWithTarget:_weakProxy]; - } - - if (_imageSource) { - CFRelease(_imageSource); - } -} - - -#pragma mark - Public Methods - -// See header for more details. -// Note: both consumer and producer are throttled: consumer by frame timings and producer by the available memory (max buffer window size). -- (UIImage *)imageLazilyCachedAtIndex:(NSUInteger)index -{ - // Early return if the requested index is beyond bounds. - // Note: We're comparing an index with a count and need to bail on greater than or equal to. - if (index >= self.frameCount) { - FLLog(FLLogLevelWarn, @"Skipping requested frame %lu beyond bounds (total frame count: %lu) for animated image: %@", (unsigned long)index, (unsigned long)self.frameCount, self); - return nil; - } - - // Remember requested frame index, this influences what we should cache next. - self.requestedFrameIndex = index; -#if defined(DEBUG) && DEBUG - if ([self.debug_delegate respondsToSelector:@selector(debug_animatedImage:didRequestCachedFrame:)]) { - [self.debug_delegate debug_animatedImage:self didRequestCachedFrame:index]; - } -#endif - - // Quick check to avoid doing any work if we already have all possible frames cached, a common case. - if ([self.cachedFrameIndexes count] < self.frameCount) { - // If we have frames that should be cached but aren't and aren't requested yet, request them. - // Exclude existing cached frames, frames already requested, and specially cached poster image. - NSMutableIndexSet *frameIndexesToAddToCacheMutable = [self frameIndexesToCache]; - [frameIndexesToAddToCacheMutable removeIndexes:self.cachedFrameIndexes]; - [frameIndexesToAddToCacheMutable removeIndexes:self.requestedFrameIndexes]; - [frameIndexesToAddToCacheMutable removeIndex:self.posterImageFrameIndex]; - NSIndexSet *frameIndexesToAddToCache = [frameIndexesToAddToCacheMutable copy]; - - // Asynchronously add frames to our cache. - if ([frameIndexesToAddToCache count] > 0) { - [self addFrameIndexesToCache:frameIndexesToAddToCache]; - } - } - - // Get the specified image. - UIImage *image = self.cachedFramesForIndexes[@(index)]; - - // Purge if needed based on the current playhead position. - [self purgeFrameCacheIfNeeded]; - - return image; -} - - -// Only called once from `-imageLazilyCachedAtIndex` but factored into its own method for logical grouping. -- (void)addFrameIndexesToCache:(NSIndexSet *)frameIndexesToAddToCache -{ - // Order matters. First, iterate over the indexes starting from the requested frame index. - // Then, if there are any indexes before the requested frame index, do those. - NSRange firstRange = NSMakeRange(self.requestedFrameIndex, self.frameCount - self.requestedFrameIndex); - NSRange secondRange = NSMakeRange(0, self.requestedFrameIndex); - if (firstRange.length + secondRange.length != self.frameCount) { - FLLog(FLLogLevelWarn, @"Two-part frame cache range doesn't equal full range."); - } - - // Add to the requested list before we actually kick them off, so they don't get into the queue twice. - [self.requestedFrameIndexes addIndexes:frameIndexesToAddToCache]; - - // Lazily create dedicated isolation queue. - if (!self.serialQueue) { - _serialQueue = dispatch_queue_create("com.flipboard.framecachingqueue", DISPATCH_QUEUE_SERIAL); - } - - // Start streaming requested frames in the background into the cache. - // Avoid capturing self in the block as there's no reason to keep doing work if the animated image went away. - FLAnimatedImage * __weak weakSelf = self; - dispatch_async(self.serialQueue, ^{ - // Produce and cache next needed frame. - void (^frameRangeBlock)(NSRange, BOOL *) = ^(NSRange range, BOOL *stop) { - // Iterate through contiguous indexes; can be faster than `enumerateIndexesInRange:options:usingBlock:`. - for (NSUInteger i = range.location; i < NSMaxRange(range); i++) { -#if defined(DEBUG) && DEBUG - CFTimeInterval predrawBeginTime = CACurrentMediaTime(); -#endif - UIImage *image = [weakSelf imageAtIndex:i]; -#if defined(DEBUG) && DEBUG - CFTimeInterval predrawDuration = CACurrentMediaTime() - predrawBeginTime; - CFTimeInterval slowdownDuration = 0.0; - if ([self.debug_delegate respondsToSelector:@selector(debug_animatedImagePredrawingSlowdownFactor:)]) { - CGFloat predrawingSlowdownFactor = [self.debug_delegate debug_animatedImagePredrawingSlowdownFactor:self]; - slowdownDuration = predrawDuration * predrawingSlowdownFactor - predrawDuration; - [NSThread sleepForTimeInterval:slowdownDuration]; - } - FLLog(FLLogLevelVerbose, @"Predrew frame %lu in %f ms for animated image: %@", (unsigned long)i, (predrawDuration + slowdownDuration) * 1000, self); -#endif - // The results get returned one by one as soon as they're ready (and not in batch). - // The benefits of having the first frames as quick as possible outweigh building up a buffer to cope with potential hiccups when the CPU suddenly gets busy. - if (image && weakSelf) { - dispatch_async(dispatch_get_main_queue(), ^{ - weakSelf.cachedFramesForIndexes[@(i)] = image; - [weakSelf.cachedFrameIndexes addIndex:i]; - [weakSelf.requestedFrameIndexes removeIndex:i]; -#if defined(DEBUG) && DEBUG - if ([weakSelf.debug_delegate respondsToSelector:@selector(debug_animatedImage:didUpdateCachedFrames:)]) { - [weakSelf.debug_delegate debug_animatedImage:weakSelf didUpdateCachedFrames:weakSelf.cachedFrameIndexes]; - } -#endif - }); - } - } - }; - - [frameIndexesToAddToCache enumerateRangesInRange:firstRange options:0 usingBlock:frameRangeBlock]; - [frameIndexesToAddToCache enumerateRangesInRange:secondRange options:0 usingBlock:frameRangeBlock]; - }); -} - - -+ (CGSize)sizeForImage:(id)image -{ - CGSize imageSize = CGSizeZero; - - // Early return for nil - if (!image) { - return imageSize; - } - - if ([image isKindOfClass:[UIImage class]]) { - UIImage *uiImage = (UIImage *)image; - imageSize = uiImage.size; - } else if ([image isKindOfClass:[FLAnimatedImage class]]) { - FLAnimatedImage *animatedImage = (FLAnimatedImage *)image; - imageSize = animatedImage.size; - } else { - // Bear trap to capture bad images; we have seen crashers cropping up on iOS 7. - FLLog(FLLogLevelError, @"`image` isn't of expected types `UIImage` or `FLAnimatedImage`: %@", image); - } - - return imageSize; -} - - -#pragma mark - Private Methods -#pragma mark Frame Loading - -- (UIImage *)imageAtIndex:(NSUInteger)index -{ - // It's very important to use the cached `_imageSource` since the random access to a frame with `CGImageSourceCreateImageAtIndex` turns from an O(1) into an O(n) operation when re-initializing the image source every time. - CGImageRef imageRef = CGImageSourceCreateImageAtIndex(_imageSource, index, NULL); - - // Early return for nil - if (!imageRef) { - return nil; - } - - UIImage *image = [UIImage imageWithCGImage:imageRef]; - CFRelease(imageRef); - - // Loading in the image object is only half the work, the displaying image view would still have to synchronosly wait and decode the image, so we go ahead and do that here on the background thread. - if (self.isPredrawingEnabled) { - image = [[self class] predrawnImageFromImage:image]; - } - - return image; -} - - -#pragma mark Frame Caching - -- (NSMutableIndexSet *)frameIndexesToCache -{ - NSMutableIndexSet *indexesToCache = nil; - // Quick check to avoid building the index set if the number of frames to cache equals the total frame count. - if (self.frameCacheSizeCurrent == self.frameCount) { - indexesToCache = [self.allFramesIndexSet mutableCopy]; - } else { - indexesToCache = [[NSMutableIndexSet alloc] init]; - - // Add indexes to the set in two separate blocks- the first starting from the requested frame index, up to the limit or the end. - // The second, if needed, the remaining number of frames beginning at index zero. - NSUInteger firstLength = MIN(self.frameCacheSizeCurrent, self.frameCount - self.requestedFrameIndex); - NSRange firstRange = NSMakeRange(self.requestedFrameIndex, firstLength); - [indexesToCache addIndexesInRange:firstRange]; - NSUInteger secondLength = self.frameCacheSizeCurrent - firstLength; - if (secondLength > 0) { - NSRange secondRange = NSMakeRange(0, secondLength); - [indexesToCache addIndexesInRange:secondRange]; - } - // Double check our math, before we add the poster image index which may increase it by one. - if ([indexesToCache count] != self.frameCacheSizeCurrent) { - FLLog(FLLogLevelWarn, @"Number of frames to cache doesn't equal expected cache size."); - } - - [indexesToCache addIndex:self.posterImageFrameIndex]; - } - - return indexesToCache; -} - - -- (void)purgeFrameCacheIfNeeded -{ - // Purge frames that are currently cached but don't need to be. - // But not if we're still under the number of frames to cache. - // This way, if all frames are allowed to be cached (the common case), we can skip all the `NSIndexSet` math below. - if ([self.cachedFrameIndexes count] > self.frameCacheSizeCurrent) { - NSMutableIndexSet *indexesToPurge = [self.cachedFrameIndexes mutableCopy]; - [indexesToPurge removeIndexes:[self frameIndexesToCache]]; - [indexesToPurge enumerateRangesUsingBlock:^(NSRange range, BOOL *stop) { - // Iterate through contiguous indexes; can be faster than `enumerateIndexesInRange:options:usingBlock:`. - for (NSUInteger i = range.location; i < NSMaxRange(range); i++) { - [self.cachedFrameIndexes removeIndex:i]; - [self.cachedFramesForIndexes removeObjectForKey:@(i)]; - // Note: Don't `CGImageSourceRemoveCacheAtIndex` on the image source for frames that we don't want cached any longer to maintain O(1) time access. -#if defined(DEBUG) && DEBUG - if ([self.debug_delegate respondsToSelector:@selector(debug_animatedImage:didUpdateCachedFrames:)]) { - dispatch_async(dispatch_get_main_queue(), ^{ - [self.debug_delegate debug_animatedImage:self didUpdateCachedFrames:self.cachedFrameIndexes]; - }); - } -#endif - } - }]; - } -} - - -- (void)growFrameCacheSizeAfterMemoryWarning:(NSNumber *)frameCacheSize -{ - self.frameCacheSizeMaxInternal = [frameCacheSize unsignedIntegerValue]; - FLLog(FLLogLevelDebug, @"Grew frame cache size max to %lu after memory warning for animated image: %@", (unsigned long)self.frameCacheSizeMaxInternal, self); - - // Schedule resetting the frame cache size max completely after a while. - const NSTimeInterval kResetDelay = 3.0; - [self.weakProxy performSelector:@selector(resetFrameCacheSizeMaxInternal) withObject:nil afterDelay:kResetDelay]; -} - - -- (void)resetFrameCacheSizeMaxInternal -{ - self.frameCacheSizeMaxInternal = FLAnimatedImageFrameCacheSizeNoLimit; - FLLog(FLLogLevelDebug, @"Reset frame cache size max (current frame cache size: %lu) for animated image: %@", (unsigned long)self.frameCacheSizeCurrent, self); -} - - -#pragma mark System Memory Warnings Notification Handler - -- (void)didReceiveMemoryWarning:(NSNotification *)notification -{ - self.memoryWarningCount++; - - // If we were about to grow larger, but got rapped on our knuckles by the system again, cancel. - [NSObject cancelPreviousPerformRequestsWithTarget:self.weakProxy selector:@selector(growFrameCacheSizeAfterMemoryWarning:) object:@(FLAnimatedImageFrameCacheSizeGrowAfterMemoryWarning)]; - [NSObject cancelPreviousPerformRequestsWithTarget:self.weakProxy selector:@selector(resetFrameCacheSizeMaxInternal) object:nil]; - - // Go down to the minimum and by that implicitly immediately purge from the cache if needed to not get jettisoned by the system and start producing frames on-demand. - FLLog(FLLogLevelDebug, @"Attempt setting frame cache size max to %lu (previous was %lu) after memory warning #%lu for animated image: %@", (unsigned long)FLAnimatedImageFrameCacheSizeLowMemory, (unsigned long)self.frameCacheSizeMaxInternal, (unsigned long)self.memoryWarningCount, self); - self.frameCacheSizeMaxInternal = FLAnimatedImageFrameCacheSizeLowMemory; - - // Schedule growing larger again after a while, but cap our attempts to prevent a periodic sawtooth wave (ramps upward and then sharply drops) of memory usage. - // - // [mem]^ (2) (5) (6) 1) Loading frames for the first time - // (*)| , , , 2) Mem warning #1; purge cache - // | /| (4)/| /| 3) Grow cache size a bit after a while, if no mem warning occurs - // | / | _/ | _/ | 4) Try to grow cache size back to optimum after a while, if no mem warning occurs - // |(1)/ |_/ |/ |__(7) 5) Mem warning #2; purge cache - // |__/ (3) 6) After repetition of (3) and (4), mem warning #3; purge cache - // +----------------------> 7) After 3 mem warnings, stay at minimum cache size - // [t] - // *) The mem high water mark before we get warned might change for every cycle. - // - const NSUInteger kGrowAttemptsMax = 2; - const NSTimeInterval kGrowDelay = 2.0; - if ((self.memoryWarningCount - 1) <= kGrowAttemptsMax) { - [self.weakProxy performSelector:@selector(growFrameCacheSizeAfterMemoryWarning:) withObject:@(FLAnimatedImageFrameCacheSizeGrowAfterMemoryWarning) afterDelay:kGrowDelay]; - } - - // Note: It's not possible to get the level of a memory warning with a public API: http://stackoverflow.com/questions/2915247/iphone-os-memory-warnings-what-do-the-different-levels-mean/2915477#2915477 -} - - -#pragma mark Image Decoding - -// Decodes the image's data and draws it off-screen fully in memory; it's thread-safe and hence can be called on a background thread. -// On success, the returned object is a new `UIImage` instance with the same content as the one passed in. -// On failure, the returned object is the unchanged passed in one; the data will not be predrawn in memory though and an error will be logged. -// First inspired by & good Karma to: https://gist.github.com/steipete/1144242 -+ (UIImage *)predrawnImageFromImage:(UIImage *)imageToPredraw -{ - // Always use a device RGB color space for simplicity and predictability what will be going on. - CGColorSpaceRef colorSpaceDeviceRGBRef = CGColorSpaceCreateDeviceRGB(); - // Early return on failure! - if (!colorSpaceDeviceRGBRef) { - FLLog(FLLogLevelError, @"Failed to `CGColorSpaceCreateDeviceRGB` for image %@", imageToPredraw); - return imageToPredraw; - } - - // Even when the image doesn't have transparency, we have to add the extra channel because Quartz doesn't support other pixel formats than 32 bpp/8 bpc for RGB: - // kCGImageAlphaNoneSkipFirst, kCGImageAlphaNoneSkipLast, kCGImageAlphaPremultipliedFirst, kCGImageAlphaPremultipliedLast - // (source: docs "Quartz 2D Programming Guide > Graphics Contexts > Table 2-1 Pixel formats supported for bitmap graphics contexts") - size_t numberOfComponents = CGColorSpaceGetNumberOfComponents(colorSpaceDeviceRGBRef) + 1; // 4: RGB + A - - // "In iOS 4.0 and later, and OS X v10.6 and later, you can pass NULL if you want Quartz to allocate memory for the bitmap." (source: docs) - void *data = NULL; - size_t width = imageToPredraw.size.width; - size_t height = imageToPredraw.size.height; - size_t bitsPerComponent = CHAR_BIT; - - size_t bitsPerPixel = (bitsPerComponent * numberOfComponents); - size_t bytesPerPixel = (bitsPerPixel / BYTE_SIZE); - size_t bytesPerRow = (bytesPerPixel * width); - - CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; - - CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageToPredraw.CGImage); - // If the alpha info doesn't match to one of the supported formats (see above), pick a reasonable supported one. - // "For bitmaps created in iOS 3.2 and later, the drawing environment uses the premultiplied ARGB format to store the bitmap data." (source: docs) - if (alphaInfo == kCGImageAlphaNone || alphaInfo == kCGImageAlphaOnly) { - alphaInfo = kCGImageAlphaNoneSkipFirst; - } else if (alphaInfo == kCGImageAlphaFirst) { - alphaInfo = kCGImageAlphaPremultipliedFirst; - } else if (alphaInfo == kCGImageAlphaLast) { - alphaInfo = kCGImageAlphaPremultipliedLast; - } - // "The constants for specifying the alpha channel information are declared with the `CGImageAlphaInfo` type but can be passed to this parameter safely." (source: docs) - bitmapInfo |= alphaInfo; - - // Create our own graphics context to draw to; `UIGraphicsGetCurrentContext`/`UIGraphicsBeginImageContextWithOptions` doesn't create a new context but returns the current one which isn't thread-safe (e.g. main thread could use it at the same time). - // Note: It's not worth caching the bitmap context for multiple frames ("unique key" would be `width`, `height` and `hasAlpha`), it's ~50% slower. Time spent in libRIP's `CGSBlendBGRA8888toARGB8888` suddenly shoots up -- not sure why. - CGContextRef bitmapContextRef = CGBitmapContextCreate(data, width, height, bitsPerComponent, bytesPerRow, colorSpaceDeviceRGBRef, bitmapInfo); - CGColorSpaceRelease(colorSpaceDeviceRGBRef); - // Early return on failure! - if (!bitmapContextRef) { - FLLog(FLLogLevelError, @"Failed to `CGBitmapContextCreate` with color space %@ and parameters (width: %zu height: %zu bitsPerComponent: %zu bytesPerRow: %zu) for image %@", colorSpaceDeviceRGBRef, width, height, bitsPerComponent, bytesPerRow, imageToPredraw); - return imageToPredraw; - } - - // Draw image in bitmap context and create image by preserving receiver's properties. - CGContextDrawImage(bitmapContextRef, CGRectMake(0.0, 0.0, imageToPredraw.size.width, imageToPredraw.size.height), imageToPredraw.CGImage); - CGImageRef predrawnImageRef = CGBitmapContextCreateImage(bitmapContextRef); - UIImage *predrawnImage = [UIImage imageWithCGImage:predrawnImageRef scale:imageToPredraw.scale orientation:imageToPredraw.imageOrientation]; - CGImageRelease(predrawnImageRef); - CGContextRelease(bitmapContextRef); - - // Early return on failure! - if (!predrawnImage) { - FLLog(FLLogLevelError, @"Failed to `imageWithCGImage:scale:orientation:` with image ref %@ created with color space %@ and bitmap context %@ and properties and properties (scale: %f orientation: %ld) for image %@", predrawnImageRef, colorSpaceDeviceRGBRef, bitmapContextRef, imageToPredraw.scale, (long)imageToPredraw.imageOrientation, imageToPredraw); - return imageToPredraw; - } - - return predrawnImage; -} - - -#pragma mark - Description - -- (NSString *)description -{ - NSString *description = [super description]; - - description = [description stringByAppendingFormat:@" size=%@", NSStringFromCGSize(self.size)]; - description = [description stringByAppendingFormat:@" frameCount=%lu", (unsigned long)self.frameCount]; - - return description; -} - - -@end - -#pragma mark - Logging - -@implementation FLAnimatedImage (Logging) - -static void (^_logBlock)(NSString *logString, FLLogLevel logLevel) = nil; -static FLLogLevel _logLevel; - -+ (void)setLogBlock:(void (^)(NSString *logString, FLLogLevel logLevel))logBlock logLevel:(FLLogLevel)logLevel -{ - _logBlock = logBlock; - _logLevel = logLevel; -} - -+ (void)logStringFromBlock:(NSString *(^)(void))stringBlock withLevel:(FLLogLevel)level -{ - if (level <= _logLevel && _logBlock && stringBlock) { - _logBlock(stringBlock(), level); - } -} - -@end - - -#pragma mark - FLWeakProxy - -@interface FLWeakProxy () - -@property (nonatomic, weak) id target; - -@end - - -@implementation FLWeakProxy - -#pragma mark Life Cycle - -// This is the designated creation method of an `FLWeakProxy` and -// as a subclass of `NSProxy` it doesn't respond to or need `-init`. -+ (instancetype)weakProxyForObject:(id)targetObject -{ - FLWeakProxy *weakProxy = [FLWeakProxy alloc]; - weakProxy.target = targetObject; - return weakProxy; -} - - -#pragma mark Forwarding Messages - -- (id)forwardingTargetForSelector:(SEL)selector -{ - // Keep it lightweight: access the ivar directly - return _target; -} - - -#pragma mark - NSWeakProxy Method Overrides -#pragma mark Handling Unimplemented Methods - -- (void)forwardInvocation:(NSInvocation *)invocation -{ - // Fallback for when target is nil. Don't do anything, just return 0/NULL/nil. - // The method signature we've received to get here is just a dummy to keep `doesNotRecognizeSelector:` from firing. - // We can't really handle struct return types here because we don't know the length. - void *nullPointer = NULL; - [invocation setReturnValue:&nullPointer]; -} - - -- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector -{ - // We only get here if `forwardingTargetForSelector:` returns nil. - // In that case, our weak target has been reclaimed. Return a dummy method signature to keep `doesNotRecognizeSelector:` from firing. - // We'll emulate the Obj-c messaging nil behavior by setting the return value to nil in `forwardInvocation:`, but we'll assume that the return value is `sizeof(void *)`. - // Other libraries handle this situation by making use of a global method signature cache, but that seems heavier than necessary and has issues as well. - // See https://www.mikeash.com/pyblog/friday-qa-2010-02-26-futures.html and https://github.com/steipete/PSTDelegateProxy/issues/1 for examples of using a method signature cache. - return [NSObject instanceMethodSignatureForSelector:@selector(init)]; -} - - -@end diff --git a/Example/Pods/FLAnimatedImage/FLAnimatedImage/FLAnimatedImageView.h b/Example/Pods/FLAnimatedImage/FLAnimatedImage/FLAnimatedImageView.h deleted file mode 100644 index c0d527aa..00000000 --- a/Example/Pods/FLAnimatedImage/FLAnimatedImage/FLAnimatedImageView.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// FLAnimatedImageView.h -// Flipboard -// -// Created by Raphael Schaad on 7/8/13. -// Copyright (c) 2013-2015 Flipboard. All rights reserved. -// - - -#import - -@class FLAnimatedImage; -@protocol FLAnimatedImageViewDebugDelegate; - - -// -// An `FLAnimatedImageView` can take an `FLAnimatedImage` and plays it automatically when in view hierarchy and stops when removed. -// The animation can also be controlled with the `UIImageView` methods `-start/stop/isAnimating`. -// It is a fully compatible `UIImageView` subclass and can be used as a drop-in component to work with existing code paths expecting to display a `UIImage`. -// Under the hood it uses a `CADisplayLink` for playback, which can be inspected with `currentFrame` & `currentFrameIndex`. -// -@interface FLAnimatedImageView : UIImageView - -// Setting `[UIImageView.image]` to a non-`nil` value clears out existing `animatedImage`. -// And vice versa, setting `animatedImage` will initially populate the `[UIImageView.image]` to its `posterImage` and then start animating and hold `currentFrame`. -@property (nonatomic, strong) FLAnimatedImage *animatedImage; -@property (nonatomic, copy) void(^loopCompletionBlock)(NSUInteger loopCountRemaining); - -@property (nonatomic, strong, readonly) UIImage *currentFrame; -@property (nonatomic, assign, readonly) NSUInteger currentFrameIndex; - -// The animation runloop mode. Enables playback during scrolling by allowing timer events (i.e. animation) with NSRunLoopCommonModes. -// To keep scrolling smooth on single-core devices such as iPhone 3GS/4 and iPod Touch 4th gen, the default run loop mode is NSDefaultRunLoopMode. Otherwise, the default is NSDefaultRunLoopMode. -@property (nonatomic, copy) NSString *runLoopMode; - -@end diff --git a/Example/Pods/FLAnimatedImage/FLAnimatedImage/FLAnimatedImageView.m b/Example/Pods/FLAnimatedImage/FLAnimatedImage/FLAnimatedImageView.m deleted file mode 100755 index ffbb6581..00000000 --- a/Example/Pods/FLAnimatedImage/FLAnimatedImage/FLAnimatedImageView.m +++ /dev/null @@ -1,437 +0,0 @@ -// -// FLAnimatedImageView.h -// Flipboard -// -// Created by Raphael Schaad on 7/8/13. -// Copyright (c) 2013-2015 Flipboard. All rights reserved. -// - - -#import "FLAnimatedImageView.h" -#import "FLAnimatedImage.h" -#import - - -#if defined(DEBUG) && DEBUG -@protocol FLAnimatedImageViewDebugDelegate -@optional -- (void)debug_animatedImageView:(FLAnimatedImageView *)animatedImageView waitingForFrame:(NSUInteger)index duration:(NSTimeInterval)duration; -@end -#endif - - -@interface FLAnimatedImageView () - -// Override of public `readonly` properties as private `readwrite` -@property (nonatomic, strong, readwrite) UIImage *currentFrame; -@property (nonatomic, assign, readwrite) NSUInteger currentFrameIndex; - -@property (nonatomic, assign) NSUInteger loopCountdown; -@property (nonatomic, assign) NSTimeInterval accumulator; -@property (nonatomic, strong) CADisplayLink *displayLink; - -@property (nonatomic, assign) BOOL shouldAnimate; // Before checking this value, call `-updateShouldAnimate` whenever the animated image or visibility (window, superview, hidden, alpha) has changed. -@property (nonatomic, assign) BOOL needsDisplayWhenImageBecomesAvailable; - -#if defined(DEBUG) && DEBUG -@property (nonatomic, weak) id debug_delegate; -#endif - -@end - - -@implementation FLAnimatedImageView -@synthesize runLoopMode = _runLoopMode; - -#pragma mark - Initializers - -// -initWithImage: isn't documented as a designated initializer of UIImageView, but it actually seems to be. -// Using -initWithImage: doesn't call any of the other designated initializers. -- (instancetype)initWithImage:(UIImage *)image -{ - self = [super initWithImage:image]; - if (self) { - [self commonInit]; - } - return self; -} - -// -initWithImage:highlightedImage: also isn't documented as a designated initializer of UIImageView, but it doesn't call any other designated initializers. -- (instancetype)initWithImage:(UIImage *)image highlightedImage:(UIImage *)highlightedImage -{ - self = [super initWithImage:image highlightedImage:highlightedImage]; - if (self) { - [self commonInit]; - } - return self; -} - -- (instancetype)initWithFrame:(CGRect)frame -{ - self = [super initWithFrame:frame]; - if (self) { - [self commonInit]; - } - return self; -} - -- (instancetype)initWithCoder:(NSCoder *)aDecoder -{ - self = [super initWithCoder:aDecoder]; - if (self) { - [self commonInit]; - } - return self; -} - -- (void)commonInit -{ - self.runLoopMode = [[self class] defaultRunLoopMode]; -} - - -#pragma mark - Accessors -#pragma mark Public - -- (void)setAnimatedImage:(FLAnimatedImage *)animatedImage -{ - if (![_animatedImage isEqual:animatedImage]) { - if (animatedImage) { - // Clear out the image. - super.image = nil; - // Ensure disabled highlighting; it's not supported (see `-setHighlighted:`). - super.highlighted = NO; - // UIImageView seems to bypass some accessors when calculating its intrinsic content size, so this ensures its intrinsic content size comes from the animated image. - [self invalidateIntrinsicContentSize]; - } else { - // Stop animating before the animated image gets cleared out. - [self stopAnimating]; - } - - _animatedImage = animatedImage; - - self.currentFrame = animatedImage.posterImage; - self.currentFrameIndex = 0; - if (animatedImage.loopCount > 0) { - self.loopCountdown = animatedImage.loopCount; - } else { - self.loopCountdown = NSUIntegerMax; - } - self.accumulator = 0.0; - - // Start animating after the new animated image has been set. - [self updateShouldAnimate]; - if (self.shouldAnimate) { - [self startAnimating]; - } - - [self.layer setNeedsDisplay]; - } -} - - -#pragma mark - Life Cycle - -- (void)dealloc -{ - // Removes the display link from all run loop modes. - [_displayLink invalidate]; -} - - -#pragma mark - UIView Method Overrides -#pragma mark Observing View-Related Changes - -- (void)didMoveToSuperview -{ - [super didMoveToSuperview]; - - [self updateShouldAnimate]; - if (self.shouldAnimate) { - [self startAnimating]; - } else { - [self stopAnimating]; - } -} - - -- (void)didMoveToWindow -{ - [super didMoveToWindow]; - - [self updateShouldAnimate]; - if (self.shouldAnimate) { - [self startAnimating]; - } else { - [self stopAnimating]; - } -} - -- (void)setAlpha:(CGFloat)alpha -{ - [super setAlpha:alpha]; - - [self updateShouldAnimate]; - if (self.shouldAnimate) { - [self startAnimating]; - } else { - [self stopAnimating]; - } -} - -- (void)setHidden:(BOOL)hidden -{ - [super setHidden:hidden]; - - [self updateShouldAnimate]; - if (self.shouldAnimate) { - [self startAnimating]; - } else { - [self stopAnimating]; - } -} - - -#pragma mark Auto Layout - -- (CGSize)intrinsicContentSize -{ - // Default to let UIImageView handle the sizing of its image, and anything else it might consider. - CGSize intrinsicContentSize = [super intrinsicContentSize]; - - // If we have have an animated image, use its image size. - // UIImageView's intrinsic content size seems to be the size of its image. The obvious approach, simply calling `-invalidateIntrinsicContentSize` when setting an animated image, results in UIImageView steadfastly returning `{UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric}` for its intrinsicContentSize. - // (Perhaps UIImageView bypasses its `-image` getter in its implementation of `-intrinsicContentSize`, as `-image` is not called after calling `-invalidateIntrinsicContentSize`.) - if (self.animatedImage) { - intrinsicContentSize = self.image.size; - } - - return intrinsicContentSize; -} - - -#pragma mark - UIImageView Method Overrides -#pragma mark Image Data - -- (UIImage *)image -{ - UIImage *image = nil; - if (self.animatedImage) { - // Initially set to the poster image. - image = self.currentFrame; - } else { - image = super.image; - } - return image; -} - - -- (void)setImage:(UIImage *)image -{ - if (image) { - // Clear out the animated image and implicitly pause animation playback. - self.animatedImage = nil; - } - - super.image = image; -} - - -#pragma mark Animating Images - -- (NSTimeInterval)frameDelayGreatestCommonDivisor -{ - // Presision is set to half of the `kFLAnimatedImageDelayTimeIntervalMinimum` in order to minimize frame dropping. - const NSTimeInterval kGreatestCommonDivisorPrecision = 2.0 / kFLAnimatedImageDelayTimeIntervalMinimum; - - NSArray *delays = self.animatedImage.delayTimesForIndexes.allValues; - - // Scales the frame delays by `kGreatestCommonDivisorPrecision` - // then converts it to an UInteger for in order to calculate the GCD. - NSUInteger scaledGCD = lrint([delays.firstObject floatValue] * kGreatestCommonDivisorPrecision); - for (NSNumber *value in delays) { - scaledGCD = gcd(lrint([value floatValue] * kGreatestCommonDivisorPrecision), scaledGCD); - } - - // Reverse to scale to get the value back into seconds. - return scaledGCD / kGreatestCommonDivisorPrecision; -} - - -static NSUInteger gcd(NSUInteger a, NSUInteger b) -{ - // http://en.wikipedia.org/wiki/Greatest_common_divisor - if (a < b) { - return gcd(b, a); - } else if (a == b) { - return b; - } - - while (true) { - NSUInteger remainder = a % b; - if (remainder == 0) { - return b; - } - a = b; - b = remainder; - } -} - - -- (void)startAnimating -{ - if (self.animatedImage) { - // Lazily create the display link. - if (!self.displayLink) { - // It is important to note the use of a weak proxy here to avoid a retain cycle. `-displayLinkWithTarget:selector:` - // will retain its target until it is invalidated. We use a weak proxy so that the image view will get deallocated - // independent of the display link's lifetime. Upon image view deallocation, we invalidate the display - // link which will lead to the deallocation of both the display link and the weak proxy. - FLWeakProxy *weakProxy = [FLWeakProxy weakProxyForObject:self]; - self.displayLink = [CADisplayLink displayLinkWithTarget:weakProxy selector:@selector(displayDidRefresh:)]; - - [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:self.runLoopMode]; - } - - // Note: The display link's `.frameInterval` value of 1 (default) means getting callbacks at the refresh rate of the display (~60Hz). - // Setting it to 2 divides the frame rate by 2 and hence calls back at every other display refresh. - const NSTimeInterval kDisplayRefreshRate = 60.0; // 60Hz - self.displayLink.frameInterval = MAX([self frameDelayGreatestCommonDivisor] * kDisplayRefreshRate, 1); - - self.displayLink.paused = NO; - } else { - [super startAnimating]; - } -} - -- (void)setRunLoopMode:(NSString *)runLoopMode -{ - if (![@[NSDefaultRunLoopMode, NSRunLoopCommonModes] containsObject:runLoopMode]) { - NSAssert(NO, @"Invalid run loop mode: %@", runLoopMode); - _runLoopMode = [[self class] defaultRunLoopMode]; - } else { - _runLoopMode = runLoopMode; - } -} - -- (void)stopAnimating -{ - if (self.animatedImage) { - self.displayLink.paused = YES; - } else { - [super stopAnimating]; - } -} - - -- (BOOL)isAnimating -{ - BOOL isAnimating = NO; - if (self.animatedImage) { - isAnimating = self.displayLink && !self.displayLink.isPaused; - } else { - isAnimating = [super isAnimating]; - } - return isAnimating; -} - - -#pragma mark Highlighted Image Unsupport - -- (void)setHighlighted:(BOOL)highlighted -{ - // Highlighted image is unsupported for animated images, but implementing it breaks the image view when embedded in a UICollectionViewCell. - if (!self.animatedImage) { - [super setHighlighted:highlighted]; - } -} - - -#pragma mark - Private Methods -#pragma mark Animation - -// Don't repeatedly check our window & superview in `-displayDidRefresh:` for performance reasons. -// Just update our cached value whenever the animated image or visibility (window, superview, hidden, alpha) is changed. -- (void)updateShouldAnimate -{ - BOOL isVisible = self.window && self.superview && ![self isHidden] && self.alpha > 0.0; - self.shouldAnimate = self.animatedImage && isVisible; -} - - -- (void)displayDidRefresh:(CADisplayLink *)displayLink -{ - // If for some reason a wild call makes it through when we shouldn't be animating, bail. - // Early return! - if (!self.shouldAnimate) { - FLLog(FLLogLevelWarn, @"Trying to animate image when we shouldn't: %@", self); - return; - } - - NSNumber *delayTimeNumber = [self.animatedImage.delayTimesForIndexes objectForKey:@(self.currentFrameIndex)]; - // If we don't have a frame delay (e.g. corrupt frame), don't update the view but skip the playhead to the next frame (in else-block). - if (delayTimeNumber) { - NSTimeInterval delayTime = [delayTimeNumber floatValue]; - // If we have a nil image (e.g. waiting for frame), don't update the view nor playhead. - UIImage *image = [self.animatedImage imageLazilyCachedAtIndex:self.currentFrameIndex]; - if (image) { - FLLog(FLLogLevelVerbose, @"Showing frame %lu for animated image: %@", (unsigned long)self.currentFrameIndex, self.animatedImage); - self.currentFrame = image; - if (self.needsDisplayWhenImageBecomesAvailable) { - [self.layer setNeedsDisplay]; - self.needsDisplayWhenImageBecomesAvailable = NO; - } - - self.accumulator += displayLink.duration * displayLink.frameInterval; - - // While-loop first inspired by & good Karma to: https://github.com/ondalabs/OLImageView/blob/master/OLImageView.m - while (self.accumulator >= delayTime) { - self.accumulator -= delayTime; - self.currentFrameIndex++; - if (self.currentFrameIndex >= self.animatedImage.frameCount) { - // If we've looped the number of times that this animated image describes, stop looping. - self.loopCountdown--; - if (self.loopCompletionBlock) { - self.loopCompletionBlock(self.loopCountdown); - } - - if (self.loopCountdown == 0) { - [self stopAnimating]; - return; - } - self.currentFrameIndex = 0; - } - // Calling `-setNeedsDisplay` will just paint the current frame, not the new frame that we may have moved to. - // Instead, set `needsDisplayWhenImageBecomesAvailable` to `YES` -- this will paint the new image once loaded. - self.needsDisplayWhenImageBecomesAvailable = YES; - } - } else { - FLLog(FLLogLevelDebug, @"Waiting for frame %lu for animated image: %@", (unsigned long)self.currentFrameIndex, self.animatedImage); -#if defined(DEBUG) && DEBUG - if ([self.debug_delegate respondsToSelector:@selector(debug_animatedImageView:waitingForFrame:duration:)]) { - [self.debug_delegate debug_animatedImageView:self waitingForFrame:self.currentFrameIndex duration:(NSTimeInterval)displayLink.duration * displayLink.frameInterval]; - } -#endif - } - } else { - self.currentFrameIndex++; - } -} - -+ (NSString *)defaultRunLoopMode -{ - // Key off `activeProcessorCount` (as opposed to `processorCount`) since the system could shut down cores in certain situations. - return [NSProcessInfo processInfo].activeProcessorCount > 1 ? NSRunLoopCommonModes : NSDefaultRunLoopMode; -} - - -#pragma mark - CALayerDelegate (Informal) -#pragma mark Providing the Layer's Content - -- (void)displayLayer:(CALayer *)layer -{ - layer.contents = (__bridge id)self.image.CGImage; -} - - -@end diff --git a/Example/Pods/FLAnimatedImage/LICENSE b/Example/Pods/FLAnimatedImage/LICENSE deleted file mode 100644 index 632653f9..00000000 --- a/Example/Pods/FLAnimatedImage/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014-2016 Flipboard - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/Example/Pods/FLAnimatedImage/README.md b/Example/Pods/FLAnimatedImage/README.md deleted file mode 100644 index 384122cd..00000000 --- a/Example/Pods/FLAnimatedImage/README.md +++ /dev/null @@ -1,103 +0,0 @@ -FLAnimatedImage is a performant animated GIF engine for iOS: - -- Plays multiple GIFs simultaneously with a playback speed comparable to desktop browsers -- Honors variable frame delays -- Behaves gracefully under memory pressure -- Eliminates delays or blocking during the first playback loop -- Interprets the frame delays of fast GIFs the same way modern browsers do - -It's a well-tested [component that powers all GIFs in Flipboard](http://engineering.flipboard.com/2014/05/animated-gif/). To understand its behavior it comes with an interactive demo: - -![Flipboard playing multiple GIFs](https://github.com/Flipboard/FLAnimatedImage/raw/master/images/flanimatedimage-demo-player.gif) - -## Who is this for? - -- Apps that don't support animated GIFs yet -- Apps that already support animated GIFs but want a higher performance solution -- People who want to tinker with the code ([the corresponding blog post](http://engineering.flipboard.com/2014/05/animated-gif/) is a great place to start; also see the *To Do* section below) - -## Installation & Usage - -FLAnimatedImage is a well encapsulated drop-in component. Simply replace your `UIImageView` instances with instances of `FLAnimatedImageView` to get animated GIF support. There is no central cache or state to manage. - -If using CocoaPods, the quickest way to try it out is to type this on the command line: - -```shell -$ pod try FLAnimatedImage -``` - -To add it to your app, copy the two classes `FLAnimatedImage.h/.m` and `FLAnimatedImageView.h/.m` into your Xcode project or add via [CocoaPods](http://cocoapods.org) by adding this to your Podfile: - -```ruby -pod 'FLAnimatedImage', '~> 1.0' -``` - -If using [Carthage](https://github.com/Carthage/Carthage), add following line into your `Cartfile` - -``` -github "Flipboard/FLAnimatedImage" -``` - -In your code, `#import "FLAnimatedImage.h"`, create an image from an animated GIF, and setup the image view to display it: - -```objective-c -FLAnimatedImage *image = [FLAnimatedImage animatedImageWithGIFData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"https://upload.wikimedia.org/wikipedia/commons/2/2c/Rotating_earth_%28large%29.gif"]]]; -FLAnimatedImageView *imageView = [[FLAnimatedImageView alloc] init]; -imageView.animatedImage = image; -imageView.frame = CGRectMake(0.0, 0.0, 100.0, 100.0); -[self.view addSubview:imageView]; -``` - -It's flexible to integrate in your custom image loading stack and backwards compatible to iOS 6. - -It uses ARC and the Apple frameworks `QuartzCore`, `ImageIO`, `MobileCoreServices`, and `CoreGraphics`. - -It is capable of fine-grained logging. A block can be set on `FLAnimatedImage` that's invoked when logging occurs with various log levels via the `+setLogBlock:logLevel:` method. For example: - -```objective-c -// Set up FLAnimatedImage logging. -[FLAnimatedImage setLogBlock:^(NSString *logString, FLLogLevel logLevel) { - // Using NSLog - NSLog(@"%@", logString); - - // ...or CocoaLumberjackLogger only logging warnings and errors - if (logLevel == FLLogLevelError) { - DDLogError(@"%@", logString); - } else if (logLevel == FLLogLevelWarn) { - DDLogWarn(@"%@", logString); - } -} logLevel:FLLogLevelWarn]; -``` - -Since FLAnimatedImage is licensed under MIT, it's compatible with the terms of using it for any app on the App Store. - -## To Do -- Support other animated image formats such as APNG or WebP (WebP support implemented [here](https://github.com/Flipboard/FLAnimatedImage/pull/86)) -- Integration into network libraries and image caches -- Investigate whether `FLAnimatedImage` should become a `UIImage` subclass -- Smarter buffering -- Bring demo app to iPhone - -This has successfully shipped to many people as is, but please do come with your questions, issues and pull requests! - -## Select apps using FLAnimatedImage -- [Dropbox](https://www.dropbox.com) -- [Medium](https://medium.com) -- [Facebook](https://facebook.com) -- [Pinterest](https://pinterest.com) -- [LiveBooth](http://www.liveboothapp.com) -- [Design Shots](https://itunes.apple.com/app/id792517951) -- [lWlVl Festival](http://lwlvl.com) -- [Close-up](http://closeu.pe) -- [Zip Code Finder](https://itunes.apple.com/app/id893031254) -- [getGIF](https://itunes.apple.com/app/id964784701) -- [Giffage](http://giffage.com) -- [Flipboard](https://flipboard.com) -- [Gifalicious](https://itunes.apple.com/us/app/gifalicious-see-your-gifs/id965346708?mt=8) -- [Slack](https://slack.com/) -- [Telegram](https://telegram.org/) -- [HashPhotos](https://itunes.apple.com/app/id685784609) -- [Ello](https://ello.co/) -- [Dumpert](http://dumpert.nl) - -If you're using FLAnimatedImage in your app please open a PR to add it to this list! diff --git a/Example/Pods/Headers/Private/FLAnimatedImage/FLAnimatedImage.h b/Example/Pods/Headers/Private/FLAnimatedImage/FLAnimatedImage.h deleted file mode 120000 index 6b3118af..00000000 --- a/Example/Pods/Headers/Private/FLAnimatedImage/FLAnimatedImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../FLAnimatedImage/FLAnimatedImage/FLAnimatedImage.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/FLAnimatedImage/FLAnimatedImageView.h b/Example/Pods/Headers/Private/FLAnimatedImage/FLAnimatedImageView.h deleted file mode 120000 index 8d98a7bc..00000000 --- a/Example/Pods/Headers/Private/FLAnimatedImage/FLAnimatedImageView.h +++ /dev/null @@ -1 +0,0 @@ -../../../FLAnimatedImage/FLAnimatedImage/FLAnimatedImageView.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINCache/Nullability.h b/Example/Pods/Headers/Private/PINCache/Nullability.h deleted file mode 120000 index b90c434a..00000000 --- a/Example/Pods/Headers/Private/PINCache/Nullability.h +++ /dev/null @@ -1 +0,0 @@ -../../../PINCache/PINCache/Nullability.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINCache/PINCache.h b/Example/Pods/Headers/Private/PINCache/PINCache.h deleted file mode 120000 index 149e0bb6..00000000 --- a/Example/Pods/Headers/Private/PINCache/PINCache.h +++ /dev/null @@ -1 +0,0 @@ -../../../PINCache/PINCache/PINCache.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINCache/PINCacheObjectSubscripting.h b/Example/Pods/Headers/Private/PINCache/PINCacheObjectSubscripting.h deleted file mode 120000 index 9d845784..00000000 --- a/Example/Pods/Headers/Private/PINCache/PINCacheObjectSubscripting.h +++ /dev/null @@ -1 +0,0 @@ -../../../PINCache/PINCache/PINCacheObjectSubscripting.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINCache/PINDiskCache.h b/Example/Pods/Headers/Private/PINCache/PINDiskCache.h deleted file mode 120000 index c5206f89..00000000 --- a/Example/Pods/Headers/Private/PINCache/PINDiskCache.h +++ /dev/null @@ -1 +0,0 @@ -../../../PINCache/PINCache/PINDiskCache.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINCache/PINMemoryCache.h b/Example/Pods/Headers/Private/PINCache/PINMemoryCache.h deleted file mode 120000 index c1b9753b..00000000 --- a/Example/Pods/Headers/Private/PINCache/PINMemoryCache.h +++ /dev/null @@ -1 +0,0 @@ -../../../PINCache/PINCache/PINMemoryCache.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/FLAnimatedImageView+PINRemoteImage.h b/Example/Pods/Headers/Private/PINRemoteImage/FLAnimatedImageView+PINRemoteImage.h deleted file mode 120000 index 0757741f..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/FLAnimatedImageView+PINRemoteImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/NSData+ImageDetectors.h b/Example/Pods/Headers/Private/PINRemoteImage/NSData+ImageDetectors.h deleted file mode 120000 index 8d98e1a4..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/NSData+ImageDetectors.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Categories/NSData+ImageDetectors.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINAlternateRepresentationProvider.h b/Example/Pods/Headers/Private/PINRemoteImage/PINAlternateRepresentationProvider.h deleted file mode 120000 index ce662f35..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINAlternateRepresentationProvider.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINAlternateRepresentationProvider.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINAnimatedImage.h b/Example/Pods/Headers/Private/PINRemoteImage/PINAnimatedImage.h deleted file mode 120000 index 4ad10fe3..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINAnimatedImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINAnimatedImage.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINAnimatedImageManager.h b/Example/Pods/Headers/Private/PINRemoteImage/PINAnimatedImageManager.h deleted file mode 120000 index c9139ffe..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINAnimatedImageManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINAnimatedImageManager.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINButton+PINRemoteImage.h b/Example/Pods/Headers/Private/PINRemoteImage/PINButton+PINRemoteImage.h deleted file mode 120000 index 0ed989a1..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINButton+PINRemoteImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Image Categories/PINButton+PINRemoteImage.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINCache+PINRemoteImageCaching.h b/Example/Pods/Headers/Private/PINRemoteImage/PINCache+PINRemoteImageCaching.h deleted file mode 120000 index d208afab..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINCache+PINRemoteImageCaching.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINCache/PINCache+PINRemoteImageCaching.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINDataTaskOperation.h b/Example/Pods/Headers/Private/PINRemoteImage/PINDataTaskOperation.h deleted file mode 120000 index 6ebb4a80..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINDataTaskOperation.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINDataTaskOperation.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINImage+DecodedImage.h b/Example/Pods/Headers/Private/PINRemoteImage/PINImage+DecodedImage.h deleted file mode 120000 index 96d0ec62..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINImage+DecodedImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Categories/PINImage+DecodedImage.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINImage+WebP.h b/Example/Pods/Headers/Private/PINRemoteImage/PINImage+WebP.h deleted file mode 120000 index 6d484bc7..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINImage+WebP.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Categories/PINImage+WebP.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINImageView+PINRemoteImage.h b/Example/Pods/Headers/Private/PINRemoteImage/PINImageView+PINRemoteImage.h deleted file mode 120000 index a94e8f7c..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINImageView+PINRemoteImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Image Categories/PINImageView+PINRemoteImage.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINProgressiveImage.h b/Example/Pods/Headers/Private/PINRemoteImage/PINProgressiveImage.h deleted file mode 120000 index 03e8769f..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINProgressiveImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINProgressiveImage.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImage.h b/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImage.h deleted file mode 120000 index 64ec7893..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImage.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageBasicCache.h b/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageBasicCache.h deleted file mode 120000 index fb7f0611..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageBasicCache.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageBasicCache.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageCaching.h b/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageCaching.h deleted file mode 120000 index 77803e51..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageCaching.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageCaching.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageCallbacks.h b/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageCallbacks.h deleted file mode 120000 index 790720bb..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageCallbacks.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageCallbacks.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageCategoryManager.h b/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageCategoryManager.h deleted file mode 120000 index cba384e6..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageCategoryManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageCategoryManager.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageDownloadTask.h b/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageDownloadTask.h deleted file mode 120000 index e492464a..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageDownloadTask.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageDownloadTask.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageMacros.h b/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageMacros.h deleted file mode 120000 index 5c9588e9..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageMacros.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageMacros.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageManager.h b/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageManager.h deleted file mode 120000 index d0e9703d..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageManager.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageManagerResult.h b/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageManagerResult.h deleted file mode 120000 index b719636b..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageManagerResult.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageManagerResult.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageMemoryContainer.h b/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageMemoryContainer.h deleted file mode 120000 index 8e2c8de9..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageMemoryContainer.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageMemoryContainer.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageProcessorTask.h b/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageProcessorTask.h deleted file mode 120000 index 89c8a48b..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageProcessorTask.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageProcessorTask.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageTask.h b/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageTask.h deleted file mode 120000 index 8379dfef..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteImageTask.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageTask.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteLock.h b/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteLock.h deleted file mode 120000 index 1712bbd3..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINRemoteLock.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteLock.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/PINRemoteImage/PINURLSessionManager.h b/Example/Pods/Headers/Private/PINRemoteImage/PINURLSessionManager.h deleted file mode 120000 index ad2ce3c8..00000000 --- a/Example/Pods/Headers/Private/PINRemoteImage/PINURLSessionManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINURLSessionManager.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/alphai.h b/Example/Pods/Headers/Private/libwebp/alphai.h deleted file mode 120000 index 3a6f3b9b..00000000 --- a/Example/Pods/Headers/Private/libwebp/alphai.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/alphai.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/backward_references.h b/Example/Pods/Headers/Private/libwebp/backward_references.h deleted file mode 120000 index 0881ff9b..00000000 --- a/Example/Pods/Headers/Private/libwebp/backward_references.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/enc/backward_references.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/bit_reader.h b/Example/Pods/Headers/Private/libwebp/bit_reader.h deleted file mode 120000 index 93789582..00000000 --- a/Example/Pods/Headers/Private/libwebp/bit_reader.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/bit_reader.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/bit_reader_inl.h b/Example/Pods/Headers/Private/libwebp/bit_reader_inl.h deleted file mode 120000 index be415894..00000000 --- a/Example/Pods/Headers/Private/libwebp/bit_reader_inl.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/bit_reader_inl.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/bit_writer.h b/Example/Pods/Headers/Private/libwebp/bit_writer.h deleted file mode 120000 index abe7119f..00000000 --- a/Example/Pods/Headers/Private/libwebp/bit_writer.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/bit_writer.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/color_cache.h b/Example/Pods/Headers/Private/libwebp/color_cache.h deleted file mode 120000 index 5bba961d..00000000 --- a/Example/Pods/Headers/Private/libwebp/color_cache.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/color_cache.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/common.h b/Example/Pods/Headers/Private/libwebp/common.h deleted file mode 120000 index 8f4827f8..00000000 --- a/Example/Pods/Headers/Private/libwebp/common.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/common.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/cost.h b/Example/Pods/Headers/Private/libwebp/cost.h deleted file mode 120000 index a9c6f4ae..00000000 --- a/Example/Pods/Headers/Private/libwebp/cost.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/enc/cost.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/decode_vp8.h b/Example/Pods/Headers/Private/libwebp/decode_vp8.h deleted file mode 120000 index b5ac83e7..00000000 --- a/Example/Pods/Headers/Private/libwebp/decode_vp8.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/decode_vp8.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/delta_palettization.h b/Example/Pods/Headers/Private/libwebp/delta_palettization.h deleted file mode 120000 index c8e6fb64..00000000 --- a/Example/Pods/Headers/Private/libwebp/delta_palettization.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/enc/delta_palettization.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/dsp.h b/Example/Pods/Headers/Private/libwebp/dsp.h deleted file mode 120000 index 1bace906..00000000 --- a/Example/Pods/Headers/Private/libwebp/dsp.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dsp/dsp.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/endian_inl.h b/Example/Pods/Headers/Private/libwebp/endian_inl.h deleted file mode 120000 index 2be74a78..00000000 --- a/Example/Pods/Headers/Private/libwebp/endian_inl.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/endian_inl.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/filters.h b/Example/Pods/Headers/Private/libwebp/filters.h deleted file mode 120000 index ab7b5327..00000000 --- a/Example/Pods/Headers/Private/libwebp/filters.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/filters.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/histogram.h b/Example/Pods/Headers/Private/libwebp/histogram.h deleted file mode 120000 index c6950516..00000000 --- a/Example/Pods/Headers/Private/libwebp/histogram.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/enc/histogram.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/huffman.h b/Example/Pods/Headers/Private/libwebp/huffman.h deleted file mode 120000 index 6245e139..00000000 --- a/Example/Pods/Headers/Private/libwebp/huffman.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/huffman.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/huffman_encode.h b/Example/Pods/Headers/Private/libwebp/huffman_encode.h deleted file mode 120000 index 19a28b2a..00000000 --- a/Example/Pods/Headers/Private/libwebp/huffman_encode.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/huffman_encode.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/lossless.h b/Example/Pods/Headers/Private/libwebp/lossless.h deleted file mode 120000 index a3b07cfe..00000000 --- a/Example/Pods/Headers/Private/libwebp/lossless.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dsp/lossless.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/mips_macro.h b/Example/Pods/Headers/Private/libwebp/mips_macro.h deleted file mode 120000 index da76de07..00000000 --- a/Example/Pods/Headers/Private/libwebp/mips_macro.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dsp/mips_macro.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/muxi.h b/Example/Pods/Headers/Private/libwebp/muxi.h deleted file mode 120000 index d96d5988..00000000 --- a/Example/Pods/Headers/Private/libwebp/muxi.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/mux/muxi.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/neon.h b/Example/Pods/Headers/Private/libwebp/neon.h deleted file mode 120000 index 8213e481..00000000 --- a/Example/Pods/Headers/Private/libwebp/neon.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dsp/neon.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/quant_levels.h b/Example/Pods/Headers/Private/libwebp/quant_levels.h deleted file mode 120000 index d620fa9c..00000000 --- a/Example/Pods/Headers/Private/libwebp/quant_levels.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/quant_levels.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/quant_levels_dec.h b/Example/Pods/Headers/Private/libwebp/quant_levels_dec.h deleted file mode 120000 index 6930b5dd..00000000 --- a/Example/Pods/Headers/Private/libwebp/quant_levels_dec.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/quant_levels_dec.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/random.h b/Example/Pods/Headers/Private/libwebp/random.h deleted file mode 120000 index 7ccc260c..00000000 --- a/Example/Pods/Headers/Private/libwebp/random.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/random.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/rescaler.h b/Example/Pods/Headers/Private/libwebp/rescaler.h deleted file mode 120000 index 3c1c538c..00000000 --- a/Example/Pods/Headers/Private/libwebp/rescaler.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/rescaler.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/thread.h b/Example/Pods/Headers/Private/libwebp/thread.h deleted file mode 120000 index 3033ec5a..00000000 --- a/Example/Pods/Headers/Private/libwebp/thread.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/thread.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/utils.h b/Example/Pods/Headers/Private/libwebp/utils.h deleted file mode 120000 index ba046686..00000000 --- a/Example/Pods/Headers/Private/libwebp/utils.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/utils.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/vp8enci.h b/Example/Pods/Headers/Private/libwebp/vp8enci.h deleted file mode 120000 index 4b202757..00000000 --- a/Example/Pods/Headers/Private/libwebp/vp8enci.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/enc/vp8enci.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/vp8i.h b/Example/Pods/Headers/Private/libwebp/vp8i.h deleted file mode 120000 index 1c5d8a56..00000000 --- a/Example/Pods/Headers/Private/libwebp/vp8i.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/vp8i.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/vp8li.h b/Example/Pods/Headers/Private/libwebp/vp8li.h deleted file mode 120000 index ee31158b..00000000 --- a/Example/Pods/Headers/Private/libwebp/vp8li.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/vp8li.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/webp/decode.h b/Example/Pods/Headers/Private/libwebp/webp/decode.h deleted file mode 120000 index cb9e6a20..00000000 --- a/Example/Pods/Headers/Private/libwebp/webp/decode.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/decode.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/webp/demux.h b/Example/Pods/Headers/Private/libwebp/webp/demux.h deleted file mode 120000 index 4b1b1081..00000000 --- a/Example/Pods/Headers/Private/libwebp/webp/demux.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/demux.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/webp/encode.h b/Example/Pods/Headers/Private/libwebp/webp/encode.h deleted file mode 120000 index 336598ae..00000000 --- a/Example/Pods/Headers/Private/libwebp/webp/encode.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/encode.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/webp/extras.h b/Example/Pods/Headers/Private/libwebp/webp/extras.h deleted file mode 120000 index 1aef3627..00000000 --- a/Example/Pods/Headers/Private/libwebp/webp/extras.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/extras.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/webp/format_constants.h b/Example/Pods/Headers/Private/libwebp/webp/format_constants.h deleted file mode 120000 index 2b3e467c..00000000 --- a/Example/Pods/Headers/Private/libwebp/webp/format_constants.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/format_constants.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/webp/mux.h b/Example/Pods/Headers/Private/libwebp/webp/mux.h deleted file mode 120000 index 03e49641..00000000 --- a/Example/Pods/Headers/Private/libwebp/webp/mux.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/mux.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/webp/mux_types.h b/Example/Pods/Headers/Private/libwebp/webp/mux_types.h deleted file mode 120000 index 20761020..00000000 --- a/Example/Pods/Headers/Private/libwebp/webp/mux_types.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/mux_types.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/webp/types.h b/Example/Pods/Headers/Private/libwebp/webp/types.h deleted file mode 120000 index e00cbb0a..00000000 --- a/Example/Pods/Headers/Private/libwebp/webp/types.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/types.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/webpi.h b/Example/Pods/Headers/Private/libwebp/webpi.h deleted file mode 120000 index 6cf10ad5..00000000 --- a/Example/Pods/Headers/Private/libwebp/webpi.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/webpi.h \ No newline at end of file diff --git a/Example/Pods/Headers/Private/libwebp/yuv.h b/Example/Pods/Headers/Private/libwebp/yuv.h deleted file mode 120000 index eaa7fa95..00000000 --- a/Example/Pods/Headers/Private/libwebp/yuv.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dsp/yuv.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/FLAnimatedImage/FLAnimatedImage.h b/Example/Pods/Headers/Public/FLAnimatedImage/FLAnimatedImage.h deleted file mode 120000 index 6b3118af..00000000 --- a/Example/Pods/Headers/Public/FLAnimatedImage/FLAnimatedImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../FLAnimatedImage/FLAnimatedImage/FLAnimatedImage.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/FLAnimatedImage/FLAnimatedImageView.h b/Example/Pods/Headers/Public/FLAnimatedImage/FLAnimatedImageView.h deleted file mode 120000 index 8d98a7bc..00000000 --- a/Example/Pods/Headers/Public/FLAnimatedImage/FLAnimatedImageView.h +++ /dev/null @@ -1 +0,0 @@ -../../../FLAnimatedImage/FLAnimatedImage/FLAnimatedImageView.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINCache/Nullability.h b/Example/Pods/Headers/Public/PINCache/Nullability.h deleted file mode 120000 index b90c434a..00000000 --- a/Example/Pods/Headers/Public/PINCache/Nullability.h +++ /dev/null @@ -1 +0,0 @@ -../../../PINCache/PINCache/Nullability.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINCache/PINCache.h b/Example/Pods/Headers/Public/PINCache/PINCache.h deleted file mode 120000 index 149e0bb6..00000000 --- a/Example/Pods/Headers/Public/PINCache/PINCache.h +++ /dev/null @@ -1 +0,0 @@ -../../../PINCache/PINCache/PINCache.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINCache/PINCacheObjectSubscripting.h b/Example/Pods/Headers/Public/PINCache/PINCacheObjectSubscripting.h deleted file mode 120000 index 9d845784..00000000 --- a/Example/Pods/Headers/Public/PINCache/PINCacheObjectSubscripting.h +++ /dev/null @@ -1 +0,0 @@ -../../../PINCache/PINCache/PINCacheObjectSubscripting.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINCache/PINDiskCache.h b/Example/Pods/Headers/Public/PINCache/PINDiskCache.h deleted file mode 120000 index c5206f89..00000000 --- a/Example/Pods/Headers/Public/PINCache/PINDiskCache.h +++ /dev/null @@ -1 +0,0 @@ -../../../PINCache/PINCache/PINDiskCache.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINCache/PINMemoryCache.h b/Example/Pods/Headers/Public/PINCache/PINMemoryCache.h deleted file mode 120000 index c1b9753b..00000000 --- a/Example/Pods/Headers/Public/PINCache/PINMemoryCache.h +++ /dev/null @@ -1 +0,0 @@ -../../../PINCache/PINCache/PINMemoryCache.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/FLAnimatedImageView+PINRemoteImage.h b/Example/Pods/Headers/Public/PINRemoteImage/FLAnimatedImageView+PINRemoteImage.h deleted file mode 120000 index 0757741f..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/FLAnimatedImageView+PINRemoteImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/NSData+ImageDetectors.h b/Example/Pods/Headers/Public/PINRemoteImage/NSData+ImageDetectors.h deleted file mode 120000 index 8d98e1a4..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/NSData+ImageDetectors.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Categories/NSData+ImageDetectors.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINAlternateRepresentationProvider.h b/Example/Pods/Headers/Public/PINRemoteImage/PINAlternateRepresentationProvider.h deleted file mode 120000 index ce662f35..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINAlternateRepresentationProvider.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINAlternateRepresentationProvider.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINAnimatedImage.h b/Example/Pods/Headers/Public/PINRemoteImage/PINAnimatedImage.h deleted file mode 120000 index 4ad10fe3..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINAnimatedImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINAnimatedImage.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINAnimatedImageManager.h b/Example/Pods/Headers/Public/PINRemoteImage/PINAnimatedImageManager.h deleted file mode 120000 index c9139ffe..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINAnimatedImageManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINAnimatedImageManager.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINButton+PINRemoteImage.h b/Example/Pods/Headers/Public/PINRemoteImage/PINButton+PINRemoteImage.h deleted file mode 120000 index 0ed989a1..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINButton+PINRemoteImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Image Categories/PINButton+PINRemoteImage.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINCache+PINRemoteImageCaching.h b/Example/Pods/Headers/Public/PINRemoteImage/PINCache+PINRemoteImageCaching.h deleted file mode 120000 index d208afab..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINCache+PINRemoteImageCaching.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINCache/PINCache+PINRemoteImageCaching.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINDataTaskOperation.h b/Example/Pods/Headers/Public/PINRemoteImage/PINDataTaskOperation.h deleted file mode 120000 index 6ebb4a80..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINDataTaskOperation.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINDataTaskOperation.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINImage+DecodedImage.h b/Example/Pods/Headers/Public/PINRemoteImage/PINImage+DecodedImage.h deleted file mode 120000 index 96d0ec62..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINImage+DecodedImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Categories/PINImage+DecodedImage.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINImage+WebP.h b/Example/Pods/Headers/Public/PINRemoteImage/PINImage+WebP.h deleted file mode 120000 index 6d484bc7..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINImage+WebP.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Categories/PINImage+WebP.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINImageView+PINRemoteImage.h b/Example/Pods/Headers/Public/PINRemoteImage/PINImageView+PINRemoteImage.h deleted file mode 120000 index a94e8f7c..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINImageView+PINRemoteImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/Image Categories/PINImageView+PINRemoteImage.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINProgressiveImage.h b/Example/Pods/Headers/Public/PINRemoteImage/PINProgressiveImage.h deleted file mode 120000 index 03e8769f..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINProgressiveImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINProgressiveImage.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImage.h b/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImage.h deleted file mode 120000 index 64ec7893..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImage.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageBasicCache.h b/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageBasicCache.h deleted file mode 120000 index fb7f0611..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageBasicCache.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageBasicCache.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageCaching.h b/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageCaching.h deleted file mode 120000 index 77803e51..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageCaching.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageCaching.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageCallbacks.h b/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageCallbacks.h deleted file mode 120000 index 790720bb..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageCallbacks.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageCallbacks.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageCategoryManager.h b/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageCategoryManager.h deleted file mode 120000 index cba384e6..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageCategoryManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageCategoryManager.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageDownloadTask.h b/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageDownloadTask.h deleted file mode 120000 index e492464a..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageDownloadTask.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageDownloadTask.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageMacros.h b/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageMacros.h deleted file mode 120000 index 5c9588e9..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageMacros.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageMacros.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageManager.h b/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageManager.h deleted file mode 120000 index d0e9703d..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageManager.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageManagerResult.h b/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageManagerResult.h deleted file mode 120000 index b719636b..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageManagerResult.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageManagerResult.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageMemoryContainer.h b/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageMemoryContainer.h deleted file mode 120000 index 8e2c8de9..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageMemoryContainer.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageMemoryContainer.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageProcessorTask.h b/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageProcessorTask.h deleted file mode 120000 index 89c8a48b..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageProcessorTask.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageProcessorTask.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageTask.h b/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageTask.h deleted file mode 120000 index 8379dfef..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteImageTask.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteImageTask.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteLock.h b/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteLock.h deleted file mode 120000 index 1712bbd3..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINRemoteLock.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINRemoteLock.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PINRemoteImage/PINURLSessionManager.h b/Example/Pods/Headers/Public/PINRemoteImage/PINURLSessionManager.h deleted file mode 120000 index ad2ce3c8..00000000 --- a/Example/Pods/Headers/Public/PINRemoteImage/PINURLSessionManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Pod/Classes/PINURLSessionManager.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/alphai.h b/Example/Pods/Headers/Public/libwebp/alphai.h deleted file mode 120000 index 3a6f3b9b..00000000 --- a/Example/Pods/Headers/Public/libwebp/alphai.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/alphai.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/backward_references.h b/Example/Pods/Headers/Public/libwebp/backward_references.h deleted file mode 120000 index 0881ff9b..00000000 --- a/Example/Pods/Headers/Public/libwebp/backward_references.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/enc/backward_references.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/bit_reader.h b/Example/Pods/Headers/Public/libwebp/bit_reader.h deleted file mode 120000 index 93789582..00000000 --- a/Example/Pods/Headers/Public/libwebp/bit_reader.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/bit_reader.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/bit_reader_inl.h b/Example/Pods/Headers/Public/libwebp/bit_reader_inl.h deleted file mode 120000 index be415894..00000000 --- a/Example/Pods/Headers/Public/libwebp/bit_reader_inl.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/bit_reader_inl.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/bit_writer.h b/Example/Pods/Headers/Public/libwebp/bit_writer.h deleted file mode 120000 index abe7119f..00000000 --- a/Example/Pods/Headers/Public/libwebp/bit_writer.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/bit_writer.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/color_cache.h b/Example/Pods/Headers/Public/libwebp/color_cache.h deleted file mode 120000 index 5bba961d..00000000 --- a/Example/Pods/Headers/Public/libwebp/color_cache.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/color_cache.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/common.h b/Example/Pods/Headers/Public/libwebp/common.h deleted file mode 120000 index 8f4827f8..00000000 --- a/Example/Pods/Headers/Public/libwebp/common.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/common.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/cost.h b/Example/Pods/Headers/Public/libwebp/cost.h deleted file mode 120000 index a9c6f4ae..00000000 --- a/Example/Pods/Headers/Public/libwebp/cost.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/enc/cost.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/decode_vp8.h b/Example/Pods/Headers/Public/libwebp/decode_vp8.h deleted file mode 120000 index b5ac83e7..00000000 --- a/Example/Pods/Headers/Public/libwebp/decode_vp8.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/decode_vp8.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/delta_palettization.h b/Example/Pods/Headers/Public/libwebp/delta_palettization.h deleted file mode 120000 index c8e6fb64..00000000 --- a/Example/Pods/Headers/Public/libwebp/delta_palettization.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/enc/delta_palettization.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/dsp.h b/Example/Pods/Headers/Public/libwebp/dsp.h deleted file mode 120000 index 1bace906..00000000 --- a/Example/Pods/Headers/Public/libwebp/dsp.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dsp/dsp.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/endian_inl.h b/Example/Pods/Headers/Public/libwebp/endian_inl.h deleted file mode 120000 index 2be74a78..00000000 --- a/Example/Pods/Headers/Public/libwebp/endian_inl.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/endian_inl.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/filters.h b/Example/Pods/Headers/Public/libwebp/filters.h deleted file mode 120000 index ab7b5327..00000000 --- a/Example/Pods/Headers/Public/libwebp/filters.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/filters.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/histogram.h b/Example/Pods/Headers/Public/libwebp/histogram.h deleted file mode 120000 index c6950516..00000000 --- a/Example/Pods/Headers/Public/libwebp/histogram.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/enc/histogram.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/huffman.h b/Example/Pods/Headers/Public/libwebp/huffman.h deleted file mode 120000 index 6245e139..00000000 --- a/Example/Pods/Headers/Public/libwebp/huffman.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/huffman.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/huffman_encode.h b/Example/Pods/Headers/Public/libwebp/huffman_encode.h deleted file mode 120000 index 19a28b2a..00000000 --- a/Example/Pods/Headers/Public/libwebp/huffman_encode.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/huffman_encode.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/lossless.h b/Example/Pods/Headers/Public/libwebp/lossless.h deleted file mode 120000 index a3b07cfe..00000000 --- a/Example/Pods/Headers/Public/libwebp/lossless.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dsp/lossless.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/mips_macro.h b/Example/Pods/Headers/Public/libwebp/mips_macro.h deleted file mode 120000 index da76de07..00000000 --- a/Example/Pods/Headers/Public/libwebp/mips_macro.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dsp/mips_macro.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/muxi.h b/Example/Pods/Headers/Public/libwebp/muxi.h deleted file mode 120000 index d96d5988..00000000 --- a/Example/Pods/Headers/Public/libwebp/muxi.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/mux/muxi.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/neon.h b/Example/Pods/Headers/Public/libwebp/neon.h deleted file mode 120000 index 8213e481..00000000 --- a/Example/Pods/Headers/Public/libwebp/neon.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dsp/neon.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/quant_levels.h b/Example/Pods/Headers/Public/libwebp/quant_levels.h deleted file mode 120000 index d620fa9c..00000000 --- a/Example/Pods/Headers/Public/libwebp/quant_levels.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/quant_levels.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/quant_levels_dec.h b/Example/Pods/Headers/Public/libwebp/quant_levels_dec.h deleted file mode 120000 index 6930b5dd..00000000 --- a/Example/Pods/Headers/Public/libwebp/quant_levels_dec.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/quant_levels_dec.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/random.h b/Example/Pods/Headers/Public/libwebp/random.h deleted file mode 120000 index 7ccc260c..00000000 --- a/Example/Pods/Headers/Public/libwebp/random.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/random.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/rescaler.h b/Example/Pods/Headers/Public/libwebp/rescaler.h deleted file mode 120000 index 3c1c538c..00000000 --- a/Example/Pods/Headers/Public/libwebp/rescaler.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/rescaler.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/thread.h b/Example/Pods/Headers/Public/libwebp/thread.h deleted file mode 120000 index 3033ec5a..00000000 --- a/Example/Pods/Headers/Public/libwebp/thread.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/thread.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/utils.h b/Example/Pods/Headers/Public/libwebp/utils.h deleted file mode 120000 index ba046686..00000000 --- a/Example/Pods/Headers/Public/libwebp/utils.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/utils/utils.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/vp8enci.h b/Example/Pods/Headers/Public/libwebp/vp8enci.h deleted file mode 120000 index 4b202757..00000000 --- a/Example/Pods/Headers/Public/libwebp/vp8enci.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/enc/vp8enci.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/vp8i.h b/Example/Pods/Headers/Public/libwebp/vp8i.h deleted file mode 120000 index 1c5d8a56..00000000 --- a/Example/Pods/Headers/Public/libwebp/vp8i.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/vp8i.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/vp8li.h b/Example/Pods/Headers/Public/libwebp/vp8li.h deleted file mode 120000 index ee31158b..00000000 --- a/Example/Pods/Headers/Public/libwebp/vp8li.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/vp8li.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/webp/decode.h b/Example/Pods/Headers/Public/libwebp/webp/decode.h deleted file mode 120000 index cb9e6a20..00000000 --- a/Example/Pods/Headers/Public/libwebp/webp/decode.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/decode.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/webp/demux.h b/Example/Pods/Headers/Public/libwebp/webp/demux.h deleted file mode 120000 index 4b1b1081..00000000 --- a/Example/Pods/Headers/Public/libwebp/webp/demux.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/demux.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/webp/encode.h b/Example/Pods/Headers/Public/libwebp/webp/encode.h deleted file mode 120000 index 336598ae..00000000 --- a/Example/Pods/Headers/Public/libwebp/webp/encode.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/encode.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/webp/extras.h b/Example/Pods/Headers/Public/libwebp/webp/extras.h deleted file mode 120000 index 1aef3627..00000000 --- a/Example/Pods/Headers/Public/libwebp/webp/extras.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/extras.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/webp/format_constants.h b/Example/Pods/Headers/Public/libwebp/webp/format_constants.h deleted file mode 120000 index 2b3e467c..00000000 --- a/Example/Pods/Headers/Public/libwebp/webp/format_constants.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/format_constants.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/webp/mux.h b/Example/Pods/Headers/Public/libwebp/webp/mux.h deleted file mode 120000 index 03e49641..00000000 --- a/Example/Pods/Headers/Public/libwebp/webp/mux.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/mux.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/webp/mux_types.h b/Example/Pods/Headers/Public/libwebp/webp/mux_types.h deleted file mode 120000 index 20761020..00000000 --- a/Example/Pods/Headers/Public/libwebp/webp/mux_types.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/mux_types.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/webp/types.h b/Example/Pods/Headers/Public/libwebp/webp/types.h deleted file mode 120000 index e00cbb0a..00000000 --- a/Example/Pods/Headers/Public/libwebp/webp/types.h +++ /dev/null @@ -1 +0,0 @@ -../../../../libwebp/src/webp/types.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/webpi.h b/Example/Pods/Headers/Public/libwebp/webpi.h deleted file mode 120000 index 6cf10ad5..00000000 --- a/Example/Pods/Headers/Public/libwebp/webpi.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dec/webpi.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/libwebp/yuv.h b/Example/Pods/Headers/Public/libwebp/yuv.h deleted file mode 120000 index eaa7fa95..00000000 --- a/Example/Pods/Headers/Public/libwebp/yuv.h +++ /dev/null @@ -1 +0,0 @@ -../../../libwebp/src/dsp/yuv.h \ No newline at end of file diff --git a/Example/Pods/Local Podspecs/PINCache.podspec.json b/Example/Pods/Local Podspecs/PINCache.podspec.json deleted file mode 100644 index ec70e3b8..00000000 --- a/Example/Pods/Local Podspecs/PINCache.podspec.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "PINCache", - "version": "3.0.0-beta", - "source_files": "PINCache/*.{h,m}", - "homepage": "https://github.com/pinterest/PINCache", - "summary": "Fast, thread safe, parallel object cache for iOS and OS X.", - "authors": { - "Garrett Moon": "garrett@pinterest.com", - "Justin Ouellette": "jstn@tumblr.com" - }, - "source": { - "git": "https://github.com/pinterest/PINCache.git", - "tag": "3.0.0-beta" - }, - "license": { - "type": "Apache 2.0", - "file": "LICENSE.txt" - }, - "requires_arc": true, - "frameworks": "Foundation", - "ios": { - "weak_frameworks": "UIKit" - }, - "osx": { - "weak_frameworks": "AppKit" - }, - "platforms": { - "ios": "5.0", - "osx": "10.7", - "tvos": "9.0", - "watchos": "2.0" - }, - "prefix_header_contents": "#ifndef TARGET_OS_WATCH\n #define TARGET_OS_WATCH 0\n#endif" -} diff --git a/Example/Pods/Local Podspecs/PINRemoteImage.podspec.json b/Example/Pods/Local Podspecs/PINRemoteImage.podspec.json deleted file mode 100644 index 45d7cdc2..00000000 --- a/Example/Pods/Local Podspecs/PINRemoteImage.podspec.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "name": "PINRemoteImage", - "version": "3.0.0-beta.3", - "summary": "A thread safe, performant, feature rich image fetcher", - "homepage": "https://github.com/pinterest/PINRemoteImage", - "license": "Apache 2.0", - "authors": { - "Garrett Moon": "garrett@pinterest.com" - }, - "source": { - "git": "https://github.com/pinterest/PINRemoteImage.git", - "tag": "3.0.0-beta.3" - }, - "social_media_url": "https://twitter.com/garrettmoon", - "platforms": { - "ios": "7.0", - "tvos": "9.0" - }, - "requires_arc": true, - "default_subspecs": [ - "FLAnimatedImage", - "PINCache" - ], - "subspecs": [ - { - "name": "Core", - "platforms": { - "ios": "7.0", - "tvos": "9.0", - "osx": "10.9" - }, - "source_files": "Pod/Classes/**/*.{h,m}", - "exclude_files": [ - "Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.h", - "Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.m", - "Pod/Classes/PINCache/**/*.{h,m}" - ], - "public_header_files": "Pod/Classes/**/*.h", - "frameworks": [ - "ImageIO", - "Accelerate" - ] - }, - { - "name": "iOS", - "platforms": { - "ios": "7.0", - "tvos": "9.0" - }, - "dependencies": { - "PINRemoteImage/Core": [ - - ] - }, - "frameworks": "UIKit" - }, - { - "name": "OSX", - "platforms": { - "osx": "10.9" - }, - "dependencies": { - "PINRemoteImage/Core": [ - - ] - }, - "frameworks": [ - "Cocoa", - "CoreServices" - ] - }, - { - "name": "tvOS", - "dependencies": { - "PINRemoteImage/iOS": [ - - ] - } - }, - { - "name": "FLAnimatedImage", - "platforms": { - "ios": "7.0" - }, - "dependencies": { - "PINRemoteImage/Core": [ - - ], - "FLAnimatedImage": [ - ">= 1.0" - ] - }, - "source_files": [ - "Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.h", - "Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.m" - ] - }, - { - "name": "WebP", - "xcconfig": { - "GCC_PREPROCESSOR_DEFINITIONS": "$(inherited) PIN_WEBP=1", - "USER_HEADER_SEARCH_PATHS": "$(inherited) $(SRCROOT)/libwebp/src" - }, - "dependencies": { - "PINRemoteImage/Core": [ - - ], - "libwebp": [ - - ] - } - }, - { - "name": "PINCache", - "dependencies": { - "PINRemoteImage/Core": [ - - ], - "PINCache": [ - ">=3.0.1-beta" - ] - }, - "source_files": "Pod/Classes/PINCache/**/*.{h,m}" - } - ] -} diff --git a/Example/Pods/Manifest.lock b/Example/Pods/Manifest.lock deleted file mode 100644 index 0ae2967b..00000000 --- a/Example/Pods/Manifest.lock +++ /dev/null @@ -1,58 +0,0 @@ -PODS: - - FLAnimatedImage (1.0.12) - - libwebp (0.5.0): - - libwebp/core (= 0.5.0) - - libwebp/dec (= 0.5.0) - - libwebp/demux (= 0.5.0) - - libwebp/dsp (= 0.5.0) - - libwebp/enc (= 0.5.0) - - libwebp/mux (= 0.5.0) - - libwebp/utils (= 0.5.0) - - libwebp/webp (= 0.5.0) - - libwebp/core (0.5.0): - - libwebp/webp - - libwebp/dec (0.5.0): - - libwebp/core - - libwebp/demux (0.5.0): - - libwebp/core - - libwebp/dsp (0.5.0): - - libwebp/core - - libwebp/enc (0.5.0): - - libwebp/core - - libwebp/mux (0.5.0): - - libwebp/core - - libwebp/utils (0.5.0): - - libwebp/core - - libwebp/webp (0.5.0) - - PINCache (3.0.1-beta) - - PINRemoteImage (3.0.0-beta.3): - - PINRemoteImage/FLAnimatedImage (= 3.0.0-beta.3) - - PINRemoteImage/PINCache (= 3.0.0-beta.3) - - PINRemoteImage/Core (3.0.0-beta.3) - - PINRemoteImage/FLAnimatedImage (3.0.0-beta.3): - - FLAnimatedImage (>= 1.0) - - PINRemoteImage/Core - - PINRemoteImage/PINCache (3.0.0-beta.3): - - PINCache (>= 3.0.1-beta) - - PINRemoteImage/Core - - PINRemoteImage/WebP (3.0.0-beta.3): - - libwebp - - PINRemoteImage/Core - -DEPENDENCIES: - - PINRemoteImage (from `../`) - - PINRemoteImage/WebP (from `../`) - -EXTERNAL SOURCES: - PINRemoteImage: - :path: ../ - -SPEC CHECKSUMS: - FLAnimatedImage: 4a0b56255d9b05f18b6dd7ee06871be5d3b89e31 - libwebp: 68ba2001ba6806ee52837ebd77a551a0b6567e4e - PINCache: 6911fe422a633e18b3d3ddf2bd4f0e55e36e2892 - PINRemoteImage: 909c740cc2878fa6b45a3cc093b87d8195a7e0fa - -PODFILE CHECKSUM: a64f6dc82868b26747c10e6c5e963d51a1ba55ba - -COCOAPODS: 1.0.0 diff --git a/Example/Pods/PINCache/LICENSE.txt b/Example/Pods/PINCache/LICENSE.txt deleted file mode 100644 index 3af296ea..00000000 --- a/Example/Pods/PINCache/LICENSE.txt +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [2013] [Tumblr, Inc.] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/Example/Pods/PINCache/PINCache/Nullability.h b/Example/Pods/PINCache/PINCache/Nullability.h deleted file mode 100644 index 437a16f3..00000000 --- a/Example/Pods/PINCache/PINCache/Nullability.h +++ /dev/null @@ -1,20 +0,0 @@ -// PINCache is a modified version of TMCache -// Modifications by Garrett Moon -// Copyright (c) 2015 Pinterest. All rights reserved. - -#ifndef PINCache_nullability_h -#define PINCache_nullability_h - -#if !__has_feature(nullability) -#define NS_ASSUME_NONNULL_BEGIN -#define NS_ASSUME_NONNULL_END -#define nullable -#define nonnull -#define null_unspecified -#define null_resettable -#define __nullable -#define __nonnull -#define __null_unspecified -#endif - -#endif diff --git a/Example/Pods/PINCache/PINCache/PINCache.h b/Example/Pods/PINCache/PINCache/PINCache.h deleted file mode 100644 index e7e5f8a1..00000000 --- a/Example/Pods/PINCache/PINCache/PINCache.h +++ /dev/null @@ -1,256 +0,0 @@ -// PINCache is a modified version of TMCache -// Modifications by Garrett Moon -// Copyright (c) 2015 Pinterest. All rights reserved. - -#import - -#import "PINDiskCache.h" -#import "PINMemoryCache.h" - -NS_ASSUME_NONNULL_BEGIN - -@class PINCache; - -/** - A callback block which provides only the cache as an argument - */ -typedef void (^PINCacheBlock)(PINCache *cache); - -/** - A callback block which provides the cache, key and object as arguments - */ -typedef void (^PINCacheObjectBlock)(PINCache *cache, NSString *key, id __nullable object); - -/** - A callback block which provides a BOOL value as argument - */ -typedef void (^PINCacheObjectContainmentBlock)(BOOL containsObject); - - -/** - `PINCache` is a thread safe key/value store designed for persisting temporary objects that are expensive to - reproduce, such as downloaded data or the results of slow processing. It is comprised of two self-similar - stores, one in memory () and one on disk (). - - `PINCache` itself actually does very little; its main function is providing a front end for a common use case: - a small, fast memory cache that asynchronously persists itself to a large, slow disk cache. When objects are - removed from the memory cache in response to an "apocalyptic" event they remain in the disk cache and are - repopulated in memory the next time they are accessed. `PINCache` also does the tedious work of creating a - dispatch group to wait for both caches to finish their operations without blocking each other. - - The parallel caches are accessible as public properties ( and ) and can be manipulated - separately if necessary. See the docs for and for more details. - - @warning when using in extension or watch extension, define PIN_APP_EXTENSIONS=1 - */ - -@interface PINCache : NSObject - -#pragma mark - -/// @name Core - -/** - The name of this cache, used to create the and also appearing in stack traces. - */ -@property (readonly) NSString *name; - -/** - A concurrent queue on which blocks passed to the asynchronous access methods are run. - */ -@property (readonly) dispatch_queue_t concurrentQueue; - -/** - Synchronously retrieves the total byte count of the on the shared disk queue. - */ -@property (readonly) NSUInteger diskByteCount; - -/** - The underlying disk cache, see for additional configuration and trimming options. - */ -@property (readonly) PINDiskCache *diskCache; - -/** - The underlying memory cache, see for additional configuration and trimming options. - */ -@property (readonly) PINMemoryCache *memoryCache; - -#pragma mark - -/// @name Initialization - -/** - A shared cache. - - @result The shared singleton cache instance. - */ -+ (instancetype)sharedCache; - -- (instancetype)init NS_UNAVAILABLE; - -/** - Multiple instances with the same name are allowed and can safely access - the same data on disk thanks to the magic of seriality. Also used to create the . - - @see name - @param name The name of the cache. - @result A new cache with the specified name. - */ -- (instancetype)initWithName:(nonnull NSString *)name; - -/** - Multiple instances with the same name are allowed and can safely access - the same data on disk thanks to the magic of seriality. Also used to create the . - - @see name - @param name The name of the cache. - @param fileExtension The file extension for files on disk. - @result A new cache with the specified name. - */ -- (instancetype)initWithName:(nonnull NSString *)name fileExtension:(nullable NSString *)fileExtension; - -/** - Multiple instances with the same name are allowed and can safely access - the same data on disk thanks to the magic of seriality. Also used to create the . - - @see name - @param name The name of the cache. - @param rootPath The path of the cache on disk. - @param fileExtension The file extension for files on disk. - @result A new cache with the specified name. - */ -- (instancetype)initWithName:(nonnull NSString *)name rootPath:(nonnull NSString *)rootPath fileExtension:(nullable NSString *)fileExtension; - -/** - Multiple instances with the same name are allowed and can safely access - the same data on disk thanks to the magic of seriality. Also used to create the . - Initializer allows you to override default NSKeyedArchiver/NSKeyedUnarchiver serialization for . - You must provide both serializer and deserializer, or opt-out to default implementation providing nil values. - - @see name - @param name The name of the cache. - @param rootPath The path of the cache on disk. - @param serializer A block used to serialize object before writing to disk. If nil provided, default NSKeyedArchiver serialized will be used. - @param deserializer A block used to deserialize object read from disk. If nil provided, default NSKeyedUnarchiver serialized will be used. - @param fileExtension The file extension for files on disk. - @result A new cache with the specified name. - */ -- (instancetype)initWithName:(nonnull NSString *)name rootPath:(nonnull NSString *)rootPath serializer:(nullable PINDiskCacheSerializerBlock)serializer deserializer:(nullable PINDiskCacheDeserializerBlock)deserializer fileExtension:(nullable NSString *)fileExtension NS_DESIGNATED_INITIALIZER; - - -#pragma mark - -/// @name Asynchronous Methods - -/** - This method determines whether an object is present for the given key in the cache. This method returns immediately - and executes the passed block after the object is available, potentially in parallel with other blocks on the - . - - @see containsObjectForKey: - @param key The key associated with the object. - @param block A block to be executed concurrently after the containment check happened - */ -- (void)containsObjectForKey:(NSString *)key block:(PINCacheObjectContainmentBlock)block; - -/** - Retrieves the object for the specified key. This method returns immediately and executes the passed - block after the object is available, potentially in parallel with other blocks on the . - - @param key The key associated with the requested object. - @param block A block to be executed concurrently when the object is available. - */ -- (void)objectForKey:(NSString *)key block:(PINCacheObjectBlock)block; - -/** - Stores an object in the cache for the specified key. This method returns immediately and executes the - passed block after the object has been stored, potentially in parallel with other blocks on the . - - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - @param block A block to be executed concurrently after the object has been stored, or nil. - */ -- (void)setObject:(id )object forKey:(NSString *)key block:(nullable PINCacheObjectBlock)block; - -/** - Removes the object for the specified key. This method returns immediately and executes the passed - block after the object has been removed, potentially in parallel with other blocks on the . - - @param key The key associated with the object to be removed. - @param block A block to be executed concurrently after the object has been removed, or nil. - */ -- (void)removeObjectForKey:(NSString *)key block:(nullable PINCacheObjectBlock)block; - -/** - Removes all objects from the cache that have not been used since the specified date. This method returns immediately and - executes the passed block after the cache has been trimmed, potentially in parallel with other blocks on the . - - @param date Objects that haven't been accessed since this date are removed from the cache. - @param block A block to be executed concurrently after the cache has been trimmed, or nil. - */ -- (void)trimToDate:(NSDate *)date block:(nullable PINCacheBlock)block; - -/** - Removes all objects from the cache.This method returns immediately and executes the passed block after the - cache has been cleared, potentially in parallel with other blocks on the . - - @param block A block to be executed concurrently after the cache has been cleared, or nil. - */ -- (void)removeAllObjects:(nullable PINCacheBlock)block; - -#pragma mark - -/// @name Synchronous Methods - -/** - This method determines whether an object is present for the given key in the cache. - - @see containsObjectForKey:block: - @param key The key associated with the object. - @result YES if an object is present for the given key in the cache, otherwise NO. - */ -- (BOOL)containsObjectForKey:(NSString *)key; - -/** - Retrieves the object for the specified key. This method blocks the calling thread until the object is available. - Uses a semaphore to achieve synchronicity on the disk cache. - - @see objectForKey:block: - @param key The key associated with the object. - @result The object for the specified key. - */ -- (__nullable id)objectForKey:(NSString *)key; - -/** - Stores an object in the cache for the specified key. This method blocks the calling thread until the object has been set. - Uses a semaphore to achieve synchronicity on the disk cache. - - @see setObject:forKey:block: - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - */ -- (void)setObject:(id )object forKey:(NSString *)key; - -/** - Removes the object for the specified key. This method blocks the calling thread until the object - has been removed. - Uses a semaphore to achieve synchronicity on the disk cache. - - @param key The key associated with the object to be removed. - */ -- (void)removeObjectForKey:(NSString *)key; - -/** - Removes all objects from the cache that have not been used since the specified date. - This method blocks the calling thread until the cache has been trimmed. - Uses a semaphore to achieve synchronicity on the disk cache. - - @param date Objects that haven't been accessed since this date are removed from the cache. - */ -- (void)trimToDate:(NSDate *)date; - -/** - Removes all objects from the cache. This method blocks the calling thread until the cache has been cleared. - Uses a semaphore to achieve synchronicity on the disk cache. - */ -- (void)removeAllObjects; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/PINCache/PINCache/PINCache.m b/Example/Pods/PINCache/PINCache/PINCache.m deleted file mode 100644 index de754099..00000000 --- a/Example/Pods/PINCache/PINCache/PINCache.m +++ /dev/null @@ -1,392 +0,0 @@ -// PINCache is a modified version of PINCache -// Modifications by Garrett Moon -// Copyright (c) 2015 Pinterest. All rights reserved. - -#import "PINCache.h" - -static NSString * const PINCachePrefix = @"com.pinterest.PINCache"; -static NSString * const PINCacheSharedName = @"PINCacheShared"; - -@interface PINCache () -#if OS_OBJECT_USE_OBJC -@property (strong, nonatomic) dispatch_queue_t concurrentQueue; -#else -@property (assign, nonatomic) dispatch_queue_t concurrentQueue; -#endif -@end - -@implementation PINCache - -#pragma mark - Initialization - - -#if !OS_OBJECT_USE_OBJC -- (void)dealloc -{ - dispatch_release(_concurrentQueue); - _concurrentQueue = nil; -} -#endif - -- (instancetype)init -{ - @throw [NSException exceptionWithName:@"Must initialize with a name" reason:@"PINCache must be initialized with a name. Call initWithName: instead." userInfo:nil]; - return [self initWithName:@""]; -} - -- (instancetype)initWithName:(NSString *)name -{ - return [self initWithName:name fileExtension:nil]; -} - -- (instancetype)initWithName:(NSString *)name fileExtension:(NSString *)fileExtension -{ - return [self initWithName:name rootPath:[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject] fileExtension:fileExtension]; -} - -- (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath fileExtension:(NSString *)fileExtension -{ - return [self initWithName:name rootPath:rootPath serializer:nil deserializer:nil fileExtension:fileExtension]; -} - -- (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath serializer:(PINDiskCacheSerializerBlock)serializer deserializer:(PINDiskCacheDeserializerBlock)deserializer fileExtension:(NSString *)fileExtension -{ - if (!name) - return nil; - - if (self = [super init]) { - _name = [name copy]; - - NSString *queueName = [[NSString alloc] initWithFormat:@"%@.%p", PINCachePrefix, (void *)self]; - _concurrentQueue = dispatch_queue_create([[NSString stringWithFormat:@"%@ Asynchronous Queue", queueName] UTF8String], DISPATCH_QUEUE_CONCURRENT); - - _diskCache = [[PINDiskCache alloc] initWithName:_name rootPath:rootPath serializer:serializer deserializer:deserializer fileExtension:fileExtension]; - _memoryCache = [[PINMemoryCache alloc] init]; - } - return self; -} - -- (NSString *)description -{ - return [[NSString alloc] initWithFormat:@"%@.%@.%p", PINCachePrefix, _name, (void *)self]; -} - -+ (instancetype)sharedCache -{ - static id cache; - static dispatch_once_t predicate; - - dispatch_once(&predicate, ^{ - cache = [[self alloc] initWithName:PINCacheSharedName]; - }); - - return cache; -} - -#pragma mark - Public Asynchronous Methods - - -- (void)containsObjectForKey:(NSString *)key block:(PINCacheObjectContainmentBlock)block -{ - if (!key || !block) { - return; - } - - __weak PINCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINCache *strongSelf = weakSelf; - - BOOL containsObject = [strongSelf containsObjectForKey:key]; - block(containsObject); - }); -} - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wshadow" - -- (void)objectForKey:(NSString *)key block:(PINCacheObjectBlock)block -{ - if (!key || !block) - return; - - __weak PINCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINCache *strongSelf = weakSelf; - if (!strongSelf) - return; - [strongSelf->_memoryCache objectForKey:key block:^(PINMemoryCache *memoryCache, NSString *memoryCacheKey, id memoryCacheObject) { - PINCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - if (memoryCacheObject) { - [strongSelf->_diskCache fileURLForKey:memoryCacheKey block:NULL]; - dispatch_async(strongSelf->_concurrentQueue, ^{ - PINCache *strongSelf = weakSelf; - if (strongSelf) - block(strongSelf, memoryCacheKey, memoryCacheObject); - }); - } else { - [strongSelf->_diskCache objectForKey:memoryCacheKey block:^(PINDiskCache *diskCache, NSString *diskCacheKey, id diskCacheObject) { - PINCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf->_memoryCache setObject:diskCacheObject forKey:diskCacheKey block:nil]; - - - dispatch_async(strongSelf->_concurrentQueue, ^{ - PINCache *strongSelf = weakSelf; - if (strongSelf) - block(strongSelf, diskCacheKey, diskCacheObject); - }); - }]; - } - }]; - }); -} - -#pragma clang diagnostic pop - -- (void)setObject:(id )object forKey:(NSString *)key block:(PINCacheObjectBlock)block -{ - if (!key || !object) - return; - - dispatch_group_t group = nil; - PINMemoryCacheObjectBlock memBlock = nil; - PINDiskCacheObjectBlock diskBlock = nil; - - if (block) { - group = dispatch_group_create(); - dispatch_group_enter(group); - dispatch_group_enter(group); - - memBlock = ^(PINMemoryCache *memoryCache, NSString *memoryCacheKey, id memoryCacheObject) { - dispatch_group_leave(group); - }; - - diskBlock = ^(PINDiskCache *diskCache, NSString *diskCacheKey, id memoryCacheObject) { - dispatch_group_leave(group); - }; - } - - [_memoryCache setObject:object forKey:key block:memBlock]; - [_diskCache setObject:object forKey:key block:diskBlock]; - - if (group) { - __weak PINCache *weakSelf = self; - dispatch_group_notify(group, _concurrentQueue, ^{ - PINCache *strongSelf = weakSelf; - if (strongSelf) - block(strongSelf, key, object); - }); - -#if !OS_OBJECT_USE_OBJC - dispatch_release(group); -#endif - } -} - -- (void)removeObjectForKey:(NSString *)key block:(PINCacheObjectBlock)block -{ - if (!key) - return; - - dispatch_group_t group = nil; - PINMemoryCacheObjectBlock memBlock = nil; - PINDiskCacheObjectBlock diskBlock = nil; - - if (block) { - group = dispatch_group_create(); - dispatch_group_enter(group); - dispatch_group_enter(group); - - memBlock = ^(PINMemoryCache *memoryCache, NSString *memoryCacheKey, id memoryCacheObject) { - dispatch_group_leave(group); - }; - - diskBlock = ^(PINDiskCache *diskCache, NSString *diskCacheKey, id memoryCacheObject) { - dispatch_group_leave(group); - }; - } - - [_memoryCache removeObjectForKey:key block:memBlock]; - [_diskCache removeObjectForKey:key block:diskBlock]; - - if (group) { - __weak PINCache *weakSelf = self; - dispatch_group_notify(group, _concurrentQueue, ^{ - PINCache *strongSelf = weakSelf; - if (strongSelf) - block(strongSelf, key, nil); - }); - -#if !OS_OBJECT_USE_OBJC - dispatch_release(group); -#endif - } -} - -- (void)removeAllObjects:(PINCacheBlock)block -{ - dispatch_group_t group = nil; - PINMemoryCacheBlock memBlock = nil; - PINDiskCacheBlock diskBlock = nil; - - if (block) { - group = dispatch_group_create(); - dispatch_group_enter(group); - dispatch_group_enter(group); - - memBlock = ^(PINMemoryCache *cache) { - dispatch_group_leave(group); - }; - - diskBlock = ^(PINDiskCache *cache) { - dispatch_group_leave(group); - }; - } - - [_memoryCache removeAllObjects:memBlock]; - [_diskCache removeAllObjects:diskBlock]; - - if (group) { - __weak PINCache *weakSelf = self; - dispatch_group_notify(group, _concurrentQueue, ^{ - PINCache *strongSelf = weakSelf; - if (strongSelf) - block(strongSelf); - }); - -#if !OS_OBJECT_USE_OBJC - dispatch_release(group); -#endif - } -} - -- (void)trimToDate:(NSDate *)date block:(PINCacheBlock)block -{ - if (!date) - return; - - dispatch_group_t group = nil; - PINMemoryCacheBlock memBlock = nil; - PINDiskCacheBlock diskBlock = nil; - - if (block) { - group = dispatch_group_create(); - dispatch_group_enter(group); - dispatch_group_enter(group); - - memBlock = ^(PINMemoryCache *cache) { - dispatch_group_leave(group); - }; - - diskBlock = ^(PINDiskCache *cache) { - dispatch_group_leave(group); - }; - } - - [_memoryCache trimToDate:date block:memBlock]; - [_diskCache trimToDate:date block:diskBlock]; - - if (group) { - __weak PINCache *weakSelf = self; - dispatch_group_notify(group, _concurrentQueue, ^{ - PINCache *strongSelf = weakSelf; - if (strongSelf) - block(strongSelf); - }); - -#if !OS_OBJECT_USE_OBJC - dispatch_release(group); -#endif - } -} - -#pragma mark - Public Synchronous Accessors - - -- (NSUInteger)diskByteCount -{ - __block NSUInteger byteCount = 0; - - [_diskCache synchronouslyLockFileAccessWhileExecutingBlock:^(PINDiskCache *diskCache) { - byteCount = diskCache.byteCount; - }]; - - return byteCount; -} - -- (BOOL)containsObjectForKey:(NSString *)key -{ - if (!key) - return NO; - - return [_memoryCache containsObjectForKey:key] || [_diskCache containsObjectForKey:key]; -} - -- (__nullable id)objectForKey:(NSString *)key -{ - if (!key) - return nil; - - __block id object = nil; - - object = [_memoryCache objectForKey:key]; - - if (object) { - // update the access time on disk - [_diskCache fileURLForKey:key block:NULL]; - } else { - object = [_diskCache objectForKey:key]; - [_memoryCache setObject:object forKey:key]; - } - - return object; -} - -- (void)setObject:(id )object forKey:(NSString *)key -{ - if (!key || !object) - return; - - [_memoryCache setObject:object forKey:key]; - [_diskCache setObject:object forKey:key]; -} - -- (id)objectForKeyedSubscript:(NSString *)key -{ - return [self objectForKey:key]; -} - -- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key -{ - [self setObject:obj forKey:key]; -} - -- (void)removeObjectForKey:(NSString *)key -{ - if (!key) - return; - - [_memoryCache removeObjectForKey:key]; - [_diskCache removeObjectForKey:key]; -} - -- (void)trimToDate:(NSDate *)date -{ - if (!date) - return; - - [_memoryCache trimToDate:date]; - [_diskCache trimToDate:date]; -} - -- (void)removeAllObjects -{ - [_memoryCache removeAllObjects]; - [_diskCache removeAllObjects]; -} - -@end diff --git a/Example/Pods/PINCache/PINCache/PINCacheObjectSubscripting.h b/Example/Pods/PINCache/PINCache/PINCacheObjectSubscripting.h deleted file mode 100644 index 353851bc..00000000 --- a/Example/Pods/PINCache/PINCache/PINCacheObjectSubscripting.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// PINCacheObjectSubscripting.h -// PINCache -// -// Created by Rocir Marcos Leite Santiago on 4/2/16. -// Copyright © 2016 Pinterest. All rights reserved. -// - -#import - -@protocol PINCacheObjectSubscripting - -@required - -/** - This method enables using literals on the receiving object, such as `id object = cache[@"key"];`. - - @param key The key associated with the object. - @result The object for the specified key. - */ -- (id)objectForKeyedSubscript:(NSString *)key; - -/** - This method enables using literals on the receiving object, such as `cache[@"key"] = object;`. - - @param object An object to be assigned for the key. - @param key A key to associate with the object. This string will be copied. - */ -- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key; - -@end diff --git a/Example/Pods/PINCache/PINCache/PINDiskCache.h b/Example/Pods/PINCache/PINCache/PINDiskCache.h deleted file mode 100644 index a0b0c2be..00000000 --- a/Example/Pods/PINCache/PINCache/PINDiskCache.h +++ /dev/null @@ -1,482 +0,0 @@ -// PINCache is a modified version of TMCache -// Modifications by Garrett Moon -// Copyright (c) 2015 Pinterest. All rights reserved. - -#import -#import "Nullability.h" - -#import "PINCacheObjectSubscripting.h" - -NS_ASSUME_NONNULL_BEGIN - -@class PINDiskCache; - -/** - A callback block which provides only the cache as an argument - */ -typedef void (^PINDiskCacheBlock)(PINDiskCache *cache); - -/** - A callback block which provides the cache, key and object as arguments - */ -typedef void (^PINDiskCacheObjectBlock)(PINDiskCache *cache, NSString *key, id __nullable object); - -/** - A callback block which provides the key and fileURL of the object - */ -typedef void (^PINDiskCacheFileURLBlock)(NSString *key, NSURL * __nullable fileURL); - -/** - A callback block which provides a BOOL value as argument - */ -typedef void (^PINDiskCacheContainsBlock)(BOOL containsObject); - -/** - * A block used to serialize object before writing to disk - * - * @param object Object to serialize - * - * @return Serialized object representation - */ -typedef NSData* __nonnull(^PINDiskCacheSerializerBlock)(id object); - -/** - * A block used to deserialize objects - * - * @param data Serialized object data - * - * @return Deserialized object - */ -typedef id __nonnull(^PINDiskCacheDeserializerBlock)(NSData* data); - - -/** - `PINDiskCache` is a thread safe key/value store backed by the file system. It accepts any object conforming - to the `NSCoding` protocol, which includes the basic Foundation data types and collection classes and also - many UIKit classes, notably `UIImage`. All work is performed on a serial queue shared by all instances in - the app, and archiving is handled by `NSKeyedArchiver`. This is a particular advantage for `UIImage` because - it skips `UIImagePNGRepresentation()` and retains information like scale and orientation. - - The designated initializer for `PINDiskCache` is . The string is used to create a directory - under Library/Caches that scopes disk access for this instance. Multiple instances with the same name are *not* - allowed as they would conflict with each other. - - Unless otherwise noted, all properties and methods are safe to access from any thread at any time. All blocks - will cause the queue to wait, making it safe to access and manipulate the actual cache files on disk for the - duration of the block. - - Because this cache is bound by disk I/O it can be much slower than , although values stored in - `PINDiskCache` persist after application relaunch. Using is recommended over using `PINDiskCache` - by itself, as it adds a fast layer of additional memory caching while still writing to disk. - - All access to the cache is dated so the that the least-used objects can be trimmed first. Setting an optional - will trigger a GCD timer to periodically to trim the cache with . - */ - -@interface PINDiskCache : NSObject - - - -#pragma mark - -/// @name Core - -/** - The name of this cache, used to create a directory under Library/Caches and also appearing in stack traces. - */ -@property (readonly) NSString *name; - -/** - The URL of the directory used by this cache, usually `Library/Caches/com.pinterest.PINDiskCache.(name)` - - @warning Do not interact with files under this URL except in or - . - */ -@property (readonly) NSURL *cacheURL; - -/** - The total number of bytes used on disk, as reported by `NSURLTotalFileAllocatedSizeKey`. - - @warning This property should only be read from a call to or - its asynchronous equivalent - - For example: - - // some background thread - - __block NSUInteger byteCount = 0; - - [_diskCache synchronouslyLockFileAccessWhileExecutingBlock:^(PINDiskCache *diskCache) { - byteCount = diskCache.byteCount; - }]; - */ -@property (readonly) NSUInteger byteCount; - -/** - The maximum number of bytes allowed on disk. This value is checked every time an object is set, if the written - size exceeds the limit a trim call is queued. Defaults to `0.0`, meaning no practical limit. - - */ -@property (assign) NSUInteger byteLimit; - -/** - The maximum number of seconds an object is allowed to exist in the cache. Setting this to a value - greater than `0.0` will start a recurring GCD timer with the same period that calls . - Setting it back to `0.0` will stop the timer. Defaults to `0.0`, meaning no limit. - - */ -@property (assign) NSTimeInterval ageLimit; - -/** - Extension for all cache files on disk. Defaults to no extension. - */ -@property (readonly) NSString *fileExtension; - -/** - The writing protection option used when writing a file on disk. This value is used every time an object is set. - NSDataWritingAtomic and NSDataWritingWithoutOverwriting are ignored if set - Defaults to NSDataWritingFileProtectionNone. - - @warning Only new files are affected by the new writing protection. If you need all files to be affected, - you'll have to purge and set the objects back to the cache - - Only available on iOS - */ -#if TARGET_OS_IPHONE -@property (assign) NSDataWritingOptions writingProtectionOption; -#endif - -/** - If ttlCache is YES, the cache behaves like a ttlCache. This means that once an object enters the - cache, it only lives as long as self.ageLimit. This has the following implications: - - Accessing an object in the cache does not extend that object's lifetime in the cache - - When attempting to access an object in the cache that has lived longer than self.ageLimit, - the cache will behave as if the object does not exist - - */ -@property (nonatomic, assign, getter=isTTLCache) BOOL ttlCache; - -#pragma mark - -/// @name Event Blocks - -/** - A block to be executed just before an object is added to the cache. The queue waits during execution. - */ -@property (copy) PINDiskCacheObjectBlock __nullable willAddObjectBlock; - -/** - A block to be executed just before an object is removed from the cache. The queue waits during execution. - */ -@property (copy) PINDiskCacheObjectBlock __nullable willRemoveObjectBlock; - -/** - A block to be executed just before all objects are removed from the cache as a result of . - The queue waits during execution. - */ -@property (copy) PINDiskCacheBlock __nullable willRemoveAllObjectsBlock; - -/** - A block to be executed just after an object is added to the cache. The queue waits during execution. - */ -@property (copy) PINDiskCacheObjectBlock __nullable didAddObjectBlock; - -/** - A block to be executed just after an object is removed from the cache. The queue waits during execution. - */ -@property (copy) PINDiskCacheObjectBlock __nullable didRemoveObjectBlock; - -/** - A block to be executed just after all objects are removed from the cache as a result of . - The queue waits during execution. - */ -@property (copy) PINDiskCacheBlock __nullable didRemoveAllObjectsBlock; - -#pragma mark - -/// @name Initialization - -/** - A shared cache. - - @result The shared singleton cache instance. - */ -+ (instancetype)sharedCache; - -/** - Empties the trash with `DISPATCH_QUEUE_PRIORITY_BACKGROUND`. Does not use lock. - */ -+ (void)emptyTrash; - -- (instancetype)init NS_UNAVAILABLE; - -/** - Multiple instances with the same name are allowed and can safely access - the same data on disk thanks to the magic of seriality. - - @see name - @param name The name of the cache. - @result A new cache with the specified name. - */ -- (instancetype)initWithName:(nonnull NSString *)name; - -/** - Multiple instances with the same name are allowed and can safely access - the same data on disk thanks to the magic of seriality. - - @see name - @param name The name of the cache. - @param fileExtension The file extension for files on disk. - @result A new cache with the specified name. - */ -- (instancetype)initWithName:(nonnull NSString *)name fileExtension:(nullable NSString *)fileExtension; - -/** - Multiple instances with the same name are allowed and can safely access - the same data on disk thanks to the magic of seriality. - - @see name - @param name The name of the cache. - @param rootPath The path of the cache. - @param fileExtension The file extension for files on disk. - @result A new cache with the specified name. - */ -- (instancetype)initWithName:(nonnull NSString *)name rootPath:(nonnull NSString *)rootPath fileExtension:(nullable NSString *)fileExtension; - -/** - The designated initializer allowing you to override default NSKeyedArchiver/NSKeyedUnarchiver serialization. - - @see name - @param name The name of the cache. - @param rootPath The path of the cache. - @param serializer A block used to serialize object. If nil provided, default NSKeyedArchiver serialized will be used. - @param deserializer A block used to deserialize object. If nil provided, default NSKeyedUnarchiver serialized will be used. - @param fileExtension The file extension for files on disk. - @result A new cache with the specified name. - */ -- (instancetype)initWithName:(nonnull NSString *)name rootPath:(nonnull NSString *)rootPath serializer:(nullable PINDiskCacheSerializerBlock)serializer deserializer:(nullable PINDiskCacheDeserializerBlock)deserializer fileExtension:(nullable NSString *)fileExtension NS_DESIGNATED_INITIALIZER; - -#pragma mark - -/// @name Asynchronous Methods -/** - Locks access to ivars and allows safe interaction with files on disk. This method returns immediately. - - @warning Calling synchronous methods on the diskCache inside this block will likely cause a deadlock. - - @param block A block to be executed when a lock is available. - */ -- (void)lockFileAccessWhileExecutingBlock:(nullable PINDiskCacheBlock)block; - -/** - This method determines whether an object is present for the given key in the cache. This method returns immediately - and executes the passed block after the object is available, potentially in parallel with other blocks on the - . - - @see containsObjectForKey: - @param key The key associated with the object. - @param block A block to be executed concurrently after the containment check happened - */ -- (void)containsObjectForKey:(NSString *)key block:(PINDiskCacheContainsBlock)block; - -/** - Retrieves the object for the specified key. This method returns immediately and executes the passed - block as soon as the object is available. - - @param key The key associated with the requested object. - @param block A block to be executed serially when the object is available. - */ -- (void)objectForKey:(NSString *)key block:(nullable PINDiskCacheObjectBlock)block; - -/** - Retrieves the fileURL for the specified key without actually reading the data from disk. This method - returns immediately and executes the passed block as soon as the object is available. - - @warning Access is protected for the duration of the block, but to maintain safe disk access do not - access this fileURL after the block has ended. - - @warning The PINDiskCache lock is held while block is executed. Any synchronous calls to the diskcache - or a cache which owns the instance of the disk cache are likely to cause a deadlock. This is why the block is - *not* passed the instance of the disk cache. You should also avoid doing extensive work while this - lock is held. - - @param key The key associated with the requested object. - @param block A block to be executed serially when the file URL is available. - */ -- (void)fileURLForKey:(NSString *)key block:(nullable PINDiskCacheFileURLBlock)block; - -/** - Stores an object in the cache for the specified key. This method returns immediately and executes the - passed block as soon as the object has been stored. - - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - @param block A block to be executed serially after the object has been stored, or nil. - */ -- (void)setObject:(id )object forKey:(NSString *)key block:(nullable PINDiskCacheObjectBlock)block; - -/** - Removes the object for the specified key. This method returns immediately and executes the passed block - as soon as the object has been removed. - - @param key The key associated with the object to be removed. - @param block A block to be executed serially after the object has been removed, or nil. - */ -- (void)removeObjectForKey:(NSString *)key block:(nullable PINDiskCacheObjectBlock)block; - -/** - Removes all objects from the cache that have not been used since the specified date. - This method returns immediately and executes the passed block as soon as the cache has been trimmed. - - @param date Objects that haven't been accessed since this date are removed from the cache. - @param block A block to be executed serially after the cache has been trimmed, or nil. - */ -- (void)trimToDate:(NSDate *)date block:(nullable PINDiskCacheBlock)block; - -/** - Removes objects from the cache, largest first, until the cache is equal to or smaller than the specified byteCount. - This method returns immediately and executes the passed block as soon as the cache has been trimmed. - - @param byteCount The cache will be trimmed equal to or smaller than this size. - @param block A block to be executed serially after the cache has been trimmed, or nil. - */ -- (void)trimToSize:(NSUInteger)byteCount block:(nullable PINDiskCacheBlock)block; - -/** - Removes objects from the cache, ordered by date (least recently used first), until the cache is equal to or smaller - than the specified byteCount. This method returns immediately and executes the passed block as soon as the cache has - been trimmed. - - @param byteCount The cache will be trimmed equal to or smaller than this size. - @param block A block to be executed serially after the cache has been trimmed, or nil. - */ -- (void)trimToSizeByDate:(NSUInteger)byteCount block:(nullable PINDiskCacheBlock)block; - -/** - Removes all objects from the cache. This method returns immediately and executes the passed block as soon as the - cache has been cleared. - - @param block A block to be executed serially after the cache has been cleared, or nil. - */ -- (void)removeAllObjects:(nullable PINDiskCacheBlock)block; - -/** - Loops through all objects in the cache (reads and writes are suspended during the enumeration). Data is not actually - read from disk, the `object` parameter of the block will be `nil` but the `fileURL` will be available. - This method returns immediately. - - @param block A block to be executed for every object in the cache. - @param completionBlock An optional block to be executed after the enumeration is complete. - - @warning The PINDiskCache lock is held while block is executed. Any synchronous calls to the diskcache - or a cache which owns the instance of the disk cache are likely to cause a deadlock. This is why the block is - *not* passed the instance of the disk cache. You should also avoid doing extensive work while this - lock is held. - - */ -- (void)enumerateObjectsWithBlock:(PINDiskCacheFileURLBlock)block completionBlock:(nullable PINDiskCacheBlock)completionBlock; - -#pragma mark - -/// @name Synchronous Methods - -/** - Locks access to ivars and allows safe interaction with files on disk. This method only returns once the block - has been run. - - @warning Calling synchronous methods on the diskCache inside this block will likely cause a deadlock. - - @param block A block to be executed when a lock is available. - */ -- (void)synchronouslyLockFileAccessWhileExecutingBlock:(nullable PINDiskCacheBlock)block; - -/** - This method determines whether an object is present for the given key in the cache. - - @see containsObjectForKey:block: - @param key The key associated with the object. - @result YES if an object is present for the given key in the cache, otherwise NO. - */ -- (BOOL)containsObjectForKey:(NSString *)key; - -/** - Retrieves the object for the specified key. This method blocks the calling thread until the - object is available. - - @see objectForKey:block: - @param key The key associated with the object. - @result The object for the specified key. - */ -- (__nullable id )objectForKey:(NSString *)key; - -/** - Retrieves the file URL for the specified key. This method blocks the calling thread until the - url is available. Do not use this URL anywhere except with . This method probably - shouldn't even exist, just use the asynchronous one. - - @see fileURLForKey:block: - @param key The key associated with the object. - @result The file URL for the specified key. - */ -- (nullable NSURL *)fileURLForKey:(nullable NSString *)key; - -/** - Stores an object in the cache for the specified key. This method blocks the calling thread until - the object has been stored. - - @see setObject:forKey:block: - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - */ -- (void)setObject:(id )object forKey:(NSString *)key; - -/** - Removes the object for the specified key. This method blocks the calling thread until the object - has been removed. - - @param key The key associated with the object to be removed. - */ -- (void)removeObjectForKey:(NSString *)key; - -/** - Removes all objects from the cache that have not been used since the specified date. - This method blocks the calling thread until the cache has been trimmed. - @param date Objects that haven't been accessed since this date are removed from the cache. - */ -- (void)trimToDate:(nullable NSDate *)date; - -/** - Removes objects from the cache, largest first, until the cache is equal to or smaller than the - specified byteCount. This method blocks the calling thread until the cache has been trimmed. - - @param byteCount The cache will be trimmed equal to or smaller than this size. - */ -- (void)trimToSize:(NSUInteger)byteCount; - -/** - Removes objects from the cache, ordered by date (least recently used first), until the cache is equal to or - smaller than the specified byteCount. This method blocks the calling thread until the cache has been trimmed. - @param byteCount The cache will be trimmed equal to or smaller than this size. - */ -- (void)trimToSizeByDate:(NSUInteger)byteCount; - -/** - Removes all objects from the cache. This method blocks the calling thread until the cache has been cleared. - */ -- (void)removeAllObjects; - -/** - Loops through all objects in the cache (reads and writes are suspended during the enumeration). Data is not actually - read from disk, the `object` parameter of the block will be `nil` but the `fileURL` will be available. - This method blocks the calling thread until all objects have been enumerated. - @param block A block to be executed for every object in the cache. - - @warning Do not call this method within the event blocks (, etc.) - Instead use the asynchronous version, . - - @warning The PINDiskCache lock is held while block is executed. Any synchronous calls to the diskcache - or a cache which owns the instance of the disk cache are likely to cause a deadlock. This is why the block is - *not* passed the instance of the disk cache. You should also avoid doing extensive work while this - lock is held. - - */ -- (void)enumerateObjectsWithBlock:(nullable PINDiskCacheFileURLBlock)block; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/PINCache/PINCache/PINDiskCache.m b/Example/Pods/PINCache/PINCache/PINDiskCache.m deleted file mode 100644 index 1cc04d51..00000000 --- a/Example/Pods/PINCache/PINCache/PINDiskCache.m +++ /dev/null @@ -1,1251 +0,0 @@ -// PINCache is a modified version of TMCache -// Modifications by Garrett Moon -// Copyright (c) 2015 Pinterest. All rights reserved. - -#import "PINDiskCache.h" - -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 -#import -#endif - -#import - -#define PINDiskCacheError(error) if (error) { NSLog(@"%@ (%d) ERROR: %@", \ -[[NSString stringWithUTF8String:__FILE__] lastPathComponent], \ -__LINE__, [error localizedDescription]); } - -static NSString * const PINDiskCachePrefix = @"com.pinterest.PINDiskCache"; -static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared"; - -typedef NS_ENUM(NSUInteger, PINDiskCacheCondition) { - PINDiskCacheConditionNotReady = 0, - PINDiskCacheConditionReady = 1, -}; - -@interface PINDiskCache () { - NSConditionLock *_instanceLock; - - PINDiskCacheSerializerBlock _serializer; - PINDiskCacheDeserializerBlock _deserializer; -} - -@property (assign) NSUInteger byteCount; -@property (strong, nonatomic) NSURL *cacheURL; -#if OS_OBJECT_USE_OBJC -@property (strong, nonatomic) dispatch_queue_t asyncQueue; -#else -@property (assign, nonatomic) dispatch_queue_t asyncQueue; -#endif -@property (strong, nonatomic) NSMutableDictionary *dates; -@property (strong, nonatomic) NSMutableDictionary *sizes; -@end - -@implementation PINDiskCache - -@synthesize willAddObjectBlock = _willAddObjectBlock; -@synthesize willRemoveObjectBlock = _willRemoveObjectBlock; -@synthesize willRemoveAllObjectsBlock = _willRemoveAllObjectsBlock; -@synthesize didAddObjectBlock = _didAddObjectBlock; -@synthesize didRemoveObjectBlock = _didRemoveObjectBlock; -@synthesize didRemoveAllObjectsBlock = _didRemoveAllObjectsBlock; -@synthesize byteLimit = _byteLimit; -@synthesize ageLimit = _ageLimit; -@synthesize ttlCache = _ttlCache; - -#if TARGET_OS_IPHONE -@synthesize writingProtectionOption = _writingProtectionOption; -#endif - -#pragma mark - Initialization - - -- (void)dealloc -{ -#if !OS_OBJECT_USE_OBJC - dispatch_release(_asyncQueue); - _asyncQueue = nil; -#endif -} - -- (instancetype)init -{ - @throw [NSException exceptionWithName:@"Must initialize with a name" reason:@"PINDiskCache must be initialized with a name. Call initWithName: instead." userInfo:nil]; - return [self initWithName:@""]; -} - -- (instancetype)initWithName:(NSString *)name -{ - return [self initWithName:name fileExtension:nil]; -} - -- (instancetype)initWithName:(NSString *)name fileExtension:(NSString *)fileExtension -{ - return [self initWithName:name rootPath:[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] fileExtension:fileExtension]; -} - -- (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath fileExtension:(NSString *)fileExtension -{ - return [self initWithName:name rootPath:rootPath serializer:nil deserializer:nil fileExtension:fileExtension]; -} - -- (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath serializer:(PINDiskCacheSerializerBlock)serializer deserializer:(PINDiskCacheDeserializerBlock)deserializer fileExtension:(NSString *)fileExtension -{ - if (!name) - return nil; - - if ((serializer && !deserializer) || - (!serializer && deserializer)){ - @throw [NSException exceptionWithName:@"Must initialize with a both serializer and deserializer" reason:@"PINDiskCache must be initialized with a serializer and deserializer." userInfo:nil]; - return nil; - } - - if (self = [super init]) { - _name = [name copy]; - _fileExtension = [fileExtension copy]; - _asyncQueue = dispatch_queue_create([[NSString stringWithFormat:@"%@ Asynchronous Queue", PINDiskCachePrefix] UTF8String], DISPATCH_QUEUE_CONCURRENT); - _instanceLock = [[NSConditionLock alloc] initWithCondition:PINDiskCacheConditionNotReady]; - _willAddObjectBlock = nil; - _willRemoveObjectBlock = nil; - _willRemoveAllObjectsBlock = nil; - _didAddObjectBlock = nil; - _didRemoveObjectBlock = nil; - _didRemoveAllObjectsBlock = nil; - - _byteCount = 0; - _byteLimit = 0; - _ageLimit = 0.0; - -#if TARGET_OS_IPHONE - _writingProtectionOption = NSDataWritingFileProtectionNone; -#endif - - _dates = [[NSMutableDictionary alloc] init]; - _sizes = [[NSMutableDictionary alloc] init]; - - NSString *pathComponent = [[NSString alloc] initWithFormat:@"%@.%@", PINDiskCachePrefix, _name]; - _cacheURL = [NSURL fileURLWithPathComponents:@[ rootPath, pathComponent ]]; - - //setup serializers - if(serializer) { - _serializer = [serializer copy]; - } else { - _serializer = self.defaultSerializer; - } - - if(deserializer) { - _deserializer = [deserializer copy]; - } else { - _deserializer = self.defaultDeserializer; - } - - //we don't want to do anything without setting up the disk cache, but we also don't want to block init, it can take a while to initialize - dispatch_async(_asyncQueue, ^{ - //should always be able to aquire the lock unless the below code is running. - [_instanceLock lockWhenCondition:PINDiskCacheConditionNotReady]; - [self _locked_createCacheDirectory]; - [self _locked_initializeDiskProperties]; - [_instanceLock unlockWithCondition:PINDiskCacheConditionReady]; - }); - } - return self; -} - -- (NSString *)description -{ - return [[NSString alloc] initWithFormat:@"%@.%@.%p", PINDiskCachePrefix, _name, (void *)self]; -} - -+ (instancetype)sharedCache -{ - static id cache; - static dispatch_once_t predicate; - - dispatch_once(&predicate, ^{ - cache = [[self alloc] initWithName:PINDiskCacheSharedName]; - }); - - return cache; -} - -#pragma mark - Private Methods - - -- (NSURL *)_locked_encodedFileURLForKey:(NSString *)key -{ - if (![key length]) - return nil; - - return [_cacheURL URLByAppendingPathComponent:[self encodedString:key]]; -} - -- (NSString *)keyForEncodedFileURL:(NSURL *)url -{ - NSString *fileName = [url lastPathComponent]; - if (!fileName) - return nil; - - return [self decodedString:fileName]; -} - -- (NSString *)encodedString:(NSString *)string -{ - if (![string length]) { - return @""; - } - - if ([string respondsToSelector:@selector(stringByAddingPercentEncodingWithAllowedCharacters:)]) { - NSString *encodedString = [string stringByAddingPercentEncodingWithAllowedCharacters:[[NSCharacterSet characterSetWithCharactersInString:@".:/%"] invertedSet]]; - if (self.fileExtension.length > 0) { - return [encodedString stringByAppendingPathExtension:self.fileExtension]; - } - else { - return encodedString; - } - } - else { - CFStringRef static const charsToEscape = CFSTR(".:/%"); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - CFStringRef escapedString = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, - (__bridge CFStringRef)string, - NULL, - charsToEscape, - kCFStringEncodingUTF8); -#pragma clang diagnostic pop - - if (self.fileExtension.length > 0) { - return [(__bridge_transfer NSString *)escapedString stringByAppendingPathExtension:self.fileExtension]; - } - else { - return (__bridge_transfer NSString *)escapedString; - } - } -} - -- (NSString *)decodedString:(NSString *)string -{ - if (![string length]) { - return @""; - } - - if ([string respondsToSelector:@selector(stringByRemovingPercentEncoding)]) { - return [string stringByRemovingPercentEncoding]; - } - else { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - CFStringRef unescapedString = CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault, - (__bridge CFStringRef)string, - CFSTR(""), - kCFStringEncodingUTF8); -#pragma clang diagnostic pop - return (__bridge_transfer NSString *)unescapedString; - } -} - --(PINDiskCacheSerializerBlock) defaultSerializer -{ - return ^NSData*(id object){ - return [NSKeyedArchiver archivedDataWithRootObject:object]; - }; -} - --(PINDiskCacheDeserializerBlock) defaultDeserializer -{ - return ^id(NSData * data){ - return [NSKeyedUnarchiver unarchiveObjectWithData:data]; - }; -} - -#pragma mark - Private Trash Methods - - -+ (dispatch_queue_t)sharedTrashQueue -{ - static dispatch_queue_t trashQueue; - static dispatch_once_t predicate; - - dispatch_once(&predicate, ^{ - NSString *queueName = [[NSString alloc] initWithFormat:@"%@.trash", PINDiskCachePrefix]; - trashQueue = dispatch_queue_create([queueName UTF8String], DISPATCH_QUEUE_SERIAL); - dispatch_set_target_queue(trashQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)); - }); - - return trashQueue; -} - -+ (NSURL *)sharedTrashURL -{ - static NSURL *sharedTrashURL; - static dispatch_once_t predicate; - - dispatch_once(&predicate, ^{ - sharedTrashURL = [[[NSURL alloc] initFileURLWithPath:NSTemporaryDirectory()] URLByAppendingPathComponent:PINDiskCachePrefix isDirectory:YES]; - - if (![[NSFileManager defaultManager] fileExistsAtPath:[sharedTrashURL path]]) { - NSError *error = nil; - [[NSFileManager defaultManager] createDirectoryAtURL:sharedTrashURL - withIntermediateDirectories:YES - attributes:nil - error:&error]; - PINDiskCacheError(error); - } - }); - - return sharedTrashURL; -} - -+(BOOL)moveItemAtURLToTrash:(NSURL *)itemURL -{ - if (![[NSFileManager defaultManager] fileExistsAtPath:[itemURL path]]) - return NO; - - NSError *error = nil; - NSString *uniqueString = [[NSProcessInfo processInfo] globallyUniqueString]; - NSURL *uniqueTrashURL = [[PINDiskCache sharedTrashURL] URLByAppendingPathComponent:uniqueString]; - BOOL moved = [[NSFileManager defaultManager] moveItemAtURL:itemURL toURL:uniqueTrashURL error:&error]; - PINDiskCacheError(error); - return moved; -} - -+ (void)emptyTrash -{ - dispatch_async([self sharedTrashQueue], ^{ - NSError *searchTrashedItemsError = nil; - NSArray *trashedItems = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:[self sharedTrashURL] - includingPropertiesForKeys:nil - options:0 - error:&searchTrashedItemsError]; - PINDiskCacheError(searchTrashedItemsError); - - for (NSURL *trashedItemURL in trashedItems) { - NSError *removeTrashedItemError = nil; - [[NSFileManager defaultManager] removeItemAtURL:trashedItemURL error:&removeTrashedItemError]; - PINDiskCacheError(removeTrashedItemError); - } - }); -} - -#pragma mark - Private Queue Methods - - -- (BOOL)_locked_createCacheDirectory -{ - if ([[NSFileManager defaultManager] fileExistsAtPath:[_cacheURL path]]) - return NO; - - NSError *error = nil; - BOOL success = [[NSFileManager defaultManager] createDirectoryAtURL:_cacheURL - withIntermediateDirectories:YES - attributes:nil - error:&error]; - PINDiskCacheError(error); - - return success; -} - -- (void)_locked_initializeDiskProperties -{ - NSUInteger byteCount = 0; - NSArray *keys = @[ NSURLContentModificationDateKey, NSURLTotalFileAllocatedSizeKey ]; - - NSError *error = nil; - NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:_cacheURL - includingPropertiesForKeys:keys - options:NSDirectoryEnumerationSkipsHiddenFiles - error:&error]; - PINDiskCacheError(error); - - for (NSURL *fileURL in files) { - NSString *key = [self keyForEncodedFileURL:fileURL]; - - error = nil; - NSDictionary *dictionary = [fileURL resourceValuesForKeys:keys error:&error]; - PINDiskCacheError(error); - - NSDate *date = [dictionary objectForKey:NSURLContentModificationDateKey]; - if (date && key) - [_dates setObject:date forKey:key]; - - NSNumber *fileSize = [dictionary objectForKey:NSURLTotalFileAllocatedSizeKey]; - if (fileSize) { - [_sizes setObject:fileSize forKey:key]; - byteCount += [fileSize unsignedIntegerValue]; - } - } - - if (byteCount > 0) - self.byteCount = byteCount; // atomic -} - -- (BOOL)_locked_setFileModificationDate:(NSDate *)date forURL:(NSURL *)fileURL -{ - if (!date || !fileURL) { - return NO; - } - - NSError *error = nil; - BOOL success = [[NSFileManager defaultManager] setAttributes:@{ NSFileModificationDate: date } - ofItemAtPath:[fileURL path] - error:&error]; - PINDiskCacheError(error); - - if (success) { - NSString *key = [self keyForEncodedFileURL:fileURL]; - if (key) { - [_dates setObject:date forKey:key]; - } - } - - return success; -} - -- (BOOL)removeFileAndExecuteBlocksForKey:(NSString *)key -{ - [self lock]; - NSURL *fileURL = [self _locked_encodedFileURLForKey:key]; - - if (!fileURL || ![[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]]) { - [self unlock]; - return NO; - } - - PINDiskCacheObjectBlock willRemoveObjectBlock = _willRemoveObjectBlock; - if (willRemoveObjectBlock) { - [self unlock]; - willRemoveObjectBlock(self, key, nil); - [self lock]; - } - - BOOL trashed = [PINDiskCache moveItemAtURLToTrash:fileURL]; - if (!trashed) { - [self unlock]; - return NO; - } - - [PINDiskCache emptyTrash]; - - NSNumber *byteSize = [_sizes objectForKey:key]; - if (byteSize) - self.byteCount = _byteCount - [byteSize unsignedIntegerValue]; // atomic - - [_sizes removeObjectForKey:key]; - [_dates removeObjectForKey:key]; - - PINDiskCacheObjectBlock didRemoveObjectBlock = _didRemoveObjectBlock; - if (didRemoveObjectBlock) { - [self unlock]; - _didRemoveObjectBlock(self, key, nil); - [self lock]; - } - - [self unlock]; - - return YES; -} - -- (void)trimDiskToSize:(NSUInteger)trimByteCount -{ - [self lock]; - if (_byteCount > trimByteCount) { - NSArray *keysSortedBySize = [_sizes keysSortedByValueUsingSelector:@selector(compare:)]; - - for (NSString *key in [keysSortedBySize reverseObjectEnumerator]) { // largest objects first - [self unlock]; - - //unlock, removeFileAndExecuteBlocksForKey handles locking itself - [self removeFileAndExecuteBlocksForKey:key]; - - [self lock]; - - if (_byteCount <= trimByteCount) - break; - } - } - [self unlock]; -} - -- (void)trimDiskToSizeByDate:(NSUInteger)trimByteCount -{ - [self lock]; - if (_byteCount > trimByteCount) { - NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)]; - - for (NSString *key in keysSortedByDate) { // oldest objects first - [self unlock]; - - //unlock, removeFileAndExecuteBlocksForKey handles locking itself - [self removeFileAndExecuteBlocksForKey:key]; - - [self lock]; - - if (_byteCount <= trimByteCount) - break; - } - } - [self unlock]; -} - -- (void)trimDiskToDate:(NSDate *)trimDate -{ - [self lock]; - NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)]; - - for (NSString *key in keysSortedByDate) { // oldest files first - NSDate *accessDate = [_dates objectForKey:key]; - if (!accessDate) - continue; - - if ([accessDate compare:trimDate] == NSOrderedAscending) { // older than trim date - [self unlock]; - - //unlock, removeFileAndExecuteBlocksForKey handles locking itself - [self removeFileAndExecuteBlocksForKey:key]; - - [self lock]; - } else { - break; - } - } - [self unlock]; -} - -- (void)trimToAgeLimitRecursively -{ - [self lock]; - NSTimeInterval ageLimit = _ageLimit; - [self unlock]; - if (ageLimit == 0.0) - return; - - NSDate *date = [[NSDate alloc] initWithTimeIntervalSinceNow:-ageLimit]; - [self trimDiskToDate:date]; - - __weak PINDiskCache *weakSelf = self; - - dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_ageLimit * NSEC_PER_SEC)); - dispatch_after(time, _asyncQueue, ^(void) { - PINDiskCache *strongSelf = weakSelf; - [strongSelf trimToAgeLimitRecursively]; - }); -} - -#pragma mark - Public Asynchronous Methods - - -- (void)lockFileAccessWhileExecutingBlock:(void(^)(PINDiskCache *diskCache))block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (block) { - [strongSelf lock]; - block(strongSelf); - [strongSelf unlock]; - } - }); -} - -- (void)containsObjectForKey:(NSString *)key block:(PINDiskCacheContainsBlock)block -{ - if (!key || !block) - return; - - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - block([strongSelf containsObjectForKey:key]); - }); -} - -- (void)objectForKey:(NSString *)key block:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - NSURL *fileURL = nil; - id object = [strongSelf objectForKey:key fileURL:&fileURL]; - - if (block) { - block(strongSelf, key, object); - } - }); -} - -- (void)fileURLForKey:(NSString *)key block:(PINDiskCacheFileURLBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - NSURL *fileURL = [strongSelf fileURLForKey:key]; - - if (block) { - [strongSelf lock]; - block(key, fileURL); - [strongSelf unlock]; - } - }); -} - -- (void)setObject:(id )object forKey:(NSString *)key block:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - NSURL *fileURL = nil; - [strongSelf setObject:object forKey:key fileURL:&fileURL]; - - if (block) { - block(strongSelf, key, object); - } - }); -} - -- (void)removeObjectForKey:(NSString *)key block:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - NSURL *fileURL = nil; - [strongSelf removeObjectForKey:key fileURL:&fileURL]; - - if (block) { - block(strongSelf, key, nil); - } - }); -} - -- (void)trimToSize:(NSUInteger)trimByteCount block:(PINDiskCacheBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - [strongSelf trimToSize:trimByteCount]; - - if (block) { - block(strongSelf); - } - }); -} - -- (void)trimToDate:(NSDate *)trimDate block:(PINDiskCacheBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - [strongSelf trimToDate:trimDate]; - - if (block) { - block(strongSelf); - } - }); -} - -- (void)trimToSizeByDate:(NSUInteger)trimByteCount block:(PINDiskCacheBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - [strongSelf trimToSizeByDate:trimByteCount]; - - if (block) { - block(strongSelf); - } - }); -} - -- (void)removeAllObjects:(PINDiskCacheBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - [strongSelf removeAllObjects]; - - if (block) { - block(strongSelf); - } - }); -} - -- (void)enumerateObjectsWithBlock:(PINDiskCacheFileURLBlock)block completionBlock:(PINDiskCacheBlock)completionBlock -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - [strongSelf enumerateObjectsWithBlock:block]; - - if (completionBlock) { - completionBlock(strongSelf); - } - }); -} - -#pragma mark - Public Synchronous Methods - - -- (void)synchronouslyLockFileAccessWhileExecutingBlock:(void(^)(PINDiskCache *diskCache))block -{ - if (block) { - [self lock]; - block(self); - [self unlock]; - } -} - -- (BOOL)containsObjectForKey:(NSString *)key -{ - return ([self fileURLForKey:key updateFileModificationDate:NO] != nil); -} - -- (__nullable id)objectForKey:(NSString *)key -{ - return [self objectForKey:key fileURL:nil]; -} - -- (id)objectForKeyedSubscript:(NSString *)key -{ - return [self objectForKey:key]; -} - -- (__nullable id )objectForKey:(NSString *)key fileURL:(NSURL **)outFileURL -{ - NSDate *now = [[NSDate alloc] init]; - - if (!key) - return nil; - - id object = nil; - NSURL *fileURL = nil; - - [self lock]; - fileURL = [self _locked_encodedFileURLForKey:key]; - object = nil; - - if ([[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]] && - // If the cache should behave like a TTL cache, then only fetch the object if there's a valid ageLimit and the object is still alive - (!self->_ttlCache || self->_ageLimit <= 0 || fabs([[_dates objectForKey:key] timeIntervalSinceDate:now]) < self->_ageLimit)) { - NSData *objectData = [[NSData alloc] initWithContentsOfFile:[fileURL path]]; - - //Be careful with locking below. We unlock here so that we're not locked while deserializing, we re-lock after. - [self unlock]; - @try { - object = _deserializer(objectData); - } - @catch (NSException *exception) { - NSError *error = nil; - [self lock]; - [[NSFileManager defaultManager] removeItemAtPath:[fileURL path] error:&error]; - [self unlock]; - PINDiskCacheError(error); - } - [self lock]; - if (!self->_ttlCache) { - [self _locked_setFileModificationDate:now forURL:fileURL]; - } - } - [self unlock]; - - if (outFileURL) { - *outFileURL = fileURL; - } - - return object; -} - -/// Helper function to call fileURLForKey:updateFileModificationDate: -- (NSURL *)fileURLForKey:(NSString *)key -{ - // Don't update the file modification time, if self is a ttlCache - return [self fileURLForKey:key updateFileModificationDate:!self->_ttlCache]; -} - -- (NSURL *)fileURLForKey:(NSString *)key updateFileModificationDate:(BOOL)updateFileModificationDate -{ - if (!key) { - return nil; - } - - NSDate *now = [[NSDate alloc] init]; - NSURL *fileURL = nil; - - [self lock]; - fileURL = [self _locked_encodedFileURLForKey:key]; - - if ([[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]]) { - if (updateFileModificationDate) { - [self _locked_setFileModificationDate:now forURL:fileURL]; - } - } else { - fileURL = nil; - } - [self unlock]; - return fileURL; -} - -- (void)setObject:(id )object forKey:(NSString *)key -{ - [self setObject:object forKey:key fileURL:nil]; -} - -- (void)setObject:(id)object forKeyedSubscript:(NSString *)key -{ - [self setObject:object forKey:key]; -} - -- (void)setObject:(id )object forKey:(NSString *)key fileURL:(NSURL **)outFileURL -{ - NSDate *now = [[NSDate alloc] init]; - - if (!key || !object) - return; - - #if TARGET_OS_IPHONE - NSDataWritingOptions writeOptions = NSDataWritingAtomic | self.writingProtectionOption; - #else - NSDataWritingOptions writeOptions = NSDataWritingAtomic; - #endif - - NSURL *fileURL = nil; - - [self lock]; - fileURL = [self _locked_encodedFileURLForKey:key]; - - PINDiskCacheObjectBlock willAddObjectBlock = self->_willAddObjectBlock; - if (willAddObjectBlock) { - [self unlock]; - willAddObjectBlock(self, key, object); - [self lock]; - } - - //We unlock here so that we're not locked while serializing. - [self unlock]; - NSData *data = _serializer(object); - [self lock]; - - NSError *writeError = nil; - - BOOL written = [data writeToURL:fileURL options:writeOptions error:&writeError]; - PINDiskCacheError(writeError); - - if (written) { - [self _locked_setFileModificationDate:now forURL:fileURL]; - - NSError *error = nil; - NSDictionary *values = [fileURL resourceValuesForKeys:@[ NSURLTotalFileAllocatedSizeKey ] error:&error]; - PINDiskCacheError(error); - - NSNumber *diskFileSize = [values objectForKey:NSURLTotalFileAllocatedSizeKey]; - if (diskFileSize) { - NSNumber *prevDiskFileSize = [self->_sizes objectForKey:key]; - if (prevDiskFileSize) { - self.byteCount = self->_byteCount - [prevDiskFileSize unsignedIntegerValue]; - } - [self->_sizes setObject:diskFileSize forKey:key]; - self.byteCount = self->_byteCount + [diskFileSize unsignedIntegerValue]; // atomic - } - - if (self->_byteLimit > 0 && self->_byteCount > self->_byteLimit) - [self trimToSizeByDate:self->_byteLimit block:nil]; - } else { - fileURL = nil; - } - - PINDiskCacheObjectBlock didAddObjectBlock = self->_didAddObjectBlock; - if (didAddObjectBlock) { - [self unlock]; - didAddObjectBlock(self, key, object); - [self lock]; - } - [self unlock]; - - if (outFileURL) { - *outFileURL = fileURL; - } -} - -- (void)removeObjectForKey:(NSString *)key -{ - [self removeObjectForKey:key fileURL:nil]; -} - -- (void)removeObjectForKey:(NSString *)key fileURL:(NSURL **)outFileURL -{ - if (!key) - return; - - NSURL *fileURL = nil; - - [self lock]; - fileURL = [self _locked_encodedFileURLForKey:key]; - [self unlock]; - - [self removeFileAndExecuteBlocksForKey:key]; - - if (outFileURL) { - *outFileURL = fileURL; - } -} - -- (void)trimToSize:(NSUInteger)trimByteCount -{ - if (trimByteCount == 0) { - [self removeAllObjects]; - return; - } - - [self trimDiskToSize:trimByteCount]; -} - -- (void)trimToDate:(NSDate *)trimDate -{ - if (!trimDate) - return; - - if ([trimDate isEqualToDate:[NSDate distantPast]]) { - [self removeAllObjects]; - return; - } - - [self trimDiskToDate:trimDate]; -} - -- (void)trimToSizeByDate:(NSUInteger)trimByteCount -{ - if (trimByteCount == 0) { - [self removeAllObjects]; - return; - } - - [self trimDiskToSizeByDate:trimByteCount]; -} - -- (void)removeAllObjects -{ - [self lock]; - PINDiskCacheBlock willRemoveAllObjectsBlock = self->_willRemoveAllObjectsBlock; - if (willRemoveAllObjectsBlock) { - [self unlock]; - willRemoveAllObjectsBlock(self); - [self lock]; - } - - [PINDiskCache moveItemAtURLToTrash:self->_cacheURL]; - [PINDiskCache emptyTrash]; - - [self _locked_createCacheDirectory]; - - [self->_dates removeAllObjects]; - [self->_sizes removeAllObjects]; - self.byteCount = 0; // atomic - - PINDiskCacheBlock didRemoveAllObjectsBlock = self->_didRemoveAllObjectsBlock; - if (didRemoveAllObjectsBlock) { - [self unlock]; - didRemoveAllObjectsBlock(self); - [self lock]; - } - - [self unlock]; -} - -- (void)enumerateObjectsWithBlock:(PINDiskCacheFileURLBlock)block -{ - if (!block) - return; - - [self lock]; - NSDate *now = [NSDate date]; - NSArray *keysSortedByDate = [self->_dates keysSortedByValueUsingSelector:@selector(compare:)]; - - for (NSString *key in keysSortedByDate) { - NSURL *fileURL = [self _locked_encodedFileURLForKey:key]; - // If the cache should behave like a TTL cache, then only fetch the object if there's a valid ageLimit and the object is still alive - if (!self->_ttlCache || self->_ageLimit <= 0 || fabs([[_dates objectForKey:key] timeIntervalSinceDate:now]) < self->_ageLimit) { - block(key, fileURL); - } - } - [self unlock]; -} - -#pragma mark - Public Thread Safe Accessors - - -- (PINDiskCacheObjectBlock)willAddObjectBlock -{ - PINDiskCacheObjectBlock block = nil; - - [self lock]; - block = _willAddObjectBlock; - [self unlock]; - - return block; -} - -- (void)setWillAddObjectBlock:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - [strongSelf lock]; - strongSelf->_willAddObjectBlock = [block copy]; - [strongSelf unlock]; - }); -} - -- (PINDiskCacheObjectBlock)willRemoveObjectBlock -{ - PINDiskCacheObjectBlock block = nil; - - [self lock]; - block = _willRemoveObjectBlock; - [self unlock]; - - return block; -} - -- (void)setWillRemoveObjectBlock:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_willRemoveObjectBlock = [block copy]; - [strongSelf unlock]; - }); -} - -- (PINDiskCacheBlock)willRemoveAllObjectsBlock -{ - PINDiskCacheBlock block = nil; - - [self lock]; - block = _willRemoveAllObjectsBlock; - [self unlock]; - - return block; -} - -- (void)setWillRemoveAllObjectsBlock:(PINDiskCacheBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_willRemoveAllObjectsBlock = [block copy]; - [strongSelf unlock]; - }); -} - -- (PINDiskCacheObjectBlock)didAddObjectBlock -{ - PINDiskCacheObjectBlock block = nil; - - [self lock]; - block = _didAddObjectBlock; - [self unlock]; - - return block; -} - -- (void)setDidAddObjectBlock:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_didAddObjectBlock = [block copy]; - [strongSelf unlock]; - }); -} - -- (PINDiskCacheObjectBlock)didRemoveObjectBlock -{ - PINDiskCacheObjectBlock block = nil; - - [self lock]; - block = _didRemoveObjectBlock; - [self unlock]; - - return block; -} - -- (void)setDidRemoveObjectBlock:(PINDiskCacheObjectBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_didRemoveObjectBlock = [block copy]; - [strongSelf unlock]; - }); -} - -- (PINDiskCacheBlock)didRemoveAllObjectsBlock -{ - PINDiskCacheBlock block = nil; - - [self lock]; - block = _didRemoveAllObjectsBlock; - [self unlock]; - - return block; -} - -- (void)setDidRemoveAllObjectsBlock:(PINDiskCacheBlock)block -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_didRemoveAllObjectsBlock = [block copy]; - [strongSelf unlock]; - }); -} - -- (NSUInteger)byteLimit -{ - NSUInteger byteLimit; - - [self lock]; - byteLimit = _byteLimit; - [self unlock]; - - return byteLimit; -} - -- (void)setByteLimit:(NSUInteger)byteLimit -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_byteLimit = byteLimit; - [strongSelf unlock]; - - if (byteLimit > 0) - [strongSelf trimDiskToSizeByDate:byteLimit]; - }); -} - -- (NSTimeInterval)ageLimit -{ - NSTimeInterval ageLimit; - - [self lock]; - ageLimit = _ageLimit; - [self unlock]; - - return ageLimit; -} - -- (void)setAgeLimit:(NSTimeInterval)ageLimit -{ - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_ageLimit = ageLimit; - [strongSelf unlock]; - - [strongSelf trimToAgeLimitRecursively]; - }); -} - -- (BOOL)isTTLCache { - BOOL isTTLCache; - - [self lock]; - isTTLCache = _ttlCache; - [self unlock]; - - return isTTLCache; -} - -- (void)setTtlCache:(BOOL)ttlCache { - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - [strongSelf lock]; - strongSelf->_ttlCache = ttlCache; - [strongSelf unlock]; - }); -} - -#if TARGET_OS_IPHONE -- (NSDataWritingOptions)writingProtectionOption { - NSDataWritingOptions option; - - [self lock]; - option = _writingProtectionOption; - [self unlock]; - - return option; -} - -- (void)setWritingProtectionOption:(NSDataWritingOptions)writingProtectionOption { - __weak PINDiskCache *weakSelf = self; - - dispatch_async(_asyncQueue, ^{ - PINDiskCache *strongSelf = weakSelf; - if (!strongSelf) - return; - - NSDataWritingOptions option = NSDataWritingFileProtectionMask & writingProtectionOption; - - [strongSelf lock]; - strongSelf->_writingProtectionOption = option; - [strongSelf unlock]; - }); -} -#endif - -- (void)lock -{ - [_instanceLock lockWhenCondition:PINDiskCacheConditionReady]; -} - -- (void)unlock -{ - [_instanceLock unlockWithCondition:PINDiskCacheConditionReady]; -} - -@end diff --git a/Example/Pods/PINCache/PINCache/PINMemoryCache.h b/Example/Pods/PINCache/PINCache/PINMemoryCache.h deleted file mode 100644 index 507122bb..00000000 --- a/Example/Pods/PINCache/PINCache/PINMemoryCache.h +++ /dev/null @@ -1,361 +0,0 @@ -// PINCache is a modified version of TMCache -// Modifications by Garrett Moon -// Copyright (c) 2015 Pinterest. All rights reserved. - -#import -#import "Nullability.h" - -#import "PINCacheObjectSubscripting.h" - -NS_ASSUME_NONNULL_BEGIN - -@class PINMemoryCache; - -/** - A callback block which provides only the cache as an argument - */ -typedef void (^PINMemoryCacheBlock)(PINMemoryCache *cache); - -/** - A callback block which provides the cache, key and object as arguments - */ -typedef void (^PINMemoryCacheObjectBlock)(PINMemoryCache *cache, NSString *key, id __nullable object); - -/** - A callback block which provides a BOOL value as argument - */ -typedef void (^PINMemoryCacheContainmentBlock)(BOOL containsObject); - - -/** - `PINMemoryCache` is a fast, thread safe key/value store similar to `NSCache`. On iOS it will clear itself - automatically to reduce memory usage when the app receives a memory warning or goes into the background. - - Access is natively synchronous. Asynchronous variations are provided. Every asynchronous method accepts a - callback block that runs on a concurrent , with cache reads and writes protected by an semaphore. - - All access to the cache is dated so the that the least-used objects can be trimmed first. Setting an - optional will trigger a GCD timer to periodically to trim the cache to that age. - - Objects can optionally be set with a "cost", which could be a byte count or any other meaningful integer. - Setting a will automatically keep the cache below that value with . - - Values will not persist after application relaunch or returning from the background. See for - a memory cache backed by a disk cache. - */ - -@interface PINMemoryCache : NSObject - -#pragma mark - -/// @name Core - -/** - A concurrent queue on which all callbacks are called. It is exposed here so that it can be set to - target some other queue, such as a global concurrent queue with a priority other than the default. - */ -@property (readonly) dispatch_queue_t concurrentQueue; - -/** - The total accumulated cost. - */ -@property (readonly) NSUInteger totalCost; - -/** - The maximum cost allowed to accumulate before objects begin to be removed with . - */ -@property (assign) NSUInteger costLimit; - -/** - The maximum number of seconds an object is allowed to exist in the cache. Setting this to a value - greater than `0.0` will start a recurring GCD timer with the same period that calls . - Setting it back to `0.0` will stop the timer. Defaults to `0.0`. - */ -@property (assign) NSTimeInterval ageLimit; - -/** - If ttlCache is YES, the cache behaves like a ttlCache. This means that once an object enters the - cache, it only lives as long as self.ageLimit. This has the following implications: - - Accessing an object in the cache does not extend that object's lifetime in the cache - - When attempting to access an object in the cache that has lived longer than self.ageLimit, - the cache will behave as if the object does not exist - - */ -@property (nonatomic, assign, getter=isTTLCache) BOOL ttlCache; - -/** - When `YES` on iOS the cache will remove all objects when the app receives a memory warning. - Defaults to `YES`. - */ -@property (assign) BOOL removeAllObjectsOnMemoryWarning; - -/** - When `YES` on iOS the cache will remove all objects when the app enters the background. - Defaults to `YES`. - */ -@property (assign) BOOL removeAllObjectsOnEnteringBackground; - -#pragma mark - -/// @name Event Blocks - -/** - A block to be executed just before an object is added to the cache. This block will be excuted within - a lock, i.e. all reads and writes are suspended for the duration of the block. - Calling synchronous methods on the cache within this callback will likely cause a deadlock. - */ -@property (copy) PINMemoryCacheObjectBlock __nullable willAddObjectBlock; - -/** - A block to be executed just before an object is removed from the cache. This block will be excuted - within a lock, i.e. all reads and writes are suspended for the duration of the block. - Calling synchronous methods on the cache within this callback will likely cause a deadlock. - */ -@property (copy) PINMemoryCacheObjectBlock __nullable willRemoveObjectBlock; - -/** - A block to be executed just before all objects are removed from the cache as a result of . - This block will be excuted within a lock, i.e. all reads and writes are suspended for the duration of the block. - Calling synchronous methods on the cache within this callback will likely cause a deadlock. - */ -@property (copy) PINMemoryCacheBlock __nullable willRemoveAllObjectsBlock; - -/** - A block to be executed just after an object is added to the cache. This block will be excuted within - a lock, i.e. all reads and writes are suspended for the duration of the block. - Calling synchronous methods on the cache within this callback will likely cause a deadlock. - */ -@property (copy) PINMemoryCacheObjectBlock __nullable didAddObjectBlock; - -/** - A block to be executed just after an object is removed from the cache. This block will be excuted - within a lock, i.e. all reads and writes are suspended for the duration of the block. - Calling synchronous methods on the cache within this callback will likely cause a deadlock. - */ -@property (copy) PINMemoryCacheObjectBlock __nullable didRemoveObjectBlock; - -/** - A block to be executed just after all objects are removed from the cache as a result of . - This block will be excuted within a lock, i.e. all reads and writes are suspended for the duration of the block. - Calling synchronous methods on the cache within this callback will likely cause a deadlock. - */ -@property (copy) PINMemoryCacheBlock __nullable didRemoveAllObjectsBlock; - -/** - A block to be executed upon receiving a memory warning (iOS only) potentially in parallel with other blocks on the . - This block will be executed regardless of the value of . Defaults to `nil`. - */ -@property (copy) PINMemoryCacheBlock __nullable didReceiveMemoryWarningBlock; - -/** - A block to be executed when the app enters the background (iOS only) potentially in parallel with other blocks on the . - This block will be executed regardless of the value of . Defaults to `nil`. - */ -@property (copy) PINMemoryCacheBlock __nullable didEnterBackgroundBlock; - -#pragma mark - -/// @name Shared Cache - -/** - A shared cache. - - @result The shared singleton cache instance. - */ -+ (instancetype)sharedCache; - -#pragma mark - -/// @name Asynchronous Methods - -/** - This method determines whether an object is present for the given key in the cache. This method returns immediately - and executes the passed block after the object is available, potentially in parallel with other blocks on the - . - - @see containsObjectForKey: - @param key The key associated with the object. - @param block A block to be executed concurrently after the containment check happened - */ -- (void)containsObjectForKey:(NSString *)key block:(PINMemoryCacheContainmentBlock)block; - -/** - Retrieves the object for the specified key. This method returns immediately and executes the passed - block after the object is available, potentially in parallel with other blocks on the . - - @param key The key associated with the requested object. - @param block A block to be executed concurrently when the object is available. - */ -- (void)objectForKey:(NSString *)key block:(nullable PINMemoryCacheObjectBlock)block; - -/** - Stores an object in the cache for the specified key. This method returns immediately and executes the - passed block after the object has been stored, potentially in parallel with other blocks on the . - - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - @param block A block to be executed concurrently after the object has been stored, or nil. - */ -- (void)setObject:(id)object forKey:(NSString *)key block:(nullable PINMemoryCacheObjectBlock)block; - -/** - Stores an object in the cache for the specified key and the specified cost. If the cost causes the total - to go over the the cache is trimmed (oldest objects first). This method returns immediately - and executes the passed block after the object has been stored, potentially in parallel with other blocks - on the . - - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - @param cost An amount to add to the . - @param block A block to be executed concurrently after the object has been stored, or nil. - */ -- (void)setObject:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost block:(nullable PINMemoryCacheObjectBlock)block; - -/** - Removes the object for the specified key. This method returns immediately and executes the passed - block after the object has been removed, potentially in parallel with other blocks on the . - - @param key The key associated with the object to be removed. - @param block A block to be executed concurrently after the object has been removed, or nil. - */ -- (void)removeObjectForKey:(NSString *)key block:(nullable PINMemoryCacheObjectBlock)block; - -/** - Removes all objects from the cache that have not been used since the specified date. - This method returns immediately and executes the passed block after the cache has been trimmed, - potentially in parallel with other blocks on the . - - @param date Objects that haven't been accessed since this date are removed from the cache. - @param block A block to be executed concurrently after the cache has been trimmed, or nil. - */ -- (void)trimToDate:(NSDate *)date block:(nullable PINMemoryCacheBlock)block; - -/** - Removes objects from the cache, costliest objects first, until the is below the specified - value. This method returns immediately and executes the passed block after the cache has been trimmed, - potentially in parallel with other blocks on the . - - @param cost The total accumulation allowed to remain after the cache has been trimmed. - @param block A block to be executed concurrently after the cache has been trimmed, or nil. - */ -- (void)trimToCost:(NSUInteger)cost block:(nullable PINMemoryCacheBlock)block; - -/** - Removes objects from the cache, ordered by date (least recently used first), until the is below - the specified value. This method returns immediately and executes the passed block after the cache has been - trimmed, potentially in parallel with other blocks on the . - - @param cost The total accumulation allowed to remain after the cache has been trimmed. - @param block A block to be executed concurrently after the cache has been trimmed, or nil. - */ -- (void)trimToCostByDate:(NSUInteger)cost block:(nullable PINMemoryCacheBlock)block; - -/** - Removes all objects from the cache. This method returns immediately and executes the passed block after - the cache has been cleared, potentially in parallel with other blocks on the . - - @param block A block to be executed concurrently after the cache has been cleared, or nil. - */ -- (void)removeAllObjects:(nullable PINMemoryCacheBlock)block; - -/** - Loops through all objects in the cache with reads and writes suspended. Calling serial methods which - write to the cache inside block may be unsafe and may result in a deadlock. This method returns immediately. - - @param block A block to be executed for every object in the cache. - @param completionBlock An optional block to be executed concurrently when the enumeration is complete. - */ -- (void)enumerateObjectsWithBlock:(PINMemoryCacheObjectBlock)block completionBlock:(nullable PINMemoryCacheBlock)completionBlock; - -#pragma mark - -/// @name Synchronous Methods - -/** - This method determines whether an object is present for the given key in the cache. - - @see containsObjectForKey:block: - @param key The key associated with the object. - @result YES if an object is present for the given key in the cache, otherwise NO. - */ -- (BOOL)containsObjectForKey:(NSString *)key; - -/** - Retrieves the object for the specified key. This method blocks the calling thread until the - object is available. - - @see objectForKey:block: - @param key The key associated with the object. - @result The object for the specified key. - */ -- (__nullable id)objectForKey:(nullable NSString *)key; - -/** - Stores an object in the cache for the specified key. This method blocks the calling thread until the object - has been set. - - @see setObject:forKey:block: - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - */ -- (void)setObject:(id)object forKey:(NSString *)key; - -/** - Stores an object in the cache for the specified key and the specified cost. If the cost causes the total - to go over the the cache is trimmed (oldest objects first). This method blocks the calling thread - until the object has been stored. - - @param object An object to store in the cache. - @param key A key to associate with the object. This string will be copied. - @param cost An amount to add to the . - */ -- (void)setObject:(nullable id)object forKey:(nullable NSString *)key withCost:(NSUInteger)cost; - -/** - Removes the object for the specified key. This method blocks the calling thread until the object - has been removed. - - @param key The key associated with the object to be removed. - */ -- (void)removeObjectForKey:(nullable NSString *)key; - -/** - Removes all objects from the cache that have not been used since the specified date. - This method blocks the calling thread until the cache has been trimmed. - - @param date Objects that haven't been accessed since this date are removed from the cache. - */ -- (void)trimToDate:(nullable NSDate *)date; - -/** - Removes objects from the cache, costliest objects first, until the is below the specified - value. This method blocks the calling thread until the cache has been trimmed. - - @param cost The total accumulation allowed to remain after the cache has been trimmed. - */ -- (void)trimToCost:(NSUInteger)cost; - -/** - Removes objects from the cache, ordered by date (least recently used first), until the is below - the specified value. This method blocks the calling thread until the cache has been trimmed. - - @param cost The total accumulation allowed to remain after the cache has been trimmed. - */ -- (void)trimToCostByDate:(NSUInteger)cost; - -/** - Removes all objects from the cache. This method blocks the calling thread until the cache has been cleared. - */ -- (void)removeAllObjects; - -/** - Loops through all objects in the cache within a memory lock (reads and writes are suspended during the enumeration). - This method blocks the calling thread until all objects have been enumerated. - Calling synchronous methods on the cache within this callback will likely cause a deadlock. - - @param block A block to be executed for every object in the cache. - - @warning Do not call this method within the event blocks (, etc.) - Instead use the asynchronous version, . - - */ -- (void)enumerateObjectsWithBlock:(nullable PINMemoryCacheObjectBlock)block; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/PINCache/PINCache/PINMemoryCache.m b/Example/Pods/PINCache/PINCache/PINMemoryCache.m deleted file mode 100644 index a040c41f..00000000 --- a/Example/Pods/PINCache/PINCache/PINMemoryCache.m +++ /dev/null @@ -1,756 +0,0 @@ -// PINCache is a modified version of TMCache -// Modifications by Garrett Moon -// Copyright (c) 2015 Pinterest. All rights reserved. - -#import "PINMemoryCache.h" - -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 -#import -#endif - -static NSString * const PINMemoryCachePrefix = @"com.pinterest.PINMemoryCache"; - -@interface PINMemoryCache () -#if OS_OBJECT_USE_OBJC -@property (strong, nonatomic) dispatch_queue_t concurrentQueue; -@property (strong, nonatomic) dispatch_semaphore_t lockSemaphore; -#else -@property (assign, nonatomic) dispatch_queue_t concurrentQueue; -@property (assign, nonatomic) dispatch_semaphore_t lockSemaphore; -#endif -@property (strong, nonatomic) NSMutableDictionary *dictionary; -@property (strong, nonatomic) NSMutableDictionary *dates; -@property (strong, nonatomic) NSMutableDictionary *costs; -@end - -@implementation PINMemoryCache - -@synthesize ageLimit = _ageLimit; -@synthesize costLimit = _costLimit; -@synthesize totalCost = _totalCost; -@synthesize ttlCache = _ttlCache; -@synthesize willAddObjectBlock = _willAddObjectBlock; -@synthesize willRemoveObjectBlock = _willRemoveObjectBlock; -@synthesize willRemoveAllObjectsBlock = _willRemoveAllObjectsBlock; -@synthesize didAddObjectBlock = _didAddObjectBlock; -@synthesize didRemoveObjectBlock = _didRemoveObjectBlock; -@synthesize didRemoveAllObjectsBlock = _didRemoveAllObjectsBlock; -@synthesize didReceiveMemoryWarningBlock = _didReceiveMemoryWarningBlock; -@synthesize didEnterBackgroundBlock = _didEnterBackgroundBlock; - -#pragma mark - Initialization - - -- (void)dealloc -{ - [[NSNotificationCenter defaultCenter] removeObserver:self]; - - #if !OS_OBJECT_USE_OBJC - dispatch_release(_concurrentQueue); - dispatch_release(_lockSemaphore); - _concurrentQueue = nil; - #endif -} - -- (instancetype)init -{ - if (self = [super init]) { - _lockSemaphore = dispatch_semaphore_create(1); - NSString *queueName = [[NSString alloc] initWithFormat:@"%@.%p", PINMemoryCachePrefix, (void *)self]; - _concurrentQueue = dispatch_queue_create([queueName UTF8String], DISPATCH_QUEUE_CONCURRENT); - - _dictionary = [[NSMutableDictionary alloc] init]; - _dates = [[NSMutableDictionary alloc] init]; - _costs = [[NSMutableDictionary alloc] init]; - - _willAddObjectBlock = nil; - _willRemoveObjectBlock = nil; - _willRemoveAllObjectsBlock = nil; - - _didAddObjectBlock = nil; - _didRemoveObjectBlock = nil; - _didRemoveAllObjectsBlock = nil; - - _didReceiveMemoryWarningBlock = nil; - _didEnterBackgroundBlock = nil; - - _ageLimit = 0.0; - _costLimit = 0; - _totalCost = 0; - - _removeAllObjectsOnMemoryWarning = YES; - _removeAllObjectsOnEnteringBackground = YES; - -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 && !TARGET_OS_WATCH - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(didReceiveEnterBackgroundNotification:) - name:UIApplicationDidEnterBackgroundNotification - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(didReceiveMemoryWarningNotification:) - name:UIApplicationDidReceiveMemoryWarningNotification - object:nil]; - -#endif - } - return self; -} - -+ (instancetype)sharedCache -{ - static id cache; - static dispatch_once_t predicate; - - dispatch_once(&predicate, ^{ - cache = [[self alloc] init]; - }); - - return cache; -} - -#pragma mark - Private Methods - - -- (void)didReceiveMemoryWarningNotification:(NSNotification *)notification { - if (self.removeAllObjectsOnMemoryWarning) - [self removeAllObjects:nil]; - - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - if (!strongSelf) { - return; - } - - [strongSelf lock]; - PINMemoryCacheBlock didReceiveMemoryWarningBlock = strongSelf->_didReceiveMemoryWarningBlock; - [strongSelf unlock]; - - if (didReceiveMemoryWarningBlock) - didReceiveMemoryWarningBlock(strongSelf); - }); -} - -- (void)didReceiveEnterBackgroundNotification:(NSNotification *)notification -{ - if (self.removeAllObjectsOnEnteringBackground) - [self removeAllObjects:nil]; - - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - if (!strongSelf) { - return; - } - - [strongSelf lock]; - PINMemoryCacheBlock didEnterBackgroundBlock = strongSelf->_didEnterBackgroundBlock; - [strongSelf unlock]; - - if (didEnterBackgroundBlock) - didEnterBackgroundBlock(strongSelf); - }); -} - -- (void)removeObjectAndExecuteBlocksForKey:(NSString *)key -{ - [self lock]; - id object = _dictionary[key]; - NSNumber *cost = _costs[key]; - PINMemoryCacheObjectBlock willRemoveObjectBlock = _willRemoveObjectBlock; - PINMemoryCacheObjectBlock didRemoveObjectBlock = _didRemoveObjectBlock; - [self unlock]; - - if (willRemoveObjectBlock) - willRemoveObjectBlock(self, key, object); - - [self lock]; - if (cost) - _totalCost -= [cost unsignedIntegerValue]; - - [_dictionary removeObjectForKey:key]; - [_dates removeObjectForKey:key]; - [_costs removeObjectForKey:key]; - [self unlock]; - - if (didRemoveObjectBlock) - didRemoveObjectBlock(self, key, nil); -} - -- (void)trimMemoryToDate:(NSDate *)trimDate -{ - [self lock]; - NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)]; - NSDictionary *dates = [_dates copy]; - [self unlock]; - - for (NSString *key in keysSortedByDate) { // oldest objects first - NSDate *accessDate = dates[key]; - if (!accessDate) - continue; - - if ([accessDate compare:trimDate] == NSOrderedAscending) { // older than trim date - [self removeObjectAndExecuteBlocksForKey:key]; - } else { - break; - } - } -} - -- (void)trimToCostLimit:(NSUInteger)limit -{ - NSUInteger totalCost = 0; - - [self lock]; - totalCost = _totalCost; - NSArray *keysSortedByCost = [_costs keysSortedByValueUsingSelector:@selector(compare:)]; - [self unlock]; - - if (totalCost <= limit) { - return; - } - - for (NSString *key in [keysSortedByCost reverseObjectEnumerator]) { // costliest objects first - [self removeObjectAndExecuteBlocksForKey:key]; - - [self lock]; - totalCost = _totalCost; - [self unlock]; - - if (totalCost <= limit) - break; - } -} - -- (void)trimToCostLimitByDate:(NSUInteger)limit -{ - NSUInteger totalCost = 0; - - [self lock]; - totalCost = _totalCost; - NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)]; - [self unlock]; - - if (totalCost <= limit) - return; - - for (NSString *key in keysSortedByDate) { // oldest objects first - [self removeObjectAndExecuteBlocksForKey:key]; - - [self lock]; - totalCost = _totalCost; - [self unlock]; - if (totalCost <= limit) - break; - } -} - -- (void)trimToAgeLimitRecursively -{ - [self lock]; - NSTimeInterval ageLimit = _ageLimit; - [self unlock]; - - if (ageLimit == 0.0) - return; - - NSDate *date = [[NSDate alloc] initWithTimeIntervalSinceNow:-ageLimit]; - - [self trimMemoryToDate:date]; - - __weak PINMemoryCache *weakSelf = self; - - dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(ageLimit * NSEC_PER_SEC)); - dispatch_after(time, _concurrentQueue, ^(void){ - PINMemoryCache *strongSelf = weakSelf; - - [strongSelf trimToAgeLimitRecursively]; - }); -} - -#pragma mark - Public Asynchronous Methods - - -- (void)containsObjectForKey:(NSString *)key block:(PINMemoryCacheContainmentBlock)block -{ - if (!key || !block) - return; - - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - BOOL containsObject = [strongSelf containsObjectForKey:key]; - - block(containsObject); - }); -} - -- (void)objectForKey:(NSString *)key block:(PINMemoryCacheObjectBlock)block -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - id object = [strongSelf objectForKey:key]; - - if (block) - block(strongSelf, key, object); - }); -} - -- (void)setObject:(id)object forKey:(NSString *)key block:(PINMemoryCacheObjectBlock)block -{ - [self setObject:object forKey:key withCost:0 block:block]; -} - -- (void)setObject:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost block:(PINMemoryCacheObjectBlock)block -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - [strongSelf setObject:object forKey:key withCost:cost]; - - if (block) - block(strongSelf, key, object); - }); -} - -- (void)removeObjectForKey:(NSString *)key block:(PINMemoryCacheObjectBlock)block -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - [strongSelf removeObjectForKey:key]; - - if (block) - block(strongSelf, key, nil); - }); -} - -- (void)trimToDate:(NSDate *)trimDate block:(PINMemoryCacheBlock)block -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - [strongSelf trimToDate:trimDate]; - - if (block) - block(strongSelf); - }); -} - -- (void)trimToCost:(NSUInteger)cost block:(PINMemoryCacheBlock)block -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - [strongSelf trimToCost:cost]; - - if (block) - block(strongSelf); - }); -} - -- (void)trimToCostByDate:(NSUInteger)cost block:(PINMemoryCacheBlock)block -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - [strongSelf trimToCostByDate:cost]; - - if (block) - block(strongSelf); - }); -} - -- (void)removeAllObjects:(PINMemoryCacheBlock)block -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - [strongSelf removeAllObjects]; - - if (block) - block(strongSelf); - }); -} - -- (void)enumerateObjectsWithBlock:(PINMemoryCacheObjectBlock)block completionBlock:(PINMemoryCacheBlock)completionBlock -{ - __weak PINMemoryCache *weakSelf = self; - - dispatch_async(_concurrentQueue, ^{ - PINMemoryCache *strongSelf = weakSelf; - [strongSelf enumerateObjectsWithBlock:block]; - - if (completionBlock) - completionBlock(strongSelf); - }); -} - -#pragma mark - Public Synchronous Methods - - -- (BOOL)containsObjectForKey:(NSString *)key -{ - if (!key) - return NO; - - [self lock]; - BOOL containsObject = (_dictionary[key] != nil); - [self unlock]; - return containsObject; -} - -- (__nullable id)objectForKey:(NSString *)key -{ - if (!key) - return nil; - - NSDate *now = [[NSDate alloc] init]; - [self lock]; - id object = nil; - // If the cache should behave like a TTL cache, then only fetch the object if there's a valid ageLimit and the object is still alive - if (!self->_ttlCache || self->_ageLimit <= 0 || fabs([[_dates objectForKey:key] timeIntervalSinceDate:now]) < self->_ageLimit) { - object = _dictionary[key]; - } - [self unlock]; - - if (object) { - [self lock]; - _dates[key] = now; - [self unlock]; - } - - return object; -} - -- (id)objectForKeyedSubscript:(NSString *)key -{ - return [self objectForKey:key]; -} - -- (void)setObject:(id)object forKey:(NSString *)key -{ - [self setObject:object forKey:key withCost:0]; -} - -- (void)setObject:(id)object forKeyedSubscript:(NSString *)key -{ - [self setObject:object forKey:key]; -} - -- (void)setObject:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost -{ - if (!key || !object) - return; - - [self lock]; - PINMemoryCacheObjectBlock willAddObjectBlock = _willAddObjectBlock; - PINMemoryCacheObjectBlock didAddObjectBlock = _didAddObjectBlock; - NSUInteger costLimit = _costLimit; - [self unlock]; - - if (willAddObjectBlock) - willAddObjectBlock(self, key, object); - - [self lock]; - NSNumber* oldCost = _costs[key]; - if (oldCost) - _totalCost -= [oldCost unsignedIntegerValue]; - - _dictionary[key] = object; - _dates[key] = [[NSDate alloc] init]; - _costs[key] = @(cost); - - _totalCost += cost; - [self unlock]; - - if (didAddObjectBlock) - didAddObjectBlock(self, key, object); - - if (costLimit > 0) - [self trimToCostByDate:costLimit]; -} - -- (void)removeObjectForKey:(NSString *)key -{ - if (!key) - return; - - [self removeObjectAndExecuteBlocksForKey:key]; -} - -- (void)trimToDate:(NSDate *)trimDate -{ - if (!trimDate) - return; - - if ([trimDate isEqualToDate:[NSDate distantPast]]) { - [self removeAllObjects]; - return; - } - - [self trimMemoryToDate:trimDate]; -} - -- (void)trimToCost:(NSUInteger)cost -{ - [self trimToCostLimit:cost]; -} - -- (void)trimToCostByDate:(NSUInteger)cost -{ - [self trimToCostLimitByDate:cost]; -} - -- (void)removeAllObjects -{ - [self lock]; - PINMemoryCacheBlock willRemoveAllObjectsBlock = _willRemoveAllObjectsBlock; - PINMemoryCacheBlock didRemoveAllObjectsBlock = _didRemoveAllObjectsBlock; - [self unlock]; - - if (willRemoveAllObjectsBlock) - willRemoveAllObjectsBlock(self); - - [self lock]; - [_dictionary removeAllObjects]; - [_dates removeAllObjects]; - [_costs removeAllObjects]; - - _totalCost = 0; - [self unlock]; - - if (didRemoveAllObjectsBlock) - didRemoveAllObjectsBlock(self); - -} - -- (void)enumerateObjectsWithBlock:(PINMemoryCacheObjectBlock)block -{ - if (!block) - return; - - [self lock]; - NSDate *now = [[NSDate alloc] init]; - NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)]; - - for (NSString *key in keysSortedByDate) { - // If the cache should behave like a TTL cache, then only fetch the object if there's a valid ageLimit and the object is still alive - if (!self->_ttlCache || self->_ageLimit <= 0 || fabs([[_dates objectForKey:key] timeIntervalSinceDate:now]) < self->_ageLimit) { - block(self, key, _dictionary[key]); - } - } - [self unlock]; -} - -#pragma mark - Public Thread Safe Accessors - - -- (PINMemoryCacheObjectBlock)willAddObjectBlock -{ - [self lock]; - PINMemoryCacheObjectBlock block = _willAddObjectBlock; - [self unlock]; - - return block; -} - -- (void)setWillAddObjectBlock:(PINMemoryCacheObjectBlock)block -{ - [self lock]; - _willAddObjectBlock = [block copy]; - [self unlock]; -} - -- (PINMemoryCacheObjectBlock)willRemoveObjectBlock -{ - [self lock]; - PINMemoryCacheObjectBlock block = _willRemoveObjectBlock; - [self unlock]; - - return block; -} - -- (void)setWillRemoveObjectBlock:(PINMemoryCacheObjectBlock)block -{ - [self lock]; - _willRemoveObjectBlock = [block copy]; - [self unlock]; -} - -- (PINMemoryCacheBlock)willRemoveAllObjectsBlock -{ - [self lock]; - PINMemoryCacheBlock block = _willRemoveAllObjectsBlock; - [self unlock]; - - return block; -} - -- (void)setWillRemoveAllObjectsBlock:(PINMemoryCacheBlock)block -{ - [self lock]; - _willRemoveAllObjectsBlock = [block copy]; - [self unlock]; -} - -- (PINMemoryCacheObjectBlock)didAddObjectBlock -{ - [self lock]; - PINMemoryCacheObjectBlock block = _didAddObjectBlock; - [self unlock]; - - return block; -} - -- (void)setDidAddObjectBlock:(PINMemoryCacheObjectBlock)block -{ - [self lock]; - _didAddObjectBlock = [block copy]; - [self unlock]; -} - -- (PINMemoryCacheObjectBlock)didRemoveObjectBlock -{ - [self lock]; - PINMemoryCacheObjectBlock block = _didRemoveObjectBlock; - [self unlock]; - - return block; -} - -- (void)setDidRemoveObjectBlock:(PINMemoryCacheObjectBlock)block -{ - [self lock]; - _didRemoveObjectBlock = [block copy]; - [self unlock]; -} - -- (PINMemoryCacheBlock)didRemoveAllObjectsBlock -{ - [self lock]; - PINMemoryCacheBlock block = _didRemoveAllObjectsBlock; - [self unlock]; - - return block; -} - -- (void)setDidRemoveAllObjectsBlock:(PINMemoryCacheBlock)block -{ - [self lock]; - _didRemoveAllObjectsBlock = [block copy]; - [self unlock]; -} - -- (PINMemoryCacheBlock)didReceiveMemoryWarningBlock -{ - [self lock]; - PINMemoryCacheBlock block = _didReceiveMemoryWarningBlock; - [self unlock]; - - return block; -} - -- (void)setDidReceiveMemoryWarningBlock:(PINMemoryCacheBlock)block -{ - [self lock]; - _didReceiveMemoryWarningBlock = [block copy]; - [self unlock]; -} - -- (PINMemoryCacheBlock)didEnterBackgroundBlock -{ - [self lock]; - PINMemoryCacheBlock block = _didEnterBackgroundBlock; - [self unlock]; - - return block; -} - -- (void)setDidEnterBackgroundBlock:(PINMemoryCacheBlock)block -{ - [self lock]; - _didEnterBackgroundBlock = [block copy]; - [self unlock]; -} - -- (NSTimeInterval)ageLimit -{ - [self lock]; - NSTimeInterval ageLimit = _ageLimit; - [self unlock]; - - return ageLimit; -} - -- (void)setAgeLimit:(NSTimeInterval)ageLimit -{ - [self lock]; - _ageLimit = ageLimit; - [self unlock]; - - [self trimToAgeLimitRecursively]; -} - -- (NSUInteger)costLimit -{ - [self lock]; - NSUInteger costLimit = _costLimit; - [self unlock]; - - return costLimit; -} - -- (void)setCostLimit:(NSUInteger)costLimit -{ - [self lock]; - _costLimit = costLimit; - [self unlock]; - - if (costLimit > 0) - [self trimToCostLimitByDate:costLimit]; -} - -- (NSUInteger)totalCost -{ - [self lock]; - NSUInteger cost = _totalCost; - [self unlock]; - - return cost; -} - -- (BOOL)isTTLCache { - BOOL isTTLCache; - - [self lock]; - isTTLCache = _ttlCache; - [self unlock]; - - return isTTLCache; -} - -- (void)setTtlCache:(BOOL)ttlCache { - [self lock]; - _ttlCache = ttlCache; - [self unlock]; -} - - -- (void)lock -{ - dispatch_semaphore_wait(_lockSemaphore, DISPATCH_TIME_FOREVER); -} - -- (void)unlock -{ - dispatch_semaphore_signal(_lockSemaphore); -} - -@end diff --git a/Example/Pods/PINCache/README.md b/Example/Pods/PINCache/README.md deleted file mode 100644 index f1701c0f..00000000 --- a/Example/Pods/PINCache/README.md +++ /dev/null @@ -1,76 +0,0 @@ -# PINCache - -[![CocoaPods](https://img.shields.io/cocoapods/v/PINCache.svg)](http://cocoadocs.org/docsets/PINCache/) -[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) -[![Tavis CI build](https://img.shields.io/travis/pinterest/PINCache.svg?style=flat)](https://travis-ci.org/pinterest/PINCache) - -## Fast, non-deadlocking parallel object cache for iOS and OS X. - -[PINCache](PINCache/PINCache.h) is a fork of [TMCache](https://github.com/tumblr/TMCache) re-architected to fix issues with deadlocking caused by heavy use. It is a key/value store designed for persisting temporary objects that are expensive to reproduce, such as downloaded data or the results of slow processing. It is comprised of two self-similar stores, one in memory ([PINMemoryCache](PINCache/PINMemoryCache.h)) and one on disk ([PINDiskCache](PINCache/PINDiskCache.h)), all backed by GCD and safe to access from multiple threads simultaneously. On iOS, `PINMemoryCache` will clear itself when the app receives a memory warning or goes into the background. Objects stored in `PINDiskCache` remain until you trim the cache yourself, either manually or by setting a byte or age limit. - -`PINCache` and `PINDiskCache` accept any object conforming to [NSCoding](https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Protocols/NSCoding_Protocol/Reference/Reference.html). Put things in like this: - -```objective-c -UIImage *img = [[UIImage alloc] initWithData:data scale:[[UIScreen mainScreen] scale]]; -[[PINCache sharedCache] setObject:img forKey:@"image" block:nil]; // returns immediately -``` - -Get them back out like this: - -```objective-c -[[PINCache sharedCache] objectForKey:@"image" - block:^(PINCache *cache, NSString *key, id object) { - UIImage *image = (UIImage *)object; - NSLog(@"image scale: %f", image.scale); - }]; -``` - -Both `PINMemoryCache` and PINDiskCache use locks to protect reads and writes. `PINCache` coordinates them so that objects added to memory are available immediately to other threads while being written to disk safely in the background. Both caches are public properties of `PINCache`, so it's easy to manipulate one or the other separately if necessary. - -Collections work too. Thanks to the magic of `NSKeyedArchiver`, objects repeated in a collection only occupy the space of one on disk: - -```objective-c -NSArray *images = @[ image, image, image ]; -[[PINCache sharedCache] setObject:images forKey:@"images"]; -NSLog(@"3 for the price of 1: %d", [[[PINCache sharedCache] diskCache] byteCount]); -``` - -## Installation - -### Manually - -[Download the latest tag](https://github.com/pinterest/PINCache/tags) and drag the `PINCache` folder into your Xcode project. - -Install the docs by double clicking the `.docset` file under `docs/`, or view them online at [cocoadocs.org](http://cocoadocs.org/docsets/PINCache/) - -### Git Submodule - - git submodule add https://github.com/pinterest/PINCache.git - git submodule update --init - -### CocoaPods - -Add [PINCache](http://cocoapods.org/?q=name%3APINCache) to your `Podfile` and run `pod install`. - -### Carthage - -Add the following line to your `Cartfile` and run `carthage update --platform ios`. Then follow [this instruction of Carthage](https://github.com/carthage/carthage#adding-frameworks-to-unit-tests-or-a-framework) to embed the framework. - -```github "pinterest/PINCache"``` - -## Requirements - -__PINCache__ requires iOS 5.0 or OS X 10.7 and greater. - -## Contact - -[Garrett Moon](mailto:garrett@pinterest.com) - -## License - -Copyright 2013 Tumblr, Inc. -Copyright 2015 Pinterest, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. [See the License](LICENSE.txt) for the specific language governing permissions and limitations under the License. diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj deleted file mode 100644 index 9c697990..00000000 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ /dev/null @@ -1,2904 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 0004ACF937FE0FA4DFB7A256A4A30F59 /* alpha.c in Sources */ = {isa = PBXBuildFile; fileRef = C5B27422AC5A4271569EDAE97CEB6F17 /* alpha.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 00706D32BB14BE2BAC347CF317AA7B5D /* dec_sse41.c in Sources */ = {isa = PBXBuildFile; fileRef = 0265BE2D31AEDDDF41979FBC57354C8E /* dec_sse41.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 00A6C4B53CAE3DEAC90728D2AB8F8D91 /* cost_mips32.c in Sources */ = {isa = PBXBuildFile; fileRef = B658559C59804C425D8304A290D34C1A /* cost_mips32.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 01321DB0A8FD67E1496C38227BB1235E /* thread.h in Headers */ = {isa = PBXBuildFile; fileRef = 857F62222AC5FE23021A419A6FABAE82 /* thread.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 0139332451F22B5C4A45464EE4EDA0F7 /* enc_mips_dsp_r2.c in Sources */ = {isa = PBXBuildFile; fileRef = D7825262E1FE9D97B12E0BC0EFB7C9BF /* enc_mips_dsp_r2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 01416F362E757F0567F57167ED4916B6 /* PINRemoteImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E871FDDF751BC234DC600369D73E9C77 /* PINRemoteImageManager.m */; }; - 01C9C04C0C6A49BFDAFE53A1E116A232 /* cost_mips32.c in Sources */ = {isa = PBXBuildFile; fileRef = B658559C59804C425D8304A290D34C1A /* cost_mips32.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 01CFD9C89E3270B7006FDA5521ADF3A5 /* yuv_mips_dsp_r2.c in Sources */ = {isa = PBXBuildFile; fileRef = 0F2199A6FDC473EB4F09E6EE25244613 /* yuv_mips_dsp_r2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 0292822977E874E768F17590CA0BCEFA /* cost.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CD9DEA21FB30AB73C90C0099E927785 /* cost.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 02E802429A2747CD95DCF3B4F2B3F94F /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 47EB0BBBD227E352F0C654CB221746E0 /* CoreGraphics.framework */; }; - 0376F4DA2265C0DE5723E4901224D5AC /* FLAnimatedImage-iOS8.1-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = FA9E654456C8CA829913FDD7536692A7 /* FLAnimatedImage-iOS8.1-dummy.m */; }; - 037B3677D814227A1DD16E95F947A09F /* lossless_mips_dsp_r2.c in Sources */ = {isa = PBXBuildFile; fileRef = 6CC19C6C38FE732E8FAFADB273C4B875 /* lossless_mips_dsp_r2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 0386E2E24A95A876232C98C31B276601 /* enc_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C46F1514984FFF0EAD26E2194696DFC /* enc_sse2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 04035DD1422C7000D0BEAC54D474D0DF /* PINRemoteImageCategoryManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 30C87FA0395C40393C9A5FEBD3D9A487 /* PINRemoteImageCategoryManager.m */; }; - 0407A1D69DB205904686A63F637711C9 /* PINAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CF8C86EE887925394FB2A05EB8A9E70 /* PINAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 051882A00EEDCA2EFDA3C09B67A30E99 /* upsampling_mips_dsp_r2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A4F81253F77AFADD78837236560B2D1 /* upsampling_mips_dsp_r2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 05B855FC0755EEFE24688FCA92D359D8 /* argb.c in Sources */ = {isa = PBXBuildFile; fileRef = 0BF65A93624E241BB3B897C3724E9D8A /* argb.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 0679E26FE575ED6F0023A03C6A8BA304 /* muxread.c in Sources */ = {isa = PBXBuildFile; fileRef = EBCE27BD363D770E1F68A3B7BDCF3FB2 /* muxread.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 07C0781173FC8DABC9132C218AE42962 /* PINProgressiveImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 98045C92DCC573962703686A5442A31E /* PINProgressiveImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 08797D53D626CAA42F6307F5DF97CF77 /* PINRemoteImageBasicCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 83B6BA1A6817533C3D3C05F8DE4C6EBD /* PINRemoteImageBasicCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 08C35431E87C80AAA8090F15978D6BE7 /* lossless.h in Headers */ = {isa = PBXBuildFile; fileRef = 214C7FB9ABE1F5CCDE0BC288B08841F8 /* lossless.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 08C4AC86FCC664865C06E565CB0242EF /* huffman_encode.h in Headers */ = {isa = PBXBuildFile; fileRef = 7F8C0B7D630C83F2B70F46CEA9682145 /* huffman_encode.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 0941B1D7A5A3111C716A8526CC4D38F9 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71AA8AB9E41A467B163EE7D8A94E637 /* MobileCoreServices.framework */; }; - 0A7DC3EEF5717FED5820904E554D4CB9 /* PINDiskCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 218578CA992697AB822E5806F687651E /* PINDiskCache.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 0B94300056C3B968DC0183363C5D72A8 /* alpha.c in Sources */ = {isa = PBXBuildFile; fileRef = 47C707489874CA3F2940F2443E636576 /* alpha.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 0BAE40E8A0977E62153C6563FA8B93BC /* PINCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 353C5D5A0588CE212B0F00A2C48517DD /* PINCache.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 0BBDD73AF4AF0357ABC6116A053B857A /* quant_levels_dec.c in Sources */ = {isa = PBXBuildFile; fileRef = 900B41D1104AA9D38B15556678CAA952 /* quant_levels_dec.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 0D36A73EFC1A549A612B415016DE55B9 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F653D3FC69B3BFEFC81B9DD1AA0BF75 /* Foundation.framework */; }; - 0EBA2FDF2D92DAA42BF169CA4A105D34 /* utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 37875A249C725E0B8CC778FE3CBFDBE3 /* utils.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 0EF938859AC555711FB24EF2ED55289E /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 47EB0BBBD227E352F0C654CB221746E0 /* CoreGraphics.framework */; }; - 0EFE7B96B2149B3ABE435F19D532FAF6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F653D3FC69B3BFEFC81B9DD1AA0BF75 /* Foundation.framework */; }; - 0F7D088A8C21ECEAFAC194FB72A8675B /* iterator.c in Sources */ = {isa = PBXBuildFile; fileRef = AE579CCAC15DEFDDC3800E74645F772C /* iterator.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 11302E5FC7B5F572CF52654F418F5473 /* PINRemoteImageCallbacks.m in Sources */ = {isa = PBXBuildFile; fileRef = A9A968FCDF89B17C154C9F844504FB82 /* PINRemoteImageCallbacks.m */; }; - 114DAC44289FE2BB304F13E7045F1DE4 /* filters.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C104E4BDC519CBCA922579793F444D3 /* filters.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 1163E3AB1BF4942A67743CC45F4D14B0 /* alpha_processing.c in Sources */ = {isa = PBXBuildFile; fileRef = 714789E6925BC6E7F73ACEFAF20258EB /* alpha_processing.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 12111027F7E75C535B8CF286694F5D79 /* picture.c in Sources */ = {isa = PBXBuildFile; fileRef = 607EC80E69037007634D0D09576D75E0 /* picture.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 1254DB31C52482BFA98735F8888C0DE8 /* backward_references.c in Sources */ = {isa = PBXBuildFile; fileRef = 77EF39AD51321F512B7910275CB80B19 /* backward_references.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 14761959400952201E7CC44EC7085701 /* enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 88762D83F869A7C6B664BED4DCB3C31B /* enc.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 1535AE3088841BB5B4CC4A379664D236 /* frame.c in Sources */ = {isa = PBXBuildFile; fileRef = A27E244DAE13B7010349EF92E73CB843 /* frame.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 15E1DAA228687C9AF2823FDDB1F8F211 /* quant_levels.h in Headers */ = {isa = PBXBuildFile; fileRef = 9FEE9320DDA11EA44F7EC0BEAE701CD8 /* quant_levels.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 15F0C9130112DA406EF8187C47063895 /* PINAlternateRepresentationProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B1DDAD593621215D969D96E5F5C2725 /* PINAlternateRepresentationProvider.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 16EDFACCF7F504D29E692C8A28381C00 /* PINRemoteImageCallbacks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F72C99527F0AAF04B3A624B82F080B4 /* PINRemoteImageCallbacks.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 17B6252E900DCAFC2A8DEA275D7C9D7C /* alpha_processing_mips_dsp_r2.c in Sources */ = {isa = PBXBuildFile; fileRef = 35EEAA1915188D7B44AA3552D66E37EF /* alpha_processing_mips_dsp_r2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 17BC3A5A96A98929CC8C51ED6F43FD2C /* config.c in Sources */ = {isa = PBXBuildFile; fileRef = 720EF0FAD6D5850D1E07D55056EC185C /* config.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 1823E61EDCEB47FEC4BEEF3BAB736F42 /* color_cache.h in Headers */ = {isa = PBXBuildFile; fileRef = 64AA202FCC931C3E07178134DFCF081A /* color_cache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 182DBA1D3BAB6E044A4BB71E287C0B04 /* histogram.h in Headers */ = {isa = PBXBuildFile; fileRef = 79FBFC39E41814D081F1DF303B6D4C1A /* histogram.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 183CBB52A68076C458FA6821615E532B /* PINRemoteImageMemoryContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 2407DB71ABCF28A8467E8CF5BAF27BD9 /* PINRemoteImageMemoryContainer.m */; }; - 18DFF245D401B429D27A9E9BCB44E63D /* encode.h in Headers */ = {isa = PBXBuildFile; fileRef = 2142E43008910E5C9A147EDAC81F1662 /* encode.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1903A6861A6A88FDEB9B49FFAEFADDB1 /* FLAnimatedImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AB8299DE2EE7A81F628229C2DE4475F /* FLAnimatedImageView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 190F70680CE8A93398DDEEAF10D7ACD7 /* lossless_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = 5C6A9B308BA81A975671A7F75DB8A30B /* lossless_sse2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 1918669ACF6325BE0C70E43DFBD34418 /* FLAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 558FF321A05CF84D6DD288EB5131A91A /* FLAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 196F75DB9446D2F1E0EA855FC788BF8A /* PINRemoteImageDownloadTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DFC450DABA13FA7A6DACB2563DF4EBB /* PINRemoteImageDownloadTask.m */; }; - 1AAC297FBC573AB935FF5C5792FD2789 /* webpenc.c in Sources */ = {isa = PBXBuildFile; fileRef = 6CD3BA129EC620FCE4B6A1CEFB684EBB /* webpenc.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 1AC5E4135914203B2398ECF2B4889189 /* lossless_neon.c in Sources */ = {isa = PBXBuildFile; fileRef = 1B3E18DE80BF2A17C07E6E4E0FE6EFA3 /* lossless_neon.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 1B745800A0F1A6857C65ADE97F789749 /* PINRemoteImageCategoryManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 7772A566D5A8C0E3A5857ABA92C85E3F /* PINRemoteImageCategoryManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1C0574F6F8BCBA5B07707B36857B6582 /* PINRemoteImageCallbacks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F72C99527F0AAF04B3A624B82F080B4 /* PINRemoteImageCallbacks.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1C6C66EA67129411883E00171B9BA888 /* cost.c in Sources */ = {isa = PBXBuildFile; fileRef = 32D0C42B671BE1D9F1D5969FA9335AF8 /* cost.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 1E4DEF8BDDFAD3240C77D9FD6F264EF5 /* webp.c in Sources */ = {isa = PBXBuildFile; fileRef = F51BB56D203552472AFC17DE1E99A7C3 /* webp.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 1E6C9CD6A15C8C13541F9C8C293F2A0A /* analysis.c in Sources */ = {isa = PBXBuildFile; fileRef = 53D3A890AAD5ADC707F4A9DD52D27B85 /* analysis.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 233FF6DF7BDAA71EAF70603CE91B52FA /* PINImage+WebP.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D8C8832F2576E41299095AC0BC38FD2 /* PINImage+WebP.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 234141D332CABCA79BA51DBE69F2A8C7 /* enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 88762D83F869A7C6B664BED4DCB3C31B /* enc.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 278123CE6DD2FEA944688D51DF871575 /* dec_clip_tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 41AC5A8B3E67A5B68BB3007A55D78284 /* dec_clip_tables.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 278E6E6B3482C87F50EABBD555602BC7 /* dec_clip_tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 41AC5A8B3E67A5B68BB3007A55D78284 /* dec_clip_tables.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 27EFA5A3482D9C619CB53574A4E261A3 /* bit_reader_inl.h in Headers */ = {isa = PBXBuildFile; fileRef = 012F1030350DF34F33932A2AF9828649 /* bit_reader_inl.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2818E3FECADF10CBD4BABE63BB4C6C05 /* PINRemoteImageDownloadTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DFC450DABA13FA7A6DACB2563DF4EBB /* PINRemoteImageDownloadTask.m */; }; - 28461D9798354B8921CB18787318F41A /* filters.c in Sources */ = {isa = PBXBuildFile; fileRef = 8331EC7DDFB650FEC54BD4AE78B60AD7 /* filters.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 2898963D10D3B561C4BA2EDAC17A5D49 /* upsampling.c in Sources */ = {isa = PBXBuildFile; fileRef = 0B594F7A5FFADE39C151EC797AB9F489 /* upsampling.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 2925436C1FDA37811C71C010F38EB469 /* decode.h in Headers */ = {isa = PBXBuildFile; fileRef = 178041EA65EA2643FFB1544EAD15F133 /* decode.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 29EC8E6F7ED1C97F2351F78E11A3E97E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F653D3FC69B3BFEFC81B9DD1AA0BF75 /* Foundation.framework */; }; - 2B4D7DE0E09DA6E5BB034F39477757BE /* alpha.c in Sources */ = {isa = PBXBuildFile; fileRef = C5B27422AC5A4271569EDAE97CEB6F17 /* alpha.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 2B73192B08E8F700FD1234DB236D2F19 /* dec_neon.c in Sources */ = {isa = PBXBuildFile; fileRef = CA050687E3568100E191E089C344E42D /* dec_neon.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 2BB234E3A01E64E6DD1ED7C26D23B1F5 /* FLAnimatedImageView+PINRemoteImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 80B82DA42B990E96F238039BE5A37EBA /* FLAnimatedImageView+PINRemoteImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2CE68F81FBD8DF011DE32D965F1BAC87 /* thread.c in Sources */ = {isa = PBXBuildFile; fileRef = 8B6992EF8D4ED26350612DA41B09241F /* thread.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 2DB5A7A3B6B171D2CA48154A172D3F87 /* format_constants.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C2F77853D7A7DB311300B17CE0414EF /* format_constants.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2DD920ECF72A76D115D519C6F3400BE4 /* PINCache-iOS7.1-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DB26F5092B0EA49F0FE38BC931A1651 /* PINCache-iOS7.1-dummy.m */; }; - 2E45A4CE7532311115EF575288FA561D /* PINImage+DecodedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C86AEDFA5808330AAA01B76F53B5D40 /* PINImage+DecodedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2F8A82147C7D40206AA6DBE5910A094F /* vp8li.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B3068DDEA7747A83391CB38DDA49680 /* vp8li.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 300207D3CA914A9EDA30EDC29A4A9C27 /* PINURLSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = D605ED50ACCB0380BF4F11E8FBBB1437 /* PINURLSessionManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 300C98AB1985EE5E8CEFA10EC506B1C7 /* PINMemoryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 10E39F3E241AEAEEA46F13D5AB934E8C /* PINMemoryCache.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 305D930DAE04FD91E0BDD00F9C13FD8F /* delta_palettization.h in Headers */ = {isa = PBXBuildFile; fileRef = D54ACF24CD711F57DD814116DE52868B /* delta_palettization.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 316B4323A7711C8345B7A2D816B7FF77 /* dec_mips32.c in Sources */ = {isa = PBXBuildFile; fileRef = B3AFF2FD5A705F1A6272A1CA3B5ED91D /* dec_mips32.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 3287496E843E62660A7752D09C953A46 /* muxedit.c in Sources */ = {isa = PBXBuildFile; fileRef = 9DEF2E0AF657BB3C88259ABC48CFB0F9 /* muxedit.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 35512EA79A122824670BAB158FAEF7EF /* cpu.c in Sources */ = {isa = PBXBuildFile; fileRef = AB1B0720BCB30CD11424558185D47401 /* cpu.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 35ABFD5C912308B29FB8FC29FCCD10CE /* PINImage+DecodedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = F3E75D9D8C09CBFE7162CD18A14C4716 /* PINImage+DecodedImage.m */; }; - 35FC2770A58816FBB78C98C8E2DE9C05 /* enc_mips32.c in Sources */ = {isa = PBXBuildFile; fileRef = 77A2E23106484646CA6EEBE045B82D53 /* enc_mips32.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 373169B2958A3417F4ACC3638E9ECCCC /* Pods-PINRemoteImage Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A57EB68D6EE28230332CD41E941F6F4 /* Pods-PINRemoteImage Tests-dummy.m */; }; - 38ECCA0587D751E1467EBB83F68DA283 /* PINImage+DecodedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C86AEDFA5808330AAA01B76F53B5D40 /* PINImage+DecodedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 39C7B9AAB26FC0FAFBE98768287898FE /* yuv_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = DAD64598A80EF9D1DB4CC444CD96C57A /* yuv_sse2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 39E19F20A393B1C63B10B41AD71C16F9 /* vp8enci.h in Headers */ = {isa = PBXBuildFile; fileRef = 150B366BB8208A11274B6720E4B82BAA /* vp8enci.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 39E314F38A395E500E59C87D57E74505 /* filters.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C104E4BDC519CBCA922579793F444D3 /* filters.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 3A471679E6B7BAB03549C378FEA70AB6 /* PINAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CF8C86EE887925394FB2A05EB8A9E70 /* PINAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3A9BAC7537D8E4609F3D90EDE1E14997 /* dec_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = 5213EDAF6EDAD2E561B5C6012EF83DFB /* dec_sse2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 3B0B7640B6CC3CFCB196CA4F0EAFA1DC /* thread.h in Headers */ = {isa = PBXBuildFile; fileRef = 857F62222AC5FE23021A419A6FABAE82 /* thread.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3BE939B8AB9EC737D3F5FE0420452FF1 /* lossless_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = 5C6A9B308BA81A975671A7F75DB8A30B /* lossless_sse2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 3C0A60917E3992A12B1F2E3186641F75 /* quant_levels_dec.h in Headers */ = {isa = PBXBuildFile; fileRef = A86125E733F084E0B1A4AA8C91EDDD27 /* quant_levels_dec.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3C2AF15BEA67744B23E478382828022D /* PINDiskCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 218578CA992697AB822E5806F687651E /* PINDiskCache.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 3CB23E5E062BA4493AF32DA17FC63E7F /* utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 37875A249C725E0B8CC778FE3CBFDBE3 /* utils.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3D2EAC67EA7479E2DC2462E476B7496E /* backward_references.h in Headers */ = {isa = PBXBuildFile; fileRef = E7BB4BC7DDFA7807A69CF44B1E3E608D /* backward_references.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3D84A6A24B7DA955BE7FB737ACDB0B2F /* PINCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 05CAFFE052DEC8B9F74C9E2D232E3A83 /* PINCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3ED42578F4A149E80A9274777D9AF714 /* lossless_neon.c in Sources */ = {isa = PBXBuildFile; fileRef = 1B3E18DE80BF2A17C07E6E4E0FE6EFA3 /* lossless_neon.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 3F50B17FC285869D5C75B57E90AB90A3 /* upsampling_neon.c in Sources */ = {isa = PBXBuildFile; fileRef = 3ADF044BE12A8FF02BDA7BB32E55E8CF /* upsampling_neon.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 3FEB1550337A45FA0F2665A7B262834E /* random.h in Headers */ = {isa = PBXBuildFile; fileRef = 10455FA91AE1DBB54A2B812BAF2EC295 /* random.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 40085A09349758FCED4B6F68D90D61DC /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71AA8AB9E41A467B163EE7D8A94E637 /* MobileCoreServices.framework */; }; - 40CFBA99E90B1CB882144F5EB7F5B0AD /* filters_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = 1EAAED9854572A4C16435ECE5BFAAE92 /* filters_sse2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 4242985D8BD117A05E1775D303F2476B /* FLAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0408075B9809BA3BEE318DC659E50B01 /* FLAnimatedImageView.m */; }; - 425DCFA0D00716477DB8A8FC7D58281C /* random.c in Sources */ = {isa = PBXBuildFile; fileRef = F49122722A201003F15B56C830C3975F /* random.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 4282767D193B3CE27A6B869824ECDD1D /* picture_psnr.c in Sources */ = {isa = PBXBuildFile; fileRef = E7DAC4AA6FE9F930F089DD2B2D65C7D9 /* picture_psnr.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 42BFF8402EDB88225D8F63F94D126DE3 /* PINRemoteImageMemoryContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 33EFDCCA6725B6A025C0CE6D742C9492 /* PINRemoteImageMemoryContainer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 44CFF3C31D62E323E78C8D02E4B1E5FD /* thread.c in Sources */ = {isa = PBXBuildFile; fileRef = 8B6992EF8D4ED26350612DA41B09241F /* thread.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 4527CC1EE8A20DA6D2C29316AF1EC76A /* enc_neon.c in Sources */ = {isa = PBXBuildFile; fileRef = E1F490854D571BFC20ECB670457326A9 /* enc_neon.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 4547FBB55E48F1B4C5267E239608A288 /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = D2D90BC191CC2EC32436085339B86DD1 /* utils.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 4638173489D90E8EF6CB683088BE41C0 /* NSData+ImageDetectors.h in Headers */ = {isa = PBXBuildFile; fileRef = E04B56655A37768CB856EDF81704256C /* NSData+ImageDetectors.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 479C55C08D17F8B60099B295EB19D595 /* PINRemoteImageTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 1241DFD8FFEAE74881C679C4BFAAF0CB /* PINRemoteImageTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 47A2F201AD9967E37C11E06111F55EFE /* PINRemoteLock.m in Sources */ = {isa = PBXBuildFile; fileRef = C33913D3A4FA1EBCAF451B75D9F43A0D /* PINRemoteLock.m */; }; - 483AAAD521A4A5256EDB61B4F2C28A73 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C052413F825981EA3580AD2C2BAA9225 /* Accelerate.framework */; }; - 48461B21F5BC138F7031A2BA85564775 /* bit_reader.c in Sources */ = {isa = PBXBuildFile; fileRef = C0BA43AA6C1395F449AED75547A748BA /* bit_reader.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 48843FAEA2D7A0A81721052B766824C2 /* mux_types.h in Headers */ = {isa = PBXBuildFile; fileRef = B2812CA075AF5AEC2D81F25DDFAAAF3A /* mux_types.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 48C4EBD3D0DF1E9F96B895EAA060940A /* PINRemoteImageBasicCache.m in Sources */ = {isa = PBXBuildFile; fileRef = A017B947F73B2A53533FE04E1308DBDE /* PINRemoteImageBasicCache.m */; }; - 4997017373D8173E03E43A8AF3D61EC5 /* PINMemoryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 10E39F3E241AEAEEA46F13D5AB934E8C /* PINMemoryCache.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 49CD48B01656D779912C5EC55E2ACC01 /* PINURLSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBC429BF6A1E9D5A40871BABE9F2237 /* PINURLSessionManager.m */; }; - 49F6C4CEF1D4DCA75581633ECA6CAA4F /* anim_encode.c in Sources */ = {isa = PBXBuildFile; fileRef = 92DD85B9CBF6ACB4C29AF647E7947C9E /* anim_encode.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 4B339D18D993C737483E4C36A806C277 /* PINAlternateRepresentationProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 6E90DD20CCBAD11352D18410B28108A3 /* PINAlternateRepresentationProvider.m */; }; - 4B4D2F6D1886D4BAA07D7BC59E2D9E76 /* rescaler.c in Sources */ = {isa = PBXBuildFile; fileRef = DAADAE10B9B88ED018D509CB2A93E4E9 /* rescaler.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 4BF7CEB85D682A38FF63EBB5CFEE857F /* buffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 60503AC34B0481BC03680C73779DED60 /* buffer.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 4C01DCD6002FEF2B8E92A9A7D04DE311 /* enc_sse41.c in Sources */ = {isa = PBXBuildFile; fileRef = C087C6A10F610ED0C0CB2DC0978E0685 /* enc_sse41.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 4CF9DE20683F8912C451C310E42DE533 /* picture_tools.c in Sources */ = {isa = PBXBuildFile; fileRef = 2DBA42E7A3D98AE56EF0A752F8765AFD /* picture_tools.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 4D0A7F82543ED24E4E27F8851387284E /* huffman_encode.c in Sources */ = {isa = PBXBuildFile; fileRef = A9B993243629B0A6934522A6FF8CC647 /* huffman_encode.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 4D1C122671558918E29094F9ADB11ACD /* cost.c in Sources */ = {isa = PBXBuildFile; fileRef = 32D0C42B671BE1D9F1D5969FA9335AF8 /* cost.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 4DD5238B688F4539E0B0C209723E2350 /* quant_levels.h in Headers */ = {isa = PBXBuildFile; fileRef = 9FEE9320DDA11EA44F7EC0BEAE701CD8 /* quant_levels.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4ED919292206CA5F5FBC7F89CFD8E028 /* PINAlternateRepresentationProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B1DDAD593621215D969D96E5F5C2725 /* PINAlternateRepresentationProvider.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4FAE8DE1C78EA87136D37A00C88F6780 /* PINRemoteImageProcessorTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CA9658CE46390D670244639D3A54EF0 /* PINRemoteImageProcessorTask.m */; }; - 500301738F1D2D1D116117C63EEC0B42 /* cost.h in Headers */ = {isa = PBXBuildFile; fileRef = DA4FCB1CD7EC1442C011DDD1DD4B6E6C /* cost.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 50B2CF854DD8BD3F6E99A419E71D4186 /* cpu.c in Sources */ = {isa = PBXBuildFile; fileRef = AB1B0720BCB30CD11424558185D47401 /* cpu.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 51A8033FCAEB810FD396D11DA57FAF73 /* rescaler.c in Sources */ = {isa = PBXBuildFile; fileRef = DAADAE10B9B88ED018D509CB2A93E4E9 /* rescaler.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 52E9BEA637A0A422D686839CAAB1A73E /* lossless.h in Headers */ = {isa = PBXBuildFile; fileRef = 214C7FB9ABE1F5CCDE0BC288B08841F8 /* lossless.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5339B942462742A04B3CB6535D4481D8 /* demux.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D7930163300F707135002DE80BA19E1 /* demux.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5399E1E14A183B1CCCED43E41F610E2F /* upsampling_neon.c in Sources */ = {isa = PBXBuildFile; fileRef = 3ADF044BE12A8FF02BDA7BB32E55E8CF /* upsampling_neon.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 5466829173BF0A8CC8E6E3C39E451B89 /* endian_inl.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E5C6A79473815063434E0F2E4D29520 /* endian_inl.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 55630CAC05EC2D5FB2CDB3E7E2F09E83 /* picture_rescale.c in Sources */ = {isa = PBXBuildFile; fileRef = 78CC59F8F4E9458E2D49B281A07F2229 /* picture_rescale.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 5563A40AE04CF8207AD853B5C752CAE5 /* io.c in Sources */ = {isa = PBXBuildFile; fileRef = C537E6806181C0537F4CA286FA555A5A /* io.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 55B07F19DAF75830CB8F789422749BB8 /* histogram.h in Headers */ = {isa = PBXBuildFile; fileRef = 79FBFC39E41814D081F1DF303B6D4C1A /* histogram.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 55B63EEFEC338F0703D6885E48E4CD2A /* PINCache+PINRemoteImageCaching.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E552CA74498CDAF688A643373EE5F59 /* PINCache+PINRemoteImageCaching.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 55E232E4F56C6EA756E62D6B7263CC63 /* PINRemoteImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E871FDDF751BC234DC600369D73E9C77 /* PINRemoteImageManager.m */; }; - 565751663C086EA87CC2A0AF00F7BD1D /* rescaler_mips_dsp_r2.c in Sources */ = {isa = PBXBuildFile; fileRef = 6E9A9E3F63F1FB1AD85D544D51E6E2D5 /* rescaler_mips_dsp_r2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 5696260A8E3C1BC595270AEE6C9847D5 /* PINRemoteImageDownloadTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D4FE1A5D3D51B90A4893BD4A7BC1605 /* PINRemoteImageDownloadTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 57CCF161CB211F53817D47202F915E55 /* rescaler_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = C483ACB475ACAEBE44AD18CE8117F757 /* rescaler_sse2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 57EAA3A0C15B483DFED406A39B3AC798 /* PINRemoteImageTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 49BA8E48355843D4444348D2F3CE5A2A /* PINRemoteImageTask.m */; }; - 57EBADB49B4A0F1A77DA90F42FA82AFA /* rescaler.c in Sources */ = {isa = PBXBuildFile; fileRef = 5372CA4722349B8FCC016DA0822A78F6 /* rescaler.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 5824AD89543214E55BEEC8F632638EB9 /* PINImage+WebP.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D8C8832F2576E41299095AC0BC38FD2 /* PINImage+WebP.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 58C3BAFAB1D12EE15AB3457B48B84C22 /* filters_mips_dsp_r2.c in Sources */ = {isa = PBXBuildFile; fileRef = 744BA9C83EECD0D33C50E4A9687206BE /* filters_mips_dsp_r2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 58ED89FBCE9BA701F4EE508096ADFC16 /* filters.h in Headers */ = {isa = PBXBuildFile; fileRef = CAD335962F5F3A0DD201ACF2854E987E /* filters.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 592716F81E894C06F33268C63B908846 /* muxinternal.c in Sources */ = {isa = PBXBuildFile; fileRef = 9236DE015259BB06676240163A58E8E6 /* muxinternal.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 595C0F058AF2944D717D149826A90466 /* PINRemoteImageProcessorTask.h in Headers */ = {isa = PBXBuildFile; fileRef = D2719F238686A19DAA50772AD0B24473 /* PINRemoteImageProcessorTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 59BEDDDB4610621B6436ED028FB22211 /* alpha_processing.c in Sources */ = {isa = PBXBuildFile; fileRef = 714789E6925BC6E7F73ACEFAF20258EB /* alpha_processing.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 5A12CF1B0922FCDF4F257CBEFDAEF649 /* NSData+ImageDetectors.m in Sources */ = {isa = PBXBuildFile; fileRef = 3F2100B7E15B9D7C1D70F7F01174BB81 /* NSData+ImageDetectors.m */; }; - 5A41B8B231CF1AA1DB6AF41F24D52521 /* token.c in Sources */ = {isa = PBXBuildFile; fileRef = E793145817656732EFAB73240C3E3178 /* token.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 5A57F08B79BA3D4A3FDA0321CF1F723A /* filters_mips_dsp_r2.c in Sources */ = {isa = PBXBuildFile; fileRef = 744BA9C83EECD0D33C50E4A9687206BE /* filters_mips_dsp_r2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 5A8471CDE0D1F5F0B2F0DB22C4401C36 /* filters.c in Sources */ = {isa = PBXBuildFile; fileRef = 8331EC7DDFB650FEC54BD4AE78B60AD7 /* filters.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 5AF32CAAD5793331EC0A08BAC8870AF4 /* extras.h in Headers */ = {isa = PBXBuildFile; fileRef = 5713CD0A1EDCA136A95924D0E6ACD21E /* extras.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5B4614FA1A63FF5700F4A96084F33EA9 /* bit_reader.c in Sources */ = {isa = PBXBuildFile; fileRef = C0BA43AA6C1395F449AED75547A748BA /* bit_reader.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 5B85FD81956AC86E6747E4EF27E54556 /* PINDataTaskOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = E591CFAEF5F2CD91BD71C372CB895E8D /* PINDataTaskOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5CA2BE4A2B43E3C252E2969812E25123 /* FLAnimatedImageView+PINRemoteImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 80B82DA42B990E96F238039BE5A37EBA /* FLAnimatedImageView+PINRemoteImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5CFA50816B763067E1BB9A4C71D9D2FD /* PINRemoteImageMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 0DEA87E879DA96FE8179AB7E3437FAF0 /* PINRemoteImageMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5D63496B8F9703245625375B885A9A85 /* vp8li.h in Headers */ = {isa = PBXBuildFile; fileRef = D48F573D6572748BB345FF5456AB1BFC /* vp8li.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5E34C5F7C811261D9CB512AD0DB93A7F /* muxi.h in Headers */ = {isa = PBXBuildFile; fileRef = 8FF6E5E092A0D1EF62802814D70809BF /* muxi.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5E53E88C095E65F3F7B35A46868F50B4 /* PINRemoteImageBasicCache.m in Sources */ = {isa = PBXBuildFile; fileRef = A017B947F73B2A53533FE04E1308DBDE /* PINRemoteImageBasicCache.m */; }; - 602846CB9212541EDB9D3C551AC1D30D /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D8947C70EA881CAD337102B182D2DBF /* ImageIO.framework */; }; - 61FD61EE3B19AAC78EBC98F5CA8E3B77 /* PINDiskCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 992A7463ACA2773D1A45DE756412EC26 /* PINDiskCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 62605E623FBCC88B6CCC2A75A21E1BE5 /* rescaler_neon.c in Sources */ = {isa = PBXBuildFile; fileRef = 86DF26C20099077471AFE39C0AD1273D /* rescaler_neon.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 627CC4104259CABA3A976E69AFD997DD /* dec_mips32.c in Sources */ = {isa = PBXBuildFile; fileRef = B3AFF2FD5A705F1A6272A1CA3B5ED91D /* dec_mips32.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 62968D6BB6F31472F545ADBC248DC565 /* PINRemoteImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C970CB7D9C79058AD603908B77D5EE1 /* PINRemoteImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 649F413385751CDF1DD65E670425C515 /* PINAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 38F931A84A926D8ED6C79AC8C84CCF6E /* PINAnimatedImage.m */; }; - 64A228C16AC751D267EB01164A6A95E5 /* mux.h in Headers */ = {isa = PBXBuildFile; fileRef = EB021361F2B386EF7FEA0D39AE0D0560 /* mux.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 64D73DD773D4C7B96CA63FCFDE06805F /* color_cache.c in Sources */ = {isa = PBXBuildFile; fileRef = 3B962ABB7F8EAC0B911CFD84D66A3651 /* color_cache.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 65FFAC6A25CFE46E1C158C4ECB7DB6C8 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D8947C70EA881CAD337102B182D2DBF /* ImageIO.framework */; }; - 668D9F73BA24CA3E783C6E43E7468CE8 /* FLAnimatedImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AB8299DE2EE7A81F628229C2DE4475F /* FLAnimatedImageView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 66FB057573152FF4E4C43B26E966F613 /* PINAnimatedImageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = AC5CD465E603C691E9153D025D8D2CFC /* PINAnimatedImageManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 6735CEBE028E06B31724C1624E8E0CB1 /* random.c in Sources */ = {isa = PBXBuildFile; fileRef = F49122722A201003F15B56C830C3975F /* random.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 674C2AF046083AAABAF5ABBDE99772A5 /* dec_neon.c in Sources */ = {isa = PBXBuildFile; fileRef = CA050687E3568100E191E089C344E42D /* dec_neon.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 689A3865648E64C9C85553EFCAB90D02 /* PINCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 05CAFFE052DEC8B9F74C9E2D232E3A83 /* PINCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 694D173D9B42D95CC8FA3305E094C7A1 /* PINCacheObjectSubscripting.h in Headers */ = {isa = PBXBuildFile; fileRef = D53423972590E5D0BC5B57B1EE01420B /* PINCacheObjectSubscripting.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 697578E001983C95E22F9949EBC3C8D7 /* PINRemoteImageProcessorTask.h in Headers */ = {isa = PBXBuildFile; fileRef = D2719F238686A19DAA50772AD0B24473 /* PINRemoteImageProcessorTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 69DF6F485FD847ED9004997CBF7979B2 /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = D2D90BC191CC2EC32436085339B86DD1 /* utils.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 6B0813FF01128C3A7CC7C6EE6CEA5768 /* idec.c in Sources */ = {isa = PBXBuildFile; fileRef = CDB88138419C0EE00024A6430572DA08 /* idec.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 6BA7E571FE5057213ECE1C7A77D8567C /* PINURLSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBC429BF6A1E9D5A40871BABE9F2237 /* PINURLSessionManager.m */; }; - 6C7F5880C6BD7CF532274878050EFC11 /* quant_levels.c in Sources */ = {isa = PBXBuildFile; fileRef = 2C3CB475C14C8FFDDBA319BA4426B6CD /* quant_levels.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 6D57E0EC289399A447DB096BD6E772CB /* cost_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = BFE6D9A7E95710BDA480F6AD7C2C5469 /* cost_sse2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 6E620A8221F571296F96473519B4CDEC /* lossless_enc_mips32.c in Sources */ = {isa = PBXBuildFile; fileRef = 821A415254215F905B6F728586A55DB5 /* lossless_enc_mips32.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 6FF8A5C31BA4D0087845AAAE368BC1B9 /* neon.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FD7680EFC0A084A1A1A16727F5A5DCE /* neon.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 70E15D53758C7C32841CAB2C86B8BAE3 /* PINMemoryCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 39135D20E627D5ACB184DC61598D908A /* PINMemoryCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7131881F05B82D5CAAA8E05D74DFB6FF /* PINImage+WebP.m in Sources */ = {isa = PBXBuildFile; fileRef = 64FD5BDCFA1A3C5B288A2DB7DC091DD3 /* PINImage+WebP.m */; }; - 71A457D2BFA5877BFB457C4F762DA2B8 /* mux_types.h in Headers */ = {isa = PBXBuildFile; fileRef = B2812CA075AF5AEC2D81F25DDFAAAF3A /* mux_types.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 720017A8DE59D1E43870315443628B85 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E2B417B7135F755185072BDBF019D1F5 /* QuartzCore.framework */; }; - 73F9EC75532839C78F6D17D18F5F62A5 /* encode.h in Headers */ = {isa = PBXBuildFile; fileRef = 2142E43008910E5C9A147EDAC81F1662 /* encode.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7423CFE8C2FAA7B3F5EC95D5FB2F5E63 /* huffman.h in Headers */ = {isa = PBXBuildFile; fileRef = FC2F9C0051E45C7BCEBE9E395DD25DC0 /* huffman.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 74BC4914A4B8F583015257514CD351AF /* backward_references.h in Headers */ = {isa = PBXBuildFile; fileRef = E7BB4BC7DDFA7807A69CF44B1E3E608D /* backward_references.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 74E54CEBE157B84620620BB2B799E56C /* dec_sse41.c in Sources */ = {isa = PBXBuildFile; fileRef = 0265BE2D31AEDDDF41979FBC57354C8E /* dec_sse41.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 752C801EB9448B3D377D6D5B33D23840 /* PINImageView+PINRemoteImage.h in Headers */ = {isa = PBXBuildFile; fileRef = E011E32618D10830CD0F3D25499CCCEF /* PINImageView+PINRemoteImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 76A7157DE2D8014C5798384BEF14E559 /* PINRemoteImageCaching.h in Headers */ = {isa = PBXBuildFile; fileRef = E9F82D54CEBA634D9389486AA9E39B78 /* PINRemoteImageCaching.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 77885CD9BF4CB77BC64FB00354B35522 /* FLAnimatedImage-iOS7.1-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 90FF34CEFA119D852ED6A6CC1B1B8F80 /* FLAnimatedImage-iOS7.1-dummy.m */; }; - 7972C9872960362D343FF03ADE652702 /* FLAnimatedImageView+PINRemoteImage.m in Sources */ = {isa = PBXBuildFile; fileRef = B37695D6592D08B979F213F2C003B750 /* FLAnimatedImageView+PINRemoteImage.m */; }; - 79C5DB040FEDB08BEA2FD6B757730C0D /* vp8li.h in Headers */ = {isa = PBXBuildFile; fileRef = D48F573D6572748BB345FF5456AB1BFC /* vp8li.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 79CC9D925488F7008308DA82F371E2C1 /* picture_rescale.c in Sources */ = {isa = PBXBuildFile; fileRef = 78CC59F8F4E9458E2D49B281A07F2229 /* picture_rescale.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 7AEA25ED69F14971588E4E00BE863778 /* vp8l.c in Sources */ = {isa = PBXBuildFile; fileRef = B6A8D042E929520D2B92010A79B74859 /* vp8l.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 7B8F4694F8F5166C36A6736C18960A30 /* cost.h in Headers */ = {isa = PBXBuildFile; fileRef = DA4FCB1CD7EC1442C011DDD1DD4B6E6C /* cost.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7BDB3207454D9848D986847B992B22EE /* alpha_processing_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = F5262B915274A6E95421C1E0556EC8C4 /* alpha_processing_sse2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 7BF2AE1D807E81EF09CEB41E6CC725FF /* PINRemoteImageMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 0DEA87E879DA96FE8179AB7E3437FAF0 /* PINRemoteImageMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7E25E37918730FB8001FA1A3CDA3DE9D /* PINRemoteImageBasicCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 83B6BA1A6817533C3D3C05F8DE4C6EBD /* PINRemoteImageBasicCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7EABB64FEE2D4EEFB16EE39C72A8D25C /* bit_reader.h in Headers */ = {isa = PBXBuildFile; fileRef = 975971A0FF20F488DAAE129FF6A5675F /* bit_reader.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7FEFFD16F71C2CB49D18A7675A2387D0 /* argb_mips_dsp_r2.c in Sources */ = {isa = PBXBuildFile; fileRef = B212B272786957617807DA03F5A6ACDC /* argb_mips_dsp_r2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 7FF167E680C08A069995E4FF213461AB /* PINAlternateRepresentationProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 6E90DD20CCBAD11352D18410B28108A3 /* PINAlternateRepresentationProvider.m */; }; - 80DBECFA6CDC16F0973722317817BAEC /* neon.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FD7680EFC0A084A1A1A16727F5A5DCE /* neon.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 814EBCA0538CD934B6628678567EFCDC /* PINCache+PINRemoteImageCaching.m in Sources */ = {isa = PBXBuildFile; fileRef = 7159655540FAD47DEEC9556993CCEE72 /* PINCache+PINRemoteImageCaching.m */; }; - 81A24DDCAF6DF14D20E29FF96E809BEF /* PINCacheObjectSubscripting.h in Headers */ = {isa = PBXBuildFile; fileRef = D53423972590E5D0BC5B57B1EE01420B /* PINCacheObjectSubscripting.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 82E8B2774E320367EA077956F9149333 /* lossless_enc_mips_dsp_r2.c in Sources */ = {isa = PBXBuildFile; fileRef = 5AA3AE62661D5123483F17B85E6BAF50 /* lossless_enc_mips_dsp_r2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 83A1CD6E4FF3FD51834F7781210CA863 /* PINRemoteImage-iOS7.1-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 111CFE021EA510C1C36F4E1BD9DB2555 /* PINRemoteImage-iOS7.1-dummy.m */; }; - 84A5216198BCE5F6B0A6B919B9EA24A3 /* webpi.h in Headers */ = {isa = PBXBuildFile; fileRef = 4EEB0E6DB39F528015E402B09A21080B /* webpi.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8591BFDDED0360AACC44F87E082FA6B4 /* anim_decode.c in Sources */ = {isa = PBXBuildFile; fileRef = CABC57871709587C1DF9AEFFEFE9DFEA /* anim_decode.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 85BDB71B2E2862B9DC854DE54E25122C /* PINRemoteImageManagerResult.h in Headers */ = {isa = PBXBuildFile; fileRef = B3D08B70814AF160D6E39CAA9801E8BB /* PINRemoteImageManagerResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8641E56BF6618238B52FF5E326D7806E /* lossless_enc_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = B5BDAC3604CA68F6DF3522591DA86A9D /* lossless_enc_sse2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 86534614F5ADF78140757E7B68BF96CB /* frame.c in Sources */ = {isa = PBXBuildFile; fileRef = A27E244DAE13B7010349EF92E73CB843 /* frame.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 866E39AA5AD820CE1522CA6CF79C8F03 /* quant_levels.c in Sources */ = {isa = PBXBuildFile; fileRef = 2C3CB475C14C8FFDDBA319BA4426B6CD /* quant_levels.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 87E73BB385F32AFAD4874CF2928FB6AB /* types.h in Headers */ = {isa = PBXBuildFile; fileRef = 2CFB1F82C8F950BD532D24B2D775E949 /* types.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 87FA697B6BC6883DB6971BE6AE842167 /* PINRemoteImageCaching.h in Headers */ = {isa = PBXBuildFile; fileRef = E9F82D54CEBA634D9389486AA9E39B78 /* PINRemoteImageCaching.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 882B6D25C787C0DC2750D4814DC16BAF /* enc_avx2.c in Sources */ = {isa = PBXBuildFile; fileRef = 58227BA313D46A3CDB4831FC0D7ADF54 /* enc_avx2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 88EE51389D92E218ED06CA7D5466DB84 /* yuv.c in Sources */ = {isa = PBXBuildFile; fileRef = C12B7C39A3055B7482896DE405F62894 /* yuv.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 89297D94D81DFAF4DA0536CD04112A7D /* PINRemoteLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B774580FBBDC1A0407CCFD9E6B7E981 /* PINRemoteLock.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 89B06498D4615744622FCA92305FCA06 /* decode_vp8.h in Headers */ = {isa = PBXBuildFile; fileRef = AB8D811A414E3B17A5006341065E7E53 /* decode_vp8.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8A12D3D63765EB2DF237E3F56B9F7596 /* Nullability.h in Headers */ = {isa = PBXBuildFile; fileRef = 3BDA9F9CCAAE9C786BBC5CAF0F2F873C /* Nullability.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8AEE3F14F012C4DF691B4FD302CCF4C2 /* mips_macro.h in Headers */ = {isa = PBXBuildFile; fileRef = 563F4A6251F82426B5EAB251160C8F6A /* mips_macro.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8B4C37DD5962B3D046CDEBCCED20C437 /* syntax.c in Sources */ = {isa = PBXBuildFile; fileRef = 831F56F938A172850886AC53ADDCF2AF /* syntax.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 8BC5F72DF2522FEDAB3E0A28723A86E2 /* bit_reader_inl.h in Headers */ = {isa = PBXBuildFile; fileRef = 012F1030350DF34F33932A2AF9828649 /* bit_reader_inl.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8C71E480585ABE7C3F34283A81C9C2C0 /* PINRemoteImageCallbacks.m in Sources */ = {isa = PBXBuildFile; fileRef = A9A968FCDF89B17C154C9F844504FB82 /* PINRemoteImageCallbacks.m */; }; - 8CA2EDCA8B6FDA9134C458E37EB9A8FB /* muxi.h in Headers */ = {isa = PBXBuildFile; fileRef = 8FF6E5E092A0D1EF62802814D70809BF /* muxi.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8E4DB9230B811C82A6E65054A6BB742F /* endian_inl.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E5C6A79473815063434E0F2E4D29520 /* endian_inl.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8E7C83B6D7B48B21695602FC2ECF2787 /* idec.c in Sources */ = {isa = PBXBuildFile; fileRef = CDB88138419C0EE00024A6430572DA08 /* idec.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 8EA34FED195C8342AC71AF98882ACD78 /* enc_mips_dsp_r2.c in Sources */ = {isa = PBXBuildFile; fileRef = D7825262E1FE9D97B12E0BC0EFB7C9BF /* enc_mips_dsp_r2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 8EAF427B87A2343FC061E16E19C337E9 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F653D3FC69B3BFEFC81B9DD1AA0BF75 /* Foundation.framework */; }; - 8F8EBDD6069E06AE8B356E38F8EBBBA0 /* webp.c in Sources */ = {isa = PBXBuildFile; fileRef = F51BB56D203552472AFC17DE1E99A7C3 /* webp.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 8FBDDD512523AF43A39ACBB46E9AF4DE /* syntax.c in Sources */ = {isa = PBXBuildFile; fileRef = 831F56F938A172850886AC53ADDCF2AF /* syntax.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 8FE0BE20BE29167C343BAA8CADA26FA5 /* libwebp-iOS7.1-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = D4323D23DC4D94234A4665AD09DD60C2 /* libwebp-iOS7.1-dummy.m */; }; - 90A176DBAB805266911C301D815DFE6A /* muxinternal.c in Sources */ = {isa = PBXBuildFile; fileRef = 9236DE015259BB06676240163A58E8E6 /* muxinternal.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 90FA2D3C61AD0C533AE59261AD685431 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F653D3FC69B3BFEFC81B9DD1AA0BF75 /* Foundation.framework */; }; - 91AE0CF3C6F67CB6A8F166FF13D8B57E /* color_cache.c in Sources */ = {isa = PBXBuildFile; fileRef = 3B962ABB7F8EAC0B911CFD84D66A3651 /* color_cache.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 91C32064B18B0608B3C7E644DC1EB13E /* alphai.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B4758BE6AB13C24A0835A3458E330F /* alphai.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 95B60590068F6B806928D8F7F95A697E /* yuv.h in Headers */ = {isa = PBXBuildFile; fileRef = 43D58C7F209EF668DC65D9780ADE2755 /* yuv.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 961655E9BA895F0BC91B2FD8F7638481 /* cost_mips_dsp_r2.c in Sources */ = {isa = PBXBuildFile; fileRef = 1DA7B7E3D3641D4BB5A28D94B23BB252 /* cost_mips_dsp_r2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 9634E001B76CEA45929789DD743A7FD3 /* PINRemoteImageManagerResult.m in Sources */ = {isa = PBXBuildFile; fileRef = B914244471E11A336CDF9E038E6B7EDB /* PINRemoteImageManagerResult.m */; }; - 96C0843610D0BB8FAF0104396195158C /* cost_mips_dsp_r2.c in Sources */ = {isa = PBXBuildFile; fileRef = 1DA7B7E3D3641D4BB5A28D94B23BB252 /* cost_mips_dsp_r2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 96FACE7A7E07FED39CA8053CA727580D /* delta_palettization.c in Sources */ = {isa = PBXBuildFile; fileRef = 90B25009CF8DCC27B2B1E0BDD881DE98 /* delta_palettization.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 970C17677DA372ACD183148B76643B05 /* decode_vp8.h in Headers */ = {isa = PBXBuildFile; fileRef = AB8D811A414E3B17A5006341065E7E53 /* decode_vp8.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9729451DA4E1E1DD364CBB544442AD42 /* muxread.c in Sources */ = {isa = PBXBuildFile; fileRef = EBCE27BD363D770E1F68A3B7BDCF3FB2 /* muxread.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 97844C6E07440AE25CF333BB7306B0E0 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E2B417B7135F755185072BDBF019D1F5 /* QuartzCore.framework */; }; - 97A860A44F9C02143E32528592862B7A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F653D3FC69B3BFEFC81B9DD1AA0BF75 /* Foundation.framework */; }; - 987AE0E18F015DE956ED6B75ACFE7A31 /* PINCache+PINRemoteImageCaching.m in Sources */ = {isa = PBXBuildFile; fileRef = 7159655540FAD47DEEC9556993CCEE72 /* PINCache+PINRemoteImageCaching.m */; }; - 98D54ED5DE7728F7438846023CD2664C /* analysis.c in Sources */ = {isa = PBXBuildFile; fileRef = 53D3A890AAD5ADC707F4A9DD52D27B85 /* analysis.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 99CB1DB9121CC7DFB6E4EDEA82EF1CDB /* dec_mips_dsp_r2.c in Sources */ = {isa = PBXBuildFile; fileRef = A0628BBA7F5A4531449289D2E671A622 /* dec_mips_dsp_r2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 9A0209B6C08A3075CBBCA462B669FD87 /* PINRemoteImageProcessorTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CA9658CE46390D670244639D3A54EF0 /* PINRemoteImageProcessorTask.m */; }; - 9A5856797DCBEE1E1AA22A0777A39CDE /* PINRemoteImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C970CB7D9C79058AD603908B77D5EE1 /* PINRemoteImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9AF44D87461219ACC8D8509F7A461EE0 /* lossless.c in Sources */ = {isa = PBXBuildFile; fileRef = 7215A5A771C283D41302F2FD6D751C77 /* lossless.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 9C64E2DD4F94C7FC10990B0DAF4A74BE /* PINRemoteImageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = B1C531F4782C6D93A9DDADBACAB004AC /* PINRemoteImageManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9CFC5B09D9C143C561A54F006962A19D /* rescaler_mips32.c in Sources */ = {isa = PBXBuildFile; fileRef = 5355B95420BA4CA130B1B5BC2D0006F1 /* rescaler_mips32.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 9D2E583621D62972169B27CBAF1FADEE /* PINRemoteLock.m in Sources */ = {isa = PBXBuildFile; fileRef = C33913D3A4FA1EBCAF451B75D9F43A0D /* PINRemoteLock.m */; }; - 9EE810C5E7A0788BFE48367C69F36D12 /* alpha.c in Sources */ = {isa = PBXBuildFile; fileRef = 47C707489874CA3F2940F2443E636576 /* alpha.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - 9F3DC05BC16EA7657024231E095A184D /* PINRemoteImageMemoryContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 2407DB71ABCF28A8467E8CF5BAF27BD9 /* PINRemoteImageMemoryContainer.m */; }; - A058007CAC0EE7673CF1F71ADCD89B8A /* dec_mips_dsp_r2.c in Sources */ = {isa = PBXBuildFile; fileRef = A0628BBA7F5A4531449289D2E671A622 /* dec_mips_dsp_r2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - A06ED4382D0BEF02C6525C68F30FCE77 /* picture_csp.c in Sources */ = {isa = PBXBuildFile; fileRef = 909CE73A4184F9ED818B6FD4B0C7AD5F /* picture_csp.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - A0A87C2434A7C4C4123135D8787AA957 /* vp8i.h in Headers */ = {isa = PBXBuildFile; fileRef = B4F4DE3D01E4668A8895C5133F55C194 /* vp8i.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A1C7460C23F542445882181942A657C7 /* PINImageView+PINRemoteImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A57FF868A49947361D299813C2E1BE3 /* PINImageView+PINRemoteImage.m */; }; - A24327F3811A225D0CA99154649D0FE9 /* yuv.c in Sources */ = {isa = PBXBuildFile; fileRef = C12B7C39A3055B7482896DE405F62894 /* yuv.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - A2670FCCE9721F5B775623B10D5C42F8 /* tree.c in Sources */ = {isa = PBXBuildFile; fileRef = 4802610EC3465AB540B7BA5AC1EC96C5 /* tree.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - A2797145317F8EC9F1DAF861062EC457 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C052413F825981EA3580AD2C2BAA9225 /* Accelerate.framework */; }; - A372CCB0E3C1AD3928866C7114558784 /* histogram.c in Sources */ = {isa = PBXBuildFile; fileRef = 9B00C7DEBAB917F26508F71DA81CB293 /* histogram.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - A3B4CB236BBC03345C742E4B3132EA76 /* upsampling.c in Sources */ = {isa = PBXBuildFile; fileRef = 0B594F7A5FFADE39C151EC797AB9F489 /* upsampling.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - A48E6464DD605C7FF4474A7CE9622768 /* picture_csp.c in Sources */ = {isa = PBXBuildFile; fileRef = 909CE73A4184F9ED818B6FD4B0C7AD5F /* picture_csp.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - A526184AEC7B6B261225136DD5013B06 /* alpha_processing_mips_dsp_r2.c in Sources */ = {isa = PBXBuildFile; fileRef = 35EEAA1915188D7B44AA3552D66E37EF /* alpha_processing_mips_dsp_r2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - A6090EE05BFBA88E517DE433D205B7F7 /* enc_neon.c in Sources */ = {isa = PBXBuildFile; fileRef = E1F490854D571BFC20ECB670457326A9 /* enc_neon.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - A6C480888298F0685EFBDE86E3A1AC9E /* PINDiskCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 992A7463ACA2773D1A45DE756412EC26 /* PINDiskCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A8824DA51EEDC5F5D23D71ED0CF0571A /* lossless.c in Sources */ = {isa = PBXBuildFile; fileRef = 7215A5A771C283D41302F2FD6D751C77 /* lossless.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - AA2A0060D91D856304940E9E6642A770 /* PINRemoteImageManagerResult.m in Sources */ = {isa = PBXBuildFile; fileRef = B914244471E11A336CDF9E038E6B7EDB /* PINRemoteImageManagerResult.m */; }; - AB8E217F3E50BDCFA2D36AD9131064C3 /* libwebp-iOS8.1-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = F80CC86086FB5C08BE0F5EEA364B93E1 /* libwebp-iOS8.1-dummy.m */; }; - AC0F7191B65E6682625781934C0A52DB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F653D3FC69B3BFEFC81B9DD1AA0BF75 /* Foundation.framework */; }; - AC146A0D055614D7EC12A959725C62F5 /* tree.c in Sources */ = {isa = PBXBuildFile; fileRef = 4802610EC3465AB540B7BA5AC1EC96C5 /* tree.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - AC4FFC6CCC0127BABAB4F4A666B47912 /* alphai.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B4758BE6AB13C24A0835A3458E330F /* alphai.h */; settings = {ATTRIBUTES = (Public, ); }; }; - ACBBDE6667DFA4AB9B0425A993C6F8F9 /* PINRemoteLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B774580FBBDC1A0407CCFD9E6B7E981 /* PINRemoteLock.h */; settings = {ATTRIBUTES = (Public, ); }; }; - ACD648ECA0722DA9052FA4816EB9670D /* PINButton+PINRemoteImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 1CE105A1A011FADA79F2388F6F937318 /* PINButton+PINRemoteImage.m */; }; - ADD5AC209E44FAA788E1CC993B051FF8 /* PINProgressiveImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 98045C92DCC573962703686A5442A31E /* PINProgressiveImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B0315647BBDB9BEC4C47AA9080740E89 /* vp8enci.h in Headers */ = {isa = PBXBuildFile; fileRef = 150B366BB8208A11274B6720E4B82BAA /* vp8enci.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B0318EB987AA4BE1946A77E64AFBAEC0 /* rescaler.c in Sources */ = {isa = PBXBuildFile; fileRef = 5372CA4722349B8FCC016DA0822A78F6 /* rescaler.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - B16F98BE7850AF777BAB6F926ECD06CC /* PINImageView+PINRemoteImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A57FF868A49947361D299813C2E1BE3 /* PINImageView+PINRemoteImage.m */; }; - B1C65ADCB0559F3ABA0D29A722BB4802 /* lossless_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B08BAC88FCA48253326E775CB905235 /* lossless_enc.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - B1FAB245AC046642495321FF0C508723 /* dsp.h in Headers */ = {isa = PBXBuildFile; fileRef = AB70F892215992CEE9D1201FAD7E6AA7 /* dsp.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B23829374B5267E41A409881CFD5ADE2 /* anim_encode.c in Sources */ = {isa = PBXBuildFile; fileRef = 92DD85B9CBF6ACB4C29AF647E7947C9E /* anim_encode.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - B2EA7299B6868F06B9AB6308F829005B /* demux.c in Sources */ = {isa = PBXBuildFile; fileRef = 688B52EC5BB98FF5D63599C29DFC312A /* demux.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - B41EAA65120415E42197E24DB3F33BC1 /* yuv_mips_dsp_r2.c in Sources */ = {isa = PBXBuildFile; fileRef = 0F2199A6FDC473EB4F09E6EE25244613 /* yuv_mips_dsp_r2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - B41F7A48C895353F3475106D01703CBD /* frame.c in Sources */ = {isa = PBXBuildFile; fileRef = 63C5FDB95E938EB802C2DAE3D5FEF41A /* frame.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - B449369C545A4EAD63485E55774562D9 /* PINRemoteImageTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 49BA8E48355843D4444348D2F3CE5A2A /* PINRemoteImageTask.m */; }; - B5443A45FD1D6555686D16F045BBC53F /* bit_writer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD5C78A000F1B4C9FD43E7995E11641 /* bit_writer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B561C803CCFF201902F88ADF29BFB37B /* quant.c in Sources */ = {isa = PBXBuildFile; fileRef = EF60DC1D3E1481DC9519566EC5C8D0C5 /* quant.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - B689B3E75A2005AACA373E61BEDA122B /* muxedit.c in Sources */ = {isa = PBXBuildFile; fileRef = 9DEF2E0AF657BB3C88259ABC48CFB0F9 /* muxedit.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - B6A7B123374A4BABD55DC2D5FC4077DA /* frame.c in Sources */ = {isa = PBXBuildFile; fileRef = 63C5FDB95E938EB802C2DAE3D5FEF41A /* frame.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - B6EA416AAC008BEA46E3D8FD2A15FE8A /* near_lossless.c in Sources */ = {isa = PBXBuildFile; fileRef = 1D9A6E336BC1B20D20200A15DE97FE07 /* near_lossless.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - B791A933232219A1837BE9C46C286ADB /* PINProgressiveImage.m in Sources */ = {isa = PBXBuildFile; fileRef = F706B7B31C8ECF7E9D2D8B6EC43DE601 /* PINProgressiveImage.m */; }; - B87638A8C714D553F462DFCF991DAABD /* argb_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = ADFA5305E9873E12C2940FD012BB0DFB /* argb_sse2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - B8D170956D295DD554B0C62AC6374AF3 /* lossless_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B08BAC88FCA48253326E775CB905235 /* lossless_enc.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - B963874CA4C32B72196F27CECB65FB74 /* PINImage+WebP.m in Sources */ = {isa = PBXBuildFile; fileRef = 64FD5BDCFA1A3C5B288A2DB7DC091DD3 /* PINImage+WebP.m */; }; - B97A940CEFB06ECACC9303EEC2EE67FC /* delta_palettization.h in Headers */ = {isa = PBXBuildFile; fileRef = D54ACF24CD711F57DD814116DE52868B /* delta_palettization.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BB5290ED3ED15BE895EBCE736AAE1171 /* PINRemoteImageCategoryManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 30C87FA0395C40393C9A5FEBD3D9A487 /* PINRemoteImageCategoryManager.m */; }; - BBB344B642B95D3E86BDB198371B00A8 /* PINButton+PINRemoteImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B4310C5981857705080A1761894CFCE /* PINButton+PINRemoteImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BC156835B5F8469833C3068EF0D4226C /* lossless_enc_neon.c in Sources */ = {isa = PBXBuildFile; fileRef = FE935F7066F02B06DF140D5544510623 /* lossless_enc_neon.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - BC63DEE61815E5101E372E796A8EEAD6 /* vp8l.c in Sources */ = {isa = PBXBuildFile; fileRef = B1DCBB4BD6A8D411B0DEDE1D0FAE5D14 /* vp8l.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - BCC2A91EF2611037A2D7EBC00AADAAD5 /* PINRemoteImageCategoryManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 7772A566D5A8C0E3A5857ABA92C85E3F /* PINRemoteImageCategoryManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BE85A4BD73AEA712392EC64BC41F2C33 /* filters.h in Headers */ = {isa = PBXBuildFile; fileRef = CAD335962F5F3A0DD201ACF2854E987E /* filters.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BEDA33100E538C96319D6041BA9C4AD7 /* upsampling_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = 733AB1F236FE28D441E92925A1A571F2 /* upsampling_sse2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - BF7FB2F305E831BC8B1914A6364D35C7 /* vp8.c in Sources */ = {isa = PBXBuildFile; fileRef = E2AC519B2CE3D60113743C8333175D2F /* vp8.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - BFC14A4370E75F8EF6B19C607AA232EC /* picture_tools.c in Sources */ = {isa = PBXBuildFile; fileRef = 2DBA42E7A3D98AE56EF0A752F8765AFD /* picture_tools.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - BFEBB0BC591A3D37FBDAD60C90AF496D /* dec.c in Sources */ = {isa = PBXBuildFile; fileRef = DE561472C6566B906DDD13BAEDE5BE0B /* dec.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - C00E99BE4B41F7E205941613AA90D762 /* demux.c in Sources */ = {isa = PBXBuildFile; fileRef = 688B52EC5BB98FF5D63599C29DFC312A /* demux.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - C066D2EF270EDB5AA3DB480366F8EE63 /* huffman.c in Sources */ = {isa = PBXBuildFile; fileRef = CABA6B135FC75D73E56B967942E32FEE /* huffman.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - C184317A40DB1D7F529AED73BD7F4CD9 /* yuv.h in Headers */ = {isa = PBXBuildFile; fileRef = 43D58C7F209EF668DC65D9780ADE2755 /* yuv.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C1AA161415B38E9AA9AFBF618616255B /* PINRemoteImageTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 1241DFD8FFEAE74881C679C4BFAAF0CB /* PINRemoteImageTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C1FE7D2C2272863066FB7E784A93E18E /* rescaler_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = C483ACB475ACAEBE44AD18CE8117F757 /* rescaler_sse2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - C24830D002366CE027026BCACC4A18D6 /* PINMemoryCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 39135D20E627D5ACB184DC61598D908A /* PINMemoryCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C3C9A22D821C07D87643AD8D65EEAEF5 /* PINAnimatedImageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = AC5CD465E603C691E9153D025D8D2CFC /* PINAnimatedImageManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C41214D2DF0D86931B4C981978288686 /* lossless_enc_mips_dsp_r2.c in Sources */ = {isa = PBXBuildFile; fileRef = 5AA3AE62661D5123483F17B85E6BAF50 /* lossless_enc_mips_dsp_r2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - C419D9EA9628B03287F589E014AD39CA /* PINCache-iOS8.1-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = CBFB5FE282C260B781F33A30312627C4 /* PINCache-iOS8.1-dummy.m */; }; - C44474CE15DC5BE147B38AA1165CE8E4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F653D3FC69B3BFEFC81B9DD1AA0BF75 /* Foundation.framework */; }; - C4903EEE9F265110CAF9B2795FA8127E /* alpha_processing_sse41.c in Sources */ = {isa = PBXBuildFile; fileRef = B44B9D1B673D69E0E05B22D2B8B030C0 /* alpha_processing_sse41.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - C55897C0A204F7ED8D4EE53434DD3097 /* tree.c in Sources */ = {isa = PBXBuildFile; fileRef = 1327B68AD49FAD487BA67EFF160D3A70 /* tree.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - C62D85E7E9A7591868B19B778B8F0BBB /* near_lossless.c in Sources */ = {isa = PBXBuildFile; fileRef = 1D9A6E336BC1B20D20200A15DE97FE07 /* near_lossless.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - C6DB8BC01B2441C51A103B2D7482B65E /* FLAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = C76C717697954739431D4428613868BB /* FLAnimatedImage.m */; }; - C70213D88F6FEFE79CCEDDAF47CCF876 /* vp8li.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B3068DDEA7747A83391CB38DDA49680 /* vp8li.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C755D8E7EA3A7A7657D84250F3A87835 /* cost.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CD9DEA21FB30AB73C90C0099E927785 /* cost.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - C7F7CEBDE70378E10E56964049DF19B8 /* PINAnimatedImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 43FC6C68D40F5409F8795B7319466C3F /* PINAnimatedImageManager.m */; }; - C88C43DA8A566A203928CC66ECD8984C /* tree.c in Sources */ = {isa = PBXBuildFile; fileRef = 1327B68AD49FAD487BA67EFF160D3A70 /* tree.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - C95745EA31CCFF0C9F857E1FA62B91D7 /* mips_macro.h in Headers */ = {isa = PBXBuildFile; fileRef = 563F4A6251F82426B5EAB251160C8F6A /* mips_macro.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CA4EAC90EA6A70CA7AB1CE91BBF5C0FC /* filter.c in Sources */ = {isa = PBXBuildFile; fileRef = 7E7AAE96331015494FBBCC39A59D1B96 /* filter.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - CA58AE9D01E859A81ADA2ADE35D2FB94 /* bit_writer.c in Sources */ = {isa = PBXBuildFile; fileRef = DCE1362772B0DA62D80285FF153F918A /* bit_writer.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - CA9FB99EE1B1F9C7DC2818BABD64B157 /* yuv_mips32.c in Sources */ = {isa = PBXBuildFile; fileRef = 15E1E4CED8473ECB3201D807233DBD5B /* yuv_mips32.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - CBBD9B450258AF7AC9FADA54DA40597F /* PINButton+PINRemoteImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 1CE105A1A011FADA79F2388F6F937318 /* PINButton+PINRemoteImage.m */; }; - CC616E25D7C8DC1EE3474E6BE920A576 /* PINImage+DecodedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = F3E75D9D8C09CBFE7162CD18A14C4716 /* PINImage+DecodedImage.m */; }; - CC72096E663B033D6DD1BF9436E427A9 /* upsampling_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = 733AB1F236FE28D441E92925A1A571F2 /* upsampling_sse2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - CC9853FB14E5EAAD528C642AE3CC5B11 /* rescaler.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D33BD68BF9C7D2AC6CB42E164315EA9 /* rescaler.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CCBE2DA7A34A3D7EAFB84ACDEF0E1B65 /* iterator.c in Sources */ = {isa = PBXBuildFile; fileRef = AE579CCAC15DEFDDC3800E74645F772C /* iterator.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - CCD662C66EBA8E5E409DEC0DF8F3C46E /* enc_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C46F1514984FFF0EAD26E2194696DFC /* enc_sse2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - CD6C580DD854E1995F35012C10266C6B /* PINProgressiveImage.m in Sources */ = {isa = PBXBuildFile; fileRef = F706B7B31C8ECF7E9D2D8B6EC43DE601 /* PINProgressiveImage.m */; }; - CD9682BA53210CDC1585F829018FA697 /* NSData+ImageDetectors.m in Sources */ = {isa = PBXBuildFile; fileRef = 3F2100B7E15B9D7C1D70F7F01174BB81 /* NSData+ImageDetectors.m */; }; - CE6FD7F6A89F79661A59E0653FAE234A /* PINImageView+PINRemoteImage.h in Headers */ = {isa = PBXBuildFile; fileRef = E011E32618D10830CD0F3D25499CCCEF /* PINImageView+PINRemoteImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CE995560DDA7F76B9AFE723675FD9860 /* bit_reader.h in Headers */ = {isa = PBXBuildFile; fileRef = 975971A0FF20F488DAAE129FF6A5675F /* bit_reader.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CEE70E951B78CEC003D017F87591662B /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D8947C70EA881CAD337102B182D2DBF /* ImageIO.framework */; }; - CF53854D86ACAF257B6E666D0BF25A76 /* huffman_encode.c in Sources */ = {isa = PBXBuildFile; fileRef = A9B993243629B0A6934522A6FF8CC647 /* huffman_encode.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - CF9CED8ACEC02B9D0ADB4876E41E22DD /* lossless_enc_neon.c in Sources */ = {isa = PBXBuildFile; fileRef = FE935F7066F02B06DF140D5544510623 /* lossless_enc_neon.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - D0129B10B1B331AE9A671E7DC9E1D771 /* rescaler_mips32.c in Sources */ = {isa = PBXBuildFile; fileRef = 5355B95420BA4CA130B1B5BC2D0006F1 /* rescaler_mips32.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - D01CABBF787ADF91555183E2EE3200F2 /* vp8.c in Sources */ = {isa = PBXBuildFile; fileRef = E2AC519B2CE3D60113743C8333175D2F /* vp8.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - D059EB8073278E02A0AB7620B418895F /* quant.c in Sources */ = {isa = PBXBuildFile; fileRef = A423E2AE5C4D3FE4158195252AE771FC /* quant.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - D0A749587EF66F144D0865D2C364A4DC /* PINRemoteImageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = B1C531F4782C6D93A9DDADBACAB004AC /* PINRemoteImageManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D12207F1A304CE8EC15D1B5E00724AB2 /* vp8l.c in Sources */ = {isa = PBXBuildFile; fileRef = B6A8D042E929520D2B92010A79B74859 /* vp8l.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - D134CE8DD2B2158815191BDCD02651CA /* Nullability.h in Headers */ = {isa = PBXBuildFile; fileRef = 3BDA9F9CCAAE9C786BBC5CAF0F2F873C /* Nullability.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D13A4BDB931ED2C143FB4346814B2DA0 /* vp8l.c in Sources */ = {isa = PBXBuildFile; fileRef = B1DCBB4BD6A8D411B0DEDE1D0FAE5D14 /* vp8l.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - D1531E5C2E0728AE882C7EC44BECA692 /* rescaler.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D33BD68BF9C7D2AC6CB42E164315EA9 /* rescaler.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D200353FC99C303663E9EF9AAF4CD27C /* webpi.h in Headers */ = {isa = PBXBuildFile; fileRef = 4EEB0E6DB39F528015E402B09A21080B /* webpi.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D258D7ADB4F60B64924713AD8987C30B /* bit_writer.c in Sources */ = {isa = PBXBuildFile; fileRef = DCE1362772B0DA62D80285FF153F918A /* bit_writer.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - D25F170379E6801602D30FA827CAFB72 /* NSData+ImageDetectors.h in Headers */ = {isa = PBXBuildFile; fileRef = E04B56655A37768CB856EDF81704256C /* NSData+ImageDetectors.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D40FF9DB7EB06CDCDE07EEC7CC13C8AD /* quant_levels_dec.h in Headers */ = {isa = PBXBuildFile; fileRef = A86125E733F084E0B1A4AA8C91EDDD27 /* quant_levels_dec.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D5D5ECE4D576B49BFFA280F3BEE2EA84 /* lossless_enc_mips32.c in Sources */ = {isa = PBXBuildFile; fileRef = 821A415254215F905B6F728586A55DB5 /* lossless_enc_mips32.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - D5F85F782DDDF740060BCA9924FA7F46 /* mux.h in Headers */ = {isa = PBXBuildFile; fileRef = EB021361F2B386EF7FEA0D39AE0D0560 /* mux.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D6559CECD47A3D58604D92FBA3CB5735 /* random.h in Headers */ = {isa = PBXBuildFile; fileRef = 10455FA91AE1DBB54A2B812BAF2EC295 /* random.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D672CD6110FB856E122E143E4E1CF455 /* token.c in Sources */ = {isa = PBXBuildFile; fileRef = E793145817656732EFAB73240C3E3178 /* token.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - D76E8F24DE3D89F26158A0E9CEA09CE5 /* enc_mips32.c in Sources */ = {isa = PBXBuildFile; fileRef = 77A2E23106484646CA6EEBE045B82D53 /* enc_mips32.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - D79E4C317A340FF3834D4101D60C7682 /* common.h in Headers */ = {isa = PBXBuildFile; fileRef = AC7A33E4F32F4D8E02EC3789E9742836 /* common.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D84711A941C2A1DB0C20AF48382BCE28 /* vp8i.h in Headers */ = {isa = PBXBuildFile; fileRef = B4F4DE3D01E4668A8895C5133F55C194 /* vp8i.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D8B13CC4D2D3AC7C22A3A72AB47B6E89 /* PINDataTaskOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D421C79F2B006908434D7B1DE81F780 /* PINDataTaskOperation.m */; }; - DB09C45682D8234921A9AADE1CA0D1ED /* dec_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = 5213EDAF6EDAD2E561B5C6012EF83DFB /* dec_sse2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - DB1612FA82B4647F60BCBEB874DA480C /* FLAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = C76C717697954739431D4428613868BB /* FLAnimatedImage.m */; }; - DC1EDB42135CC9428D8A5CD30D8A5C02 /* lossless_enc_sse41.c in Sources */ = {isa = PBXBuildFile; fileRef = 960EF3F3E2682BEDC0ECC3C6D6225344 /* lossless_enc_sse41.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - DC68CD48BA599CA63A5338059E45E0A7 /* PINAnimatedImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 43FC6C68D40F5409F8795B7319466C3F /* PINAnimatedImageManager.m */; }; - DC8F42F97D63D24BDD5066CB92B7ABC3 /* picture.c in Sources */ = {isa = PBXBuildFile; fileRef = 607EC80E69037007634D0D09576D75E0 /* picture.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - DD69BBEBEAFF56E661E56D4FA7BFB67A /* PINRemoteImage-iOS8.1-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 8985F88BB7DF50762E13F4EF5068605D /* PINRemoteImage-iOS8.1-dummy.m */; }; - DD9AD81E8235D5A70802FA6C2458DEA3 /* alpha_processing_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = F5262B915274A6E95421C1E0556EC8C4 /* alpha_processing_sse2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - DDFF66F42076861E58CC39AFD17458C9 /* extras.h in Headers */ = {isa = PBXBuildFile; fileRef = 5713CD0A1EDCA136A95924D0E6ACD21E /* extras.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DED66A8B6EE6984BFF9F2D720F28A817 /* webpenc.c in Sources */ = {isa = PBXBuildFile; fileRef = 6CD3BA129EC620FCE4B6A1CEFB684EBB /* webpenc.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - DFD406C814E3F1C096705EA7E82B263B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F653D3FC69B3BFEFC81B9DD1AA0BF75 /* Foundation.framework */; }; - E0529802AA59F4EEB458A6494E21C10D /* argb_mips_dsp_r2.c in Sources */ = {isa = PBXBuildFile; fileRef = B212B272786957617807DA03F5A6ACDC /* argb_mips_dsp_r2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - E06825484A00FA86FCB598DB299C0286 /* quant.c in Sources */ = {isa = PBXBuildFile; fileRef = A423E2AE5C4D3FE4158195252AE771FC /* quant.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - E1481D3DCADA0D1E0882F10B99AF1107 /* rescaler_neon.c in Sources */ = {isa = PBXBuildFile; fileRef = 86DF26C20099077471AFE39C0AD1273D /* rescaler_neon.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - E1AB0DCB025C237D0A7FFC697EBB7FF1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F653D3FC69B3BFEFC81B9DD1AA0BF75 /* Foundation.framework */; }; - E28D9EE4A0025BAB8ADFD18B32008FD8 /* enc_avx2.c in Sources */ = {isa = PBXBuildFile; fileRef = 58227BA313D46A3CDB4831FC0D7ADF54 /* enc_avx2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - E2C92FE45DE6DDEED5A3ABE63DAE06BC /* lossless_enc_sse41.c in Sources */ = {isa = PBXBuildFile; fileRef = 960EF3F3E2682BEDC0ECC3C6D6225344 /* lossless_enc_sse41.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - E33144C5A56699C308E9DD2B9B62C6E3 /* filters_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = 1EAAED9854572A4C16435ECE5BFAAE92 /* filters_sse2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - E3841FCEA72F066486D18187E8D20782 /* backward_references.c in Sources */ = {isa = PBXBuildFile; fileRef = 77EF39AD51321F512B7910275CB80B19 /* backward_references.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - E499B8E0C7DFC3E50F1C156BF0B0B66A /* delta_palettization.c in Sources */ = {isa = PBXBuildFile; fileRef = 90B25009CF8DCC27B2B1E0BDD881DE98 /* delta_palettization.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - E4C0AAB20014EE7477D84E08A1075224 /* types.h in Headers */ = {isa = PBXBuildFile; fileRef = 2CFB1F82C8F950BD532D24B2D775E949 /* types.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E50697F8A3FB97FF76EEA79F6582A9E8 /* PINCache+PINRemoteImageCaching.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E552CA74498CDAF688A643373EE5F59 /* PINCache+PINRemoteImageCaching.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E50A7D40A8FE825535E0013FABBD0A5E /* FLAnimatedImageView+PINRemoteImage.m in Sources */ = {isa = PBXBuildFile; fileRef = B37695D6592D08B979F213F2C003B750 /* FLAnimatedImageView+PINRemoteImage.m */; }; - E5EDAC1FE3F085E877F962D4E3498B4C /* upsampling_mips_dsp_r2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A4F81253F77AFADD78837236560B2D1 /* upsampling_mips_dsp_r2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - E6B83A1E05309B3291B0A0A6CCF582A5 /* yuv_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = DAD64598A80EF9D1DB4CC444CD96C57A /* yuv_sse2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - E7340C99D2BC858136F429CA6961464B /* PINRemoteImageManagerResult.h in Headers */ = {isa = PBXBuildFile; fileRef = B3D08B70814AF160D6E39CAA9801E8BB /* PINRemoteImageManagerResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E8581192AD4C4806BA63326C5B15B933 /* demux.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D7930163300F707135002DE80BA19E1 /* demux.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E8A1B4232D3BE70967E70C265E2FC2D9 /* huffman_encode.h in Headers */ = {isa = PBXBuildFile; fileRef = 7F8C0B7D630C83F2B70F46CEA9682145 /* huffman_encode.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E8CDA40BF3460DD83F5E8F09068D4F11 /* color_cache.h in Headers */ = {isa = PBXBuildFile; fileRef = 64AA202FCC931C3E07178134DFCF081A /* color_cache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E8F83EC2C711D9B5679B55012B08ABCD /* picture_psnr.c in Sources */ = {isa = PBXBuildFile; fileRef = E7DAC4AA6FE9F930F089DD2B2D65C7D9 /* picture_psnr.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - E949D0F07FB2E4CE98D9C00B4FDE2352 /* format_constants.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C2F77853D7A7DB311300B17CE0414EF /* format_constants.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E9FF63035E5FB9C7B4CC13B7D9C0D7E1 /* FLAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0408075B9809BA3BEE318DC659E50B01 /* FLAnimatedImageView.m */; }; - EA3275C78F818202B2F9F66192A8E7F5 /* dec.c in Sources */ = {isa = PBXBuildFile; fileRef = DE561472C6566B906DDD13BAEDE5BE0B /* dec.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - EA3D0F856F9071FC3139318554B18D3A /* PINDataTaskOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D421C79F2B006908434D7B1DE81F780 /* PINDataTaskOperation.m */; }; - EABC062586F5AD1BD4FEBCA9ED026180 /* PINRemoteImageMemoryContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 33EFDCCA6725B6A025C0CE6D742C9492 /* PINRemoteImageMemoryContainer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EAFE2851556D2DDC570438801D948207 /* rescaler_mips_dsp_r2.c in Sources */ = {isa = PBXBuildFile; fileRef = 6E9A9E3F63F1FB1AD85D544D51E6E2D5 /* rescaler_mips_dsp_r2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - EB9A67A667E9CAA4FB5ED871B3C447B7 /* common.h in Headers */ = {isa = PBXBuildFile; fileRef = AC7A33E4F32F4D8E02EC3789E9742836 /* common.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EBC106167C193A969D6D2D710CC40BC2 /* quant_levels_dec.c in Sources */ = {isa = PBXBuildFile; fileRef = 900B41D1104AA9D38B15556678CAA952 /* quant_levels_dec.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - EBD9D5A50B91DB0B86A0FBCA7B99EE1A /* dsp.h in Headers */ = {isa = PBXBuildFile; fileRef = AB70F892215992CEE9D1201FAD7E6AA7 /* dsp.h */; settings = {ATTRIBUTES = (Public, ); }; }; - ECCFB72A1C043C692029AA4B777FE3E8 /* PINCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 353C5D5A0588CE212B0F00A2C48517DD /* PINCache.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - EDA5FCDC0CFE5CCC10F0B15FF778A6B0 /* bit_writer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD5C78A000F1B4C9FD43E7995E11641 /* bit_writer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EE86D33F6218BB990E5DA26EA9403C61 /* PINAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 38F931A84A926D8ED6C79AC8C84CCF6E /* PINAnimatedImage.m */; }; - EF15B97A0881D801AB7DEFE149E09EF3 /* anim_decode.c in Sources */ = {isa = PBXBuildFile; fileRef = CABC57871709587C1DF9AEFFEFE9DFEA /* anim_decode.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - EF8B037430B0599809A8475F218A4AB6 /* huffman.c in Sources */ = {isa = PBXBuildFile; fileRef = CABA6B135FC75D73E56B967942E32FEE /* huffman.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - F01A83F5D4FE48EA5979D4BACEF51EC3 /* config.c in Sources */ = {isa = PBXBuildFile; fileRef = 720EF0FAD6D5850D1E07D55056EC185C /* config.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - F04EA78A279461D73453838E188BE0E9 /* PINDataTaskOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = E591CFAEF5F2CD91BD71C372CB895E8D /* PINDataTaskOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F085EC7146EB30339860F510569AF542 /* decode.h in Headers */ = {isa = PBXBuildFile; fileRef = 178041EA65EA2643FFB1544EAD15F133 /* decode.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F17275AF13E7DBB966CBDA3F9EAA3473 /* yuv_mips32.c in Sources */ = {isa = PBXBuildFile; fileRef = 15E1E4CED8473ECB3201D807233DBD5B /* yuv_mips32.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - F364B7343773DD0BD6AE5717F8F79C86 /* PINButton+PINRemoteImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B4310C5981857705080A1761894CFCE /* PINButton+PINRemoteImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F5F9F8D3E0AEC6188F99FA05371B8F19 /* enc_sse41.c in Sources */ = {isa = PBXBuildFile; fileRef = C087C6A10F610ED0C0CB2DC0978E0685 /* enc_sse41.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - F70800BFFE49AA461F17EF80581AC865 /* histogram.c in Sources */ = {isa = PBXBuildFile; fileRef = 9B00C7DEBAB917F26508F71DA81CB293 /* histogram.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - F739630F44036B96E422E0B92FFC01CF /* PINURLSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = D605ED50ACCB0380BF4F11E8FBBB1437 /* PINURLSessionManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F7CAC092242DA4F7B938BF068BB36543 /* lossless_enc_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = B5BDAC3604CA68F6DF3522591DA86A9D /* lossless_enc_sse2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - F8DFDCDD6CF6EF8F6C2B654727F47E95 /* io.c in Sources */ = {isa = PBXBuildFile; fileRef = C537E6806181C0537F4CA286FA555A5A /* io.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - F9879D5E68B7D9BEA54C9BB62633FC07 /* FLAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 558FF321A05CF84D6DD288EB5131A91A /* FLAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - FAF214553BE87E4F148F238FB9B9A2FC /* argb.c in Sources */ = {isa = PBXBuildFile; fileRef = 0BF65A93624E241BB3B897C3724E9D8A /* argb.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - FB97D571ABECBDDAFC1E27CD900704E4 /* Pods-PINRemoteImage-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = D175F0B2CE4974DA4A1448ED5888697D /* Pods-PINRemoteImage-dummy.m */; }; - FBAB5AE5952559C9464333340168310D /* argb_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = ADFA5305E9873E12C2940FD012BB0DFB /* argb_sse2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - FC4873BB2F350452C76F1CFC70C1EBC0 /* cost_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = BFE6D9A7E95710BDA480F6AD7C2C5469 /* cost_sse2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - FC573CB0C99ACE8FD5681F3FC404E2C1 /* huffman.h in Headers */ = {isa = PBXBuildFile; fileRef = FC2F9C0051E45C7BCEBE9E395DD25DC0 /* huffman.h */; settings = {ATTRIBUTES = (Public, ); }; }; - FCAE46A39D0C55DEAE9D6B6A20BA1D1E /* lossless_mips_dsp_r2.c in Sources */ = {isa = PBXBuildFile; fileRef = 6CC19C6C38FE732E8FAFADB273C4B875 /* lossless_mips_dsp_r2.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - FCF01FBF7D21C3870DD74F0A90C730F0 /* quant.c in Sources */ = {isa = PBXBuildFile; fileRef = EF60DC1D3E1481DC9519566EC5C8D0C5 /* quant.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - FE38EA8B299B98D6094D0B8B323D113A /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D8947C70EA881CAD337102B182D2DBF /* ImageIO.framework */; }; - FE43CFE249F8BA34C0F3BAFAE2148BD4 /* alpha_processing_sse41.c in Sources */ = {isa = PBXBuildFile; fileRef = B44B9D1B673D69E0E05B22D2B8B030C0 /* alpha_processing_sse41.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - FEBA128C41FDDE070C8A66090156D7C4 /* PINRemoteImageDownloadTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D4FE1A5D3D51B90A4893BD4A7BC1605 /* PINRemoteImageDownloadTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; - FEE32BB49E61823986EB6AC8712BEC00 /* filter.c in Sources */ = {isa = PBXBuildFile; fileRef = 7E7AAE96331015494FBBCC39A59D1B96 /* filter.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; - FF3DF41B20FD5560B51FBF8DB326D59B /* buffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 60503AC34B0481BC03680C73779DED60 /* buffer.c */; settings = {COMPILER_FLAGS = "-D_THREAD_SAFE -fno-objc-arc"; }; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 134D6BC4F1BF93D2BF671CE2A93458CD /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 51E046FCB539FE8A23DFDD38C3222B17; - remoteInfo = "libwebp-iOS7.1"; - }; - 1826D6540FAAB7D5E03719DA656945C0 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = CDDDE8D404074B9DC4C2291002D159F8; - remoteInfo = "FLAnimatedImage-iOS8.1"; - }; - 1AA6B7DDBE093223BF00B56E0FDD39E0 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = DDC608954898A7553EB8B23009B076E2; - remoteInfo = "PINRemoteImage-iOS7.1"; - }; - 3BD3D3B9D765D571CAA8F1839A9EDD19 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 2A4983A5807EEB91056950FD76E2D683; - remoteInfo = "PINCache-iOS7.1"; - }; - 4B08178EC60A403F5E80CD7DCB1EB352 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 6C34D713988BD49857279690E3652CD0; - remoteInfo = "libwebp-iOS8.1"; - }; - 738D8CE34837483FB59A3AE9B27351E9 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 02F173FA63D3D03EA7E6CA9FFE3A0761; - remoteInfo = "PINCache-iOS8.1"; - }; - 797399D7635AD8BFF31BD128C6058DE6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 2A4983A5807EEB91056950FD76E2D683; - remoteInfo = "PINCache-iOS7.1"; - }; - 908845F958625ABB800EF08D1F6FE067 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 88946788461561787CE22BC14B767C3A; - remoteInfo = "FLAnimatedImage-iOS7.1"; - }; - 9726DCCD95AA248F03F76994B3B915C4 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 51E046FCB539FE8A23DFDD38C3222B17; - remoteInfo = "libwebp-iOS7.1"; - }; - BAD0109B4FB4906E7680931A5455DC97 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 12CBE23502187E04EA33A1CAA9CBE617; - remoteInfo = "PINRemoteImage-iOS8.1"; - }; - D26F4FA5AC4D79D13AC9DE4E54C56E21 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 51E046FCB539FE8A23DFDD38C3222B17; - remoteInfo = "libwebp-iOS7.1"; - }; - E5017633B2BE6115FB50632AE2017A45 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 2A4983A5807EEB91056950FD76E2D683; - remoteInfo = "PINCache-iOS7.1"; - }; - E8A35CED3C5BBAA39E5D70997822C3E7 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 88946788461561787CE22BC14B767C3A; - remoteInfo = "FLAnimatedImage-iOS7.1"; - }; - EC9123A0F3D1830DE149613FD144013E /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 88946788461561787CE22BC14B767C3A; - remoteInfo = "FLAnimatedImage-iOS7.1"; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 00B2BEE1D596A306899DFE0B44C7D72A /* Pods-PINRemoteImage-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PINRemoteImage-resources.sh"; sourceTree = ""; }; - 012F1030350DF34F33932A2AF9828649 /* bit_reader_inl.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = bit_reader_inl.h; path = src/utils/bit_reader_inl.h; sourceTree = ""; }; - 023E4D6CDD5B2AE15094E18B317A97F4 /* libFLAnimatedImage-iOS8.1.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libFLAnimatedImage-iOS8.1.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 0265BE2D31AEDDDF41979FBC57354C8E /* dec_sse41.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = dec_sse41.c; path = src/dsp/dec_sse41.c; sourceTree = ""; }; - 0408075B9809BA3BEE318DC659E50B01 /* FLAnimatedImageView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLAnimatedImageView.m; path = FLAnimatedImage/FLAnimatedImageView.m; sourceTree = ""; }; - 05CAFFE052DEC8B9F74C9E2D232E3A83 /* PINCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = PINCache.h; path = PINCache/PINCache.h; sourceTree = ""; }; - 09B1CEDC1BC1C6533A03C6091562729C /* PINRemoteImage-iOS8.1-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "PINRemoteImage-iOS8.1-prefix.pch"; path = "../PINRemoteImage-iOS8.1/PINRemoteImage-iOS8.1-prefix.pch"; sourceTree = ""; }; - 0B594F7A5FFADE39C151EC797AB9F489 /* upsampling.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = upsampling.c; path = src/dsp/upsampling.c; sourceTree = ""; }; - 0B774580FBBDC1A0407CCFD9E6B7E981 /* PINRemoteLock.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = PINRemoteLock.h; sourceTree = ""; }; - 0BF65A93624E241BB3B897C3724E9D8A /* argb.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = argb.c; path = src/dsp/argb.c; sourceTree = ""; }; - 0C970CB7D9C79058AD603908B77D5EE1 /* PINRemoteImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = PINRemoteImage.h; sourceTree = ""; }; - 0DEA87E879DA96FE8179AB7E3437FAF0 /* PINRemoteImageMacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageMacros.h; sourceTree = ""; }; - 0E0409379FF7ECC8CD099D8BB8F2BC75 /* libwebp-iOS7.1-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "libwebp-iOS7.1-prefix.pch"; sourceTree = ""; }; - 0EC0DF5B2E9F7B941F2DCB6F54F7F0BA /* Pods-PINRemoteImage-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PINRemoteImage-acknowledgements.plist"; sourceTree = ""; }; - 0F2199A6FDC473EB4F09E6EE25244613 /* yuv_mips_dsp_r2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = yuv_mips_dsp_r2.c; path = src/dsp/yuv_mips_dsp_r2.c; sourceTree = ""; }; - 0F72C99527F0AAF04B3A624B82F080B4 /* PINRemoteImageCallbacks.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageCallbacks.h; sourceTree = ""; }; - 0FD5C78A000F1B4C9FD43E7995E11641 /* bit_writer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = bit_writer.h; path = src/utils/bit_writer.h; sourceTree = ""; }; - 10455FA91AE1DBB54A2B812BAF2EC295 /* random.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = random.h; path = src/utils/random.h; sourceTree = ""; }; - 10E39F3E241AEAEEA46F13D5AB934E8C /* PINMemoryCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = PINMemoryCache.m; path = PINCache/PINMemoryCache.m; sourceTree = ""; }; - 111CFE021EA510C1C36F4E1BD9DB2555 /* PINRemoteImage-iOS7.1-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PINRemoteImage-iOS7.1-dummy.m"; sourceTree = ""; }; - 1241DFD8FFEAE74881C679C4BFAAF0CB /* PINRemoteImageTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageTask.h; sourceTree = ""; }; - 1327B68AD49FAD487BA67EFF160D3A70 /* tree.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = tree.c; path = src/enc/tree.c; sourceTree = ""; }; - 13E434C0AE2F99377B4587AE15199116 /* Pods-PINRemoteImage Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PINRemoteImage Tests.release.xcconfig"; sourceTree = ""; }; - 150B366BB8208A11274B6720E4B82BAA /* vp8enci.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = vp8enci.h; path = src/enc/vp8enci.h; sourceTree = ""; }; - 15B4758BE6AB13C24A0835A3458E330F /* alphai.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = alphai.h; path = src/dec/alphai.h; sourceTree = ""; }; - 15E1E4CED8473ECB3201D807233DBD5B /* yuv_mips32.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = yuv_mips32.c; path = src/dsp/yuv_mips32.c; sourceTree = ""; }; - 178041EA65EA2643FFB1544EAD15F133 /* decode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = decode.h; path = src/webp/decode.h; sourceTree = ""; }; - 1AB8299DE2EE7A81F628229C2DE4475F /* FLAnimatedImageView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLAnimatedImageView.h; path = FLAnimatedImage/FLAnimatedImageView.h; sourceTree = ""; }; - 1B3E18DE80BF2A17C07E6E4E0FE6EFA3 /* lossless_neon.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = lossless_neon.c; path = src/dsp/lossless_neon.c; sourceTree = ""; }; - 1CD9DEA21FB30AB73C90C0099E927785 /* cost.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = cost.c; path = src/enc/cost.c; sourceTree = ""; }; - 1CE105A1A011FADA79F2388F6F937318 /* PINButton+PINRemoteImage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PINButton+PINRemoteImage.m"; sourceTree = ""; }; - 1CF8C86EE887925394FB2A05EB8A9E70 /* PINAnimatedImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = PINAnimatedImage.h; sourceTree = ""; }; - 1D9A6E336BC1B20D20200A15DE97FE07 /* near_lossless.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = near_lossless.c; path = src/enc/near_lossless.c; sourceTree = ""; }; - 1DA7B7E3D3641D4BB5A28D94B23BB252 /* cost_mips_dsp_r2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = cost_mips_dsp_r2.c; path = src/dsp/cost_mips_dsp_r2.c; sourceTree = ""; }; - 1EAAED9854572A4C16435ECE5BFAAE92 /* filters_sse2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = filters_sse2.c; path = src/dsp/filters_sse2.c; sourceTree = ""; }; - 1FD7680EFC0A084A1A1A16727F5A5DCE /* neon.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = neon.h; path = src/dsp/neon.h; sourceTree = ""; }; - 2142E43008910E5C9A147EDAC81F1662 /* encode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = encode.h; path = src/webp/encode.h; sourceTree = ""; }; - 214C7FB9ABE1F5CCDE0BC288B08841F8 /* lossless.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = lossless.h; path = src/dsp/lossless.h; sourceTree = ""; }; - 218578CA992697AB822E5806F687651E /* PINDiskCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = PINDiskCache.m; path = PINCache/PINDiskCache.m; sourceTree = ""; }; - 2407DB71ABCF28A8467E8CF5BAF27BD9 /* PINRemoteImageMemoryContainer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageMemoryContainer.m; sourceTree = ""; }; - 2C3CB475C14C8FFDDBA319BA4426B6CD /* quant_levels.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = quant_levels.c; path = src/utils/quant_levels.c; sourceTree = ""; }; - 2CFB1F82C8F950BD532D24B2D775E949 /* types.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = types.h; path = src/webp/types.h; sourceTree = ""; }; - 2DBA42E7A3D98AE56EF0A752F8765AFD /* picture_tools.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = picture_tools.c; path = src/enc/picture_tools.c; sourceTree = ""; }; - 2DFC450DABA13FA7A6DACB2563DF4EBB /* PINRemoteImageDownloadTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageDownloadTask.m; sourceTree = ""; }; - 30C87FA0395C40393C9A5FEBD3D9A487 /* PINRemoteImageCategoryManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageCategoryManager.m; sourceTree = ""; }; - 30CF9B4AAE62C4612A11127E869B1D76 /* libPods-PINRemoteImage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PINRemoteImage.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 3268D31245A99137C0933AF68F05DBBA /* PINCache-iOS8.1.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "PINCache-iOS8.1.xcconfig"; path = "../PINCache-iOS8.1/PINCache-iOS8.1.xcconfig"; sourceTree = ""; }; - 32D0C42B671BE1D9F1D5969FA9335AF8 /* cost.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = cost.c; path = src/dsp/cost.c; sourceTree = ""; }; - 33EFDCCA6725B6A025C0CE6D742C9492 /* PINRemoteImageMemoryContainer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageMemoryContainer.h; sourceTree = ""; }; - 353C5D5A0588CE212B0F00A2C48517DD /* PINCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = PINCache.m; path = PINCache/PINCache.m; sourceTree = ""; }; - 35EEAA1915188D7B44AA3552D66E37EF /* alpha_processing_mips_dsp_r2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = alpha_processing_mips_dsp_r2.c; path = src/dsp/alpha_processing_mips_dsp_r2.c; sourceTree = ""; }; - 37875A249C725E0B8CC778FE3CBFDBE3 /* utils.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = utils.h; path = src/utils/utils.h; sourceTree = ""; }; - 38F931A84A926D8ED6C79AC8C84CCF6E /* PINAnimatedImage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = PINAnimatedImage.m; sourceTree = ""; }; - 39135D20E627D5ACB184DC61598D908A /* PINMemoryCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = PINMemoryCache.h; path = PINCache/PINMemoryCache.h; sourceTree = ""; }; - 3ADF044BE12A8FF02BDA7BB32E55E8CF /* upsampling_neon.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = upsampling_neon.c; path = src/dsp/upsampling_neon.c; sourceTree = ""; }; - 3B1DDAD593621215D969D96E5F5C2725 /* PINAlternateRepresentationProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = PINAlternateRepresentationProvider.h; sourceTree = ""; }; - 3B962ABB7F8EAC0B911CFD84D66A3651 /* color_cache.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = color_cache.c; path = src/utils/color_cache.c; sourceTree = ""; }; - 3BDA9F9CCAAE9C786BBC5CAF0F2F873C /* Nullability.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Nullability.h; path = PINCache/Nullability.h; sourceTree = ""; }; - 3C104E4BDC519CBCA922579793F444D3 /* filters.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = filters.c; path = src/dsp/filters.c; sourceTree = ""; }; - 3F2100B7E15B9D7C1D70F7F01174BB81 /* NSData+ImageDetectors.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "NSData+ImageDetectors.m"; sourceTree = ""; }; - 41AC5A8B3E67A5B68BB3007A55D78284 /* dec_clip_tables.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = dec_clip_tables.c; path = src/dsp/dec_clip_tables.c; sourceTree = ""; }; - 43D58C7F209EF668DC65D9780ADE2755 /* yuv.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = yuv.h; path = src/dsp/yuv.h; sourceTree = ""; }; - 43FC6C68D40F5409F8795B7319466C3F /* PINAnimatedImageManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = PINAnimatedImageManager.m; sourceTree = ""; }; - 47C707489874CA3F2940F2443E636576 /* alpha.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = alpha.c; path = src/enc/alpha.c; sourceTree = ""; }; - 47EB0BBBD227E352F0C654CB221746E0 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; }; - 4802610EC3465AB540B7BA5AC1EC96C5 /* tree.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = tree.c; path = src/dec/tree.c; sourceTree = ""; }; - 49BA8E48355843D4444348D2F3CE5A2A /* PINRemoteImageTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageTask.m; sourceTree = ""; }; - 4A57EB68D6EE28230332CD41E941F6F4 /* Pods-PINRemoteImage Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PINRemoteImage Tests-dummy.m"; sourceTree = ""; }; - 4B08BAC88FCA48253326E775CB905235 /* lossless_enc.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = lossless_enc.c; path = src/dsp/lossless_enc.c; sourceTree = ""; }; - 4C2F77853D7A7DB311300B17CE0414EF /* format_constants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = format_constants.h; path = src/webp/format_constants.h; sourceTree = ""; }; - 4C46F1514984FFF0EAD26E2194696DFC /* enc_sse2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = enc_sse2.c; path = src/dsp/enc_sse2.c; sourceTree = ""; }; - 4D33BD68BF9C7D2AC6CB42E164315EA9 /* rescaler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = rescaler.h; path = src/utils/rescaler.h; sourceTree = ""; }; - 4D6B18220592A6A66D54E1EDA2B6ABE6 /* libPINRemoteImage-iOS7.1.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPINRemoteImage-iOS7.1.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 4D8C8832F2576E41299095AC0BC38FD2 /* PINImage+WebP.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PINImage+WebP.h"; sourceTree = ""; }; - 4EEB0E6DB39F528015E402B09A21080B /* webpi.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = webpi.h; path = src/dec/webpi.h; sourceTree = ""; }; - 5213EDAF6EDAD2E561B5C6012EF83DFB /* dec_sse2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = dec_sse2.c; path = src/dsp/dec_sse2.c; sourceTree = ""; }; - 5355B95420BA4CA130B1B5BC2D0006F1 /* rescaler_mips32.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = rescaler_mips32.c; path = src/dsp/rescaler_mips32.c; sourceTree = ""; }; - 5372CA4722349B8FCC016DA0822A78F6 /* rescaler.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = rescaler.c; path = src/dsp/rescaler.c; sourceTree = ""; }; - 53D3A890AAD5ADC707F4A9DD52D27B85 /* analysis.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = analysis.c; path = src/enc/analysis.c; sourceTree = ""; }; - 558FF321A05CF84D6DD288EB5131A91A /* FLAnimatedImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLAnimatedImage.h; path = FLAnimatedImage/FLAnimatedImage.h; sourceTree = ""; }; - 563F4A6251F82426B5EAB251160C8F6A /* mips_macro.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = mips_macro.h; path = src/dsp/mips_macro.h; sourceTree = ""; }; - 5713CD0A1EDCA136A95924D0E6ACD21E /* extras.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = extras.h; path = src/webp/extras.h; sourceTree = ""; }; - 57C7DA2DFA0213BB337A4A1989FA1E10 /* libwebp-iOS8.1.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "libwebp-iOS8.1.xcconfig"; path = "../libwebp-iOS8.1/libwebp-iOS8.1.xcconfig"; sourceTree = ""; }; - 58227BA313D46A3CDB4831FC0D7ADF54 /* enc_avx2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = enc_avx2.c; path = src/dsp/enc_avx2.c; sourceTree = ""; }; - 5A3A10263F91713FAA7A0DF102A64451 /* FLAnimatedImage-iOS7.1.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "FLAnimatedImage-iOS7.1.xcconfig"; sourceTree = ""; }; - 5AA3AE62661D5123483F17B85E6BAF50 /* lossless_enc_mips_dsp_r2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = lossless_enc_mips_dsp_r2.c; path = src/dsp/lossless_enc_mips_dsp_r2.c; sourceTree = ""; }; - 5C6A9B308BA81A975671A7F75DB8A30B /* lossless_sse2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = lossless_sse2.c; path = src/dsp/lossless_sse2.c; sourceTree = ""; }; - 5D7930163300F707135002DE80BA19E1 /* demux.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = demux.h; path = src/webp/demux.h; sourceTree = ""; }; - 5E552CA74498CDAF688A643373EE5F59 /* PINCache+PINRemoteImageCaching.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PINCache+PINRemoteImageCaching.h"; sourceTree = ""; }; - 5E5C6A79473815063434E0F2E4D29520 /* endian_inl.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = endian_inl.h; path = src/utils/endian_inl.h; sourceTree = ""; }; - 60503AC34B0481BC03680C73779DED60 /* buffer.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = buffer.c; path = src/dec/buffer.c; sourceTree = ""; }; - 607EC80E69037007634D0D09576D75E0 /* picture.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = picture.c; path = src/enc/picture.c; sourceTree = ""; }; - 63C5FDB95E938EB802C2DAE3D5FEF41A /* frame.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = frame.c; path = src/dec/frame.c; sourceTree = ""; }; - 64A2DC53D4E243C57B9AAE1310B85AFC /* libPINCache-iOS8.1.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPINCache-iOS8.1.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 64AA202FCC931C3E07178134DFCF081A /* color_cache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = color_cache.h; path = src/utils/color_cache.h; sourceTree = ""; }; - 64FD5BDCFA1A3C5B288A2DB7DC091DD3 /* PINImage+WebP.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PINImage+WebP.m"; sourceTree = ""; }; - 655D1EAFD3BB047F093C9F5514DEA4D9 /* FLAnimatedImage-iOS8.1.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "FLAnimatedImage-iOS8.1.xcconfig"; path = "../FLAnimatedImage-iOS8.1/FLAnimatedImage-iOS8.1.xcconfig"; sourceTree = ""; }; - 688B52EC5BB98FF5D63599C29DFC312A /* demux.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = demux.c; path = src/demux/demux.c; sourceTree = ""; }; - 6AAB128F5E8D4D59D34CA86049D051BF /* libwebp-iOS7.1.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "libwebp-iOS7.1.xcconfig"; sourceTree = ""; }; - 6C86AEDFA5808330AAA01B76F53B5D40 /* PINImage+DecodedImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PINImage+DecodedImage.h"; sourceTree = ""; }; - 6CC19C6C38FE732E8FAFADB273C4B875 /* lossless_mips_dsp_r2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = lossless_mips_dsp_r2.c; path = src/dsp/lossless_mips_dsp_r2.c; sourceTree = ""; }; - 6CD3BA129EC620FCE4B6A1CEFB684EBB /* webpenc.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = webpenc.c; path = src/enc/webpenc.c; sourceTree = ""; }; - 6D421C79F2B006908434D7B1DE81F780 /* PINDataTaskOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = PINDataTaskOperation.m; sourceTree = ""; }; - 6D8947C70EA881CAD337102B182D2DBF /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk/System/Library/Frameworks/ImageIO.framework; sourceTree = DEVELOPER_DIR; }; - 6E90DD20CCBAD11352D18410B28108A3 /* PINAlternateRepresentationProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = PINAlternateRepresentationProvider.m; sourceTree = ""; }; - 6E9A9E3F63F1FB1AD85D544D51E6E2D5 /* rescaler_mips_dsp_r2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = rescaler_mips_dsp_r2.c; path = src/dsp/rescaler_mips_dsp_r2.c; sourceTree = ""; }; - 6F579E1BD144AC8C4974FDE70107BE70 /* liblibwebp-iOS8.1.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "liblibwebp-iOS8.1.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 6FFB5369DE5023467EE00C37356BDA50 /* Pods-PINRemoteImage.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PINRemoteImage.debug.xcconfig"; sourceTree = ""; }; - 714789E6925BC6E7F73ACEFAF20258EB /* alpha_processing.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = alpha_processing.c; path = src/dsp/alpha_processing.c; sourceTree = ""; }; - 7159655540FAD47DEEC9556993CCEE72 /* PINCache+PINRemoteImageCaching.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PINCache+PINRemoteImageCaching.m"; sourceTree = ""; }; - 720EF0FAD6D5850D1E07D55056EC185C /* config.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = config.c; path = src/enc/config.c; sourceTree = ""; }; - 7215A5A771C283D41302F2FD6D751C77 /* lossless.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = lossless.c; path = src/dsp/lossless.c; sourceTree = ""; }; - 733AB1F236FE28D441E92925A1A571F2 /* upsampling_sse2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = upsampling_sse2.c; path = src/dsp/upsampling_sse2.c; sourceTree = ""; }; - 744BA9C83EECD0D33C50E4A9687206BE /* filters_mips_dsp_r2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = filters_mips_dsp_r2.c; path = src/dsp/filters_mips_dsp_r2.c; sourceTree = ""; }; - 7772A566D5A8C0E3A5857ABA92C85E3F /* PINRemoteImageCategoryManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageCategoryManager.h; sourceTree = ""; }; - 77A2E23106484646CA6EEBE045B82D53 /* enc_mips32.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = enc_mips32.c; path = src/dsp/enc_mips32.c; sourceTree = ""; }; - 77EF39AD51321F512B7910275CB80B19 /* backward_references.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = backward_references.c; path = src/enc/backward_references.c; sourceTree = ""; }; - 78CC59F8F4E9458E2D49B281A07F2229 /* picture_rescale.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = picture_rescale.c; path = src/enc/picture_rescale.c; sourceTree = ""; }; - 79E6D85CF8A0B7F8AD014890501095BE /* FLAnimatedImage-iOS7.1-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FLAnimatedImage-iOS7.1-prefix.pch"; sourceTree = ""; }; - 79FBFC39E41814D081F1DF303B6D4C1A /* histogram.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = histogram.h; path = src/enc/histogram.h; sourceTree = ""; }; - 7B4310C5981857705080A1761894CFCE /* PINButton+PINRemoteImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PINButton+PINRemoteImage.h"; sourceTree = ""; }; - 7E7AAE96331015494FBBCC39A59D1B96 /* filter.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = filter.c; path = src/enc/filter.c; sourceTree = ""; }; - 7EC874C64657EE6521C5F4CADA9EDCE9 /* Pods-PINRemoteImage Tests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PINRemoteImage Tests-frameworks.sh"; sourceTree = ""; }; - 7F8C0B7D630C83F2B70F46CEA9682145 /* huffman_encode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = huffman_encode.h; path = src/utils/huffman_encode.h; sourceTree = ""; }; - 80B82DA42B990E96F238039BE5A37EBA /* FLAnimatedImageView+PINRemoteImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FLAnimatedImageView+PINRemoteImage.h"; sourceTree = ""; }; - 821A415254215F905B6F728586A55DB5 /* lossless_enc_mips32.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = lossless_enc_mips32.c; path = src/dsp/lossless_enc_mips32.c; sourceTree = ""; }; - 831F56F938A172850886AC53ADDCF2AF /* syntax.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = syntax.c; path = src/enc/syntax.c; sourceTree = ""; }; - 8331EC7DDFB650FEC54BD4AE78B60AD7 /* filters.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = filters.c; path = src/utils/filters.c; sourceTree = ""; }; - 83AD546FC18944E8A75A64F70663903F /* libPods-PINRemoteImage Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PINRemoteImage Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 83B6BA1A6817533C3D3C05F8DE4C6EBD /* PINRemoteImageBasicCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageBasicCache.h; sourceTree = ""; }; - 857F62222AC5FE23021A419A6FABAE82 /* thread.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = thread.h; path = src/utils/thread.h; sourceTree = ""; }; - 86DF26C20099077471AFE39C0AD1273D /* rescaler_neon.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = rescaler_neon.c; path = src/dsp/rescaler_neon.c; sourceTree = ""; }; - 88762D83F869A7C6B664BED4DCB3C31B /* enc.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = enc.c; path = src/dsp/enc.c; sourceTree = ""; }; - 8898CB4CE3A428DA8AAFDA288619C550 /* PINRemoteImage-iOS8.1.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "PINRemoteImage-iOS8.1.xcconfig"; path = "../PINRemoteImage-iOS8.1/PINRemoteImage-iOS8.1.xcconfig"; sourceTree = ""; }; - 8985F88BB7DF50762E13F4EF5068605D /* PINRemoteImage-iOS8.1-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "PINRemoteImage-iOS8.1-dummy.m"; path = "../PINRemoteImage-iOS8.1/PINRemoteImage-iOS8.1-dummy.m"; sourceTree = ""; }; - 8A294F3206E113303E2E6CB0A9399068 /* Pods-PINRemoteImage-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PINRemoteImage-frameworks.sh"; sourceTree = ""; }; - 8A4F81253F77AFADD78837236560B2D1 /* upsampling_mips_dsp_r2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = upsampling_mips_dsp_r2.c; path = src/dsp/upsampling_mips_dsp_r2.c; sourceTree = ""; }; - 8B3068DDEA7747A83391CB38DDA49680 /* vp8li.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = vp8li.h; path = src/dec/vp8li.h; sourceTree = ""; }; - 8B6992EF8D4ED26350612DA41B09241F /* thread.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = thread.c; path = src/utils/thread.c; sourceTree = ""; }; - 8CA9658CE46390D670244639D3A54EF0 /* PINRemoteImageProcessorTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageProcessorTask.m; sourceTree = ""; }; - 8FF6E5E092A0D1EF62802814D70809BF /* muxi.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = muxi.h; path = src/mux/muxi.h; sourceTree = ""; }; - 900B41D1104AA9D38B15556678CAA952 /* quant_levels_dec.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = quant_levels_dec.c; path = src/utils/quant_levels_dec.c; sourceTree = ""; }; - 909CE73A4184F9ED818B6FD4B0C7AD5F /* picture_csp.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = picture_csp.c; path = src/enc/picture_csp.c; sourceTree = ""; }; - 90B25009CF8DCC27B2B1E0BDD881DE98 /* delta_palettization.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = delta_palettization.c; path = src/enc/delta_palettization.c; sourceTree = ""; }; - 90FF34CEFA119D852ED6A6CC1B1B8F80 /* FLAnimatedImage-iOS7.1-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FLAnimatedImage-iOS7.1-dummy.m"; sourceTree = ""; }; - 9236DE015259BB06676240163A58E8E6 /* muxinternal.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = muxinternal.c; path = src/mux/muxinternal.c; sourceTree = ""; }; - 925E841ADB0E805F18D8FC6955AE572C /* Pods-PINRemoteImage Tests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PINRemoteImage Tests-resources.sh"; sourceTree = ""; }; - 92CAD77B67D37C3BEBCF08EEE0125E79 /* PINRemoteImage-iOS7.1.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "PINRemoteImage-iOS7.1.xcconfig"; sourceTree = ""; }; - 92DD85B9CBF6ACB4C29AF647E7947C9E /* anim_encode.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = anim_encode.c; path = src/mux/anim_encode.c; sourceTree = ""; }; - 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 960EF3F3E2682BEDC0ECC3C6D6225344 /* lossless_enc_sse41.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = lossless_enc_sse41.c; path = src/dsp/lossless_enc_sse41.c; sourceTree = ""; }; - 975971A0FF20F488DAAE129FF6A5675F /* bit_reader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = bit_reader.h; path = src/utils/bit_reader.h; sourceTree = ""; }; - 98045C92DCC573962703686A5442A31E /* PINProgressiveImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = PINProgressiveImage.h; sourceTree = ""; }; - 992A7463ACA2773D1A45DE756412EC26 /* PINDiskCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = PINDiskCache.h; path = PINCache/PINDiskCache.h; sourceTree = ""; }; - 9A57FF868A49947361D299813C2E1BE3 /* PINImageView+PINRemoteImage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PINImageView+PINRemoteImage.m"; sourceTree = ""; }; - 9B00C7DEBAB917F26508F71DA81CB293 /* histogram.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = histogram.c; path = src/enc/histogram.c; sourceTree = ""; }; - 9D4FE1A5D3D51B90A4893BD4A7BC1605 /* PINRemoteImageDownloadTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageDownloadTask.h; sourceTree = ""; }; - 9DB26F5092B0EA49F0FE38BC931A1651 /* PINCache-iOS7.1-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PINCache-iOS7.1-dummy.m"; sourceTree = ""; }; - 9DC66597442F789D5534FC6812440458 /* FLAnimatedImage-iOS8.1-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FLAnimatedImage-iOS8.1-prefix.pch"; path = "../FLAnimatedImage-iOS8.1/FLAnimatedImage-iOS8.1-prefix.pch"; sourceTree = ""; }; - 9DEF2E0AF657BB3C88259ABC48CFB0F9 /* muxedit.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = muxedit.c; path = src/mux/muxedit.c; sourceTree = ""; }; - 9F653D3FC69B3BFEFC81B9DD1AA0BF75 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - 9F92C25C401D4D5A02B9A9FEC78C98CE /* libFLAnimatedImage-iOS7.1.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libFLAnimatedImage-iOS7.1.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 9FEE9320DDA11EA44F7EC0BEAE701CD8 /* quant_levels.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = quant_levels.h; path = src/utils/quant_levels.h; sourceTree = ""; }; - A017B947F73B2A53533FE04E1308DBDE /* PINRemoteImageBasicCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageBasicCache.m; sourceTree = ""; }; - A0628BBA7F5A4531449289D2E671A622 /* dec_mips_dsp_r2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = dec_mips_dsp_r2.c; path = src/dsp/dec_mips_dsp_r2.c; sourceTree = ""; }; - A27E244DAE13B7010349EF92E73CB843 /* frame.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = frame.c; path = src/enc/frame.c; sourceTree = ""; }; - A423E2AE5C4D3FE4158195252AE771FC /* quant.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = quant.c; path = src/dec/quant.c; sourceTree = ""; }; - A86125E733F084E0B1A4AA8C91EDDD27 /* quant_levels_dec.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = quant_levels_dec.h; path = src/utils/quant_levels_dec.h; sourceTree = ""; }; - A9A968FCDF89B17C154C9F844504FB82 /* PINRemoteImageCallbacks.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageCallbacks.m; sourceTree = ""; }; - A9B993243629B0A6934522A6FF8CC647 /* huffman_encode.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = huffman_encode.c; path = src/utils/huffman_encode.c; sourceTree = ""; }; - AB1B0720BCB30CD11424558185D47401 /* cpu.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = cpu.c; path = src/dsp/cpu.c; sourceTree = ""; }; - AB70F892215992CEE9D1201FAD7E6AA7 /* dsp.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = dsp.h; path = src/dsp/dsp.h; sourceTree = ""; }; - AB8D811A414E3B17A5006341065E7E53 /* decode_vp8.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = decode_vp8.h; path = src/dec/decode_vp8.h; sourceTree = ""; }; - AC5CD465E603C691E9153D025D8D2CFC /* PINAnimatedImageManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = PINAnimatedImageManager.h; sourceTree = ""; }; - AC7A33E4F32F4D8E02EC3789E9742836 /* common.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = common.h; path = src/dec/common.h; sourceTree = ""; }; - ADFA5305E9873E12C2940FD012BB0DFB /* argb_sse2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = argb_sse2.c; path = src/dsp/argb_sse2.c; sourceTree = ""; }; - AE579CCAC15DEFDDC3800E74645F772C /* iterator.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = iterator.c; path = src/enc/iterator.c; sourceTree = ""; }; - AFA3D68CD9574EC464F56E813615E080 /* PINCache-iOS7.1.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "PINCache-iOS7.1.xcconfig"; sourceTree = ""; }; - B1C531F4782C6D93A9DDADBACAB004AC /* PINRemoteImageManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageManager.h; sourceTree = ""; }; - B1DCBB4BD6A8D411B0DEDE1D0FAE5D14 /* vp8l.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = vp8l.c; path = src/dec/vp8l.c; sourceTree = ""; }; - B212B272786957617807DA03F5A6ACDC /* argb_mips_dsp_r2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = argb_mips_dsp_r2.c; path = src/dsp/argb_mips_dsp_r2.c; sourceTree = ""; }; - B2812CA075AF5AEC2D81F25DDFAAAF3A /* mux_types.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = mux_types.h; path = src/webp/mux_types.h; sourceTree = ""; }; - B2DA8820D153800A564142BBB03DED79 /* Pods-PINRemoteImage.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PINRemoteImage.release.xcconfig"; sourceTree = ""; }; - B37695D6592D08B979F213F2C003B750 /* FLAnimatedImageView+PINRemoteImage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FLAnimatedImageView+PINRemoteImage.m"; sourceTree = ""; }; - B3AFF2FD5A705F1A6272A1CA3B5ED91D /* dec_mips32.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = dec_mips32.c; path = src/dsp/dec_mips32.c; sourceTree = ""; }; - B3D08B70814AF160D6E39CAA9801E8BB /* PINRemoteImageManagerResult.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageManagerResult.h; sourceTree = ""; }; - B44B9D1B673D69E0E05B22D2B8B030C0 /* alpha_processing_sse41.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = alpha_processing_sse41.c; path = src/dsp/alpha_processing_sse41.c; sourceTree = ""; }; - B4F4DE3D01E4668A8895C5133F55C194 /* vp8i.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = vp8i.h; path = src/dec/vp8i.h; sourceTree = ""; }; - B5BDAC3604CA68F6DF3522591DA86A9D /* lossless_enc_sse2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = lossless_enc_sse2.c; path = src/dsp/lossless_enc_sse2.c; sourceTree = ""; }; - B658559C59804C425D8304A290D34C1A /* cost_mips32.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = cost_mips32.c; path = src/dsp/cost_mips32.c; sourceTree = ""; }; - B6A8D042E929520D2B92010A79B74859 /* vp8l.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = vp8l.c; path = src/enc/vp8l.c; sourceTree = ""; }; - B6D792D666FFF7A9EEDA342548B2FB3B /* Pods-PINRemoteImage-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-PINRemoteImage-acknowledgements.markdown"; sourceTree = ""; }; - B914244471E11A336CDF9E038E6B7EDB /* PINRemoteImageManagerResult.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageManagerResult.m; sourceTree = ""; }; - BFE6D9A7E95710BDA480F6AD7C2C5469 /* cost_sse2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = cost_sse2.c; path = src/dsp/cost_sse2.c; sourceTree = ""; }; - C01F47D4080C1D2D7D49F894E89131F0 /* Pods-PINRemoteImage Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PINRemoteImage Tests.debug.xcconfig"; sourceTree = ""; }; - C052413F825981EA3580AD2C2BAA9225 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk/System/Library/Frameworks/Accelerate.framework; sourceTree = DEVELOPER_DIR; }; - C087C6A10F610ED0C0CB2DC0978E0685 /* enc_sse41.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = enc_sse41.c; path = src/dsp/enc_sse41.c; sourceTree = ""; }; - C0BA43AA6C1395F449AED75547A748BA /* bit_reader.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = bit_reader.c; path = src/utils/bit_reader.c; sourceTree = ""; }; - C12B7C39A3055B7482896DE405F62894 /* yuv.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = yuv.c; path = src/dsp/yuv.c; sourceTree = ""; }; - C33913D3A4FA1EBCAF451B75D9F43A0D /* PINRemoteLock.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = PINRemoteLock.m; sourceTree = ""; }; - C483ACB475ACAEBE44AD18CE8117F757 /* rescaler_sse2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = rescaler_sse2.c; path = src/dsp/rescaler_sse2.c; sourceTree = ""; }; - C537E6806181C0537F4CA286FA555A5A /* io.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = io.c; path = src/dec/io.c; sourceTree = ""; }; - C5B27422AC5A4271569EDAE97CEB6F17 /* alpha.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = alpha.c; path = src/dec/alpha.c; sourceTree = ""; }; - C76C717697954739431D4428613868BB /* FLAnimatedImage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLAnimatedImage.m; path = FLAnimatedImage/FLAnimatedImage.m; sourceTree = ""; }; - CA050687E3568100E191E089C344E42D /* dec_neon.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = dec_neon.c; path = src/dsp/dec_neon.c; sourceTree = ""; }; - CABA6B135FC75D73E56B967942E32FEE /* huffman.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = huffman.c; path = src/utils/huffman.c; sourceTree = ""; }; - CABC57871709587C1DF9AEFFEFE9DFEA /* anim_decode.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = anim_decode.c; path = src/demux/anim_decode.c; sourceTree = ""; }; - CAD335962F5F3A0DD201ACF2854E987E /* filters.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = filters.h; path = src/utils/filters.h; sourceTree = ""; }; - CBFB5FE282C260B781F33A30312627C4 /* PINCache-iOS8.1-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "PINCache-iOS8.1-dummy.m"; path = "../PINCache-iOS8.1/PINCache-iOS8.1-dummy.m"; sourceTree = ""; }; - CDB88138419C0EE00024A6430572DA08 /* idec.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = idec.c; path = src/dec/idec.c; sourceTree = ""; }; - CEBC429BF6A1E9D5A40871BABE9F2237 /* PINURLSessionManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = PINURLSessionManager.m; sourceTree = ""; }; - CF81690C1E5546DC02C0A6488E23F380 /* libPINCache-iOS7.1.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPINCache-iOS7.1.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - D175F0B2CE4974DA4A1448ED5888697D /* Pods-PINRemoteImage-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PINRemoteImage-dummy.m"; sourceTree = ""; }; - D2719F238686A19DAA50772AD0B24473 /* PINRemoteImageProcessorTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageProcessorTask.h; sourceTree = ""; }; - D2D90BC191CC2EC32436085339B86DD1 /* utils.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = utils.c; path = src/utils/utils.c; sourceTree = ""; }; - D4323D23DC4D94234A4665AD09DD60C2 /* libwebp-iOS7.1-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "libwebp-iOS7.1-dummy.m"; sourceTree = ""; }; - D48F573D6572748BB345FF5456AB1BFC /* vp8li.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = vp8li.h; path = src/enc/vp8li.h; sourceTree = ""; }; - D53423972590E5D0BC5B57B1EE01420B /* PINCacheObjectSubscripting.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = PINCacheObjectSubscripting.h; path = PINCache/PINCacheObjectSubscripting.h; sourceTree = ""; }; - D54ACF24CD711F57DD814116DE52868B /* delta_palettization.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = delta_palettization.h; path = src/enc/delta_palettization.h; sourceTree = ""; }; - D605ED50ACCB0380BF4F11E8FBBB1437 /* PINURLSessionManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = PINURLSessionManager.h; sourceTree = ""; }; - D6B09A07B11F90DFDD40A5AD07515534 /* libwebp-iOS8.1-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "libwebp-iOS8.1-prefix.pch"; path = "../libwebp-iOS8.1/libwebp-iOS8.1-prefix.pch"; sourceTree = ""; }; - D7825262E1FE9D97B12E0BC0EFB7C9BF /* enc_mips_dsp_r2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = enc_mips_dsp_r2.c; path = src/dsp/enc_mips_dsp_r2.c; sourceTree = ""; }; - DA4FCB1CD7EC1442C011DDD1DD4B6E6C /* cost.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = cost.h; path = src/enc/cost.h; sourceTree = ""; }; - DAADAE10B9B88ED018D509CB2A93E4E9 /* rescaler.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = rescaler.c; path = src/utils/rescaler.c; sourceTree = ""; }; - DAD64598A80EF9D1DB4CC444CD96C57A /* yuv_sse2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = yuv_sse2.c; path = src/dsp/yuv_sse2.c; sourceTree = ""; }; - DB369F98C5C2DEC6912E81A4826183DB /* PINCache-iOS7.1-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PINCache-iOS7.1-prefix.pch"; sourceTree = ""; }; - DCE1362772B0DA62D80285FF153F918A /* bit_writer.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = bit_writer.c; path = src/utils/bit_writer.c; sourceTree = ""; }; - DE561472C6566B906DDD13BAEDE5BE0B /* dec.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = dec.c; path = src/dsp/dec.c; sourceTree = ""; }; - E011E32618D10830CD0F3D25499CCCEF /* PINImageView+PINRemoteImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PINImageView+PINRemoteImage.h"; sourceTree = ""; }; - E04B56655A37768CB856EDF81704256C /* NSData+ImageDetectors.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "NSData+ImageDetectors.h"; sourceTree = ""; }; - E1F490854D571BFC20ECB670457326A9 /* enc_neon.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = enc_neon.c; path = src/dsp/enc_neon.c; sourceTree = ""; }; - E2AC519B2CE3D60113743C8333175D2F /* vp8.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = vp8.c; path = src/dec/vp8.c; sourceTree = ""; }; - E2B417B7135F755185072BDBF019D1F5 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; }; - E591CFAEF5F2CD91BD71C372CB895E8D /* PINDataTaskOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = PINDataTaskOperation.h; sourceTree = ""; }; - E71AA8AB9E41A467B163EE7D8A94E637 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk/System/Library/Frameworks/MobileCoreServices.framework; sourceTree = DEVELOPER_DIR; }; - E793145817656732EFAB73240C3E3178 /* token.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = token.c; path = src/enc/token.c; sourceTree = ""; }; - E7BB4BC7DDFA7807A69CF44B1E3E608D /* backward_references.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = backward_references.h; path = src/enc/backward_references.h; sourceTree = ""; }; - E7DAC4AA6FE9F930F089DD2B2D65C7D9 /* picture_psnr.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = picture_psnr.c; path = src/enc/picture_psnr.c; sourceTree = ""; }; - E83E3CE028483394478A705F4318988C /* liblibwebp-iOS7.1.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "liblibwebp-iOS7.1.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - E871FDDF751BC234DC600369D73E9C77 /* PINRemoteImageManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageManager.m; sourceTree = ""; }; - E8DC16D8343C6B5F58F22D35E08B7AFF /* PINRemoteImage-iOS7.1-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PINRemoteImage-iOS7.1-prefix.pch"; sourceTree = ""; }; - E9F82D54CEBA634D9389486AA9E39B78 /* PINRemoteImageCaching.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageCaching.h; sourceTree = ""; }; - EB021361F2B386EF7FEA0D39AE0D0560 /* mux.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = mux.h; path = src/webp/mux.h; sourceTree = ""; }; - EBCE27BD363D770E1F68A3B7BDCF3FB2 /* muxread.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = muxread.c; path = src/mux/muxread.c; sourceTree = ""; }; - EBE8E798B6138FBD9E3F50312579BFE1 /* Pods-PINRemoteImage Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-PINRemoteImage Tests-acknowledgements.markdown"; sourceTree = ""; }; - EF43DEED6C32D2DD3B05AC63D5505F1B /* libPINRemoteImage-iOS8.1.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPINRemoteImage-iOS8.1.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - EF60DC1D3E1481DC9519566EC5C8D0C5 /* quant.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = quant.c; path = src/enc/quant.c; sourceTree = ""; }; - EFCDAE94007C5CDD0791A5B8F4E8CA05 /* PINCache-iOS8.1-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "PINCache-iOS8.1-prefix.pch"; path = "../PINCache-iOS8.1/PINCache-iOS8.1-prefix.pch"; sourceTree = ""; }; - F3E75D9D8C09CBFE7162CD18A14C4716 /* PINImage+DecodedImage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PINImage+DecodedImage.m"; sourceTree = ""; }; - F4502839F40C1A395760CF3DEA205151 /* Pods-PINRemoteImage Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PINRemoteImage Tests-acknowledgements.plist"; sourceTree = ""; }; - F49122722A201003F15B56C830C3975F /* random.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = random.c; path = src/utils/random.c; sourceTree = ""; }; - F51BB56D203552472AFC17DE1E99A7C3 /* webp.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = webp.c; path = src/dec/webp.c; sourceTree = ""; }; - F5262B915274A6E95421C1E0556EC8C4 /* alpha_processing_sse2.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = alpha_processing_sse2.c; path = src/dsp/alpha_processing_sse2.c; sourceTree = ""; }; - F706B7B31C8ECF7E9D2D8B6EC43DE601 /* PINProgressiveImage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = PINProgressiveImage.m; sourceTree = ""; }; - F80CC86086FB5C08BE0F5EEA364B93E1 /* libwebp-iOS8.1-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "libwebp-iOS8.1-dummy.m"; path = "../libwebp-iOS8.1/libwebp-iOS8.1-dummy.m"; sourceTree = ""; }; - FA9E654456C8CA829913FDD7536692A7 /* FLAnimatedImage-iOS8.1-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FLAnimatedImage-iOS8.1-dummy.m"; path = "../FLAnimatedImage-iOS8.1/FLAnimatedImage-iOS8.1-dummy.m"; sourceTree = ""; }; - FC2F9C0051E45C7BCEBE9E395DD25DC0 /* huffman.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = huffman.h; path = src/utils/huffman.h; sourceTree = ""; }; - FE935F7066F02B06DF140D5544510623 /* lossless_enc_neon.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = lossless_enc_neon.c; path = src/dsp/lossless_enc_neon.c; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 024376E8671A81E874A6F988B23DAC81 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - AC0F7191B65E6682625781934C0A52DB /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 2DBDFCC62D6790976C21261E967ECF85 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 02E802429A2747CD95DCF3B4F2B3F94F /* CoreGraphics.framework in Frameworks */, - C44474CE15DC5BE147B38AA1165CE8E4 /* Foundation.framework in Frameworks */, - CEE70E951B78CEC003D017F87591662B /* ImageIO.framework in Frameworks */, - 40085A09349758FCED4B6F68D90D61DC /* MobileCoreServices.framework in Frameworks */, - 97844C6E07440AE25CF333BB7306B0E0 /* QuartzCore.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3D66F1CD9AAE6BBDD17C217D2BDA74D4 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 483AAAD521A4A5256EDB61B4F2C28A73 /* Accelerate.framework in Frameworks */, - DFD406C814E3F1C096705EA7E82B263B /* Foundation.framework in Frameworks */, - 602846CB9212541EDB9D3C551AC1D30D /* ImageIO.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4EFF950FC490FE65279D048D18B9AB57 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 90FA2D3C61AD0C533AE59261AD685431 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 5E26864A97E9EBDE2CDAEE5F36C6B9C2 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 29EC8E6F7ED1C97F2351F78E11A3E97E /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - CA5171DB8F301B582A6F317514FF665C /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - A2797145317F8EC9F1DAF861062EC457 /* Accelerate.framework in Frameworks */, - E1AB0DCB025C237D0A7FFC697EBB7FF1 /* Foundation.framework in Frameworks */, - FE38EA8B299B98D6094D0B8B323D113A /* ImageIO.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - EB86966E567965E78DDCD6E6EF4F8F68 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 0EF938859AC555711FB24EF2ED55289E /* CoreGraphics.framework in Frameworks */, - 8EAF427B87A2343FC061E16E19C337E9 /* Foundation.framework in Frameworks */, - 65FFAC6A25CFE46E1C158C4ECB7DB6C8 /* ImageIO.framework in Frameworks */, - 0941B1D7A5A3111C716A8526CC4D38F9 /* MobileCoreServices.framework in Frameworks */, - 720017A8DE59D1E43870315443628B85 /* QuartzCore.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - F36166F704E8BEE42160CCBC7F75C0A2 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 0EFE7B96B2149B3ABE435F19D532FAF6 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - FE299AB28B03D90A191D8CFBD8B31455 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 97A860A44F9C02143E32528592862B7A /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - FE2E97B2EBDEFE715269D8160DE1F82C /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 0D36A73EFC1A549A612B415016DE55B9 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 030537BAFDD8F41975D8F3F973EB201D /* Image Categories */ = { - isa = PBXGroup; - children = ( - 7B4310C5981857705080A1761894CFCE /* PINButton+PINRemoteImage.h */, - 1CE105A1A011FADA79F2388F6F937318 /* PINButton+PINRemoteImage.m */, - E011E32618D10830CD0F3D25499CCCEF /* PINImageView+PINRemoteImage.h */, - 9A57FF868A49947361D299813C2E1BE3 /* PINImageView+PINRemoteImage.m */, - ); - path = "Image Categories"; - sourceTree = ""; - }; - 0F75DF6C7C5F002280EC53F48E80B587 /* Frameworks */ = { - isa = PBXGroup; - children = ( - ADD521F825DB12A7D43A23CE3CF166A7 /* iOS */, - ); - name = Frameworks; - sourceTree = ""; - }; - 16DC906C97716507CA9874432FD75C6A /* PINCache */ = { - isa = PBXGroup; - children = ( - 3BDA9F9CCAAE9C786BBC5CAF0F2F873C /* Nullability.h */, - 05CAFFE052DEC8B9F74C9E2D232E3A83 /* PINCache.h */, - 353C5D5A0588CE212B0F00A2C48517DD /* PINCache.m */, - D53423972590E5D0BC5B57B1EE01420B /* PINCacheObjectSubscripting.h */, - 992A7463ACA2773D1A45DE756412EC26 /* PINDiskCache.h */, - 218578CA992697AB822E5806F687651E /* PINDiskCache.m */, - 39135D20E627D5ACB184DC61598D908A /* PINMemoryCache.h */, - 10E39F3E241AEAEEA46F13D5AB934E8C /* PINMemoryCache.m */, - 706AFC82122E7D73E61824F253C319B2 /* Support Files */, - ); - path = PINCache; - sourceTree = ""; - }; - 1899A515500D0ACE21642792DDE55586 /* Classes */ = { - isa = PBXGroup; - children = ( - A8DF18413A1274DD2070FF1B99038367 /* Image Categories */, - ); - path = Classes; - sourceTree = ""; - }; - 1ADC944728D1EC76DD9D61E6E3C352CC /* PINCache */ = { - isa = PBXGroup; - children = ( - 5E552CA74498CDAF688A643373EE5F59 /* PINCache+PINRemoteImageCaching.h */, - 7159655540FAD47DEEC9556993CCEE72 /* PINCache+PINRemoteImageCaching.m */, - ); - path = PINCache; - sourceTree = ""; - }; - 224CFEE2C7BD14B124F137CB64B5FBB4 /* FLAnimatedImage */ = { - isa = PBXGroup; - children = ( - AB14623F966B7A9E001F095CADC32E2B /* Pod */, - ); - name = FLAnimatedImage; - sourceTree = ""; - }; - 22A52AAD1EE943CE17A3EF447DB848C7 /* Targets Support Files */ = { - isa = PBXGroup; - children = ( - D9E5AD6F99DB843F94B9C670DAEA79CC /* Pods-PINRemoteImage */, - 5BDBA0AA4F2B35D55707AB81D8831346 /* Pods-PINRemoteImage Tests */, - ); - name = "Targets Support Files"; - sourceTree = ""; - }; - 3389019077CC8544427FEDFEC1F11A91 /* FLAnimatedImage */ = { - isa = PBXGroup; - children = ( - 558FF321A05CF84D6DD288EB5131A91A /* FLAnimatedImage.h */, - C76C717697954739431D4428613868BB /* FLAnimatedImage.m */, - 1AB8299DE2EE7A81F628229C2DE4475F /* FLAnimatedImageView.h */, - 0408075B9809BA3BEE318DC659E50B01 /* FLAnimatedImageView.m */, - 80E73BA392408BCA43E8E67C5067DEE1 /* Support Files */, - ); - path = FLAnimatedImage; - sourceTree = ""; - }; - 43CC7AEB2A369D1955DA46FC9C2EA709 /* Pod */ = { - isa = PBXGroup; - children = ( - F34665D3C8A092C24D6305F2BD9A22AC /* Classes */, - ); - path = Pod; - sourceTree = ""; - }; - 493D0521BC724D54BC9CA9CC98A15582 /* Support Files */ = { - isa = PBXGroup; - children = ( - 6AAB128F5E8D4D59D34CA86049D051BF /* libwebp-iOS7.1.xcconfig */, - D4323D23DC4D94234A4665AD09DD60C2 /* libwebp-iOS7.1-dummy.m */, - 0E0409379FF7ECC8CD099D8BB8F2BC75 /* libwebp-iOS7.1-prefix.pch */, - 57C7DA2DFA0213BB337A4A1989FA1E10 /* libwebp-iOS8.1.xcconfig */, - F80CC86086FB5C08BE0F5EEA364B93E1 /* libwebp-iOS8.1-dummy.m */, - D6B09A07B11F90DFDD40A5AD07515534 /* libwebp-iOS8.1-prefix.pch */, - ); - name = "Support Files"; - path = "../Target Support Files/libwebp-iOS7.1"; - sourceTree = ""; - }; - 4A3C5C33FDAB2F7DB5407C29ABEEF000 /* libwebp */ = { - isa = PBXGroup; - children = ( - 8E5DC8D0C5E1B7E9E0FAC57D9A73A739 /* core */, - 68ADF359D71538BA5F890FB6FF141248 /* demux */, - 93B25F2CE6D15BD0E058EEA7813A872A /* mux */, - 493D0521BC724D54BC9CA9CC98A15582 /* Support Files */, - 8A16533F359DEB0E0527475E759B3B47 /* webp */, - ); - path = libwebp; - sourceTree = ""; - }; - 5BDBA0AA4F2B35D55707AB81D8831346 /* Pods-PINRemoteImage Tests */ = { - isa = PBXGroup; - children = ( - EBE8E798B6138FBD9E3F50312579BFE1 /* Pods-PINRemoteImage Tests-acknowledgements.markdown */, - F4502839F40C1A395760CF3DEA205151 /* Pods-PINRemoteImage Tests-acknowledgements.plist */, - 4A57EB68D6EE28230332CD41E941F6F4 /* Pods-PINRemoteImage Tests-dummy.m */, - 7EC874C64657EE6521C5F4CADA9EDCE9 /* Pods-PINRemoteImage Tests-frameworks.sh */, - 925E841ADB0E805F18D8FC6955AE572C /* Pods-PINRemoteImage Tests-resources.sh */, - C01F47D4080C1D2D7D49F894E89131F0 /* Pods-PINRemoteImage Tests.debug.xcconfig */, - 13E434C0AE2F99377B4587AE15199116 /* Pods-PINRemoteImage Tests.release.xcconfig */, - ); - name = "Pods-PINRemoteImage Tests"; - path = "Target Support Files/Pods-PINRemoteImage Tests"; - sourceTree = ""; - }; - 6528EAAB7F722A401153BB3A21D11638 /* Core */ = { - isa = PBXGroup; - children = ( - 70A82B1F8D9DB5F5A40DF189404EE56C /* Pod */, - ); - name = Core; - sourceTree = ""; - }; - 68ADF359D71538BA5F890FB6FF141248 /* demux */ = { - isa = PBXGroup; - children = ( - CABC57871709587C1DF9AEFFEFE9DFEA /* anim_decode.c */, - 688B52EC5BB98FF5D63599C29DFC312A /* demux.c */, - ); - name = demux; - sourceTree = ""; - }; - 706AFC82122E7D73E61824F253C319B2 /* Support Files */ = { - isa = PBXGroup; - children = ( - AFA3D68CD9574EC464F56E813615E080 /* PINCache-iOS7.1.xcconfig */, - 9DB26F5092B0EA49F0FE38BC931A1651 /* PINCache-iOS7.1-dummy.m */, - DB369F98C5C2DEC6912E81A4826183DB /* PINCache-iOS7.1-prefix.pch */, - 3268D31245A99137C0933AF68F05DBBA /* PINCache-iOS8.1.xcconfig */, - CBFB5FE282C260B781F33A30312627C4 /* PINCache-iOS8.1-dummy.m */, - EFCDAE94007C5CDD0791A5B8F4E8CA05 /* PINCache-iOS8.1-prefix.pch */, - ); - name = "Support Files"; - path = "../Target Support Files/PINCache-iOS7.1"; - sourceTree = ""; - }; - 70A82B1F8D9DB5F5A40DF189404EE56C /* Pod */ = { - isa = PBXGroup; - children = ( - CF9AB2C1E145CD1F1DB6FE4087977FFE /* Classes */, - ); - path = Pod; - sourceTree = ""; - }; - 7508908D12F8631BCCC8D9169014D84C /* Products */ = { - isa = PBXGroup; - children = ( - 9F92C25C401D4D5A02B9A9FEC78C98CE /* libFLAnimatedImage-iOS7.1.a */, - 023E4D6CDD5B2AE15094E18B317A97F4 /* libFLAnimatedImage-iOS8.1.a */, - E83E3CE028483394478A705F4318988C /* liblibwebp-iOS7.1.a */, - 6F579E1BD144AC8C4974FDE70107BE70 /* liblibwebp-iOS8.1.a */, - CF81690C1E5546DC02C0A6488E23F380 /* libPINCache-iOS7.1.a */, - 64A2DC53D4E243C57B9AAE1310B85AFC /* libPINCache-iOS8.1.a */, - 4D6B18220592A6A66D54E1EDA2B6ABE6 /* libPINRemoteImage-iOS7.1.a */, - EF43DEED6C32D2DD3B05AC63D5505F1B /* libPINRemoteImage-iOS8.1.a */, - 30CF9B4AAE62C4612A11127E869B1D76 /* libPods-PINRemoteImage.a */, - 83AD546FC18944E8A75A64F70663903F /* libPods-PINRemoteImage Tests.a */, - ); - name = Products; - sourceTree = ""; - }; - 757B34F6EB0DD0147BCC83315D361322 /* Pods */ = { - isa = PBXGroup; - children = ( - 3389019077CC8544427FEDFEC1F11A91 /* FLAnimatedImage */, - 4A3C5C33FDAB2F7DB5407C29ABEEF000 /* libwebp */, - 16DC906C97716507CA9874432FD75C6A /* PINCache */, - ); - name = Pods; - sourceTree = ""; - }; - 7DB346D0F39D3F0E887471402A8071AB = { - isa = PBXGroup; - children = ( - 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, - 949599385D4FF2FF1B0CCBB3B8CB601B /* Development Pods */, - 0F75DF6C7C5F002280EC53F48E80B587 /* Frameworks */, - 757B34F6EB0DD0147BCC83315D361322 /* Pods */, - 7508908D12F8631BCCC8D9169014D84C /* Products */, - 22A52AAD1EE943CE17A3EF447DB848C7 /* Targets Support Files */, - ); - sourceTree = ""; - }; - 80E73BA392408BCA43E8E67C5067DEE1 /* Support Files */ = { - isa = PBXGroup; - children = ( - 5A3A10263F91713FAA7A0DF102A64451 /* FLAnimatedImage-iOS7.1.xcconfig */, - 90FF34CEFA119D852ED6A6CC1B1B8F80 /* FLAnimatedImage-iOS7.1-dummy.m */, - 79E6D85CF8A0B7F8AD014890501095BE /* FLAnimatedImage-iOS7.1-prefix.pch */, - 655D1EAFD3BB047F093C9F5514DEA4D9 /* FLAnimatedImage-iOS8.1.xcconfig */, - FA9E654456C8CA829913FDD7536692A7 /* FLAnimatedImage-iOS8.1-dummy.m */, - 9DC66597442F789D5534FC6812440458 /* FLAnimatedImage-iOS8.1-prefix.pch */, - ); - name = "Support Files"; - path = "../Target Support Files/FLAnimatedImage-iOS7.1"; - sourceTree = ""; - }; - 85229F7C60D8473AEF3E6476A7B2AD6A /* PINRemoteImage */ = { - isa = PBXGroup; - children = ( - 6528EAAB7F722A401153BB3A21D11638 /* Core */, - 224CFEE2C7BD14B124F137CB64B5FBB4 /* FLAnimatedImage */, - 9C31BDC07A6CBC1699EAF2828610AEA6 /* PINCache */, - A3D8AE244B32CFC4991C66CB2CF1CDB3 /* Support Files */, - ); - name = PINRemoteImage; - path = ../..; - sourceTree = ""; - }; - 8A16533F359DEB0E0527475E759B3B47 /* webp */ = { - isa = PBXGroup; - children = ( - 178041EA65EA2643FFB1544EAD15F133 /* decode.h */, - 5D7930163300F707135002DE80BA19E1 /* demux.h */, - 2142E43008910E5C9A147EDAC81F1662 /* encode.h */, - 5713CD0A1EDCA136A95924D0E6ACD21E /* extras.h */, - 4C2F77853D7A7DB311300B17CE0414EF /* format_constants.h */, - EB021361F2B386EF7FEA0D39AE0D0560 /* mux.h */, - B2812CA075AF5AEC2D81F25DDFAAAF3A /* mux_types.h */, - 2CFB1F82C8F950BD532D24B2D775E949 /* types.h */, - ); - name = webp; - sourceTree = ""; - }; - 8E5DC8D0C5E1B7E9E0FAC57D9A73A739 /* core */ = { - isa = PBXGroup; - children = ( - C5B27422AC5A4271569EDAE97CEB6F17 /* alpha.c */, - 47C707489874CA3F2940F2443E636576 /* alpha.c */, - 714789E6925BC6E7F73ACEFAF20258EB /* alpha_processing.c */, - 35EEAA1915188D7B44AA3552D66E37EF /* alpha_processing_mips_dsp_r2.c */, - F5262B915274A6E95421C1E0556EC8C4 /* alpha_processing_sse2.c */, - B44B9D1B673D69E0E05B22D2B8B030C0 /* alpha_processing_sse41.c */, - 15B4758BE6AB13C24A0835A3458E330F /* alphai.h */, - 53D3A890AAD5ADC707F4A9DD52D27B85 /* analysis.c */, - 0BF65A93624E241BB3B897C3724E9D8A /* argb.c */, - B212B272786957617807DA03F5A6ACDC /* argb_mips_dsp_r2.c */, - ADFA5305E9873E12C2940FD012BB0DFB /* argb_sse2.c */, - 77EF39AD51321F512B7910275CB80B19 /* backward_references.c */, - E7BB4BC7DDFA7807A69CF44B1E3E608D /* backward_references.h */, - C0BA43AA6C1395F449AED75547A748BA /* bit_reader.c */, - 975971A0FF20F488DAAE129FF6A5675F /* bit_reader.h */, - 012F1030350DF34F33932A2AF9828649 /* bit_reader_inl.h */, - DCE1362772B0DA62D80285FF153F918A /* bit_writer.c */, - 0FD5C78A000F1B4C9FD43E7995E11641 /* bit_writer.h */, - 60503AC34B0481BC03680C73779DED60 /* buffer.c */, - 3B962ABB7F8EAC0B911CFD84D66A3651 /* color_cache.c */, - 64AA202FCC931C3E07178134DFCF081A /* color_cache.h */, - AC7A33E4F32F4D8E02EC3789E9742836 /* common.h */, - 720EF0FAD6D5850D1E07D55056EC185C /* config.c */, - 32D0C42B671BE1D9F1D5969FA9335AF8 /* cost.c */, - 1CD9DEA21FB30AB73C90C0099E927785 /* cost.c */, - DA4FCB1CD7EC1442C011DDD1DD4B6E6C /* cost.h */, - B658559C59804C425D8304A290D34C1A /* cost_mips32.c */, - 1DA7B7E3D3641D4BB5A28D94B23BB252 /* cost_mips_dsp_r2.c */, - BFE6D9A7E95710BDA480F6AD7C2C5469 /* cost_sse2.c */, - AB1B0720BCB30CD11424558185D47401 /* cpu.c */, - DE561472C6566B906DDD13BAEDE5BE0B /* dec.c */, - 41AC5A8B3E67A5B68BB3007A55D78284 /* dec_clip_tables.c */, - B3AFF2FD5A705F1A6272A1CA3B5ED91D /* dec_mips32.c */, - A0628BBA7F5A4531449289D2E671A622 /* dec_mips_dsp_r2.c */, - CA050687E3568100E191E089C344E42D /* dec_neon.c */, - 5213EDAF6EDAD2E561B5C6012EF83DFB /* dec_sse2.c */, - 0265BE2D31AEDDDF41979FBC57354C8E /* dec_sse41.c */, - AB8D811A414E3B17A5006341065E7E53 /* decode_vp8.h */, - 90B25009CF8DCC27B2B1E0BDD881DE98 /* delta_palettization.c */, - D54ACF24CD711F57DD814116DE52868B /* delta_palettization.h */, - AB70F892215992CEE9D1201FAD7E6AA7 /* dsp.h */, - 88762D83F869A7C6B664BED4DCB3C31B /* enc.c */, - 58227BA313D46A3CDB4831FC0D7ADF54 /* enc_avx2.c */, - 77A2E23106484646CA6EEBE045B82D53 /* enc_mips32.c */, - D7825262E1FE9D97B12E0BC0EFB7C9BF /* enc_mips_dsp_r2.c */, - E1F490854D571BFC20ECB670457326A9 /* enc_neon.c */, - 4C46F1514984FFF0EAD26E2194696DFC /* enc_sse2.c */, - C087C6A10F610ED0C0CB2DC0978E0685 /* enc_sse41.c */, - 5E5C6A79473815063434E0F2E4D29520 /* endian_inl.h */, - 7E7AAE96331015494FBBCC39A59D1B96 /* filter.c */, - 8331EC7DDFB650FEC54BD4AE78B60AD7 /* filters.c */, - 3C104E4BDC519CBCA922579793F444D3 /* filters.c */, - CAD335962F5F3A0DD201ACF2854E987E /* filters.h */, - 744BA9C83EECD0D33C50E4A9687206BE /* filters_mips_dsp_r2.c */, - 1EAAED9854572A4C16435ECE5BFAAE92 /* filters_sse2.c */, - 63C5FDB95E938EB802C2DAE3D5FEF41A /* frame.c */, - A27E244DAE13B7010349EF92E73CB843 /* frame.c */, - 9B00C7DEBAB917F26508F71DA81CB293 /* histogram.c */, - 79FBFC39E41814D081F1DF303B6D4C1A /* histogram.h */, - CABA6B135FC75D73E56B967942E32FEE /* huffman.c */, - FC2F9C0051E45C7BCEBE9E395DD25DC0 /* huffman.h */, - A9B993243629B0A6934522A6FF8CC647 /* huffman_encode.c */, - 7F8C0B7D630C83F2B70F46CEA9682145 /* huffman_encode.h */, - CDB88138419C0EE00024A6430572DA08 /* idec.c */, - C537E6806181C0537F4CA286FA555A5A /* io.c */, - AE579CCAC15DEFDDC3800E74645F772C /* iterator.c */, - 7215A5A771C283D41302F2FD6D751C77 /* lossless.c */, - 214C7FB9ABE1F5CCDE0BC288B08841F8 /* lossless.h */, - 4B08BAC88FCA48253326E775CB905235 /* lossless_enc.c */, - 821A415254215F905B6F728586A55DB5 /* lossless_enc_mips32.c */, - 5AA3AE62661D5123483F17B85E6BAF50 /* lossless_enc_mips_dsp_r2.c */, - FE935F7066F02B06DF140D5544510623 /* lossless_enc_neon.c */, - B5BDAC3604CA68F6DF3522591DA86A9D /* lossless_enc_sse2.c */, - 960EF3F3E2682BEDC0ECC3C6D6225344 /* lossless_enc_sse41.c */, - 6CC19C6C38FE732E8FAFADB273C4B875 /* lossless_mips_dsp_r2.c */, - 1B3E18DE80BF2A17C07E6E4E0FE6EFA3 /* lossless_neon.c */, - 5C6A9B308BA81A975671A7F75DB8A30B /* lossless_sse2.c */, - 563F4A6251F82426B5EAB251160C8F6A /* mips_macro.h */, - 1D9A6E336BC1B20D20200A15DE97FE07 /* near_lossless.c */, - 1FD7680EFC0A084A1A1A16727F5A5DCE /* neon.h */, - 607EC80E69037007634D0D09576D75E0 /* picture.c */, - 909CE73A4184F9ED818B6FD4B0C7AD5F /* picture_csp.c */, - E7DAC4AA6FE9F930F089DD2B2D65C7D9 /* picture_psnr.c */, - 78CC59F8F4E9458E2D49B281A07F2229 /* picture_rescale.c */, - 2DBA42E7A3D98AE56EF0A752F8765AFD /* picture_tools.c */, - A423E2AE5C4D3FE4158195252AE771FC /* quant.c */, - EF60DC1D3E1481DC9519566EC5C8D0C5 /* quant.c */, - 2C3CB475C14C8FFDDBA319BA4426B6CD /* quant_levels.c */, - 9FEE9320DDA11EA44F7EC0BEAE701CD8 /* quant_levels.h */, - 900B41D1104AA9D38B15556678CAA952 /* quant_levels_dec.c */, - A86125E733F084E0B1A4AA8C91EDDD27 /* quant_levels_dec.h */, - F49122722A201003F15B56C830C3975F /* random.c */, - 10455FA91AE1DBB54A2B812BAF2EC295 /* random.h */, - DAADAE10B9B88ED018D509CB2A93E4E9 /* rescaler.c */, - 5372CA4722349B8FCC016DA0822A78F6 /* rescaler.c */, - 4D33BD68BF9C7D2AC6CB42E164315EA9 /* rescaler.h */, - 5355B95420BA4CA130B1B5BC2D0006F1 /* rescaler_mips32.c */, - 6E9A9E3F63F1FB1AD85D544D51E6E2D5 /* rescaler_mips_dsp_r2.c */, - 86DF26C20099077471AFE39C0AD1273D /* rescaler_neon.c */, - C483ACB475ACAEBE44AD18CE8117F757 /* rescaler_sse2.c */, - 831F56F938A172850886AC53ADDCF2AF /* syntax.c */, - 8B6992EF8D4ED26350612DA41B09241F /* thread.c */, - 857F62222AC5FE23021A419A6FABAE82 /* thread.h */, - E793145817656732EFAB73240C3E3178 /* token.c */, - 4802610EC3465AB540B7BA5AC1EC96C5 /* tree.c */, - 1327B68AD49FAD487BA67EFF160D3A70 /* tree.c */, - 0B594F7A5FFADE39C151EC797AB9F489 /* upsampling.c */, - 8A4F81253F77AFADD78837236560B2D1 /* upsampling_mips_dsp_r2.c */, - 3ADF044BE12A8FF02BDA7BB32E55E8CF /* upsampling_neon.c */, - 733AB1F236FE28D441E92925A1A571F2 /* upsampling_sse2.c */, - D2D90BC191CC2EC32436085339B86DD1 /* utils.c */, - 37875A249C725E0B8CC778FE3CBFDBE3 /* utils.h */, - E2AC519B2CE3D60113743C8333175D2F /* vp8.c */, - 150B366BB8208A11274B6720E4B82BAA /* vp8enci.h */, - B4F4DE3D01E4668A8895C5133F55C194 /* vp8i.h */, - B1DCBB4BD6A8D411B0DEDE1D0FAE5D14 /* vp8l.c */, - B6A8D042E929520D2B92010A79B74859 /* vp8l.c */, - 8B3068DDEA7747A83391CB38DDA49680 /* vp8li.h */, - D48F573D6572748BB345FF5456AB1BFC /* vp8li.h */, - F51BB56D203552472AFC17DE1E99A7C3 /* webp.c */, - 6CD3BA129EC620FCE4B6A1CEFB684EBB /* webpenc.c */, - 4EEB0E6DB39F528015E402B09A21080B /* webpi.h */, - C12B7C39A3055B7482896DE405F62894 /* yuv.c */, - 43D58C7F209EF668DC65D9780ADE2755 /* yuv.h */, - 15E1E4CED8473ECB3201D807233DBD5B /* yuv_mips32.c */, - 0F2199A6FDC473EB4F09E6EE25244613 /* yuv_mips_dsp_r2.c */, - DAD64598A80EF9D1DB4CC444CD96C57A /* yuv_sse2.c */, - ); - name = core; - sourceTree = ""; - }; - 93B25F2CE6D15BD0E058EEA7813A872A /* mux */ = { - isa = PBXGroup; - children = ( - 92DD85B9CBF6ACB4C29AF647E7947C9E /* anim_encode.c */, - 9DEF2E0AF657BB3C88259ABC48CFB0F9 /* muxedit.c */, - 8FF6E5E092A0D1EF62802814D70809BF /* muxi.h */, - 9236DE015259BB06676240163A58E8E6 /* muxinternal.c */, - EBCE27BD363D770E1F68A3B7BDCF3FB2 /* muxread.c */, - ); - name = mux; - sourceTree = ""; - }; - 949599385D4FF2FF1B0CCBB3B8CB601B /* Development Pods */ = { - isa = PBXGroup; - children = ( - 85229F7C60D8473AEF3E6476A7B2AD6A /* PINRemoteImage */, - ); - name = "Development Pods"; - sourceTree = ""; - }; - 9C31BDC07A6CBC1699EAF2828610AEA6 /* PINCache */ = { - isa = PBXGroup; - children = ( - 43CC7AEB2A369D1955DA46FC9C2EA709 /* Pod */, - ); - name = PINCache; - sourceTree = ""; - }; - A3D8AE244B32CFC4991C66CB2CF1CDB3 /* Support Files */ = { - isa = PBXGroup; - children = ( - 92CAD77B67D37C3BEBCF08EEE0125E79 /* PINRemoteImage-iOS7.1.xcconfig */, - 111CFE021EA510C1C36F4E1BD9DB2555 /* PINRemoteImage-iOS7.1-dummy.m */, - E8DC16D8343C6B5F58F22D35E08B7AFF /* PINRemoteImage-iOS7.1-prefix.pch */, - 8898CB4CE3A428DA8AAFDA288619C550 /* PINRemoteImage-iOS8.1.xcconfig */, - 8985F88BB7DF50762E13F4EF5068605D /* PINRemoteImage-iOS8.1-dummy.m */, - 09B1CEDC1BC1C6533A03C6091562729C /* PINRemoteImage-iOS8.1-prefix.pch */, - ); - name = "Support Files"; - path = "Example/Pods/Target Support Files/PINRemoteImage-iOS7.1"; - sourceTree = ""; - }; - A8DF18413A1274DD2070FF1B99038367 /* Image Categories */ = { - isa = PBXGroup; - children = ( - 80B82DA42B990E96F238039BE5A37EBA /* FLAnimatedImageView+PINRemoteImage.h */, - B37695D6592D08B979F213F2C003B750 /* FLAnimatedImageView+PINRemoteImage.m */, - ); - path = "Image Categories"; - sourceTree = ""; - }; - AB14623F966B7A9E001F095CADC32E2B /* Pod */ = { - isa = PBXGroup; - children = ( - 1899A515500D0ACE21642792DDE55586 /* Classes */, - ); - path = Pod; - sourceTree = ""; - }; - ADD521F825DB12A7D43A23CE3CF166A7 /* iOS */ = { - isa = PBXGroup; - children = ( - C052413F825981EA3580AD2C2BAA9225 /* Accelerate.framework */, - 47EB0BBBD227E352F0C654CB221746E0 /* CoreGraphics.framework */, - 9F653D3FC69B3BFEFC81B9DD1AA0BF75 /* Foundation.framework */, - 6D8947C70EA881CAD337102B182D2DBF /* ImageIO.framework */, - E71AA8AB9E41A467B163EE7D8A94E637 /* MobileCoreServices.framework */, - E2B417B7135F755185072BDBF019D1F5 /* QuartzCore.framework */, - ); - name = iOS; - sourceTree = ""; - }; - C89F5D029794B69DC39B4F7122AB9AB5 /* Categories */ = { - isa = PBXGroup; - children = ( - E04B56655A37768CB856EDF81704256C /* NSData+ImageDetectors.h */, - 3F2100B7E15B9D7C1D70F7F01174BB81 /* NSData+ImageDetectors.m */, - 6C86AEDFA5808330AAA01B76F53B5D40 /* PINImage+DecodedImage.h */, - F3E75D9D8C09CBFE7162CD18A14C4716 /* PINImage+DecodedImage.m */, - 4D8C8832F2576E41299095AC0BC38FD2 /* PINImage+WebP.h */, - 64FD5BDCFA1A3C5B288A2DB7DC091DD3 /* PINImage+WebP.m */, - ); - path = Categories; - sourceTree = ""; - }; - CF9AB2C1E145CD1F1DB6FE4087977FFE /* Classes */ = { - isa = PBXGroup; - children = ( - 3B1DDAD593621215D969D96E5F5C2725 /* PINAlternateRepresentationProvider.h */, - 6E90DD20CCBAD11352D18410B28108A3 /* PINAlternateRepresentationProvider.m */, - 1CF8C86EE887925394FB2A05EB8A9E70 /* PINAnimatedImage.h */, - 38F931A84A926D8ED6C79AC8C84CCF6E /* PINAnimatedImage.m */, - AC5CD465E603C691E9153D025D8D2CFC /* PINAnimatedImageManager.h */, - 43FC6C68D40F5409F8795B7319466C3F /* PINAnimatedImageManager.m */, - E591CFAEF5F2CD91BD71C372CB895E8D /* PINDataTaskOperation.h */, - 6D421C79F2B006908434D7B1DE81F780 /* PINDataTaskOperation.m */, - 98045C92DCC573962703686A5442A31E /* PINProgressiveImage.h */, - F706B7B31C8ECF7E9D2D8B6EC43DE601 /* PINProgressiveImage.m */, - 0C970CB7D9C79058AD603908B77D5EE1 /* PINRemoteImage.h */, - 83B6BA1A6817533C3D3C05F8DE4C6EBD /* PINRemoteImageBasicCache.h */, - A017B947F73B2A53533FE04E1308DBDE /* PINRemoteImageBasicCache.m */, - E9F82D54CEBA634D9389486AA9E39B78 /* PINRemoteImageCaching.h */, - 0F72C99527F0AAF04B3A624B82F080B4 /* PINRemoteImageCallbacks.h */, - A9A968FCDF89B17C154C9F844504FB82 /* PINRemoteImageCallbacks.m */, - 7772A566D5A8C0E3A5857ABA92C85E3F /* PINRemoteImageCategoryManager.h */, - 30C87FA0395C40393C9A5FEBD3D9A487 /* PINRemoteImageCategoryManager.m */, - 9D4FE1A5D3D51B90A4893BD4A7BC1605 /* PINRemoteImageDownloadTask.h */, - 2DFC450DABA13FA7A6DACB2563DF4EBB /* PINRemoteImageDownloadTask.m */, - 0DEA87E879DA96FE8179AB7E3437FAF0 /* PINRemoteImageMacros.h */, - B1C531F4782C6D93A9DDADBACAB004AC /* PINRemoteImageManager.h */, - E871FDDF751BC234DC600369D73E9C77 /* PINRemoteImageManager.m */, - B3D08B70814AF160D6E39CAA9801E8BB /* PINRemoteImageManagerResult.h */, - B914244471E11A336CDF9E038E6B7EDB /* PINRemoteImageManagerResult.m */, - 33EFDCCA6725B6A025C0CE6D742C9492 /* PINRemoteImageMemoryContainer.h */, - 2407DB71ABCF28A8467E8CF5BAF27BD9 /* PINRemoteImageMemoryContainer.m */, - D2719F238686A19DAA50772AD0B24473 /* PINRemoteImageProcessorTask.h */, - 8CA9658CE46390D670244639D3A54EF0 /* PINRemoteImageProcessorTask.m */, - 1241DFD8FFEAE74881C679C4BFAAF0CB /* PINRemoteImageTask.h */, - 49BA8E48355843D4444348D2F3CE5A2A /* PINRemoteImageTask.m */, - 0B774580FBBDC1A0407CCFD9E6B7E981 /* PINRemoteLock.h */, - C33913D3A4FA1EBCAF451B75D9F43A0D /* PINRemoteLock.m */, - D605ED50ACCB0380BF4F11E8FBBB1437 /* PINURLSessionManager.h */, - CEBC429BF6A1E9D5A40871BABE9F2237 /* PINURLSessionManager.m */, - C89F5D029794B69DC39B4F7122AB9AB5 /* Categories */, - 030537BAFDD8F41975D8F3F973EB201D /* Image Categories */, - ); - path = Classes; - sourceTree = ""; - }; - D9E5AD6F99DB843F94B9C670DAEA79CC /* Pods-PINRemoteImage */ = { - isa = PBXGroup; - children = ( - B6D792D666FFF7A9EEDA342548B2FB3B /* Pods-PINRemoteImage-acknowledgements.markdown */, - 0EC0DF5B2E9F7B941F2DCB6F54F7F0BA /* Pods-PINRemoteImage-acknowledgements.plist */, - D175F0B2CE4974DA4A1448ED5888697D /* Pods-PINRemoteImage-dummy.m */, - 8A294F3206E113303E2E6CB0A9399068 /* Pods-PINRemoteImage-frameworks.sh */, - 00B2BEE1D596A306899DFE0B44C7D72A /* Pods-PINRemoteImage-resources.sh */, - 6FFB5369DE5023467EE00C37356BDA50 /* Pods-PINRemoteImage.debug.xcconfig */, - B2DA8820D153800A564142BBB03DED79 /* Pods-PINRemoteImage.release.xcconfig */, - ); - name = "Pods-PINRemoteImage"; - path = "Target Support Files/Pods-PINRemoteImage"; - sourceTree = ""; - }; - F34665D3C8A092C24D6305F2BD9A22AC /* Classes */ = { - isa = PBXGroup; - children = ( - 1ADC944728D1EC76DD9D61E6E3C352CC /* PINCache */, - ); - path = Classes; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 5804478EA0515C96EDC92ACD1BFCA3D1 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - F9879D5E68B7D9BEA54C9BB62633FC07 /* FLAnimatedImage.h in Headers */, - 668D9F73BA24CA3E783C6E43E7468CE8 /* FLAnimatedImageView.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7138886CF34BF491E29A667FA3C89103 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 5CA2BE4A2B43E3C252E2969812E25123 /* FLAnimatedImageView+PINRemoteImage.h in Headers */, - D25F170379E6801602D30FA827CAFB72 /* NSData+ImageDetectors.h in Headers */, - 4ED919292206CA5F5FBC7F89CFD8E028 /* PINAlternateRepresentationProvider.h in Headers */, - 3A471679E6B7BAB03549C378FEA70AB6 /* PINAnimatedImage.h in Headers */, - 66FB057573152FF4E4C43B26E966F613 /* PINAnimatedImageManager.h in Headers */, - BBB344B642B95D3E86BDB198371B00A8 /* PINButton+PINRemoteImage.h in Headers */, - E50697F8A3FB97FF76EEA79F6582A9E8 /* PINCache+PINRemoteImageCaching.h in Headers */, - F04EA78A279461D73453838E188BE0E9 /* PINDataTaskOperation.h in Headers */, - 2E45A4CE7532311115EF575288FA561D /* PINImage+DecodedImage.h in Headers */, - 5824AD89543214E55BEEC8F632638EB9 /* PINImage+WebP.h in Headers */, - CE6FD7F6A89F79661A59E0653FAE234A /* PINImageView+PINRemoteImage.h in Headers */, - 07C0781173FC8DABC9132C218AE42962 /* PINProgressiveImage.h in Headers */, - 9A5856797DCBEE1E1AA22A0777A39CDE /* PINRemoteImage.h in Headers */, - 08797D53D626CAA42F6307F5DF97CF77 /* PINRemoteImageBasicCache.h in Headers */, - 87FA697B6BC6883DB6971BE6AE842167 /* PINRemoteImageCaching.h in Headers */, - 16EDFACCF7F504D29E692C8A28381C00 /* PINRemoteImageCallbacks.h in Headers */, - BCC2A91EF2611037A2D7EBC00AADAAD5 /* PINRemoteImageCategoryManager.h in Headers */, - 5696260A8E3C1BC595270AEE6C9847D5 /* PINRemoteImageDownloadTask.h in Headers */, - 5CFA50816B763067E1BB9A4C71D9D2FD /* PINRemoteImageMacros.h in Headers */, - D0A749587EF66F144D0865D2C364A4DC /* PINRemoteImageManager.h in Headers */, - 85BDB71B2E2862B9DC854DE54E25122C /* PINRemoteImageManagerResult.h in Headers */, - 42BFF8402EDB88225D8F63F94D126DE3 /* PINRemoteImageMemoryContainer.h in Headers */, - 595C0F058AF2944D717D149826A90466 /* PINRemoteImageProcessorTask.h in Headers */, - C1AA161415B38E9AA9AFBF618616255B /* PINRemoteImageTask.h in Headers */, - 89297D94D81DFAF4DA0536CD04112A7D /* PINRemoteLock.h in Headers */, - F739630F44036B96E422E0B92FFC01CF /* PINURLSessionManager.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 953ED8D1A81D46C71EB6E3963E90E668 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 91C32064B18B0608B3C7E644DC1EB13E /* alphai.h in Headers */, - 3D2EAC67EA7479E2DC2462E476B7496E /* backward_references.h in Headers */, - CE995560DDA7F76B9AFE723675FD9860 /* bit_reader.h in Headers */, - 8BC5F72DF2522FEDAB3E0A28723A86E2 /* bit_reader_inl.h in Headers */, - EDA5FCDC0CFE5CCC10F0B15FF778A6B0 /* bit_writer.h in Headers */, - 1823E61EDCEB47FEC4BEEF3BAB736F42 /* color_cache.h in Headers */, - D79E4C317A340FF3834D4101D60C7682 /* common.h in Headers */, - 7B8F4694F8F5166C36A6736C18960A30 /* cost.h in Headers */, - 2925436C1FDA37811C71C010F38EB469 /* decode.h in Headers */, - 89B06498D4615744622FCA92305FCA06 /* decode_vp8.h in Headers */, - B97A940CEFB06ECACC9303EEC2EE67FC /* delta_palettization.h in Headers */, - E8581192AD4C4806BA63326C5B15B933 /* demux.h in Headers */, - B1FAB245AC046642495321FF0C508723 /* dsp.h in Headers */, - 73F9EC75532839C78F6D17D18F5F62A5 /* encode.h in Headers */, - 8E4DB9230B811C82A6E65054A6BB742F /* endian_inl.h in Headers */, - DDFF66F42076861E58CC39AFD17458C9 /* extras.h in Headers */, - BE85A4BD73AEA712392EC64BC41F2C33 /* filters.h in Headers */, - E949D0F07FB2E4CE98D9C00B4FDE2352 /* format_constants.h in Headers */, - 182DBA1D3BAB6E044A4BB71E287C0B04 /* histogram.h in Headers */, - FC573CB0C99ACE8FD5681F3FC404E2C1 /* huffman.h in Headers */, - E8A1B4232D3BE70967E70C265E2FC2D9 /* huffman_encode.h in Headers */, - 08C35431E87C80AAA8090F15978D6BE7 /* lossless.h in Headers */, - 8AEE3F14F012C4DF691B4FD302CCF4C2 /* mips_macro.h in Headers */, - 64A228C16AC751D267EB01164A6A95E5 /* mux.h in Headers */, - 48843FAEA2D7A0A81721052B766824C2 /* mux_types.h in Headers */, - 5E34C5F7C811261D9CB512AD0DB93A7F /* muxi.h in Headers */, - 6FF8A5C31BA4D0087845AAAE368BC1B9 /* neon.h in Headers */, - 15E1DAA228687C9AF2823FDDB1F8F211 /* quant_levels.h in Headers */, - D40FF9DB7EB06CDCDE07EEC7CC13C8AD /* quant_levels_dec.h in Headers */, - D6559CECD47A3D58604D92FBA3CB5735 /* random.h in Headers */, - CC9853FB14E5EAAD528C642AE3CC5B11 /* rescaler.h in Headers */, - 01321DB0A8FD67E1496C38227BB1235E /* thread.h in Headers */, - E4C0AAB20014EE7477D84E08A1075224 /* types.h in Headers */, - 3CB23E5E062BA4493AF32DA17FC63E7F /* utils.h in Headers */, - B0315647BBDB9BEC4C47AA9080740E89 /* vp8enci.h in Headers */, - D84711A941C2A1DB0C20AF48382BCE28 /* vp8i.h in Headers */, - 2F8A82147C7D40206AA6DBE5910A094F /* vp8li.h in Headers */, - 5D63496B8F9703245625375B885A9A85 /* vp8li.h in Headers */, - D200353FC99C303663E9EF9AAF4CD27C /* webpi.h in Headers */, - 95B60590068F6B806928D8F7F95A697E /* yuv.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - A8BD463C26E7A80924A3E86A3235EBD8 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - D134CE8DD2B2158815191BDCD02651CA /* Nullability.h in Headers */, - 3D84A6A24B7DA955BE7FB737ACDB0B2F /* PINCache.h in Headers */, - 694D173D9B42D95CC8FA3305E094C7A1 /* PINCacheObjectSubscripting.h in Headers */, - 61FD61EE3B19AAC78EBC98F5CA8E3B77 /* PINDiskCache.h in Headers */, - 70E15D53758C7C32841CAB2C86B8BAE3 /* PINMemoryCache.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - AB0AF8BA453C06F23CFB1E6C6B124C4B /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 1918669ACF6325BE0C70E43DFBD34418 /* FLAnimatedImage.h in Headers */, - 1903A6861A6A88FDEB9B49FFAEFADDB1 /* FLAnimatedImageView.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C2C659958B22B20F9E3315DF62A34BA3 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - AC4FFC6CCC0127BABAB4F4A666B47912 /* alphai.h in Headers */, - 74BC4914A4B8F583015257514CD351AF /* backward_references.h in Headers */, - 7EABB64FEE2D4EEFB16EE39C72A8D25C /* bit_reader.h in Headers */, - 27EFA5A3482D9C619CB53574A4E261A3 /* bit_reader_inl.h in Headers */, - B5443A45FD1D6555686D16F045BBC53F /* bit_writer.h in Headers */, - E8CDA40BF3460DD83F5E8F09068D4F11 /* color_cache.h in Headers */, - EB9A67A667E9CAA4FB5ED871B3C447B7 /* common.h in Headers */, - 500301738F1D2D1D116117C63EEC0B42 /* cost.h in Headers */, - F085EC7146EB30339860F510569AF542 /* decode.h in Headers */, - 970C17677DA372ACD183148B76643B05 /* decode_vp8.h in Headers */, - 305D930DAE04FD91E0BDD00F9C13FD8F /* delta_palettization.h in Headers */, - 5339B942462742A04B3CB6535D4481D8 /* demux.h in Headers */, - EBD9D5A50B91DB0B86A0FBCA7B99EE1A /* dsp.h in Headers */, - 18DFF245D401B429D27A9E9BCB44E63D /* encode.h in Headers */, - 5466829173BF0A8CC8E6E3C39E451B89 /* endian_inl.h in Headers */, - 5AF32CAAD5793331EC0A08BAC8870AF4 /* extras.h in Headers */, - 58ED89FBCE9BA701F4EE508096ADFC16 /* filters.h in Headers */, - 2DB5A7A3B6B171D2CA48154A172D3F87 /* format_constants.h in Headers */, - 55B07F19DAF75830CB8F789422749BB8 /* histogram.h in Headers */, - 7423CFE8C2FAA7B3F5EC95D5FB2F5E63 /* huffman.h in Headers */, - 08C4AC86FCC664865C06E565CB0242EF /* huffman_encode.h in Headers */, - 52E9BEA637A0A422D686839CAAB1A73E /* lossless.h in Headers */, - C95745EA31CCFF0C9F857E1FA62B91D7 /* mips_macro.h in Headers */, - D5F85F782DDDF740060BCA9924FA7F46 /* mux.h in Headers */, - 71A457D2BFA5877BFB457C4F762DA2B8 /* mux_types.h in Headers */, - 8CA2EDCA8B6FDA9134C458E37EB9A8FB /* muxi.h in Headers */, - 80DBECFA6CDC16F0973722317817BAEC /* neon.h in Headers */, - 4DD5238B688F4539E0B0C209723E2350 /* quant_levels.h in Headers */, - 3C0A60917E3992A12B1F2E3186641F75 /* quant_levels_dec.h in Headers */, - 3FEB1550337A45FA0F2665A7B262834E /* random.h in Headers */, - D1531E5C2E0728AE882C7EC44BECA692 /* rescaler.h in Headers */, - 3B0B7640B6CC3CFCB196CA4F0EAFA1DC /* thread.h in Headers */, - 87E73BB385F32AFAD4874CF2928FB6AB /* types.h in Headers */, - 0EBA2FDF2D92DAA42BF169CA4A105D34 /* utils.h in Headers */, - 39E19F20A393B1C63B10B41AD71C16F9 /* vp8enci.h in Headers */, - A0A87C2434A7C4C4123135D8787AA957 /* vp8i.h in Headers */, - C70213D88F6FEFE79CCEDDAF47CCF876 /* vp8li.h in Headers */, - 79C5DB040FEDB08BEA2FD6B757730C0D /* vp8li.h in Headers */, - 84A5216198BCE5F6B0A6B919B9EA24A3 /* webpi.h in Headers */, - C184317A40DB1D7F529AED73BD7F4CD9 /* yuv.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C98605E830908266C8A663BBFED5F310 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 8A12D3D63765EB2DF237E3F56B9F7596 /* Nullability.h in Headers */, - 689A3865648E64C9C85553EFCAB90D02 /* PINCache.h in Headers */, - 81A24DDCAF6DF14D20E29FF96E809BEF /* PINCacheObjectSubscripting.h in Headers */, - A6C480888298F0685EFBDE86E3A1AC9E /* PINDiskCache.h in Headers */, - C24830D002366CE027026BCACC4A18D6 /* PINMemoryCache.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E84CA7023FBB58AD908C8DCD7E7BA774 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 2BB234E3A01E64E6DD1ED7C26D23B1F5 /* FLAnimatedImageView+PINRemoteImage.h in Headers */, - 4638173489D90E8EF6CB683088BE41C0 /* NSData+ImageDetectors.h in Headers */, - 15F0C9130112DA406EF8187C47063895 /* PINAlternateRepresentationProvider.h in Headers */, - 0407A1D69DB205904686A63F637711C9 /* PINAnimatedImage.h in Headers */, - C3C9A22D821C07D87643AD8D65EEAEF5 /* PINAnimatedImageManager.h in Headers */, - F364B7343773DD0BD6AE5717F8F79C86 /* PINButton+PINRemoteImage.h in Headers */, - 55B63EEFEC338F0703D6885E48E4CD2A /* PINCache+PINRemoteImageCaching.h in Headers */, - 5B85FD81956AC86E6747E4EF27E54556 /* PINDataTaskOperation.h in Headers */, - 38ECCA0587D751E1467EBB83F68DA283 /* PINImage+DecodedImage.h in Headers */, - 233FF6DF7BDAA71EAF70603CE91B52FA /* PINImage+WebP.h in Headers */, - 752C801EB9448B3D377D6D5B33D23840 /* PINImageView+PINRemoteImage.h in Headers */, - ADD5AC209E44FAA788E1CC993B051FF8 /* PINProgressiveImage.h in Headers */, - 62968D6BB6F31472F545ADBC248DC565 /* PINRemoteImage.h in Headers */, - 7E25E37918730FB8001FA1A3CDA3DE9D /* PINRemoteImageBasicCache.h in Headers */, - 76A7157DE2D8014C5798384BEF14E559 /* PINRemoteImageCaching.h in Headers */, - 1C0574F6F8BCBA5B07707B36857B6582 /* PINRemoteImageCallbacks.h in Headers */, - 1B745800A0F1A6857C65ADE97F789749 /* PINRemoteImageCategoryManager.h in Headers */, - FEBA128C41FDDE070C8A66090156D7C4 /* PINRemoteImageDownloadTask.h in Headers */, - 7BF2AE1D807E81EF09CEB41E6CC725FF /* PINRemoteImageMacros.h in Headers */, - 9C64E2DD4F94C7FC10990B0DAF4A74BE /* PINRemoteImageManager.h in Headers */, - E7340C99D2BC858136F429CA6961464B /* PINRemoteImageManagerResult.h in Headers */, - EABC062586F5AD1BD4FEBCA9ED026180 /* PINRemoteImageMemoryContainer.h in Headers */, - 697578E001983C95E22F9949EBC3C8D7 /* PINRemoteImageProcessorTask.h in Headers */, - 479C55C08D17F8B60099B295EB19D595 /* PINRemoteImageTask.h in Headers */, - ACBBDE6667DFA4AB9B0425A993C6F8F9 /* PINRemoteLock.h in Headers */, - 300207D3CA914A9EDA30EDC29A4A9C27 /* PINURLSessionManager.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 02F173FA63D3D03EA7E6CA9FFE3A0761 /* PINCache-iOS8.1 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 683B0F92BD75D7498575AD7BAA86DE8A /* Build configuration list for PBXNativeTarget "PINCache-iOS8.1" */; - buildPhases = ( - 52A6AE990040ABB7CDE75A27D70AD6E1 /* Sources */, - 4EFF950FC490FE65279D048D18B9AB57 /* Frameworks */, - A8BD463C26E7A80924A3E86A3235EBD8 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "PINCache-iOS8.1"; - productName = "PINCache-iOS8.1"; - productReference = 64A2DC53D4E243C57B9AAE1310B85AFC /* libPINCache-iOS8.1.a */; - productType = "com.apple.product-type.library.static"; - }; - 12CBE23502187E04EA33A1CAA9CBE617 /* PINRemoteImage-iOS8.1 */ = { - isa = PBXNativeTarget; - buildConfigurationList = E6422E5B433DD68BE8B8292DC11CC79C /* Build configuration list for PBXNativeTarget "PINRemoteImage-iOS8.1" */; - buildPhases = ( - 67B6058917AC730B6542E1FA813F037D /* Sources */, - 3D66F1CD9AAE6BBDD17C217D2BDA74D4 /* Frameworks */, - E84CA7023FBB58AD908C8DCD7E7BA774 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - 04E64BA9DF8D4F362643D47A9F71FBFC /* PBXTargetDependency */, - BBC4E7B53B1C28B5A3ECF4A7C2F6017D /* PBXTargetDependency */, - 50B77AB0C0427806146B0309FFD71AFE /* PBXTargetDependency */, - ); - name = "PINRemoteImage-iOS8.1"; - productName = "PINRemoteImage-iOS8.1"; - productReference = EF43DEED6C32D2DD3B05AC63D5505F1B /* libPINRemoteImage-iOS8.1.a */; - productType = "com.apple.product-type.library.static"; - }; - 2A4983A5807EEB91056950FD76E2D683 /* PINCache-iOS7.1 */ = { - isa = PBXNativeTarget; - buildConfigurationList = EE6A6FAB2E4BD052DF208659E1D78572 /* Build configuration list for PBXNativeTarget "PINCache-iOS7.1" */; - buildPhases = ( - 630B26DC14CE53CEB19F60D7697EDA78 /* Sources */, - F36166F704E8BEE42160CCBC7F75C0A2 /* Frameworks */, - C98605E830908266C8A663BBFED5F310 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "PINCache-iOS7.1"; - productName = "PINCache-iOS7.1"; - productReference = CF81690C1E5546DC02C0A6488E23F380 /* libPINCache-iOS7.1.a */; - productType = "com.apple.product-type.library.static"; - }; - 3ACDE5A60732296F730B7C822B09CCA3 /* Pods-PINRemoteImage Tests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 73CFD4AA76FC05FC90A8FD8973BEBC4E /* Build configuration list for PBXNativeTarget "Pods-PINRemoteImage Tests" */; - buildPhases = ( - F9C29BD6DC2BCD2FC581641CFD9588BA /* Sources */, - 5E26864A97E9EBDE2CDAEE5F36C6B9C2 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 6279DA4A233659212D5C7EA23AFD44E2 /* PBXTargetDependency */, - 4517234704DE1359E5D8AF57AA10010A /* PBXTargetDependency */, - F5CC318EC9E91D2A148AC4B60BE01141 /* PBXTargetDependency */, - 546137B884C7D2992EB19D78674CC08C /* PBXTargetDependency */, - ); - name = "Pods-PINRemoteImage Tests"; - productName = "Pods-PINRemoteImage Tests"; - productReference = 83AD546FC18944E8A75A64F70663903F /* libPods-PINRemoteImage Tests.a */; - productType = "com.apple.product-type.library.static"; - }; - 51E046FCB539FE8A23DFDD38C3222B17 /* libwebp-iOS7.1 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 9BDC4000E61D29DF99A2F13B3E38BFDE /* Build configuration list for PBXNativeTarget "libwebp-iOS7.1" */; - buildPhases = ( - 2E16CB535C6189D38A1F877FF3A8D435 /* Sources */, - FE2E97B2EBDEFE715269D8160DE1F82C /* Frameworks */, - 953ED8D1A81D46C71EB6E3963E90E668 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "libwebp-iOS7.1"; - productName = "libwebp-iOS7.1"; - productReference = E83E3CE028483394478A705F4318988C /* liblibwebp-iOS7.1.a */; - productType = "com.apple.product-type.library.static"; - }; - 6C34D713988BD49857279690E3652CD0 /* libwebp-iOS8.1 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 847EE451806ED13FD70697B2383D1CD5 /* Build configuration list for PBXNativeTarget "libwebp-iOS8.1" */; - buildPhases = ( - B36E2893B37B02D704345BC8C9C628C1 /* Sources */, - 024376E8671A81E874A6F988B23DAC81 /* Frameworks */, - C2C659958B22B20F9E3315DF62A34BA3 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "libwebp-iOS8.1"; - productName = "libwebp-iOS8.1"; - productReference = 6F579E1BD144AC8C4974FDE70107BE70 /* liblibwebp-iOS8.1.a */; - productType = "com.apple.product-type.library.static"; - }; - 88946788461561787CE22BC14B767C3A /* FLAnimatedImage-iOS7.1 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 8BA82A19CA3C518B43793113656FB1DD /* Build configuration list for PBXNativeTarget "FLAnimatedImage-iOS7.1" */; - buildPhases = ( - 051AE6A68C0C34485EF6EDAF0FF5F165 /* Sources */, - EB86966E567965E78DDCD6E6EF4F8F68 /* Frameworks */, - AB0AF8BA453C06F23CFB1E6C6B124C4B /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "FLAnimatedImage-iOS7.1"; - productName = "FLAnimatedImage-iOS7.1"; - productReference = 9F92C25C401D4D5A02B9A9FEC78C98CE /* libFLAnimatedImage-iOS7.1.a */; - productType = "com.apple.product-type.library.static"; - }; - CDDDE8D404074B9DC4C2291002D159F8 /* FLAnimatedImage-iOS8.1 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 87ACFCDB3A177BC0081CF7E2C7068A8F /* Build configuration list for PBXNativeTarget "FLAnimatedImage-iOS8.1" */; - buildPhases = ( - 83274F54EBCEE94999A87571D0D94573 /* Sources */, - 2DBDFCC62D6790976C21261E967ECF85 /* Frameworks */, - 5804478EA0515C96EDC92ACD1BFCA3D1 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "FLAnimatedImage-iOS8.1"; - productName = "FLAnimatedImage-iOS8.1"; - productReference = 023E4D6CDD5B2AE15094E18B317A97F4 /* libFLAnimatedImage-iOS8.1.a */; - productType = "com.apple.product-type.library.static"; - }; - DD458F968DA031155A9660CA36F43628 /* Pods-PINRemoteImage */ = { - isa = PBXNativeTarget; - buildConfigurationList = 00AB695DCA9D77EEB2DCD36592266E29 /* Build configuration list for PBXNativeTarget "Pods-PINRemoteImage" */; - buildPhases = ( - 087A23F3CCF97143C5FB43B305C0D9C0 /* Sources */, - FE299AB28B03D90A191D8CFBD8B31455 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 8EB8E69002973167328D71F4FCD92C79 /* PBXTargetDependency */, - 4F432B49F490EBB55944825FE2DC21A2 /* PBXTargetDependency */, - D522C79608873A7AF7C5677EF8DAF3BB /* PBXTargetDependency */, - E5AE2BB1E9402675081481A6A47D715D /* PBXTargetDependency */, - ); - name = "Pods-PINRemoteImage"; - productName = "Pods-PINRemoteImage"; - productReference = 30CF9B4AAE62C4612A11127E869B1D76 /* libPods-PINRemoteImage.a */; - productType = "com.apple.product-type.library.static"; - }; - DDC608954898A7553EB8B23009B076E2 /* PINRemoteImage-iOS7.1 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 69D364B990CE319D0F13C54D914121C3 /* Build configuration list for PBXNativeTarget "PINRemoteImage-iOS7.1" */; - buildPhases = ( - E8A989741CDA61D4A918A0FDF2A3BE96 /* Sources */, - CA5171DB8F301B582A6F317514FF665C /* Frameworks */, - 7138886CF34BF491E29A667FA3C89103 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - 8CA82B9B4E4537EAE1370F614FEFBBA5 /* PBXTargetDependency */, - 5CC64E612385EB9DF78846C24A85809B /* PBXTargetDependency */, - DFD090B1D6D65E70184F951B3016AD0E /* PBXTargetDependency */, - ); - name = "PINRemoteImage-iOS7.1"; - productName = "PINRemoteImage-iOS7.1"; - productReference = 4D6B18220592A6A66D54E1EDA2B6ABE6 /* libPINRemoteImage-iOS7.1.a */; - productType = "com.apple.product-type.library.static"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0700; - }; - buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 7DB346D0F39D3F0E887471402A8071AB; - productRefGroup = 7508908D12F8631BCCC8D9169014D84C /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 88946788461561787CE22BC14B767C3A /* FLAnimatedImage-iOS7.1 */, - CDDDE8D404074B9DC4C2291002D159F8 /* FLAnimatedImage-iOS8.1 */, - 51E046FCB539FE8A23DFDD38C3222B17 /* libwebp-iOS7.1 */, - 6C34D713988BD49857279690E3652CD0 /* libwebp-iOS8.1 */, - 2A4983A5807EEB91056950FD76E2D683 /* PINCache-iOS7.1 */, - 02F173FA63D3D03EA7E6CA9FFE3A0761 /* PINCache-iOS8.1 */, - DDC608954898A7553EB8B23009B076E2 /* PINRemoteImage-iOS7.1 */, - 12CBE23502187E04EA33A1CAA9CBE617 /* PINRemoteImage-iOS8.1 */, - DD458F968DA031155A9660CA36F43628 /* Pods-PINRemoteImage */, - 3ACDE5A60732296F730B7C822B09CCA3 /* Pods-PINRemoteImage Tests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - 051AE6A68C0C34485EF6EDAF0FF5F165 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 77885CD9BF4CB77BC64FB00354B35522 /* FLAnimatedImage-iOS7.1-dummy.m in Sources */, - C6DB8BC01B2441C51A103B2D7482B65E /* FLAnimatedImage.m in Sources */, - E9FF63035E5FB9C7B4CC13B7D9C0D7E1 /* FLAnimatedImageView.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 087A23F3CCF97143C5FB43B305C0D9C0 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - FB97D571ABECBDDAFC1E27CD900704E4 /* Pods-PINRemoteImage-dummy.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 2E16CB535C6189D38A1F877FF3A8D435 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0004ACF937FE0FA4DFB7A256A4A30F59 /* alpha.c in Sources */, - 0B94300056C3B968DC0183363C5D72A8 /* alpha.c in Sources */, - 59BEDDDB4610621B6436ED028FB22211 /* alpha_processing.c in Sources */, - A526184AEC7B6B261225136DD5013B06 /* alpha_processing_mips_dsp_r2.c in Sources */, - 7BDB3207454D9848D986847B992B22EE /* alpha_processing_sse2.c in Sources */, - C4903EEE9F265110CAF9B2795FA8127E /* alpha_processing_sse41.c in Sources */, - 98D54ED5DE7728F7438846023CD2664C /* analysis.c in Sources */, - EF15B97A0881D801AB7DEFE149E09EF3 /* anim_decode.c in Sources */, - 49F6C4CEF1D4DCA75581633ECA6CAA4F /* anim_encode.c in Sources */, - 05B855FC0755EEFE24688FCA92D359D8 /* argb.c in Sources */, - 7FEFFD16F71C2CB49D18A7675A2387D0 /* argb_mips_dsp_r2.c in Sources */, - B87638A8C714D553F462DFCF991DAABD /* argb_sse2.c in Sources */, - E3841FCEA72F066486D18187E8D20782 /* backward_references.c in Sources */, - 5B4614FA1A63FF5700F4A96084F33EA9 /* bit_reader.c in Sources */, - D258D7ADB4F60B64924713AD8987C30B /* bit_writer.c in Sources */, - FF3DF41B20FD5560B51FBF8DB326D59B /* buffer.c in Sources */, - 91AE0CF3C6F67CB6A8F166FF13D8B57E /* color_cache.c in Sources */, - F01A83F5D4FE48EA5979D4BACEF51EC3 /* config.c in Sources */, - 0292822977E874E768F17590CA0BCEFA /* cost.c in Sources */, - 1C6C66EA67129411883E00171B9BA888 /* cost.c in Sources */, - 00A6C4B53CAE3DEAC90728D2AB8F8D91 /* cost_mips32.c in Sources */, - 96C0843610D0BB8FAF0104396195158C /* cost_mips_dsp_r2.c in Sources */, - 6D57E0EC289399A447DB096BD6E772CB /* cost_sse2.c in Sources */, - 50B2CF854DD8BD3F6E99A419E71D4186 /* cpu.c in Sources */, - EA3275C78F818202B2F9F66192A8E7F5 /* dec.c in Sources */, - 278123CE6DD2FEA944688D51DF871575 /* dec_clip_tables.c in Sources */, - 316B4323A7711C8345B7A2D816B7FF77 /* dec_mips32.c in Sources */, - 99CB1DB9121CC7DFB6E4EDEA82EF1CDB /* dec_mips_dsp_r2.c in Sources */, - 2B73192B08E8F700FD1234DB236D2F19 /* dec_neon.c in Sources */, - 3A9BAC7537D8E4609F3D90EDE1E14997 /* dec_sse2.c in Sources */, - 74E54CEBE157B84620620BB2B799E56C /* dec_sse41.c in Sources */, - E499B8E0C7DFC3E50F1C156BF0B0B66A /* delta_palettization.c in Sources */, - B2EA7299B6868F06B9AB6308F829005B /* demux.c in Sources */, - 234141D332CABCA79BA51DBE69F2A8C7 /* enc.c in Sources */, - E28D9EE4A0025BAB8ADFD18B32008FD8 /* enc_avx2.c in Sources */, - 35FC2770A58816FBB78C98C8E2DE9C05 /* enc_mips32.c in Sources */, - 8EA34FED195C8342AC71AF98882ACD78 /* enc_mips_dsp_r2.c in Sources */, - A6090EE05BFBA88E517DE433D205B7F7 /* enc_neon.c in Sources */, - 0386E2E24A95A876232C98C31B276601 /* enc_sse2.c in Sources */, - 4C01DCD6002FEF2B8E92A9A7D04DE311 /* enc_sse41.c in Sources */, - FEE32BB49E61823986EB6AC8712BEC00 /* filter.c in Sources */, - 39E314F38A395E500E59C87D57E74505 /* filters.c in Sources */, - 5A8471CDE0D1F5F0B2F0DB22C4401C36 /* filters.c in Sources */, - 58C3BAFAB1D12EE15AB3457B48B84C22 /* filters_mips_dsp_r2.c in Sources */, - 40CFBA99E90B1CB882144F5EB7F5B0AD /* filters_sse2.c in Sources */, - 86534614F5ADF78140757E7B68BF96CB /* frame.c in Sources */, - B41F7A48C895353F3475106D01703CBD /* frame.c in Sources */, - A372CCB0E3C1AD3928866C7114558784 /* histogram.c in Sources */, - EF8B037430B0599809A8475F218A4AB6 /* huffman.c in Sources */, - CF53854D86ACAF257B6E666D0BF25A76 /* huffman_encode.c in Sources */, - 6B0813FF01128C3A7CC7C6EE6CEA5768 /* idec.c in Sources */, - F8DFDCDD6CF6EF8F6C2B654727F47E95 /* io.c in Sources */, - CCBE2DA7A34A3D7EAFB84ACDEF0E1B65 /* iterator.c in Sources */, - 8FE0BE20BE29167C343BAA8CADA26FA5 /* libwebp-iOS7.1-dummy.m in Sources */, - 9AF44D87461219ACC8D8509F7A461EE0 /* lossless.c in Sources */, - B1C65ADCB0559F3ABA0D29A722BB4802 /* lossless_enc.c in Sources */, - D5D5ECE4D576B49BFFA280F3BEE2EA84 /* lossless_enc_mips32.c in Sources */, - 82E8B2774E320367EA077956F9149333 /* lossless_enc_mips_dsp_r2.c in Sources */, - CF9CED8ACEC02B9D0ADB4876E41E22DD /* lossless_enc_neon.c in Sources */, - 8641E56BF6618238B52FF5E326D7806E /* lossless_enc_sse2.c in Sources */, - DC1EDB42135CC9428D8A5CD30D8A5C02 /* lossless_enc_sse41.c in Sources */, - 037B3677D814227A1DD16E95F947A09F /* lossless_mips_dsp_r2.c in Sources */, - 3ED42578F4A149E80A9274777D9AF714 /* lossless_neon.c in Sources */, - 190F70680CE8A93398DDEEAF10D7ACD7 /* lossless_sse2.c in Sources */, - B689B3E75A2005AACA373E61BEDA122B /* muxedit.c in Sources */, - 592716F81E894C06F33268C63B908846 /* muxinternal.c in Sources */, - 0679E26FE575ED6F0023A03C6A8BA304 /* muxread.c in Sources */, - B6EA416AAC008BEA46E3D8FD2A15FE8A /* near_lossless.c in Sources */, - DC8F42F97D63D24BDD5066CB92B7ABC3 /* picture.c in Sources */, - A06ED4382D0BEF02C6525C68F30FCE77 /* picture_csp.c in Sources */, - E8F83EC2C711D9B5679B55012B08ABCD /* picture_psnr.c in Sources */, - 79CC9D925488F7008308DA82F371E2C1 /* picture_rescale.c in Sources */, - BFC14A4370E75F8EF6B19C607AA232EC /* picture_tools.c in Sources */, - FCF01FBF7D21C3870DD74F0A90C730F0 /* quant.c in Sources */, - D059EB8073278E02A0AB7620B418895F /* quant.c in Sources */, - 866E39AA5AD820CE1522CA6CF79C8F03 /* quant_levels.c in Sources */, - EBC106167C193A969D6D2D710CC40BC2 /* quant_levels_dec.c in Sources */, - 425DCFA0D00716477DB8A8FC7D58281C /* random.c in Sources */, - 57EBADB49B4A0F1A77DA90F42FA82AFA /* rescaler.c in Sources */, - 4B4D2F6D1886D4BAA07D7BC59E2D9E76 /* rescaler.c in Sources */, - 9CFC5B09D9C143C561A54F006962A19D /* rescaler_mips32.c in Sources */, - 565751663C086EA87CC2A0AF00F7BD1D /* rescaler_mips_dsp_r2.c in Sources */, - 62605E623FBCC88B6CCC2A75A21E1BE5 /* rescaler_neon.c in Sources */, - 57CCF161CB211F53817D47202F915E55 /* rescaler_sse2.c in Sources */, - 8FBDDD512523AF43A39ACBB46E9AF4DE /* syntax.c in Sources */, - 2CE68F81FBD8DF011DE32D965F1BAC87 /* thread.c in Sources */, - 5A41B8B231CF1AA1DB6AF41F24D52521 /* token.c in Sources */, - C55897C0A204F7ED8D4EE53434DD3097 /* tree.c in Sources */, - AC146A0D055614D7EC12A959725C62F5 /* tree.c in Sources */, - A3B4CB236BBC03345C742E4B3132EA76 /* upsampling.c in Sources */, - E5EDAC1FE3F085E877F962D4E3498B4C /* upsampling_mips_dsp_r2.c in Sources */, - 5399E1E14A183B1CCCED43E41F610E2F /* upsampling_neon.c in Sources */, - CC72096E663B033D6DD1BF9436E427A9 /* upsampling_sse2.c in Sources */, - 69DF6F485FD847ED9004997CBF7979B2 /* utils.c in Sources */, - BF7FB2F305E831BC8B1914A6364D35C7 /* vp8.c in Sources */, - BC63DEE61815E5101E372E796A8EEAD6 /* vp8l.c in Sources */, - D12207F1A304CE8EC15D1B5E00724AB2 /* vp8l.c in Sources */, - 1E4DEF8BDDFAD3240C77D9FD6F264EF5 /* webp.c in Sources */, - 1AAC297FBC573AB935FF5C5792FD2789 /* webpenc.c in Sources */, - A24327F3811A225D0CA99154649D0FE9 /* yuv.c in Sources */, - F17275AF13E7DBB966CBDA3F9EAA3473 /* yuv_mips32.c in Sources */, - 01CFD9C89E3270B7006FDA5521ADF3A5 /* yuv_mips_dsp_r2.c in Sources */, - 39C7B9AAB26FC0FAFBE98768287898FE /* yuv_sse2.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 52A6AE990040ABB7CDE75A27D70AD6E1 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - C419D9EA9628B03287F589E014AD39CA /* PINCache-iOS8.1-dummy.m in Sources */, - ECCFB72A1C043C692029AA4B777FE3E8 /* PINCache.m in Sources */, - 3C2AF15BEA67744B23E478382828022D /* PINDiskCache.m in Sources */, - 300C98AB1985EE5E8CEFA10EC506B1C7 /* PINMemoryCache.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 630B26DC14CE53CEB19F60D7697EDA78 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 2DD920ECF72A76D115D519C6F3400BE4 /* PINCache-iOS7.1-dummy.m in Sources */, - 0BAE40E8A0977E62153C6563FA8B93BC /* PINCache.m in Sources */, - 0A7DC3EEF5717FED5820904E554D4CB9 /* PINDiskCache.m in Sources */, - 4997017373D8173E03E43A8AF3D61EC5 /* PINMemoryCache.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 67B6058917AC730B6542E1FA813F037D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7972C9872960362D343FF03ADE652702 /* FLAnimatedImageView+PINRemoteImage.m in Sources */, - 5A12CF1B0922FCDF4F257CBEFDAEF649 /* NSData+ImageDetectors.m in Sources */, - 7FF167E680C08A069995E4FF213461AB /* PINAlternateRepresentationProvider.m in Sources */, - EE86D33F6218BB990E5DA26EA9403C61 /* PINAnimatedImage.m in Sources */, - DC68CD48BA599CA63A5338059E45E0A7 /* PINAnimatedImageManager.m in Sources */, - CBBD9B450258AF7AC9FADA54DA40597F /* PINButton+PINRemoteImage.m in Sources */, - 987AE0E18F015DE956ED6B75ACFE7A31 /* PINCache+PINRemoteImageCaching.m in Sources */, - EA3D0F856F9071FC3139318554B18D3A /* PINDataTaskOperation.m in Sources */, - CC616E25D7C8DC1EE3474E6BE920A576 /* PINImage+DecodedImage.m in Sources */, - B963874CA4C32B72196F27CECB65FB74 /* PINImage+WebP.m in Sources */, - B16F98BE7850AF777BAB6F926ECD06CC /* PINImageView+PINRemoteImage.m in Sources */, - CD6C580DD854E1995F35012C10266C6B /* PINProgressiveImage.m in Sources */, - DD69BBEBEAFF56E661E56D4FA7BFB67A /* PINRemoteImage-iOS8.1-dummy.m in Sources */, - 5E53E88C095E65F3F7B35A46868F50B4 /* PINRemoteImageBasicCache.m in Sources */, - 8C71E480585ABE7C3F34283A81C9C2C0 /* PINRemoteImageCallbacks.m in Sources */, - BB5290ED3ED15BE895EBCE736AAE1171 /* PINRemoteImageCategoryManager.m in Sources */, - 2818E3FECADF10CBD4BABE63BB4C6C05 /* PINRemoteImageDownloadTask.m in Sources */, - 01416F362E757F0567F57167ED4916B6 /* PINRemoteImageManager.m in Sources */, - AA2A0060D91D856304940E9E6642A770 /* PINRemoteImageManagerResult.m in Sources */, - 183CBB52A68076C458FA6821615E532B /* PINRemoteImageMemoryContainer.m in Sources */, - 4FAE8DE1C78EA87136D37A00C88F6780 /* PINRemoteImageProcessorTask.m in Sources */, - 57EAA3A0C15B483DFED406A39B3AC798 /* PINRemoteImageTask.m in Sources */, - 47A2F201AD9967E37C11E06111F55EFE /* PINRemoteLock.m in Sources */, - 6BA7E571FE5057213ECE1C7A77D8567C /* PINURLSessionManager.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 83274F54EBCEE94999A87571D0D94573 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0376F4DA2265C0DE5723E4901224D5AC /* FLAnimatedImage-iOS8.1-dummy.m in Sources */, - DB1612FA82B4647F60BCBEB874DA480C /* FLAnimatedImage.m in Sources */, - 4242985D8BD117A05E1775D303F2476B /* FLAnimatedImageView.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B36E2893B37B02D704345BC8C9C628C1 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 2B4D7DE0E09DA6E5BB034F39477757BE /* alpha.c in Sources */, - 9EE810C5E7A0788BFE48367C69F36D12 /* alpha.c in Sources */, - 1163E3AB1BF4942A67743CC45F4D14B0 /* alpha_processing.c in Sources */, - 17B6252E900DCAFC2A8DEA275D7C9D7C /* alpha_processing_mips_dsp_r2.c in Sources */, - DD9AD81E8235D5A70802FA6C2458DEA3 /* alpha_processing_sse2.c in Sources */, - FE43CFE249F8BA34C0F3BAFAE2148BD4 /* alpha_processing_sse41.c in Sources */, - 1E6C9CD6A15C8C13541F9C8C293F2A0A /* analysis.c in Sources */, - 8591BFDDED0360AACC44F87E082FA6B4 /* anim_decode.c in Sources */, - B23829374B5267E41A409881CFD5ADE2 /* anim_encode.c in Sources */, - FAF214553BE87E4F148F238FB9B9A2FC /* argb.c in Sources */, - E0529802AA59F4EEB458A6494E21C10D /* argb_mips_dsp_r2.c in Sources */, - FBAB5AE5952559C9464333340168310D /* argb_sse2.c in Sources */, - 1254DB31C52482BFA98735F8888C0DE8 /* backward_references.c in Sources */, - 48461B21F5BC138F7031A2BA85564775 /* bit_reader.c in Sources */, - CA58AE9D01E859A81ADA2ADE35D2FB94 /* bit_writer.c in Sources */, - 4BF7CEB85D682A38FF63EBB5CFEE857F /* buffer.c in Sources */, - 64D73DD773D4C7B96CA63FCFDE06805F /* color_cache.c in Sources */, - 17BC3A5A96A98929CC8C51ED6F43FD2C /* config.c in Sources */, - C755D8E7EA3A7A7657D84250F3A87835 /* cost.c in Sources */, - 4D1C122671558918E29094F9ADB11ACD /* cost.c in Sources */, - 01C9C04C0C6A49BFDAFE53A1E116A232 /* cost_mips32.c in Sources */, - 961655E9BA895F0BC91B2FD8F7638481 /* cost_mips_dsp_r2.c in Sources */, - FC4873BB2F350452C76F1CFC70C1EBC0 /* cost_sse2.c in Sources */, - 35512EA79A122824670BAB158FAEF7EF /* cpu.c in Sources */, - BFEBB0BC591A3D37FBDAD60C90AF496D /* dec.c in Sources */, - 278E6E6B3482C87F50EABBD555602BC7 /* dec_clip_tables.c in Sources */, - 627CC4104259CABA3A976E69AFD997DD /* dec_mips32.c in Sources */, - A058007CAC0EE7673CF1F71ADCD89B8A /* dec_mips_dsp_r2.c in Sources */, - 674C2AF046083AAABAF5ABBDE99772A5 /* dec_neon.c in Sources */, - DB09C45682D8234921A9AADE1CA0D1ED /* dec_sse2.c in Sources */, - 00706D32BB14BE2BAC347CF317AA7B5D /* dec_sse41.c in Sources */, - 96FACE7A7E07FED39CA8053CA727580D /* delta_palettization.c in Sources */, - C00E99BE4B41F7E205941613AA90D762 /* demux.c in Sources */, - 14761959400952201E7CC44EC7085701 /* enc.c in Sources */, - 882B6D25C787C0DC2750D4814DC16BAF /* enc_avx2.c in Sources */, - D76E8F24DE3D89F26158A0E9CEA09CE5 /* enc_mips32.c in Sources */, - 0139332451F22B5C4A45464EE4EDA0F7 /* enc_mips_dsp_r2.c in Sources */, - 4527CC1EE8A20DA6D2C29316AF1EC76A /* enc_neon.c in Sources */, - CCD662C66EBA8E5E409DEC0DF8F3C46E /* enc_sse2.c in Sources */, - F5F9F8D3E0AEC6188F99FA05371B8F19 /* enc_sse41.c in Sources */, - CA4EAC90EA6A70CA7AB1CE91BBF5C0FC /* filter.c in Sources */, - 114DAC44289FE2BB304F13E7045F1DE4 /* filters.c in Sources */, - 28461D9798354B8921CB18787318F41A /* filters.c in Sources */, - 5A57F08B79BA3D4A3FDA0321CF1F723A /* filters_mips_dsp_r2.c in Sources */, - E33144C5A56699C308E9DD2B9B62C6E3 /* filters_sse2.c in Sources */, - 1535AE3088841BB5B4CC4A379664D236 /* frame.c in Sources */, - B6A7B123374A4BABD55DC2D5FC4077DA /* frame.c in Sources */, - F70800BFFE49AA461F17EF80581AC865 /* histogram.c in Sources */, - C066D2EF270EDB5AA3DB480366F8EE63 /* huffman.c in Sources */, - 4D0A7F82543ED24E4E27F8851387284E /* huffman_encode.c in Sources */, - 8E7C83B6D7B48B21695602FC2ECF2787 /* idec.c in Sources */, - 5563A40AE04CF8207AD853B5C752CAE5 /* io.c in Sources */, - 0F7D088A8C21ECEAFAC194FB72A8675B /* iterator.c in Sources */, - AB8E217F3E50BDCFA2D36AD9131064C3 /* libwebp-iOS8.1-dummy.m in Sources */, - A8824DA51EEDC5F5D23D71ED0CF0571A /* lossless.c in Sources */, - B8D170956D295DD554B0C62AC6374AF3 /* lossless_enc.c in Sources */, - 6E620A8221F571296F96473519B4CDEC /* lossless_enc_mips32.c in Sources */, - C41214D2DF0D86931B4C981978288686 /* lossless_enc_mips_dsp_r2.c in Sources */, - BC156835B5F8469833C3068EF0D4226C /* lossless_enc_neon.c in Sources */, - F7CAC092242DA4F7B938BF068BB36543 /* lossless_enc_sse2.c in Sources */, - E2C92FE45DE6DDEED5A3ABE63DAE06BC /* lossless_enc_sse41.c in Sources */, - FCAE46A39D0C55DEAE9D6B6A20BA1D1E /* lossless_mips_dsp_r2.c in Sources */, - 1AC5E4135914203B2398ECF2B4889189 /* lossless_neon.c in Sources */, - 3BE939B8AB9EC737D3F5FE0420452FF1 /* lossless_sse2.c in Sources */, - 3287496E843E62660A7752D09C953A46 /* muxedit.c in Sources */, - 90A176DBAB805266911C301D815DFE6A /* muxinternal.c in Sources */, - 9729451DA4E1E1DD364CBB544442AD42 /* muxread.c in Sources */, - C62D85E7E9A7591868B19B778B8F0BBB /* near_lossless.c in Sources */, - 12111027F7E75C535B8CF286694F5D79 /* picture.c in Sources */, - A48E6464DD605C7FF4474A7CE9622768 /* picture_csp.c in Sources */, - 4282767D193B3CE27A6B869824ECDD1D /* picture_psnr.c in Sources */, - 55630CAC05EC2D5FB2CDB3E7E2F09E83 /* picture_rescale.c in Sources */, - 4CF9DE20683F8912C451C310E42DE533 /* picture_tools.c in Sources */, - B561C803CCFF201902F88ADF29BFB37B /* quant.c in Sources */, - E06825484A00FA86FCB598DB299C0286 /* quant.c in Sources */, - 6C7F5880C6BD7CF532274878050EFC11 /* quant_levels.c in Sources */, - 0BBDD73AF4AF0357ABC6116A053B857A /* quant_levels_dec.c in Sources */, - 6735CEBE028E06B31724C1624E8E0CB1 /* random.c in Sources */, - B0318EB987AA4BE1946A77E64AFBAEC0 /* rescaler.c in Sources */, - 51A8033FCAEB810FD396D11DA57FAF73 /* rescaler.c in Sources */, - D0129B10B1B331AE9A671E7DC9E1D771 /* rescaler_mips32.c in Sources */, - EAFE2851556D2DDC570438801D948207 /* rescaler_mips_dsp_r2.c in Sources */, - E1481D3DCADA0D1E0882F10B99AF1107 /* rescaler_neon.c in Sources */, - C1FE7D2C2272863066FB7E784A93E18E /* rescaler_sse2.c in Sources */, - 8B4C37DD5962B3D046CDEBCCED20C437 /* syntax.c in Sources */, - 44CFF3C31D62E323E78C8D02E4B1E5FD /* thread.c in Sources */, - D672CD6110FB856E122E143E4E1CF455 /* token.c in Sources */, - C88C43DA8A566A203928CC66ECD8984C /* tree.c in Sources */, - A2670FCCE9721F5B775623B10D5C42F8 /* tree.c in Sources */, - 2898963D10D3B561C4BA2EDAC17A5D49 /* upsampling.c in Sources */, - 051882A00EEDCA2EFDA3C09B67A30E99 /* upsampling_mips_dsp_r2.c in Sources */, - 3F50B17FC285869D5C75B57E90AB90A3 /* upsampling_neon.c in Sources */, - BEDA33100E538C96319D6041BA9C4AD7 /* upsampling_sse2.c in Sources */, - 4547FBB55E48F1B4C5267E239608A288 /* utils.c in Sources */, - D01CABBF787ADF91555183E2EE3200F2 /* vp8.c in Sources */, - D13A4BDB931ED2C143FB4346814B2DA0 /* vp8l.c in Sources */, - 7AEA25ED69F14971588E4E00BE863778 /* vp8l.c in Sources */, - 8F8EBDD6069E06AE8B356E38F8EBBBA0 /* webp.c in Sources */, - DED66A8B6EE6984BFF9F2D720F28A817 /* webpenc.c in Sources */, - 88EE51389D92E218ED06CA7D5466DB84 /* yuv.c in Sources */, - CA9FB99EE1B1F9C7DC2818BABD64B157 /* yuv_mips32.c in Sources */, - B41EAA65120415E42197E24DB3F33BC1 /* yuv_mips_dsp_r2.c in Sources */, - E6B83A1E05309B3291B0A0A6CCF582A5 /* yuv_sse2.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E8A989741CDA61D4A918A0FDF2A3BE96 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - E50A7D40A8FE825535E0013FABBD0A5E /* FLAnimatedImageView+PINRemoteImage.m in Sources */, - CD9682BA53210CDC1585F829018FA697 /* NSData+ImageDetectors.m in Sources */, - 4B339D18D993C737483E4C36A806C277 /* PINAlternateRepresentationProvider.m in Sources */, - 649F413385751CDF1DD65E670425C515 /* PINAnimatedImage.m in Sources */, - C7F7CEBDE70378E10E56964049DF19B8 /* PINAnimatedImageManager.m in Sources */, - ACD648ECA0722DA9052FA4816EB9670D /* PINButton+PINRemoteImage.m in Sources */, - 814EBCA0538CD934B6628678567EFCDC /* PINCache+PINRemoteImageCaching.m in Sources */, - D8B13CC4D2D3AC7C22A3A72AB47B6E89 /* PINDataTaskOperation.m in Sources */, - 35ABFD5C912308B29FB8FC29FCCD10CE /* PINImage+DecodedImage.m in Sources */, - 7131881F05B82D5CAAA8E05D74DFB6FF /* PINImage+WebP.m in Sources */, - A1C7460C23F542445882181942A657C7 /* PINImageView+PINRemoteImage.m in Sources */, - B791A933232219A1837BE9C46C286ADB /* PINProgressiveImage.m in Sources */, - 83A1CD6E4FF3FD51834F7781210CA863 /* PINRemoteImage-iOS7.1-dummy.m in Sources */, - 48C4EBD3D0DF1E9F96B895EAA060940A /* PINRemoteImageBasicCache.m in Sources */, - 11302E5FC7B5F572CF52654F418F5473 /* PINRemoteImageCallbacks.m in Sources */, - 04035DD1422C7000D0BEAC54D474D0DF /* PINRemoteImageCategoryManager.m in Sources */, - 196F75DB9446D2F1E0EA855FC788BF8A /* PINRemoteImageDownloadTask.m in Sources */, - 55E232E4F56C6EA756E62D6B7263CC63 /* PINRemoteImageManager.m in Sources */, - 9634E001B76CEA45929789DD743A7FD3 /* PINRemoteImageManagerResult.m in Sources */, - 9F3DC05BC16EA7657024231E095A184D /* PINRemoteImageMemoryContainer.m in Sources */, - 9A0209B6C08A3075CBBCA462B669FD87 /* PINRemoteImageProcessorTask.m in Sources */, - B449369C545A4EAD63485E55774562D9 /* PINRemoteImageTask.m in Sources */, - 9D2E583621D62972169B27CBAF1FADEE /* PINRemoteLock.m in Sources */, - 49CD48B01656D779912C5EC55E2ACC01 /* PINURLSessionManager.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - F9C29BD6DC2BCD2FC581641CFD9588BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 373169B2958A3417F4ACC3638E9ECCCC /* Pods-PINRemoteImage Tests-dummy.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 04E64BA9DF8D4F362643D47A9F71FBFC /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "FLAnimatedImage-iOS7.1"; - target = 88946788461561787CE22BC14B767C3A /* FLAnimatedImage-iOS7.1 */; - targetProxy = 908845F958625ABB800EF08D1F6FE067 /* PBXContainerItemProxy */; - }; - 4517234704DE1359E5D8AF57AA10010A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "PINCache-iOS8.1"; - target = 02F173FA63D3D03EA7E6CA9FFE3A0761 /* PINCache-iOS8.1 */; - targetProxy = 738D8CE34837483FB59A3AE9B27351E9 /* PBXContainerItemProxy */; - }; - 4F432B49F490EBB55944825FE2DC21A2 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "PINCache-iOS7.1"; - target = 2A4983A5807EEB91056950FD76E2D683 /* PINCache-iOS7.1 */; - targetProxy = 797399D7635AD8BFF31BD128C6058DE6 /* PBXContainerItemProxy */; - }; - 50B77AB0C0427806146B0309FFD71AFE /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "libwebp-iOS7.1"; - target = 51E046FCB539FE8A23DFDD38C3222B17 /* libwebp-iOS7.1 */; - targetProxy = 134D6BC4F1BF93D2BF671CE2A93458CD /* PBXContainerItemProxy */; - }; - 546137B884C7D2992EB19D78674CC08C /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "libwebp-iOS8.1"; - target = 6C34D713988BD49857279690E3652CD0 /* libwebp-iOS8.1 */; - targetProxy = 4B08178EC60A403F5E80CD7DCB1EB352 /* PBXContainerItemProxy */; - }; - 5CC64E612385EB9DF78846C24A85809B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "PINCache-iOS7.1"; - target = 2A4983A5807EEB91056950FD76E2D683 /* PINCache-iOS7.1 */; - targetProxy = 3BD3D3B9D765D571CAA8F1839A9EDD19 /* PBXContainerItemProxy */; - }; - 6279DA4A233659212D5C7EA23AFD44E2 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "FLAnimatedImage-iOS8.1"; - target = CDDDE8D404074B9DC4C2291002D159F8 /* FLAnimatedImage-iOS8.1 */; - targetProxy = 1826D6540FAAB7D5E03719DA656945C0 /* PBXContainerItemProxy */; - }; - 8CA82B9B4E4537EAE1370F614FEFBBA5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "FLAnimatedImage-iOS7.1"; - target = 88946788461561787CE22BC14B767C3A /* FLAnimatedImage-iOS7.1 */; - targetProxy = E8A35CED3C5BBAA39E5D70997822C3E7 /* PBXContainerItemProxy */; - }; - 8EB8E69002973167328D71F4FCD92C79 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "FLAnimatedImage-iOS7.1"; - target = 88946788461561787CE22BC14B767C3A /* FLAnimatedImage-iOS7.1 */; - targetProxy = EC9123A0F3D1830DE149613FD144013E /* PBXContainerItemProxy */; - }; - BBC4E7B53B1C28B5A3ECF4A7C2F6017D /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "PINCache-iOS7.1"; - target = 2A4983A5807EEB91056950FD76E2D683 /* PINCache-iOS7.1 */; - targetProxy = E5017633B2BE6115FB50632AE2017A45 /* PBXContainerItemProxy */; - }; - D522C79608873A7AF7C5677EF8DAF3BB /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "PINRemoteImage-iOS7.1"; - target = DDC608954898A7553EB8B23009B076E2 /* PINRemoteImage-iOS7.1 */; - targetProxy = 1AA6B7DDBE093223BF00B56E0FDD39E0 /* PBXContainerItemProxy */; - }; - DFD090B1D6D65E70184F951B3016AD0E /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "libwebp-iOS7.1"; - target = 51E046FCB539FE8A23DFDD38C3222B17 /* libwebp-iOS7.1 */; - targetProxy = 9726DCCD95AA248F03F76994B3B915C4 /* PBXContainerItemProxy */; - }; - E5AE2BB1E9402675081481A6A47D715D /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "libwebp-iOS7.1"; - target = 51E046FCB539FE8A23DFDD38C3222B17 /* libwebp-iOS7.1 */; - targetProxy = D26F4FA5AC4D79D13AC9DE4E54C56E21 /* PBXContainerItemProxy */; - }; - F5CC318EC9E91D2A148AC4B60BE01141 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "PINRemoteImage-iOS8.1"; - target = 12CBE23502187E04EA33A1CAA9CBE617 /* PINRemoteImage-iOS8.1 */; - targetProxy = BAD0109B4FB4906E7680931A5455DC97 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 011C497008D57699EF2FD928A32E0F90 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 6FFB5369DE5023467EE00C37356BDA50 /* Pods-PINRemoteImage.debug.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; - MACH_O_TYPE = staticlib; - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - 04CD50465644789A7A026CC5F527BAF1 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 13E434C0AE2F99377B4587AE15199116 /* Pods-PINRemoteImage Tests.release.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; - MACH_O_TYPE = staticlib; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Release; - }; - 1B95ADD998A4516DB3DCD47ACD464FEF /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = C01F47D4080C1D2D7D49F894E89131F0 /* Pods-PINRemoteImage Tests.debug.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; - MACH_O_TYPE = staticlib; - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - 53B24DC53567B863A4EC939BA8C91EFC /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_DEBUG=1", - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; - ONLY_ACTIVE_ARCH = YES; - STRIP_INSTALLED_PRODUCT = NO; - SYMROOT = "${SRCROOT}/../build"; - }; - name = Debug; - }; - 56D8810974C126570C90F31F12CBC847 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 655D1EAFD3BB047F093C9F5514DEA4D9 /* FLAnimatedImage-iOS8.1.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/FLAnimatedImage-iOS8.1/FLAnimatedImage-iOS8.1-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - 655A5B997FCFD0609882785F49F62C95 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 92CAD77B67D37C3BEBCF08EEE0125E79 /* PINRemoteImage-iOS7.1.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/PINRemoteImage-iOS7.1/PINRemoteImage-iOS7.1-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Release; - }; - 6E8650B586063F4B0A6C383981C0C203 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_RELEASE=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; - STRIP_INSTALLED_PRODUCT = NO; - SYMROOT = "${SRCROOT}/../build"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 735D6846D928A37924FFB2607DC91022 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 3268D31245A99137C0933AF68F05DBBA /* PINCache-iOS8.1.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/PINCache-iOS8.1/PINCache-iOS8.1-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 5.0; - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - 7654DB880820767DB496838D7A4AB9C2 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 8898CB4CE3A428DA8AAFDA288619C550 /* PINRemoteImage-iOS8.1.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/PINRemoteImage-iOS8.1/PINRemoteImage-iOS8.1-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Release; - }; - 7E72C079CB873398130E5E2FBA7EF35E /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 5A3A10263F91713FAA7A0DF102A64451 /* FLAnimatedImage-iOS7.1.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/FLAnimatedImage-iOS7.1/FLAnimatedImage-iOS7.1-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Release; - }; - 8F6963601678C2655E18C485ED23DDBA /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 5A3A10263F91713FAA7A0DF102A64451 /* FLAnimatedImage-iOS7.1.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/FLAnimatedImage-iOS7.1/FLAnimatedImage-iOS7.1-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - 94CAD62CDE31951621798B3255145FCB /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 6AAB128F5E8D4D59D34CA86049D051BF /* libwebp-iOS7.1.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/libwebp-iOS7.1/libwebp-iOS7.1-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 4.3; - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - 95EC018007671BDF554D1B9748550018 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 6AAB128F5E8D4D59D34CA86049D051BF /* libwebp-iOS7.1.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/libwebp-iOS7.1/libwebp-iOS7.1-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 4.3; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Release; - }; - 9975305BC58057727BBD4F06CE55D3DA /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 57C7DA2DFA0213BB337A4A1989FA1E10 /* libwebp-iOS8.1.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/libwebp-iOS8.1/libwebp-iOS8.1-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 4.3; - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - B58826B1B91C37102BF9070DFCE39915 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = AFA3D68CD9574EC464F56E813615E080 /* PINCache-iOS7.1.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/PINCache-iOS7.1/PINCache-iOS7.1-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 5.0; - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - B6D8514EE0050B31ECEF9ECFEF63ED86 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 8898CB4CE3A428DA8AAFDA288619C550 /* PINRemoteImage-iOS8.1.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/PINRemoteImage-iOS8.1/PINRemoteImage-iOS8.1-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - D150A85CECAE1B61FD8315F71E5E26DF /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 655D1EAFD3BB047F093C9F5514DEA4D9 /* FLAnimatedImage-iOS8.1.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/FLAnimatedImage-iOS8.1/FLAnimatedImage-iOS8.1-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Release; - }; - D6E2429B3FF7720BC0245E7FF71B784D /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 92CAD77B67D37C3BEBCF08EEE0125E79 /* PINRemoteImage-iOS7.1.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/PINRemoteImage-iOS7.1/PINRemoteImage-iOS7.1-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - D963392F41856C2B78975600A8617C89 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = AFA3D68CD9574EC464F56E813615E080 /* PINCache-iOS7.1.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/PINCache-iOS7.1/PINCache-iOS7.1-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 5.0; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Release; - }; - DD4AC9D4BC45214F757A7308F24F3F24 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 57C7DA2DFA0213BB337A4A1989FA1E10 /* libwebp-iOS8.1.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/libwebp-iOS8.1/libwebp-iOS8.1-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 4.3; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Release; - }; - E9F4AFDE99505B7C05B1905B264A5D55 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 3268D31245A99137C0933AF68F05DBBA /* PINCache-iOS8.1.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/PINCache-iOS8.1/PINCache-iOS8.1-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 5.0; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Release; - }; - FCADB3FF5A014DCD89141F5CCF11B977 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = B2DA8820D153800A564142BBB03DED79 /* Pods-PINRemoteImage.release.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; - MACH_O_TYPE = staticlib; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 00AB695DCA9D77EEB2DCD36592266E29 /* Build configuration list for PBXNativeTarget "Pods-PINRemoteImage" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 011C497008D57699EF2FD928A32E0F90 /* Debug */, - FCADB3FF5A014DCD89141F5CCF11B977 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 53B24DC53567B863A4EC939BA8C91EFC /* Debug */, - 6E8650B586063F4B0A6C383981C0C203 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 683B0F92BD75D7498575AD7BAA86DE8A /* Build configuration list for PBXNativeTarget "PINCache-iOS8.1" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 735D6846D928A37924FFB2607DC91022 /* Debug */, - E9F4AFDE99505B7C05B1905B264A5D55 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 69D364B990CE319D0F13C54D914121C3 /* Build configuration list for PBXNativeTarget "PINRemoteImage-iOS7.1" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - D6E2429B3FF7720BC0245E7FF71B784D /* Debug */, - 655A5B997FCFD0609882785F49F62C95 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 73CFD4AA76FC05FC90A8FD8973BEBC4E /* Build configuration list for PBXNativeTarget "Pods-PINRemoteImage Tests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1B95ADD998A4516DB3DCD47ACD464FEF /* Debug */, - 04CD50465644789A7A026CC5F527BAF1 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 847EE451806ED13FD70697B2383D1CD5 /* Build configuration list for PBXNativeTarget "libwebp-iOS8.1" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 9975305BC58057727BBD4F06CE55D3DA /* Debug */, - DD4AC9D4BC45214F757A7308F24F3F24 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 87ACFCDB3A177BC0081CF7E2C7068A8F /* Build configuration list for PBXNativeTarget "FLAnimatedImage-iOS8.1" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 56D8810974C126570C90F31F12CBC847 /* Debug */, - D150A85CECAE1B61FD8315F71E5E26DF /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 8BA82A19CA3C518B43793113656FB1DD /* Build configuration list for PBXNativeTarget "FLAnimatedImage-iOS7.1" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 8F6963601678C2655E18C485ED23DDBA /* Debug */, - 7E72C079CB873398130E5E2FBA7EF35E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 9BDC4000E61D29DF99A2F13B3E38BFDE /* Build configuration list for PBXNativeTarget "libwebp-iOS7.1" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 94CAD62CDE31951621798B3255145FCB /* Debug */, - 95EC018007671BDF554D1B9748550018 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - E6422E5B433DD68BE8B8292DC11CC79C /* Build configuration list for PBXNativeTarget "PINRemoteImage-iOS8.1" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - B6D8514EE0050B31ECEF9ECFEF63ED86 /* Debug */, - 7654DB880820767DB496838D7A4AB9C2 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - EE6A6FAB2E4BD052DF208659E1D78572 /* Build configuration list for PBXNativeTarget "PINCache-iOS7.1" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - B58826B1B91C37102BF9070DFCE39915 /* Debug */, - D963392F41856C2B78975600A8617C89 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */; -} diff --git a/Example/Pods/Target Support Files/FLAnimatedImage-iOS7.1/FLAnimatedImage-iOS7.1-dummy.m b/Example/Pods/Target Support Files/FLAnimatedImage-iOS7.1/FLAnimatedImage-iOS7.1-dummy.m deleted file mode 100644 index a05699d9..00000000 --- a/Example/Pods/Target Support Files/FLAnimatedImage-iOS7.1/FLAnimatedImage-iOS7.1-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_FLAnimatedImage_iOS7_1 : NSObject -@end -@implementation PodsDummy_FLAnimatedImage_iOS7_1 -@end diff --git a/Example/Pods/Target Support Files/FLAnimatedImage-iOS7.1/FLAnimatedImage-iOS7.1-prefix.pch b/Example/Pods/Target Support Files/FLAnimatedImage-iOS7.1/FLAnimatedImage-iOS7.1-prefix.pch deleted file mode 100644 index aa992a4a..00000000 --- a/Example/Pods/Target Support Files/FLAnimatedImage-iOS7.1/FLAnimatedImage-iOS7.1-prefix.pch +++ /dev/null @@ -1,4 +0,0 @@ -#ifdef __OBJC__ -#import -#endif - diff --git a/Example/Pods/Target Support Files/FLAnimatedImage-iOS7.1/FLAnimatedImage-iOS7.1.xcconfig b/Example/Pods/Target Support Files/FLAnimatedImage-iOS7.1/FLAnimatedImage-iOS7.1.xcconfig deleted file mode 100644 index 5a6cf3d5..00000000 --- a/Example/Pods/Target Support Files/FLAnimatedImage-iOS7.1/FLAnimatedImage-iOS7.1.xcconfig +++ /dev/null @@ -1,9 +0,0 @@ -CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/FLAnimatedImage-iOS7.1 -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/FLAnimatedImage" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/FLAnimatedImage" "${PODS_ROOT}/Headers/Public/PINCache" "${PODS_ROOT}/Headers/Public/PINRemoteImage" "${PODS_ROOT}/Headers/Public/libwebp" -OTHER_LDFLAGS = -framework "CoreGraphics" -framework "ImageIO" -framework "MobileCoreServices" -framework "QuartzCore" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES diff --git a/Example/Pods/Target Support Files/FLAnimatedImage-iOS8.1/FLAnimatedImage-iOS8.1-dummy.m b/Example/Pods/Target Support Files/FLAnimatedImage-iOS8.1/FLAnimatedImage-iOS8.1-dummy.m deleted file mode 100644 index a4ed3eba..00000000 --- a/Example/Pods/Target Support Files/FLAnimatedImage-iOS8.1/FLAnimatedImage-iOS8.1-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_FLAnimatedImage_iOS8_1 : NSObject -@end -@implementation PodsDummy_FLAnimatedImage_iOS8_1 -@end diff --git a/Example/Pods/Target Support Files/FLAnimatedImage-iOS8.1/FLAnimatedImage-iOS8.1-prefix.pch b/Example/Pods/Target Support Files/FLAnimatedImage-iOS8.1/FLAnimatedImage-iOS8.1-prefix.pch deleted file mode 100644 index aa992a4a..00000000 --- a/Example/Pods/Target Support Files/FLAnimatedImage-iOS8.1/FLAnimatedImage-iOS8.1-prefix.pch +++ /dev/null @@ -1,4 +0,0 @@ -#ifdef __OBJC__ -#import -#endif - diff --git a/Example/Pods/Target Support Files/FLAnimatedImage-iOS8.1/FLAnimatedImage-iOS8.1.xcconfig b/Example/Pods/Target Support Files/FLAnimatedImage-iOS8.1/FLAnimatedImage-iOS8.1.xcconfig deleted file mode 100644 index 2672fbfa..00000000 --- a/Example/Pods/Target Support Files/FLAnimatedImage-iOS8.1/FLAnimatedImage-iOS8.1.xcconfig +++ /dev/null @@ -1,9 +0,0 @@ -CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/FLAnimatedImage-iOS8.1 -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/FLAnimatedImage" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/FLAnimatedImage" "${PODS_ROOT}/Headers/Public/PINCache" "${PODS_ROOT}/Headers/Public/PINRemoteImage" "${PODS_ROOT}/Headers/Public/libwebp" -OTHER_LDFLAGS = -framework "CoreGraphics" -framework "ImageIO" -framework "MobileCoreServices" -framework "QuartzCore" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES diff --git a/Example/Pods/Target Support Files/PINCache-iOS7.1/PINCache-iOS7.1-dummy.m b/Example/Pods/Target Support Files/PINCache-iOS7.1/PINCache-iOS7.1-dummy.m deleted file mode 100644 index 1c058761..00000000 --- a/Example/Pods/Target Support Files/PINCache-iOS7.1/PINCache-iOS7.1-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_PINCache_iOS7_1 : NSObject -@end -@implementation PodsDummy_PINCache_iOS7_1 -@end diff --git a/Example/Pods/Target Support Files/PINCache-iOS7.1/PINCache-iOS7.1-prefix.pch b/Example/Pods/Target Support Files/PINCache-iOS7.1/PINCache-iOS7.1-prefix.pch deleted file mode 100644 index 5e15de4f..00000000 --- a/Example/Pods/Target Support Files/PINCache-iOS7.1/PINCache-iOS7.1-prefix.pch +++ /dev/null @@ -1,7 +0,0 @@ -#ifdef __OBJC__ -#import -#endif - -#ifndef TARGET_OS_WATCH - #define TARGET_OS_WATCH 0 -#endif diff --git a/Example/Pods/Target Support Files/PINCache-iOS7.1/PINCache-iOS7.1.xcconfig b/Example/Pods/Target Support Files/PINCache-iOS7.1/PINCache-iOS7.1.xcconfig deleted file mode 100644 index 0a4a5e38..00000000 --- a/Example/Pods/Target Support Files/PINCache-iOS7.1/PINCache-iOS7.1.xcconfig +++ /dev/null @@ -1,9 +0,0 @@ -CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/PINCache-iOS7.1 -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/PINCache" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/FLAnimatedImage" "${PODS_ROOT}/Headers/Public/PINCache" "${PODS_ROOT}/Headers/Public/PINRemoteImage" "${PODS_ROOT}/Headers/Public/libwebp" -OTHER_LDFLAGS = -framework "Foundation" -weak_framework "UIKit" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES diff --git a/Example/Pods/Target Support Files/PINCache-iOS8.1/PINCache-iOS8.1-dummy.m b/Example/Pods/Target Support Files/PINCache-iOS8.1/PINCache-iOS8.1-dummy.m deleted file mode 100644 index eaee62d4..00000000 --- a/Example/Pods/Target Support Files/PINCache-iOS8.1/PINCache-iOS8.1-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_PINCache_iOS8_1 : NSObject -@end -@implementation PodsDummy_PINCache_iOS8_1 -@end diff --git a/Example/Pods/Target Support Files/PINCache-iOS8.1/PINCache-iOS8.1-prefix.pch b/Example/Pods/Target Support Files/PINCache-iOS8.1/PINCache-iOS8.1-prefix.pch deleted file mode 100644 index 5e15de4f..00000000 --- a/Example/Pods/Target Support Files/PINCache-iOS8.1/PINCache-iOS8.1-prefix.pch +++ /dev/null @@ -1,7 +0,0 @@ -#ifdef __OBJC__ -#import -#endif - -#ifndef TARGET_OS_WATCH - #define TARGET_OS_WATCH 0 -#endif diff --git a/Example/Pods/Target Support Files/PINCache-iOS8.1/PINCache-iOS8.1.xcconfig b/Example/Pods/Target Support Files/PINCache-iOS8.1/PINCache-iOS8.1.xcconfig deleted file mode 100644 index b0d32c55..00000000 --- a/Example/Pods/Target Support Files/PINCache-iOS8.1/PINCache-iOS8.1.xcconfig +++ /dev/null @@ -1,9 +0,0 @@ -CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/PINCache-iOS8.1 -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/PINCache" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/FLAnimatedImage" "${PODS_ROOT}/Headers/Public/PINCache" "${PODS_ROOT}/Headers/Public/PINRemoteImage" "${PODS_ROOT}/Headers/Public/libwebp" -OTHER_LDFLAGS = -framework "Foundation" -weak_framework "UIKit" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES diff --git a/Example/Pods/Target Support Files/PINRemoteImage-iOS7.1/PINRemoteImage-iOS7.1-dummy.m b/Example/Pods/Target Support Files/PINRemoteImage-iOS7.1/PINRemoteImage-iOS7.1-dummy.m deleted file mode 100644 index e03c8585..00000000 --- a/Example/Pods/Target Support Files/PINRemoteImage-iOS7.1/PINRemoteImage-iOS7.1-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_PINRemoteImage_iOS7_1 : NSObject -@end -@implementation PodsDummy_PINRemoteImage_iOS7_1 -@end diff --git a/Example/Pods/Target Support Files/PINRemoteImage-iOS7.1/PINRemoteImage-iOS7.1-prefix.pch b/Example/Pods/Target Support Files/PINRemoteImage-iOS7.1/PINRemoteImage-iOS7.1-prefix.pch deleted file mode 100644 index aa992a4a..00000000 --- a/Example/Pods/Target Support Files/PINRemoteImage-iOS7.1/PINRemoteImage-iOS7.1-prefix.pch +++ /dev/null @@ -1,4 +0,0 @@ -#ifdef __OBJC__ -#import -#endif - diff --git a/Example/Pods/Target Support Files/PINRemoteImage-iOS7.1/PINRemoteImage-iOS7.1.xcconfig b/Example/Pods/Target Support Files/PINRemoteImage-iOS7.1/PINRemoteImage-iOS7.1.xcconfig deleted file mode 100644 index b8c826bb..00000000 --- a/Example/Pods/Target Support Files/PINRemoteImage-iOS7.1/PINRemoteImage-iOS7.1.xcconfig +++ /dev/null @@ -1,11 +0,0 @@ -CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/PINRemoteImage-iOS7.1 -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PIN_WEBP=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/PINRemoteImage" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/FLAnimatedImage" "${PODS_ROOT}/Headers/Public/PINCache" "${PODS_ROOT}/Headers/Public/PINRemoteImage" "${PODS_ROOT}/Headers/Public/libwebp" -LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/FLAnimatedImage-iOS7.1" "$PODS_CONFIGURATION_BUILD_DIR/PINCache-iOS7.1" "$PODS_CONFIGURATION_BUILD_DIR/libwebp-iOS7.1" -OTHER_LDFLAGS = -framework "Accelerate" -framework "ImageIO" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES -USER_HEADER_SEARCH_PATHS = $(inherited) $(SRCROOT)/libwebp/src diff --git a/Example/Pods/Target Support Files/PINRemoteImage-iOS8.1/PINRemoteImage-iOS8.1-dummy.m b/Example/Pods/Target Support Files/PINRemoteImage-iOS8.1/PINRemoteImage-iOS8.1-dummy.m deleted file mode 100644 index 3f45ca78..00000000 --- a/Example/Pods/Target Support Files/PINRemoteImage-iOS8.1/PINRemoteImage-iOS8.1-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_PINRemoteImage_iOS8_1 : NSObject -@end -@implementation PodsDummy_PINRemoteImage_iOS8_1 -@end diff --git a/Example/Pods/Target Support Files/PINRemoteImage-iOS8.1/PINRemoteImage-iOS8.1-prefix.pch b/Example/Pods/Target Support Files/PINRemoteImage-iOS8.1/PINRemoteImage-iOS8.1-prefix.pch deleted file mode 100644 index aa992a4a..00000000 --- a/Example/Pods/Target Support Files/PINRemoteImage-iOS8.1/PINRemoteImage-iOS8.1-prefix.pch +++ /dev/null @@ -1,4 +0,0 @@ -#ifdef __OBJC__ -#import -#endif - diff --git a/Example/Pods/Target Support Files/PINRemoteImage-iOS8.1/PINRemoteImage-iOS8.1.xcconfig b/Example/Pods/Target Support Files/PINRemoteImage-iOS8.1/PINRemoteImage-iOS8.1.xcconfig deleted file mode 100644 index 790b6fc3..00000000 --- a/Example/Pods/Target Support Files/PINRemoteImage-iOS8.1/PINRemoteImage-iOS8.1.xcconfig +++ /dev/null @@ -1,11 +0,0 @@ -CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/PINRemoteImage-iOS8.1 -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PIN_WEBP=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/PINRemoteImage" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/FLAnimatedImage" "${PODS_ROOT}/Headers/Public/PINCache" "${PODS_ROOT}/Headers/Public/PINRemoteImage" "${PODS_ROOT}/Headers/Public/libwebp" -LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/FLAnimatedImage-iOS7.1" "$PODS_CONFIGURATION_BUILD_DIR/PINCache-iOS7.1" "$PODS_CONFIGURATION_BUILD_DIR/libwebp-iOS7.1" -OTHER_LDFLAGS = -framework "Accelerate" -framework "ImageIO" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES -USER_HEADER_SEARCH_PATHS = $(inherited) $(SRCROOT)/libwebp/src diff --git a/Example/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests-acknowledgements.markdown b/Example/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests-acknowledgements.markdown deleted file mode 100644 index f94d32a1..00000000 --- a/Example/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests-acknowledgements.markdown +++ /dev/null @@ -1,284 +0,0 @@ -# Acknowledgements -This application makes use of the following third party libraries: - -## FLAnimatedImage - -The MIT License (MIT) - -Copyright (c) 2014-2016 Flipboard - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -## PINCache - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [2013] [Tumblr, Inc.] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - -## PINRemoteImage - -Copyright (c) 2015-2016 Pinterest, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - -## libwebp - -Copyright (c) 2010, Google Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of Google nor the names of its contributors may - be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -Generated by CocoaPods - https://cocoapods.org diff --git a/Example/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests-acknowledgements.plist b/Example/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests-acknowledgements.plist deleted file mode 100644 index db89cbbd..00000000 --- a/Example/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests-acknowledgements.plist +++ /dev/null @@ -1,326 +0,0 @@ - - - - - PreferenceSpecifiers - - - FooterText - This application makes use of the following third party libraries: - Title - Acknowledgements - Type - PSGroupSpecifier - - - FooterText - The MIT License (MIT) - -Copyright (c) 2014-2016 Flipboard - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - Title - FLAnimatedImage - Type - PSGroupSpecifier - - - FooterText - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [2013] [Tumblr, Inc.] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - Title - PINCache - Type - PSGroupSpecifier - - - FooterText - Copyright (c) 2015-2016 Pinterest, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - Title - PINRemoteImage - Type - PSGroupSpecifier - - - FooterText - Copyright (c) 2010, Google Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of Google nor the names of its contributors may - be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - Title - libwebp - Type - PSGroupSpecifier - - - FooterText - Generated by CocoaPods - https://cocoapods.org - Title - - Type - PSGroupSpecifier - - - StringsTable - Acknowledgements - Title - Acknowledgements - - diff --git a/Example/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests-dummy.m b/Example/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests-dummy.m deleted file mode 100644 index a6c8ec34..00000000 --- a/Example/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Pods_PINRemoteImage_Tests : NSObject -@end -@implementation PodsDummy_Pods_PINRemoteImage_Tests -@end diff --git a/Example/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests-frameworks.sh b/Example/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests-frameworks.sh deleted file mode 100755 index 893c16a6..00000000 --- a/Example/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests-frameworks.sh +++ /dev/null @@ -1,84 +0,0 @@ -#!/bin/sh -set -e - -echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" -mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - -SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" - -install_framework() -{ - if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then - local source="${BUILT_PRODUCTS_DIR}/$1" - elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then - local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" - elif [ -r "$1" ]; then - local source="$1" - fi - - local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - - if [ -L "${source}" ]; then - echo "Symlinked..." - source="$(readlink "${source}")" - fi - - # use filter instead of exclude so missing patterns dont' throw errors - echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" - rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" - - local basename - basename="$(basename -s .framework "$1")" - binary="${destination}/${basename}.framework/${basename}" - if ! [ -r "$binary" ]; then - binary="${destination}/${basename}" - fi - - # Strip invalid architectures so "fat" simulator / device frameworks work on device - if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then - strip_invalid_archs "$binary" - fi - - # Resign the code if required by the build settings to avoid unstable apps - code_sign_if_enabled "${destination}/$(basename "$1")" - - # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. - if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then - local swift_runtime_libs - swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) - for lib in $swift_runtime_libs; do - echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" - rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" - code_sign_if_enabled "${destination}/${lib}" - done - fi -} - -# Signs a framework with the provided identity -code_sign_if_enabled() { - if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then - # Use the current code_sign_identitiy - echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" - echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\"" - /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1" - fi -} - -# Strip invalid architectures -strip_invalid_archs() { - binary="$1" - # Get architectures for current file - archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" - stripped="" - for arch in $archs; do - if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then - # Strip non-valid architectures in-place - lipo -remove "$arch" -output "$binary" "$binary" || exit 1 - stripped="$stripped $arch" - fi - done - if [[ "$stripped" ]]; then - echo "Stripped $binary of architectures:$stripped" - fi -} - diff --git a/Example/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests-resources.sh b/Example/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests-resources.sh deleted file mode 100755 index e768f929..00000000 --- a/Example/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests-resources.sh +++ /dev/null @@ -1,102 +0,0 @@ -#!/bin/sh -set -e - -mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" - -RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt -> "$RESOURCES_TO_COPY" - -XCASSET_FILES=() - -case "${TARGETED_DEVICE_FAMILY}" in - 1,2) - TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" - ;; - 1) - TARGET_DEVICE_ARGS="--target-device iphone" - ;; - 2) - TARGET_DEVICE_ARGS="--target-device ipad" - ;; - *) - TARGET_DEVICE_ARGS="--target-device mac" - ;; -esac - -realpath() { - DIRECTORY="$(cd "${1%/*}" && pwd)" - FILENAME="${1##*/}" - echo "$DIRECTORY/$FILENAME" -} - -install_resource() -{ - if [[ "$1" = /* ]] ; then - RESOURCE_PATH="$1" - else - RESOURCE_PATH="${PODS_ROOT}/$1" - fi - if [[ ! -e "$RESOURCE_PATH" ]] ; then - cat << EOM -error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. -EOM - exit 1 - fi - case $RESOURCE_PATH in - *.storyboard) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" - ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} - ;; - *.xib) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT}" - ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" - ;; - *.framework) - echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - ;; - *.xcdatamodel) - echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" - xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" - ;; - *.xcdatamodeld) - echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" - xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" - ;; - *.xcmappingmodel) - echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" - xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" - ;; - *.xcassets) - ABSOLUTE_XCASSET_FILE=$(realpath "$RESOURCE_PATH") - XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") - ;; - *) - echo "$RESOURCE_PATH" - echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" - ;; - esac -} - -mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then - mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" - rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -fi -rm -f "$RESOURCES_TO_COPY" - -if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] -then - # Find all other xcassets (this unfortunately includes those of path pods and other targets). - OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) - while read line; do - if [[ $line != "`realpath $PODS_ROOT`*" ]]; then - XCASSET_FILES+=("$line") - fi - done <<<"$OTHER_XCASSETS" - - printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -fi diff --git a/Example/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests.debug.xcconfig b/Example/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests.debug.xcconfig deleted file mode 100644 index 6bb07817..00000000 --- a/Example/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests.debug.xcconfig +++ /dev/null @@ -1,9 +0,0 @@ -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PIN_WEBP=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/FLAnimatedImage" "${PODS_ROOT}/Headers/Public/PINCache" "${PODS_ROOT}/Headers/Public/PINRemoteImage" "${PODS_ROOT}/Headers/Public/libwebp" -LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/FLAnimatedImage-iOS8.1" "$PODS_CONFIGURATION_BUILD_DIR/PINCache-iOS8.1" "$PODS_CONFIGURATION_BUILD_DIR/PINRemoteImage-iOS8.1" "$PODS_CONFIGURATION_BUILD_DIR/libwebp-iOS8.1" -OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/FLAnimatedImage" -isystem "${PODS_ROOT}/Headers/Public/PINCache" -isystem "${PODS_ROOT}/Headers/Public/PINRemoteImage" -isystem "${PODS_ROOT}/Headers/Public/libwebp" -OTHER_LDFLAGS = $(inherited) -ObjC -l"FLAnimatedImage-iOS8.1" -l"PINCache-iOS8.1" -l"PINRemoteImage-iOS8.1" -l"libwebp-iOS8.1" -framework "Accelerate" -framework "CoreGraphics" -framework "Foundation" -framework "ImageIO" -framework "MobileCoreServices" -framework "QuartzCore" -weak_framework "UIKit" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT}/Pods -USER_HEADER_SEARCH_PATHS = $(inherited) $(SRCROOT)/libwebp/src diff --git a/Example/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests.release.xcconfig b/Example/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests.release.xcconfig deleted file mode 100644 index 6bb07817..00000000 --- a/Example/Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests.release.xcconfig +++ /dev/null @@ -1,9 +0,0 @@ -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PIN_WEBP=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/FLAnimatedImage" "${PODS_ROOT}/Headers/Public/PINCache" "${PODS_ROOT}/Headers/Public/PINRemoteImage" "${PODS_ROOT}/Headers/Public/libwebp" -LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/FLAnimatedImage-iOS8.1" "$PODS_CONFIGURATION_BUILD_DIR/PINCache-iOS8.1" "$PODS_CONFIGURATION_BUILD_DIR/PINRemoteImage-iOS8.1" "$PODS_CONFIGURATION_BUILD_DIR/libwebp-iOS8.1" -OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/FLAnimatedImage" -isystem "${PODS_ROOT}/Headers/Public/PINCache" -isystem "${PODS_ROOT}/Headers/Public/PINRemoteImage" -isystem "${PODS_ROOT}/Headers/Public/libwebp" -OTHER_LDFLAGS = $(inherited) -ObjC -l"FLAnimatedImage-iOS8.1" -l"PINCache-iOS8.1" -l"PINRemoteImage-iOS8.1" -l"libwebp-iOS8.1" -framework "Accelerate" -framework "CoreGraphics" -framework "Foundation" -framework "ImageIO" -framework "MobileCoreServices" -framework "QuartzCore" -weak_framework "UIKit" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT}/Pods -USER_HEADER_SEARCH_PATHS = $(inherited) $(SRCROOT)/libwebp/src diff --git a/Example/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-acknowledgements.markdown b/Example/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-acknowledgements.markdown deleted file mode 100644 index f94d32a1..00000000 --- a/Example/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-acknowledgements.markdown +++ /dev/null @@ -1,284 +0,0 @@ -# Acknowledgements -This application makes use of the following third party libraries: - -## FLAnimatedImage - -The MIT License (MIT) - -Copyright (c) 2014-2016 Flipboard - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -## PINCache - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [2013] [Tumblr, Inc.] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - -## PINRemoteImage - -Copyright (c) 2015-2016 Pinterest, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - -## libwebp - -Copyright (c) 2010, Google Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of Google nor the names of its contributors may - be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -Generated by CocoaPods - https://cocoapods.org diff --git a/Example/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-acknowledgements.plist b/Example/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-acknowledgements.plist deleted file mode 100644 index db89cbbd..00000000 --- a/Example/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-acknowledgements.plist +++ /dev/null @@ -1,326 +0,0 @@ - - - - - PreferenceSpecifiers - - - FooterText - This application makes use of the following third party libraries: - Title - Acknowledgements - Type - PSGroupSpecifier - - - FooterText - The MIT License (MIT) - -Copyright (c) 2014-2016 Flipboard - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - Title - FLAnimatedImage - Type - PSGroupSpecifier - - - FooterText - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [2013] [Tumblr, Inc.] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - Title - PINCache - Type - PSGroupSpecifier - - - FooterText - Copyright (c) 2015-2016 Pinterest, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - Title - PINRemoteImage - Type - PSGroupSpecifier - - - FooterText - Copyright (c) 2010, Google Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of Google nor the names of its contributors may - be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - Title - libwebp - Type - PSGroupSpecifier - - - FooterText - Generated by CocoaPods - https://cocoapods.org - Title - - Type - PSGroupSpecifier - - - StringsTable - Acknowledgements - Title - Acknowledgements - - diff --git a/Example/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-dummy.m b/Example/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-dummy.m deleted file mode 100644 index f17cca3c..00000000 --- a/Example/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Pods_PINRemoteImage : NSObject -@end -@implementation PodsDummy_Pods_PINRemoteImage -@end diff --git a/Example/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-frameworks.sh b/Example/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-frameworks.sh deleted file mode 100755 index 893c16a6..00000000 --- a/Example/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-frameworks.sh +++ /dev/null @@ -1,84 +0,0 @@ -#!/bin/sh -set -e - -echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" -mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - -SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" - -install_framework() -{ - if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then - local source="${BUILT_PRODUCTS_DIR}/$1" - elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then - local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" - elif [ -r "$1" ]; then - local source="$1" - fi - - local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - - if [ -L "${source}" ]; then - echo "Symlinked..." - source="$(readlink "${source}")" - fi - - # use filter instead of exclude so missing patterns dont' throw errors - echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" - rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" - - local basename - basename="$(basename -s .framework "$1")" - binary="${destination}/${basename}.framework/${basename}" - if ! [ -r "$binary" ]; then - binary="${destination}/${basename}" - fi - - # Strip invalid architectures so "fat" simulator / device frameworks work on device - if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then - strip_invalid_archs "$binary" - fi - - # Resign the code if required by the build settings to avoid unstable apps - code_sign_if_enabled "${destination}/$(basename "$1")" - - # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. - if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then - local swift_runtime_libs - swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) - for lib in $swift_runtime_libs; do - echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" - rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" - code_sign_if_enabled "${destination}/${lib}" - done - fi -} - -# Signs a framework with the provided identity -code_sign_if_enabled() { - if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then - # Use the current code_sign_identitiy - echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" - echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\"" - /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1" - fi -} - -# Strip invalid architectures -strip_invalid_archs() { - binary="$1" - # Get architectures for current file - archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" - stripped="" - for arch in $archs; do - if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then - # Strip non-valid architectures in-place - lipo -remove "$arch" -output "$binary" "$binary" || exit 1 - stripped="$stripped $arch" - fi - done - if [[ "$stripped" ]]; then - echo "Stripped $binary of architectures:$stripped" - fi -} - diff --git a/Example/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-resources.sh b/Example/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-resources.sh deleted file mode 100755 index e768f929..00000000 --- a/Example/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage-resources.sh +++ /dev/null @@ -1,102 +0,0 @@ -#!/bin/sh -set -e - -mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" - -RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt -> "$RESOURCES_TO_COPY" - -XCASSET_FILES=() - -case "${TARGETED_DEVICE_FAMILY}" in - 1,2) - TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" - ;; - 1) - TARGET_DEVICE_ARGS="--target-device iphone" - ;; - 2) - TARGET_DEVICE_ARGS="--target-device ipad" - ;; - *) - TARGET_DEVICE_ARGS="--target-device mac" - ;; -esac - -realpath() { - DIRECTORY="$(cd "${1%/*}" && pwd)" - FILENAME="${1##*/}" - echo "$DIRECTORY/$FILENAME" -} - -install_resource() -{ - if [[ "$1" = /* ]] ; then - RESOURCE_PATH="$1" - else - RESOURCE_PATH="${PODS_ROOT}/$1" - fi - if [[ ! -e "$RESOURCE_PATH" ]] ; then - cat << EOM -error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. -EOM - exit 1 - fi - case $RESOURCE_PATH in - *.storyboard) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" - ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} - ;; - *.xib) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT}" - ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" - ;; - *.framework) - echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - ;; - *.xcdatamodel) - echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" - xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" - ;; - *.xcdatamodeld) - echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" - xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" - ;; - *.xcmappingmodel) - echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" - xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" - ;; - *.xcassets) - ABSOLUTE_XCASSET_FILE=$(realpath "$RESOURCE_PATH") - XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") - ;; - *) - echo "$RESOURCE_PATH" - echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" - ;; - esac -} - -mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then - mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" - rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -fi -rm -f "$RESOURCES_TO_COPY" - -if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] -then - # Find all other xcassets (this unfortunately includes those of path pods and other targets). - OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) - while read line; do - if [[ $line != "`realpath $PODS_ROOT`*" ]]; then - XCASSET_FILES+=("$line") - fi - done <<<"$OTHER_XCASSETS" - - printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -fi diff --git a/Example/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage.debug.xcconfig b/Example/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage.debug.xcconfig deleted file mode 100644 index abade538..00000000 --- a/Example/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage.debug.xcconfig +++ /dev/null @@ -1,9 +0,0 @@ -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PIN_WEBP=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/FLAnimatedImage" "${PODS_ROOT}/Headers/Public/PINCache" "${PODS_ROOT}/Headers/Public/PINRemoteImage" "${PODS_ROOT}/Headers/Public/libwebp" -LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/FLAnimatedImage-iOS7.1" "$PODS_CONFIGURATION_BUILD_DIR/PINCache-iOS7.1" "$PODS_CONFIGURATION_BUILD_DIR/PINRemoteImage-iOS7.1" "$PODS_CONFIGURATION_BUILD_DIR/libwebp-iOS7.1" -OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/FLAnimatedImage" -isystem "${PODS_ROOT}/Headers/Public/PINCache" -isystem "${PODS_ROOT}/Headers/Public/PINRemoteImage" -isystem "${PODS_ROOT}/Headers/Public/libwebp" -OTHER_LDFLAGS = $(inherited) -ObjC -l"FLAnimatedImage-iOS7.1" -l"PINCache-iOS7.1" -l"PINRemoteImage-iOS7.1" -l"libwebp-iOS7.1" -framework "Accelerate" -framework "CoreGraphics" -framework "Foundation" -framework "ImageIO" -framework "MobileCoreServices" -framework "QuartzCore" -weak_framework "UIKit" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT}/Pods -USER_HEADER_SEARCH_PATHS = $(inherited) $(SRCROOT)/libwebp/src diff --git a/Example/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage.release.xcconfig b/Example/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage.release.xcconfig deleted file mode 100644 index abade538..00000000 --- a/Example/Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage.release.xcconfig +++ /dev/null @@ -1,9 +0,0 @@ -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PIN_WEBP=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/FLAnimatedImage" "${PODS_ROOT}/Headers/Public/PINCache" "${PODS_ROOT}/Headers/Public/PINRemoteImage" "${PODS_ROOT}/Headers/Public/libwebp" -LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/FLAnimatedImage-iOS7.1" "$PODS_CONFIGURATION_BUILD_DIR/PINCache-iOS7.1" "$PODS_CONFIGURATION_BUILD_DIR/PINRemoteImage-iOS7.1" "$PODS_CONFIGURATION_BUILD_DIR/libwebp-iOS7.1" -OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/FLAnimatedImage" -isystem "${PODS_ROOT}/Headers/Public/PINCache" -isystem "${PODS_ROOT}/Headers/Public/PINRemoteImage" -isystem "${PODS_ROOT}/Headers/Public/libwebp" -OTHER_LDFLAGS = $(inherited) -ObjC -l"FLAnimatedImage-iOS7.1" -l"PINCache-iOS7.1" -l"PINRemoteImage-iOS7.1" -l"libwebp-iOS7.1" -framework "Accelerate" -framework "CoreGraphics" -framework "Foundation" -framework "ImageIO" -framework "MobileCoreServices" -framework "QuartzCore" -weak_framework "UIKit" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT}/Pods -USER_HEADER_SEARCH_PATHS = $(inherited) $(SRCROOT)/libwebp/src diff --git a/Example/Pods/Target Support Files/libwebp-iOS7.1/libwebp-iOS7.1-dummy.m b/Example/Pods/Target Support Files/libwebp-iOS7.1/libwebp-iOS7.1-dummy.m deleted file mode 100644 index c0222849..00000000 --- a/Example/Pods/Target Support Files/libwebp-iOS7.1/libwebp-iOS7.1-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_libwebp_iOS7_1 : NSObject -@end -@implementation PodsDummy_libwebp_iOS7_1 -@end diff --git a/Example/Pods/Target Support Files/libwebp-iOS7.1/libwebp-iOS7.1-prefix.pch b/Example/Pods/Target Support Files/libwebp-iOS7.1/libwebp-iOS7.1-prefix.pch deleted file mode 100644 index aa992a4a..00000000 --- a/Example/Pods/Target Support Files/libwebp-iOS7.1/libwebp-iOS7.1-prefix.pch +++ /dev/null @@ -1,4 +0,0 @@ -#ifdef __OBJC__ -#import -#endif - diff --git a/Example/Pods/Target Support Files/libwebp-iOS7.1/libwebp-iOS7.1.xcconfig b/Example/Pods/Target Support Files/libwebp-iOS7.1/libwebp-iOS7.1.xcconfig deleted file mode 100644 index 2f2bd264..00000000 --- a/Example/Pods/Target Support Files/libwebp-iOS7.1/libwebp-iOS7.1.xcconfig +++ /dev/null @@ -1,8 +0,0 @@ -CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/libwebp-iOS7.1 -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/libwebp" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/FLAnimatedImage" "${PODS_ROOT}/Headers/Public/PINCache" "${PODS_ROOT}/Headers/Public/PINRemoteImage" "${PODS_ROOT}/Headers/Public/libwebp" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES diff --git a/Example/Pods/Target Support Files/libwebp-iOS8.1/libwebp-iOS8.1-dummy.m b/Example/Pods/Target Support Files/libwebp-iOS8.1/libwebp-iOS8.1-dummy.m deleted file mode 100644 index 9dd7ce60..00000000 --- a/Example/Pods/Target Support Files/libwebp-iOS8.1/libwebp-iOS8.1-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_libwebp_iOS8_1 : NSObject -@end -@implementation PodsDummy_libwebp_iOS8_1 -@end diff --git a/Example/Pods/Target Support Files/libwebp-iOS8.1/libwebp-iOS8.1-prefix.pch b/Example/Pods/Target Support Files/libwebp-iOS8.1/libwebp-iOS8.1-prefix.pch deleted file mode 100644 index aa992a4a..00000000 --- a/Example/Pods/Target Support Files/libwebp-iOS8.1/libwebp-iOS8.1-prefix.pch +++ /dev/null @@ -1,4 +0,0 @@ -#ifdef __OBJC__ -#import -#endif - diff --git a/Example/Pods/Target Support Files/libwebp-iOS8.1/libwebp-iOS8.1.xcconfig b/Example/Pods/Target Support Files/libwebp-iOS8.1/libwebp-iOS8.1.xcconfig deleted file mode 100644 index a8ea3731..00000000 --- a/Example/Pods/Target Support Files/libwebp-iOS8.1/libwebp-iOS8.1.xcconfig +++ /dev/null @@ -1,8 +0,0 @@ -CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/libwebp-iOS8.1 -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/libwebp" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/FLAnimatedImage" "${PODS_ROOT}/Headers/Public/PINCache" "${PODS_ROOT}/Headers/Public/PINRemoteImage" "${PODS_ROOT}/Headers/Public/libwebp" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES diff --git a/Example/Pods/libwebp/COPYING b/Example/Pods/libwebp/COPYING deleted file mode 100644 index 7a6f9954..00000000 --- a/Example/Pods/libwebp/COPYING +++ /dev/null @@ -1,30 +0,0 @@ -Copyright (c) 2010, Google Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of Google nor the names of its contributors may - be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/Example/Pods/libwebp/README b/Example/Pods/libwebp/README deleted file mode 100644 index 381b9270..00000000 --- a/Example/Pods/libwebp/README +++ /dev/null @@ -1,649 +0,0 @@ - __ __ ____ ____ ____ - / \\/ \/ _ \/ _ )/ _ \ - \ / __/ _ \ __/ - \__\__/\____/\_____/__/ ____ ___ - / _/ / \ \ / _ \/ _/ - / \_/ / / \ \ __/ \__ - \____/____/\_____/_____/____/v0.5.0 - -Description: -============ - -WebP codec: library to encode and decode images in WebP format. This package -contains the library that can be used in other programs to add WebP support, -as well as the command line tools 'cwebp' and 'dwebp'. - -See http://developers.google.com/speed/webp - -The latest source tree is available at -https://chromium.googlesource.com/webm/libwebp - -It is released under the same license as the WebM project. -See http://www.webmproject.org/license/software/ or the -file "COPYING" file for details. An additional intellectual -property rights grant can be found in the file PATENTS. - -Building: -========= - -Windows build: --------------- - -By running: - - nmake /f Makefile.vc CFG=release-static RTLIBCFG=static OBJDIR=output - -the directory output\release-static\(x64|x86)\bin will contain the tools -cwebp.exe and dwebp.exe. The directory output\release-static\(x64|x86)\lib will -contain the libwebp static library. -The target architecture (x86/x64) is detected by Makefile.vc from the Visual -Studio compiler (cl.exe) available in the system path. - -Unix build using makefile.unix: -------------------------------- - -On platforms with GNU tools installed (gcc and make), running - - make -f makefile.unix - -will build the binaries examples/cwebp and examples/dwebp, along -with the static library src/libwebp.a. No system-wide installation -is supplied, as this is a simple alternative to the full installation -system based on the autoconf tools (see below). -Please refer to makefile.unix for additional details and customizations. - -Using autoconf tools: ---------------------- -Prerequisites: -A compiler (e.g., gcc), make, autoconf, automake, libtool. -On a Debian-like system the following should install everything you need for a -minimal build: -$ sudo apt-get install gcc make autoconf automake libtool - -When building from git sources, you will need to run autogen.sh to generate the -configure script. - -./configure -make -make install - -should be all you need to have the following files - -/usr/local/include/webp/decode.h -/usr/local/include/webp/encode.h -/usr/local/include/webp/types.h -/usr/local/lib/libwebp.* -/usr/local/bin/cwebp -/usr/local/bin/dwebp - -installed. - -Note: A decode-only library, libwebpdecoder, is available using the -'--enable-libwebpdecoder' flag. The encode library is built separately and can -be installed independently using a minor modification in the corresponding -Makefile.am configure files (see comments there). See './configure --help' for -more options. - -SWIG bindings: --------------- - -To generate language bindings from swig/libwebp.swig at least swig-1.3 -(http://www.swig.org) is required. - -Currently the following functions are mapped: -Decode: - WebPGetDecoderVersion - WebPGetInfo - WebPDecodeRGBA - WebPDecodeARGB - WebPDecodeBGRA - WebPDecodeBGR - WebPDecodeRGB - -Encode: - WebPGetEncoderVersion - WebPEncodeRGBA - WebPEncodeBGRA - WebPEncodeRGB - WebPEncodeBGR - WebPEncodeLosslessRGBA - WebPEncodeLosslessBGRA - WebPEncodeLosslessRGB - WebPEncodeLosslessBGR - -See swig/README for more detailed build instructions. - -Java bindings: - -To build the swig-generated JNI wrapper code at least JDK-1.5 (or equivalent) -is necessary for enum support. The output is intended to be a shared object / -DLL that can be loaded via System.loadLibrary("webp_jni"). - -Python bindings: - -To build the swig-generated Python extension code at least Python 2.6 is -required. Python < 2.6 may build with some minor changes to libwebp.swig or the -generated code, but is untested. - -Encoding tool: -============== - -The examples/ directory contains tools for encoding (cwebp) and -decoding (dwebp) images. - -The easiest use should look like: - cwebp input.png -q 80 -o output.webp -which will convert the input file to a WebP file using a quality factor of 80 -on a 0->100 scale (0 being the lowest quality, 100 being the best. Default -value is 75). -You might want to try the -lossless flag too, which will compress the source -(in RGBA format) without any loss. The -q quality parameter will in this case -control the amount of processing time spent trying to make the output file as -small as possible. - -A longer list of options is available using the -longhelp command line flag: - -> cwebp -longhelp -Usage: - cwebp [-preset <...>] [options] in_file [-o out_file] - -If input size (-s) for an image is not specified, it is -assumed to be a PNG, JPEG, TIFF or WebP file. - -Options: - -h / -help ............ short help - -H / -longhelp ........ long help - -q ............. quality factor (0:small..100:big) - -alpha_q ......... transparency-compression quality (0..100) - -preset ....... preset setting, one of: - default, photo, picture, - drawing, icon, text - -preset must come first, as it overwrites other parameters - -z ............... activates lossless preset with given - level in [0:fast, ..., 9:slowest] - - -m ............... compression method (0=fast, 6=slowest) - -segments ........ number of segments to use (1..4) - -size ............ target size (in bytes) - -psnr .......... target PSNR (in dB. typically: 42) - - -s ......... input size (width x height) for YUV - -sns ............. spatial noise shaping (0:off, 100:max) - -f ............... filter strength (0=off..100) - -sharpness ....... filter sharpness (0:most .. 7:least sharp) - -strong ................ use strong filter instead of simple (default) - -nostrong .............. use simple filter instead of strong - -partition_limit . limit quality to fit the 512k limit on - the first partition (0=no degradation ... 100=full) - -pass ............ analysis pass number (1..10) - -crop .. crop picture with the given rectangle - -resize ........ resize picture (after any cropping) - -mt .................... use multi-threading if available - -low_memory ............ reduce memory usage (slower encoding) - -map ............. print map of extra info - -print_psnr ............ prints averaged PSNR distortion - -print_ssim ............ prints averaged SSIM distortion - -print_lsim ............ prints local-similarity distortion - -d .......... dump the compressed output (PGM file) - -alpha_method .... transparency-compression method (0..1) - -alpha_filter . predictive filtering for alpha plane, - one of: none, fast (default) or best - -exact ................. preserve RGB values in transparent area - -blend_alpha ..... blend colors against background color - expressed as RGB values written in - hexadecimal, e.g. 0xc0e0d0 for red=0xc0 - green=0xe0 and blue=0xd0 - -noalpha ............... discard any transparency information - -lossless .............. encode image losslessly - -near_lossless ... use near-lossless image - preprocessing (0..100=off) - -hint ......... specify image characteristics hint, - one of: photo, picture or graph - - -metadata ..... comma separated list of metadata to - copy from the input to the output if present. - Valid values: all, none (default), exif, icc, xmp - - -short ................. condense printed message - -quiet ................. don't print anything - -version ............... print version number and exit - -noasm ................. disable all assembly optimizations - -v ..................... verbose, e.g. print encoding/decoding times - -progress .............. report encoding progress - -Experimental Options: - -jpeg_like ............. roughly match expected JPEG size - -af .................... auto-adjust filter strength - -pre ............. pre-processing filter - -The main options you might want to try in order to further tune the -visual quality are: - -preset - -sns - -f - -m - -Namely: - * 'preset' will set up a default encoding configuration targeting a - particular type of input. It should appear first in the list of options, - so that subsequent options can take effect on top of this preset. - Default value is 'default'. - * 'sns' will progressively turn on (when going from 0 to 100) some additional - visual optimizations (like: segmentation map re-enforcement). This option - will balance the bit allocation differently. It tries to take bits from the - "easy" parts of the picture and use them in the "difficult" ones instead. - Usually, raising the sns value (at fixed -q value) leads to larger files, - but with better quality. - Typical value is around '75'. - * 'f' option directly links to the filtering strength used by the codec's - in-loop processing. The higher the value, the smoother the - highly-compressed area will look. This is particularly useful when aiming - at very small files. Typical values are around 20-30. Note that using the - option -strong/-nostrong will change the type of filtering. Use "-f 0" to - turn filtering off. - * 'm' controls the trade-off between encoding speed and quality. Default is 4. - You can try -m 5 or -m 6 to explore more (time-consuming) encoding - possibilities. A lower value will result in faster encoding at the expense - of quality. - -Decoding tool: -============== - -There is a decoding sample in examples/dwebp.c which will take -a .webp file and decode it to a PNG image file (amongst other formats). -This is simply to demonstrate the use of the API. You can verify the -file test.webp decodes to exactly the same as test_ref.ppm by using: - - cd examples - ./dwebp test.webp -ppm -o test.ppm - diff test.ppm test_ref.ppm - -The full list of options is available using -h: - -> dwebp -h -Usage: dwebp in_file [options] [-o out_file] - -Decodes the WebP image file to PNG format [Default] -Use following options to convert into alternate image formats: - -pam ......... save the raw RGBA samples as a color PAM - -ppm ......... save the raw RGB samples as a color PPM - -bmp ......... save as uncompressed BMP format - -tiff ........ save as uncompressed TIFF format - -pgm ......... save the raw YUV samples as a grayscale PGM - file with IMC4 layout - -yuv ......... save the raw YUV samples in flat layout - - Other options are: - -version .... print version number and exit - -nofancy ..... don't use the fancy YUV420 upscaler - -nofilter .... disable in-loop filtering - -nodither .... disable dithering - -dither .. dithering strength (in 0..100) - -alpha_dither use alpha-plane dithering if needed - -mt .......... use multi-threading - -crop ... crop output with the given rectangle - -resize ......... scale the output (*after* any cropping) - -flip ........ flip the output vertically - -alpha ....... only save the alpha plane - -incremental . use incremental decoding (useful for tests) - -h ....... this help message - -v ....... verbose (e.g. print encoding/decoding times) - -quiet ....... quiet mode, don't print anything - -noasm ....... disable all assembly optimizations - -Visualization tool: -=================== - -There's a little self-serve visualization tool called 'vwebp' under the -examples/ directory. It uses OpenGL to open a simple drawing window and show -a decoded WebP file. It's not yet integrated in the automake build system, but -you can try to manually compile it using the recommendations below. - -Usage: vwebp in_file [options] - -Decodes the WebP image file and visualize it using OpenGL -Options are: - -version .... print version number and exit - -noicc ....... don't use the icc profile if present - -nofancy ..... don't use the fancy YUV420 upscaler - -nofilter .... disable in-loop filtering - -dither dithering strength (0..100), default=50 - -noalphadither disable alpha plane dithering - -mt .......... use multi-threading - -info ........ print info - -h ....... this help message - -Keyboard shortcuts: - 'c' ................ toggle use of color profile - 'i' ................ overlay file information - 'q' / 'Q' / ESC .... quit - -Building: ---------- - -Prerequisites: -1) OpenGL & OpenGL Utility Toolkit (GLUT) - Linux: - $ sudo apt-get install freeglut3-dev mesa-common-dev - Mac + XCode: - - These libraries should be available in the OpenGL / GLUT frameworks. - Windows: - http://freeglut.sourceforge.net/index.php#download - -2) (Optional) qcms (Quick Color Management System) - i. Download qcms from Mozilla / Chromium: - http://hg.mozilla.org/mozilla-central/file/0e7639e3bdfb/gfx/qcms - http://src.chromium.org/viewvc/chrome/trunk/src/third_party/qcms - ii. Build and archive the source files as libqcms.a / qcms.lib - iii. Update makefile.unix / Makefile.vc - a) Define WEBP_HAVE_QCMS - b) Update include / library paths to reference the qcms directory. - -Build using makefile.unix / Makefile.vc: -$ make -f makefile.unix examples/vwebp -> nmake /f Makefile.vc CFG=release-static \ - ../obj/x64/release-static/bin/vwebp.exe - -Animated GIF conversion: -======================== -Animated GIF files can be converted to WebP files with animation using the -gif2webp utility available under examples/. The files can then be viewed using -vwebp. - -Usage: - gif2webp [options] gif_file -o webp_file -Options: - -h / -help ............ this help - -lossy ................. encode image using lossy compression - -mixed ................. for each frame in the image, pick lossy - or lossless compression heuristically - -q ............. quality factor (0:small..100:big) - -m ............... compression method (0=fast, 6=slowest) - -min_size .............. minimize output size (default:off) - lossless compression by default; can be - combined with -q, -m, -lossy or -mixed - options - -kmin ............ min distance between key frames - -kmax ............ max distance between key frames - -f ............... filter strength (0=off..100) - -metadata ..... comma separated list of metadata to - copy from the input to the output if present - Valid values: all, none, icc, xmp (default) - -mt .................... use multi-threading if available - - -version ............... print version number and exit - -v ..................... verbose - -quiet ................. don't print anything - -Building: ---------- -With the libgif development files installed, gif2webp can be built using -makefile.unix: -$ make -f makefile.unix examples/gif2webp - -or using autoconf: -$ ./configure --enable-everything -$ make - -Comparison of animated images: -============================== -Test utility anim_diff under examples/ can be used to compare two animated -images (each can be GIF or WebP). - -Usage: anim_diff [options] - -Options: - -dump_frames dump decoded frames in PAM format - -min_psnr ... minimum per-frame PSNR - -raw_comparison ..... if this flag is not used, RGB is - premultiplied before comparison - -Building: ---------- -With the libgif development files and a C++ compiler installed, anim_diff can -be built using makefile.unix: -$ make -f makefile.unix examples/anim_diff - -or using autoconf: -$ ./configure --enable-everything -$ make - -Encoding API: -============= - -The main encoding functions are available in the header src/webp/encode.h -The ready-to-use ones are: -size_t WebPEncodeRGB(const uint8_t* rgb, int width, int height, int stride, - float quality_factor, uint8_t** output); -size_t WebPEncodeBGR(const uint8_t* bgr, int width, int height, int stride, - float quality_factor, uint8_t** output); -size_t WebPEncodeRGBA(const uint8_t* rgba, int width, int height, int stride, - float quality_factor, uint8_t** output); -size_t WebPEncodeBGRA(const uint8_t* bgra, int width, int height, int stride, - float quality_factor, uint8_t** output); - -They will convert raw RGB samples to a WebP data. The only control supplied -is the quality factor. - -There are some variants for using the lossless format: - -size_t WebPEncodeLosslessRGB(const uint8_t* rgb, int width, int height, - int stride, uint8_t** output); -size_t WebPEncodeLosslessBGR(const uint8_t* bgr, int width, int height, - int stride, uint8_t** output); -size_t WebPEncodeLosslessRGBA(const uint8_t* rgba, int width, int height, - int stride, uint8_t** output); -size_t WebPEncodeLosslessBGRA(const uint8_t* bgra, int width, int height, - int stride, uint8_t** output); - -Of course in this case, no quality factor is needed since the compression -occurs without loss of the input values, at the expense of larger output sizes. - -Advanced encoding API: ----------------------- - -A more advanced API is based on the WebPConfig and WebPPicture structures. - -WebPConfig contains the encoding settings and is not tied to a particular -picture. -WebPPicture contains input data, on which some WebPConfig will be used for -compression. -The encoding flow looks like: - --------------------------------------- BEGIN PSEUDO EXAMPLE - -#include - - // Setup a config, starting form a preset and tuning some additional - // parameters - WebPConfig config; - if (!WebPConfigPreset(&config, WEBP_PRESET_PHOTO, quality_factor)) - return 0; // version error - } - // ... additional tuning - config.sns_strength = 90; - config.filter_sharpness = 6; - config_error = WebPValidateConfig(&config); // not mandatory, but useful - - // Setup the input data - WebPPicture pic; - if (!WebPPictureInit(&pic)) { - return 0; // version error - } - pic.width = width; - pic.height = height; - // allocated picture of dimension width x height - if (!WebPPictureAllocate(&pic)) { - return 0; // memory error - } - // at this point, 'pic' has been initialized as a container, - // and can receive the Y/U/V samples. - // Alternatively, one could use ready-made import functions like - // WebPPictureImportRGB(), which will take care of memory allocation. - // In any case, past this point, one will have to call - // WebPPictureFree(&pic) to reclaim memory. - - // Set up a byte-output write method. WebPMemoryWriter, for instance. - WebPMemoryWriter wrt; - WebPMemoryWriterInit(&wrt); // initialize 'wrt' - - pic.writer = MyFileWriter; - pic.custom_ptr = my_opaque_structure_to_make_MyFileWriter_work; - - // Compress! - int ok = WebPEncode(&config, &pic); // ok = 0 => error occurred! - WebPPictureFree(&pic); // must be called independently of the 'ok' result. - - // output data should have been handled by the writer at that point. - // -> compressed data is the memory buffer described by wrt.mem / wrt.size - - // deallocate the memory used by compressed data - WebPMemoryWriterClear(&wrt); - --------------------------------------- END PSEUDO EXAMPLE - -Decoding API: -============= - -This is mainly just one function to call: - -#include "webp/decode.h" -uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size, - int* width, int* height); - -Please have a look at the file src/webp/decode.h for the details. -There are variants for decoding in BGR/RGBA/ARGB/BGRA order, along with -decoding to raw Y'CbCr samples. One can also decode the image directly into a -pre-allocated buffer. - -To detect a WebP file and gather the picture's dimensions, the function: - int WebPGetInfo(const uint8_t* data, size_t data_size, - int* width, int* height); -is supplied. No decoding is involved when using it. - -Incremental decoding API: -========================= - -In the case when data is being progressively transmitted, pictures can still -be incrementally decoded using a slightly more complicated API. Decoder state -is stored into an instance of the WebPIDecoder object. This object can be -created with the purpose of decoding either RGB or Y'CbCr samples. -For instance: - - WebPDecBuffer buffer; - WebPInitDecBuffer(&buffer); - buffer.colorspace = MODE_BGR; - ... - WebPIDecoder* idec = WebPINewDecoder(&buffer); - -As data is made progressively available, this incremental-decoder object -can be used to decode the picture further. There are two (mutually exclusive) -ways to pass freshly arrived data: - -either by appending the fresh bytes: - - WebPIAppend(idec, fresh_data, size_of_fresh_data); - -or by just mentioning the new size of the transmitted data: - - WebPIUpdate(idec, buffer, size_of_transmitted_buffer); - -Note that 'buffer' can be modified between each call to WebPIUpdate, in -particular when the buffer is resized to accommodate larger data. - -These functions will return the decoding status: either VP8_STATUS_SUSPENDED if -decoding is not finished yet or VP8_STATUS_OK when decoding is done. Any other -status is an error condition. - -The 'idec' object must always be released (even upon an error condition) by -calling: WebPDelete(idec). - -To retrieve partially decoded picture samples, one must use the corresponding -method: WebPIDecGetRGB or WebPIDecGetYUVA. -It will return the last displayable pixel row. - -Lastly, note that decoding can also be performed into a pre-allocated pixel -buffer. This buffer must be passed when creating a WebPIDecoder, calling -WebPINewRGB() or WebPINewYUVA(). - -Please have a look at the src/webp/decode.h header for further details. - -Advanced Decoding API: -====================== - -WebP decoding supports an advanced API which provides on-the-fly cropping and -rescaling, something of great usefulness on memory-constrained environments like -mobile phones. Basically, the memory usage will scale with the output's size, -not the input's, when one only needs a quick preview or a zoomed in portion of -an otherwise too-large picture. Some CPU can be saved too, incidentally. - --------------------------------------- BEGIN PSEUDO EXAMPLE - // A) Init a configuration object - WebPDecoderConfig config; - CHECK(WebPInitDecoderConfig(&config)); - - // B) optional: retrieve the bitstream's features. - CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK); - - // C) Adjust 'config' options, if needed - config.options.no_fancy_upsampling = 1; - config.options.use_scaling = 1; - config.options.scaled_width = scaledWidth(); - config.options.scaled_height = scaledHeight(); - // etc. - - // D) Specify 'config' output options for specifying output colorspace. - // Optionally the external image decode buffer can also be specified. - config.output.colorspace = MODE_BGRA; - // Optionally, the config.output can be pointed to an external buffer as - // well for decoding the image. This externally supplied memory buffer - // should be big enough to store the decoded picture. - config.output.u.RGBA.rgba = (uint8_t*) memory_buffer; - config.output.u.RGBA.stride = scanline_stride; - config.output.u.RGBA.size = total_size_of_the_memory_buffer; - config.output.is_external_memory = 1; - - // E) Decode the WebP image. There are two variants w.r.t decoding image. - // The first one (E.1) decodes the full image and the second one (E.2) is - // used to incrementally decode the image using small input buffers. - // Any one of these steps can be used to decode the WebP image. - - // E.1) Decode full image. - CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK); - - // E.2) Decode image incrementally. - WebPIDecoder* const idec = WebPIDecode(NULL, NULL, &config); - CHECK(idec != NULL); - while (bytes_remaining > 0) { - VP8StatusCode status = WebPIAppend(idec, input, bytes_read); - if (status == VP8_STATUS_OK || status == VP8_STATUS_SUSPENDED) { - bytes_remaining -= bytes_read; - } else { - break; - } - } - WebPIDelete(idec); - - // F) Decoded image is now in config.output (and config.output.u.RGBA). - // It can be saved, displayed or otherwise processed. - - // G) Reclaim memory allocated in config's object. It's safe to call - // this function even if the memory is external and wasn't allocated - // by WebPDecode(). - WebPFreeDecBuffer(&config.output); - --------------------------------------- END PSEUDO EXAMPLE - -Bugs: -===== - -Please report all bugs to our issue tracker: - https://bugs.chromium.org/p/webp -Patches welcome! See this page to get started: - http://www.webmproject.org/code/contribute/submitting-patches/ - -Discuss: -======== - -Email: webp-discuss@webmproject.org -Web: http://groups.google.com/a/webmproject.org/group/webp-discuss diff --git a/Example/Pods/libwebp/README.mux b/Example/Pods/libwebp/README.mux deleted file mode 100644 index aa077e8d..00000000 --- a/Example/Pods/libwebp/README.mux +++ /dev/null @@ -1,210 +0,0 @@ - __ __ ____ ____ ____ __ __ _ __ __ - / \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\ - \ / __/ _ \ __/ / / (_/ /__ - \__\__/\_____/_____/__/ \__//_/\_____/__/___/v0.3.0 - - -Description: -============ - -WebPMux: set of two libraries 'Mux' and 'Demux' for creation, extraction and -manipulation of an extended format WebP file, which can have features like -color profile, metadata and animation. Reference command-line tools 'webpmux' -and 'vwebp' as well as the WebP container specification -'doc/webp-container-spec.txt' are also provided in this package. - -WebP Mux tool: -============== - -The examples/ directory contains a tool (webpmux) for manipulating WebP -files. The webpmux tool can be used to create an extended format WebP file and -also to extract or strip relevant data from such a file. - -A list of options is available using the -help command line flag: - -> webpmux -help -Usage: webpmux -get GET_OPTIONS INPUT -o OUTPUT - webpmux -set SET_OPTIONS INPUT -o OUTPUT - webpmux -strip STRIP_OPTIONS INPUT -o OUTPUT - webpmux -frame FRAME_OPTIONS [-frame...] [-loop LOOP_COUNT] - [-bgcolor BACKGROUND_COLOR] -o OUTPUT - webpmux -info INPUT - webpmux [-h|-help] - webpmux -version - -GET_OPTIONS: - Extract relevant data: - icc get ICC profile - exif get EXIF metadata - xmp get XMP metadata - frame n get nth frame - -SET_OPTIONS: - Set color profile/metadata: - icc file.icc set ICC profile - exif file.exif set EXIF metadata - xmp file.xmp set XMP metadata - where: 'file.icc' contains the ICC profile to be set, - 'file.exif' contains the EXIF metadata to be set - 'file.xmp' contains the XMP metadata to be set - -STRIP_OPTIONS: - Strip color profile/metadata: - icc strip ICC profile - exif strip EXIF metadata - xmp strip XMP metadata - -FRAME_OPTIONS(i): - Create animation: - file_i +di+[xi+yi[+mi[bi]]] - where: 'file_i' is the i'th animation frame (WebP format), - 'di' is the pause duration before next frame, - 'xi','yi' specify the image offset for this frame, - 'mi' is the dispose method for this frame (0 or 1), - 'bi' is the blending method for this frame (+b or -b) - -LOOP_COUNT: - Number of times to repeat the animation. - Valid range is 0 to 65535 [Default: 0 (infinite)]. - -BACKGROUND_COLOR: - Background color of the canvas. - A,R,G,B - where: 'A', 'R', 'G' and 'B' are integers in the range 0 to 255 specifying - the Alpha, Red, Green and Blue component values respectively - [Default: 255,255,255,255] - -INPUT & OUTPUT are in WebP format. - -Note: The nature of EXIF, XMP and ICC data is not checked and is assumed to be -valid. - -Visualization tool: -=================== - -The examples/ directory also contains a tool (vwebp) for viewing WebP files. -It decodes the image and visualizes it using OpenGL. See the libwebp README -for details on building and running this program. - -Mux API: -======== -The Mux API contains methods for adding data to and reading data from WebP -files. This API currently supports XMP/EXIF metadata, ICC profile and animation. -Other features may be added in subsequent releases. - -Example#1 (pseudo code): Creating a WebPMux object with image data, color -profile and XMP metadata. - - int copy_data = 0; - WebPMux* mux = WebPMuxNew(); - // ... (Prepare image data). - WebPMuxSetImage(mux, &image, copy_data); - // ... (Prepare ICC profile data). - WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data); - // ... (Prepare XMP metadata). - WebPMuxSetChunk(mux, "XMP ", &xmp, copy_data); - // Get data from mux in WebP RIFF format. - WebPMuxAssemble(mux, &output_data); - WebPMuxDelete(mux); - // ... (Consume output_data; e.g. write output_data.bytes to file). - WebPDataClear(&output_data); - - -Example#2 (pseudo code): Get image and color profile data from a WebP file. - - int copy_data = 0; - // ... (Read data from file). - WebPMux* mux = WebPMuxCreate(&data, copy_data); - WebPMuxGetFrame(mux, 1, &image); - // ... (Consume image; e.g. call WebPDecode() to decode the data). - WebPMuxGetChunk(mux, "ICCP", &icc_profile); - // ... (Consume icc_profile). - WebPMuxDelete(mux); - free(data); - - -For a detailed Mux API reference, please refer to the header file -(src/webp/mux.h). - -Demux API: -========== -The Demux API enables extraction of images and extended format data from -WebP files. This API currently supports reading of XMP/EXIF metadata, ICC -profile and animated images. Other features may be added in subsequent -releases. - -Code example: Demuxing WebP data to extract all the frames, ICC profile -and EXIF/XMP metadata. - - WebPDemuxer* demux = WebPDemux(&webp_data); - uint32_t width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH); - uint32_t height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT); - // ... (Get information about the features present in the WebP file). - uint32_t flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS); - - // ... (Iterate over all frames). - WebPIterator iter; - if (WebPDemuxGetFrame(demux, 1, &iter)) { - do { - // ... (Consume 'iter'; e.g. Decode 'iter.fragment' with WebPDecode(), - // ... and get other frame properties like width, height, offsets etc. - // ... see 'struct WebPIterator' below for more info). - } while (WebPDemuxNextFrame(&iter)); - WebPDemuxReleaseIterator(&iter); - } - - // ... (Extract metadata). - WebPChunkIterator chunk_iter; - if (flags & ICCP_FLAG) WebPDemuxGetChunk(demux, "ICCP", 1, &chunk_iter); - // ... (Consume the ICC profile in 'chunk_iter.chunk'). - WebPDemuxReleaseChunkIterator(&chunk_iter); - if (flags & EXIF_FLAG) WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter); - // ... (Consume the EXIF metadata in 'chunk_iter.chunk'). - WebPDemuxReleaseChunkIterator(&chunk_iter); - if (flags & XMP_FLAG) WebPDemuxGetChunk(demux, "XMP ", 1, &chunk_iter); - // ... (Consume the XMP metadata in 'chunk_iter.chunk'). - WebPDemuxReleaseChunkIterator(&chunk_iter); - WebPDemuxDelete(demux); - - -For a detailed Demux API reference, please refer to the header file -(src/webp/demux.h). - -AnimEncoder API: -================ -The AnimEncoder API can be used to create animated WebP images. - -Code example: - - WebPAnimEncoderOptions enc_options; - WebPAnimEncoderOptionsInit(&enc_options); - // ... (Tune 'enc_options' as needed). - WebPAnimEncoder* enc = WebPAnimEncoderNew(width, height, &enc_options); - while() { - WebPConfig config; - WebPConfigInit(&config); - // ... (Tune 'config' as needed). - WebPAnimEncoderAdd(enc, frame, duration, &config); - } - WebPAnimEncoderAssemble(enc, webp_data); - WebPAnimEncoderDelete(enc); - // ... (Write the 'webp_data' to a file, or re-mux it further). - - -For a detailed AnimEncoder API reference, please refer to the header file -(src/webp/mux.h). - - -Bugs: -===== - -Please report all bugs to our issue tracker: - https://bugs.chromium.org/p/webp -Patches welcome! See this page to get started: - http://www.webmproject.org/code/contribute/submitting-patches/ - -Discuss: -======== - -Email: webp-discuss@webmproject.org -Web: http://groups.google.com/a/webmproject.org/group/webp-discuss diff --git a/Example/Pods/libwebp/src/dec/alpha.c b/Example/Pods/libwebp/src/dec/alpha.c deleted file mode 100644 index 52216fc4..00000000 --- a/Example/Pods/libwebp/src/dec/alpha.c +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Alpha-plane decompression. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include "./alphai.h" -#include "./vp8i.h" -#include "./vp8li.h" -#include "../dsp/dsp.h" -#include "../utils/quant_levels_dec.h" -#include "../utils/utils.h" -#include "../webp/format_constants.h" - -//------------------------------------------------------------------------------ -// ALPHDecoder object. - -ALPHDecoder* ALPHNew(void) { - ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); - return dec; -} - -void ALPHDelete(ALPHDecoder* const dec) { - if (dec != NULL) { - VP8LDelete(dec->vp8l_dec_); - dec->vp8l_dec_ = NULL; - WebPSafeFree(dec); - } -} - -//------------------------------------------------------------------------------ -// Decoding. - -// Initialize alpha decoding by parsing the alpha header and decoding the image -// header for alpha data stored using lossless compression. -// Returns false in case of error in alpha header (data too short, invalid -// compression method or filter, error in lossless header data etc). -static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data, - size_t data_size, int width, int height, uint8_t* output) { - int ok = 0; - const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN; - const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN; - int rsrv; - - assert(width > 0 && height > 0); - assert(data != NULL && output != NULL); - - dec->width_ = width; - dec->height_ = height; - - if (data_size <= ALPHA_HEADER_LEN) { - return 0; - } - - dec->method_ = (data[0] >> 0) & 0x03; - dec->filter_ = (data[0] >> 2) & 0x03; - dec->pre_processing_ = (data[0] >> 4) & 0x03; - rsrv = (data[0] >> 6) & 0x03; - if (dec->method_ < ALPHA_NO_COMPRESSION || - dec->method_ > ALPHA_LOSSLESS_COMPRESSION || - dec->filter_ >= WEBP_FILTER_LAST || - dec->pre_processing_ > ALPHA_PREPROCESSED_LEVELS || - rsrv != 0) { - return 0; - } - - if (dec->method_ == ALPHA_NO_COMPRESSION) { - const size_t alpha_decoded_size = dec->width_ * dec->height_; - ok = (alpha_data_size >= alpha_decoded_size); - } else { - assert(dec->method_ == ALPHA_LOSSLESS_COMPRESSION); - ok = VP8LDecodeAlphaHeader(dec, alpha_data, alpha_data_size, output); - } - VP8FiltersInit(); - return ok; -} - -// Decodes, unfilters and dequantizes *at least* 'num_rows' rows of alpha -// starting from row number 'row'. It assumes that rows up to (row - 1) have -// already been decoded. -// Returns false in case of bitstream error. -static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) { - ALPHDecoder* const alph_dec = dec->alph_dec_; - const int width = alph_dec->width_; - const int height = alph_dec->height_; - WebPUnfilterFunc unfilter_func = WebPUnfilters[alph_dec->filter_]; - uint8_t* const output = dec->alpha_plane_; - if (alph_dec->method_ == ALPHA_NO_COMPRESSION) { - const size_t offset = row * width; - const size_t num_pixels = num_rows * width; - assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN + offset + num_pixels); - memcpy(dec->alpha_plane_ + offset, - dec->alpha_data_ + ALPHA_HEADER_LEN + offset, num_pixels); - } else { // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION - assert(alph_dec->vp8l_dec_ != NULL); - if (!VP8LDecodeAlphaImageStream(alph_dec, row + num_rows)) { - return 0; - } - } - - if (unfilter_func != NULL) { - unfilter_func(width, height, width, row, num_rows, output); - } - - if (row + num_rows == dec->pic_hdr_.height_) { - dec->is_alpha_decoded_ = 1; - } - return 1; -} - -//------------------------------------------------------------------------------ -// Main entry point. - -const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, - int row, int num_rows) { - const int width = dec->pic_hdr_.width_; - const int height = dec->pic_hdr_.height_; - - if (row < 0 || num_rows <= 0 || row + num_rows > height) { - return NULL; // sanity check. - } - - if (row == 0) { - // Initialize decoding. - assert(dec->alpha_plane_ != NULL); - dec->alph_dec_ = ALPHNew(); - if (dec->alph_dec_ == NULL) return NULL; - if (!ALPHInit(dec->alph_dec_, dec->alpha_data_, dec->alpha_data_size_, - width, height, dec->alpha_plane_)) { - ALPHDelete(dec->alph_dec_); - dec->alph_dec_ = NULL; - return NULL; - } - // if we allowed use of alpha dithering, check whether it's needed at all - if (dec->alph_dec_->pre_processing_ != ALPHA_PREPROCESSED_LEVELS) { - dec->alpha_dithering_ = 0; // disable dithering - } else { - num_rows = height; // decode everything in one pass - } - } - - if (!dec->is_alpha_decoded_) { - int ok = 0; - assert(dec->alph_dec_ != NULL); - ok = ALPHDecode(dec, row, num_rows); - if (ok && dec->alpha_dithering_ > 0) { - ok = WebPDequantizeLevels(dec->alpha_plane_, width, height, - dec->alpha_dithering_); - } - if (!ok || dec->is_alpha_decoded_) { - ALPHDelete(dec->alph_dec_); - dec->alph_dec_ = NULL; - } - if (!ok) return NULL; // Error. - } - - // Return a pointer to the current decoded row. - return dec->alpha_plane_ + row * width; -} diff --git a/Example/Pods/libwebp/src/dec/alphai.h b/Example/Pods/libwebp/src/dec/alphai.h deleted file mode 100644 index 5fa230ca..00000000 --- a/Example/Pods/libwebp/src/dec/alphai.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Alpha decoder: internal header. -// -// Author: Urvang (urvang@google.com) - -#ifndef WEBP_DEC_ALPHAI_H_ -#define WEBP_DEC_ALPHAI_H_ - -#include "./webpi.h" -#include "../utils/filters.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct VP8LDecoder; // Defined in dec/vp8li.h. - -typedef struct ALPHDecoder ALPHDecoder; -struct ALPHDecoder { - int width_; - int height_; - int method_; - WEBP_FILTER_TYPE filter_; - int pre_processing_; - struct VP8LDecoder* vp8l_dec_; - VP8Io io_; - int use_8b_decode; // Although alpha channel requires only 1 byte per - // pixel, sometimes VP8LDecoder may need to allocate - // 4 bytes per pixel internally during decode. -}; - -//------------------------------------------------------------------------------ -// internal functions. Not public. - -// Allocates a new alpha decoder instance. -ALPHDecoder* ALPHNew(void); - -// Clears and deallocates an alpha decoder instance. -void ALPHDelete(ALPHDecoder* const dec); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_DEC_ALPHAI_H_ */ diff --git a/Example/Pods/libwebp/src/dec/buffer.c b/Example/Pods/libwebp/src/dec/buffer.c deleted file mode 100644 index 9ed2b3fe..00000000 --- a/Example/Pods/libwebp/src/dec/buffer.c +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Everything about WebPDecBuffer -// -// Author: Skal (pascal.massimino@gmail.com) - -#include - -#include "./vp8i.h" -#include "./webpi.h" -#include "../utils/utils.h" - -//------------------------------------------------------------------------------ -// WebPDecBuffer - -// Number of bytes per pixel for the different color-spaces. -static const int kModeBpp[MODE_LAST] = { - 3, 4, 3, 4, 4, 2, 2, - 4, 4, 4, 2, // pre-multiplied modes - 1, 1 }; - -// Check that webp_csp_mode is within the bounds of WEBP_CSP_MODE. -// Convert to an integer to handle both the unsigned/signed enum cases -// without the need for casting to remove type limit warnings. -static int IsValidColorspace(int webp_csp_mode) { - return (webp_csp_mode >= MODE_RGB && webp_csp_mode < MODE_LAST); -} - -// strictly speaking, the very last (or first, if flipped) row -// doesn't require padding. -#define MIN_BUFFER_SIZE(WIDTH, HEIGHT, STRIDE) \ - (uint64_t)(STRIDE) * ((HEIGHT) - 1) + (WIDTH) - -static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) { - int ok = 1; - const WEBP_CSP_MODE mode = buffer->colorspace; - const int width = buffer->width; - const int height = buffer->height; - if (!IsValidColorspace(mode)) { - ok = 0; - } else if (!WebPIsRGBMode(mode)) { // YUV checks - const WebPYUVABuffer* const buf = &buffer->u.YUVA; - const int uv_width = (width + 1) / 2; - const int uv_height = (height + 1) / 2; - const int y_stride = abs(buf->y_stride); - const int u_stride = abs(buf->u_stride); - const int v_stride = abs(buf->v_stride); - const int a_stride = abs(buf->a_stride); - const uint64_t y_size = MIN_BUFFER_SIZE(width, height, y_stride); - const uint64_t u_size = MIN_BUFFER_SIZE(uv_width, uv_height, u_stride); - const uint64_t v_size = MIN_BUFFER_SIZE(uv_width, uv_height, v_stride); - const uint64_t a_size = MIN_BUFFER_SIZE(width, height, a_stride); - ok &= (y_size <= buf->y_size); - ok &= (u_size <= buf->u_size); - ok &= (v_size <= buf->v_size); - ok &= (y_stride >= width); - ok &= (u_stride >= uv_width); - ok &= (v_stride >= uv_width); - ok &= (buf->y != NULL); - ok &= (buf->u != NULL); - ok &= (buf->v != NULL); - if (mode == MODE_YUVA) { - ok &= (a_stride >= width); - ok &= (a_size <= buf->a_size); - ok &= (buf->a != NULL); - } - } else { // RGB checks - const WebPRGBABuffer* const buf = &buffer->u.RGBA; - const int stride = abs(buf->stride); - const uint64_t size = MIN_BUFFER_SIZE(width, height, stride); - ok &= (size <= buf->size); - ok &= (stride >= width * kModeBpp[mode]); - ok &= (buf->rgba != NULL); - } - return ok ? VP8_STATUS_OK : VP8_STATUS_INVALID_PARAM; -} -#undef MIN_BUFFER_SIZE - -static VP8StatusCode AllocateBuffer(WebPDecBuffer* const buffer) { - const int w = buffer->width; - const int h = buffer->height; - const WEBP_CSP_MODE mode = buffer->colorspace; - - if (w <= 0 || h <= 0 || !IsValidColorspace(mode)) { - return VP8_STATUS_INVALID_PARAM; - } - - if (!buffer->is_external_memory && buffer->private_memory == NULL) { - uint8_t* output; - int uv_stride = 0, a_stride = 0; - uint64_t uv_size = 0, a_size = 0, total_size; - // We need memory and it hasn't been allocated yet. - // => initialize output buffer, now that dimensions are known. - const int stride = w * kModeBpp[mode]; - const uint64_t size = (uint64_t)stride * h; - - if (!WebPIsRGBMode(mode)) { - uv_stride = (w + 1) / 2; - uv_size = (uint64_t)uv_stride * ((h + 1) / 2); - if (mode == MODE_YUVA) { - a_stride = w; - a_size = (uint64_t)a_stride * h; - } - } - total_size = size + 2 * uv_size + a_size; - - // Security/sanity checks - output = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*output)); - if (output == NULL) { - return VP8_STATUS_OUT_OF_MEMORY; - } - buffer->private_memory = output; - - if (!WebPIsRGBMode(mode)) { // YUVA initialization - WebPYUVABuffer* const buf = &buffer->u.YUVA; - buf->y = output; - buf->y_stride = stride; - buf->y_size = (size_t)size; - buf->u = output + size; - buf->u_stride = uv_stride; - buf->u_size = (size_t)uv_size; - buf->v = output + size + uv_size; - buf->v_stride = uv_stride; - buf->v_size = (size_t)uv_size; - if (mode == MODE_YUVA) { - buf->a = output + size + 2 * uv_size; - } - buf->a_size = (size_t)a_size; - buf->a_stride = a_stride; - } else { // RGBA initialization - WebPRGBABuffer* const buf = &buffer->u.RGBA; - buf->rgba = output; - buf->stride = stride; - buf->size = (size_t)size; - } - } - return CheckDecBuffer(buffer); -} - -VP8StatusCode WebPFlipBuffer(WebPDecBuffer* const buffer) { - if (buffer == NULL) { - return VP8_STATUS_INVALID_PARAM; - } - if (WebPIsRGBMode(buffer->colorspace)) { - WebPRGBABuffer* const buf = &buffer->u.RGBA; - buf->rgba += (buffer->height - 1) * buf->stride; - buf->stride = -buf->stride; - } else { - WebPYUVABuffer* const buf = &buffer->u.YUVA; - const int H = buffer->height; - buf->y += (H - 1) * buf->y_stride; - buf->y_stride = -buf->y_stride; - buf->u += ((H - 1) >> 1) * buf->u_stride; - buf->u_stride = -buf->u_stride; - buf->v += ((H - 1) >> 1) * buf->v_stride; - buf->v_stride = -buf->v_stride; - if (buf->a != NULL) { - buf->a += (H - 1) * buf->a_stride; - buf->a_stride = -buf->a_stride; - } - } - return VP8_STATUS_OK; -} - -VP8StatusCode WebPAllocateDecBuffer(int w, int h, - const WebPDecoderOptions* const options, - WebPDecBuffer* const out) { - VP8StatusCode status; - if (out == NULL || w <= 0 || h <= 0) { - return VP8_STATUS_INVALID_PARAM; - } - if (options != NULL) { // First, apply options if there is any. - if (options->use_cropping) { - const int cw = options->crop_width; - const int ch = options->crop_height; - const int x = options->crop_left & ~1; - const int y = options->crop_top & ~1; - if (x < 0 || y < 0 || cw <= 0 || ch <= 0 || x + cw > w || y + ch > h) { - return VP8_STATUS_INVALID_PARAM; // out of frame boundary. - } - w = cw; - h = ch; - } - if (options->use_scaling) { - int scaled_width = options->scaled_width; - int scaled_height = options->scaled_height; - if (!WebPRescalerGetScaledDimensions( - w, h, &scaled_width, &scaled_height)) { - return VP8_STATUS_INVALID_PARAM; - } - w = scaled_width; - h = scaled_height; - } - } - out->width = w; - out->height = h; - - // Then, allocate buffer for real. - status = AllocateBuffer(out); - if (status != VP8_STATUS_OK) return status; - - // Use the stride trick if vertical flip is needed. - if (options != NULL && options->flip) { - status = WebPFlipBuffer(out); - } - return status; -} - -//------------------------------------------------------------------------------ -// constructors / destructors - -int WebPInitDecBufferInternal(WebPDecBuffer* buffer, int version) { - if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { - return 0; // version mismatch - } - if (buffer == NULL) return 0; - memset(buffer, 0, sizeof(*buffer)); - return 1; -} - -void WebPFreeDecBuffer(WebPDecBuffer* buffer) { - if (buffer != NULL) { - if (!buffer->is_external_memory) { - WebPSafeFree(buffer->private_memory); - } - buffer->private_memory = NULL; - } -} - -void WebPCopyDecBuffer(const WebPDecBuffer* const src, - WebPDecBuffer* const dst) { - if (src != NULL && dst != NULL) { - *dst = *src; - if (src->private_memory != NULL) { - dst->is_external_memory = 1; // dst buffer doesn't own the memory. - dst->private_memory = NULL; - } - } -} - -// Copy and transfer ownership from src to dst (beware of parameter order!) -void WebPGrabDecBuffer(WebPDecBuffer* const src, WebPDecBuffer* const dst) { - if (src != NULL && dst != NULL) { - *dst = *src; - if (src->private_memory != NULL) { - src->is_external_memory = 1; // src relinquishes ownership - src->private_memory = NULL; - } - } -} - -//------------------------------------------------------------------------------ - diff --git a/Example/Pods/libwebp/src/dec/common.h b/Example/Pods/libwebp/src/dec/common.h deleted file mode 100644 index 6961e224..00000000 --- a/Example/Pods/libwebp/src/dec/common.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Definitions and macros common to encoding and decoding -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_DEC_COMMON_H_ -#define WEBP_DEC_COMMON_H_ - -// intra prediction modes -enum { B_DC_PRED = 0, // 4x4 modes - B_TM_PRED = 1, - B_VE_PRED = 2, - B_HE_PRED = 3, - B_RD_PRED = 4, - B_VR_PRED = 5, - B_LD_PRED = 6, - B_VL_PRED = 7, - B_HD_PRED = 8, - B_HU_PRED = 9, - NUM_BMODES = B_HU_PRED + 1 - B_DC_PRED, // = 10 - - // Luma16 or UV modes - DC_PRED = B_DC_PRED, V_PRED = B_VE_PRED, - H_PRED = B_HE_PRED, TM_PRED = B_TM_PRED, - B_PRED = NUM_BMODES, // refined I4x4 mode - NUM_PRED_MODES = 4, - - // special modes - B_DC_PRED_NOTOP = 4, - B_DC_PRED_NOLEFT = 5, - B_DC_PRED_NOTOPLEFT = 6, - NUM_B_DC_MODES = 7 }; - -enum { MB_FEATURE_TREE_PROBS = 3, - NUM_MB_SEGMENTS = 4, - NUM_REF_LF_DELTAS = 4, - NUM_MODE_LF_DELTAS = 4, // I4x4, ZERO, *, SPLIT - MAX_NUM_PARTITIONS = 8, - // Probabilities - NUM_TYPES = 4, // 0: i16-AC, 1: i16-DC, 2:chroma-AC, 3:i4-AC - NUM_BANDS = 8, - NUM_CTX = 3, - NUM_PROBAS = 11 - }; - -#endif // WEBP_DEC_COMMON_H_ diff --git a/Example/Pods/libwebp/src/dec/decode_vp8.h b/Example/Pods/libwebp/src/dec/decode_vp8.h deleted file mode 100644 index b9337bbe..00000000 --- a/Example/Pods/libwebp/src/dec/decode_vp8.h +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Low-level API for VP8 decoder -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_WEBP_DECODE_VP8_H_ -#define WEBP_WEBP_DECODE_VP8_H_ - -#include "../webp/decode.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//------------------------------------------------------------------------------ -// Lower-level API -// -// These functions provide fine-grained control of the decoding process. -// The call flow should resemble: -// -// VP8Io io; -// VP8InitIo(&io); -// io.data = data; -// io.data_size = size; -// /* customize io's functions (setup()/put()/teardown()) if needed. */ -// -// VP8Decoder* dec = VP8New(); -// bool ok = VP8Decode(dec); -// if (!ok) printf("Error: %s\n", VP8StatusMessage(dec)); -// VP8Delete(dec); -// return ok; - -// Input / Output -typedef struct VP8Io VP8Io; -typedef int (*VP8IoPutHook)(const VP8Io* io); -typedef int (*VP8IoSetupHook)(VP8Io* io); -typedef void (*VP8IoTeardownHook)(const VP8Io* io); - -struct VP8Io { - // set by VP8GetHeaders() - int width, height; // picture dimensions, in pixels (invariable). - // These are the original, uncropped dimensions. - // The actual area passed to put() is stored - // in mb_w / mb_h fields. - - // set before calling put() - int mb_y; // position of the current rows (in pixels) - int mb_w; // number of columns in the sample - int mb_h; // number of rows in the sample - const uint8_t* y, *u, *v; // rows to copy (in yuv420 format) - int y_stride; // row stride for luma - int uv_stride; // row stride for chroma - - void* opaque; // user data - - // called when fresh samples are available. Currently, samples are in - // YUV420 format, and can be up to width x 24 in size (depending on the - // in-loop filtering level, e.g.). Should return false in case of error - // or abort request. The actual size of the area to update is mb_w x mb_h - // in size, taking cropping into account. - VP8IoPutHook put; - - // called just before starting to decode the blocks. - // Must return false in case of setup error, true otherwise. If false is - // returned, teardown() will NOT be called. But if the setup succeeded - // and true is returned, then teardown() will always be called afterward. - VP8IoSetupHook setup; - - // Called just after block decoding is finished (or when an error occurred - // during put()). Is NOT called if setup() failed. - VP8IoTeardownHook teardown; - - // this is a recommendation for the user-side yuv->rgb converter. This flag - // is set when calling setup() hook and can be overwritten by it. It then - // can be taken into consideration during the put() method. - int fancy_upsampling; - - // Input buffer. - size_t data_size; - const uint8_t* data; - - // If true, in-loop filtering will not be performed even if present in the - // bitstream. Switching off filtering may speed up decoding at the expense - // of more visible blocking. Note that output will also be non-compliant - // with the VP8 specifications. - int bypass_filtering; - - // Cropping parameters. - int use_cropping; - int crop_left, crop_right, crop_top, crop_bottom; - - // Scaling parameters. - int use_scaling; - int scaled_width, scaled_height; - - // If non NULL, pointer to the alpha data (if present) corresponding to the - // start of the current row (That is: it is pre-offset by mb_y and takes - // cropping into account). - const uint8_t* a; -}; - -// Internal, version-checked, entry point -int VP8InitIoInternal(VP8Io* const, int); - -// Set the custom IO function pointers and user-data. The setter for IO hooks -// should be called before initiating incremental decoding. Returns true if -// WebPIDecoder object is successfully modified, false otherwise. -int WebPISetIOHooks(WebPIDecoder* const idec, - VP8IoPutHook put, - VP8IoSetupHook setup, - VP8IoTeardownHook teardown, - void* user_data); - -// Main decoding object. This is an opaque structure. -typedef struct VP8Decoder VP8Decoder; - -// Create a new decoder object. -VP8Decoder* VP8New(void); - -// Must be called to make sure 'io' is initialized properly. -// Returns false in case of version mismatch. Upon such failure, no other -// decoding function should be called (VP8Decode, VP8GetHeaders, ...) -static WEBP_INLINE int VP8InitIo(VP8Io* const io) { - return VP8InitIoInternal(io, WEBP_DECODER_ABI_VERSION); -} - -// Decode the VP8 frame header. Returns true if ok. -// Note: 'io->data' must be pointing to the start of the VP8 frame header. -int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io); - -// Decode a picture. Will call VP8GetHeaders() if it wasn't done already. -// Returns false in case of error. -int VP8Decode(VP8Decoder* const dec, VP8Io* const io); - -// Return current status of the decoder: -VP8StatusCode VP8Status(VP8Decoder* const dec); - -// return readable string corresponding to the last status. -const char* VP8StatusMessage(VP8Decoder* const dec); - -// Resets the decoder in its initial state, reclaiming memory. -// Not a mandatory call between calls to VP8Decode(). -void VP8Clear(VP8Decoder* const dec); - -// Destroy the decoder object. -void VP8Delete(VP8Decoder* const dec); - -//------------------------------------------------------------------------------ -// Miscellaneous VP8/VP8L bitstream probing functions. - -// Returns true if the next 3 bytes in data contain the VP8 signature. -WEBP_EXTERN(int) VP8CheckSignature(const uint8_t* const data, size_t data_size); - -// Validates the VP8 data-header and retrieves basic header information viz -// width and height. Returns 0 in case of formatting error. *width/*height -// can be passed NULL. -WEBP_EXTERN(int) VP8GetInfo( - const uint8_t* data, - size_t data_size, // data available so far - size_t chunk_size, // total data size expected in the chunk - int* const width, int* const height); - -// Returns true if the next byte(s) in data is a VP8L signature. -WEBP_EXTERN(int) VP8LCheckSignature(const uint8_t* const data, size_t size); - -// Validates the VP8L data-header and retrieves basic header information viz -// width, height and alpha. Returns 0 in case of formatting error. -// width/height/has_alpha can be passed NULL. -WEBP_EXTERN(int) VP8LGetInfo( - const uint8_t* data, size_t data_size, // data available so far - int* const width, int* const height, int* const has_alpha); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_WEBP_DECODE_VP8_H_ */ diff --git a/Example/Pods/libwebp/src/dec/frame.c b/Example/Pods/libwebp/src/dec/frame.c deleted file mode 100644 index b882133e..00000000 --- a/Example/Pods/libwebp/src/dec/frame.c +++ /dev/null @@ -1,822 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Frame-reconstruction function. Memory allocation. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include "./vp8i.h" -#include "../utils/utils.h" - -//------------------------------------------------------------------------------ -// Main reconstruction function. - -static const int kScan[16] = { - 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS, - 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS, - 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS, - 0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS -}; - -static int CheckMode(int mb_x, int mb_y, int mode) { - if (mode == B_DC_PRED) { - if (mb_x == 0) { - return (mb_y == 0) ? B_DC_PRED_NOTOPLEFT : B_DC_PRED_NOLEFT; - } else { - return (mb_y == 0) ? B_DC_PRED_NOTOP : B_DC_PRED; - } - } - return mode; -} - -static void Copy32b(uint8_t* const dst, const uint8_t* const src) { - memcpy(dst, src, 4); -} - -static WEBP_INLINE void DoTransform(uint32_t bits, const int16_t* const src, - uint8_t* const dst) { - switch (bits >> 30) { - case 3: - VP8Transform(src, dst, 0); - break; - case 2: - VP8TransformAC3(src, dst); - break; - case 1: - VP8TransformDC(src, dst); - break; - default: - break; - } -} - -static void DoUVTransform(uint32_t bits, const int16_t* const src, - uint8_t* const dst) { - if (bits & 0xff) { // any non-zero coeff at all? - if (bits & 0xaa) { // any non-zero AC coefficient? - VP8TransformUV(src, dst); // note we don't use the AC3 variant for U/V - } else { - VP8TransformDCUV(src, dst); - } - } -} - -static void ReconstructRow(const VP8Decoder* const dec, - const VP8ThreadContext* ctx) { - int j; - int mb_x; - const int mb_y = ctx->mb_y_; - const int cache_id = ctx->id_; - uint8_t* const y_dst = dec->yuv_b_ + Y_OFF; - uint8_t* const u_dst = dec->yuv_b_ + U_OFF; - uint8_t* const v_dst = dec->yuv_b_ + V_OFF; - - // Initialize left-most block. - for (j = 0; j < 16; ++j) { - y_dst[j * BPS - 1] = 129; - } - for (j = 0; j < 8; ++j) { - u_dst[j * BPS - 1] = 129; - v_dst[j * BPS - 1] = 129; - } - - // Init top-left sample on left column too. - if (mb_y > 0) { - y_dst[-1 - BPS] = u_dst[-1 - BPS] = v_dst[-1 - BPS] = 129; - } else { - // we only need to do this init once at block (0,0). - // Afterward, it remains valid for the whole topmost row. - memset(y_dst - BPS - 1, 127, 16 + 4 + 1); - memset(u_dst - BPS - 1, 127, 8 + 1); - memset(v_dst - BPS - 1, 127, 8 + 1); - } - - // Reconstruct one row. - for (mb_x = 0; mb_x < dec->mb_w_; ++mb_x) { - const VP8MBData* const block = ctx->mb_data_ + mb_x; - - // Rotate in the left samples from previously decoded block. We move four - // pixels at a time for alignment reason, and because of in-loop filter. - if (mb_x > 0) { - for (j = -1; j < 16; ++j) { - Copy32b(&y_dst[j * BPS - 4], &y_dst[j * BPS + 12]); - } - for (j = -1; j < 8; ++j) { - Copy32b(&u_dst[j * BPS - 4], &u_dst[j * BPS + 4]); - Copy32b(&v_dst[j * BPS - 4], &v_dst[j * BPS + 4]); - } - } - { - // bring top samples into the cache - VP8TopSamples* const top_yuv = dec->yuv_t_ + mb_x; - const int16_t* const coeffs = block->coeffs_; - uint32_t bits = block->non_zero_y_; - int n; - - if (mb_y > 0) { - memcpy(y_dst - BPS, top_yuv[0].y, 16); - memcpy(u_dst - BPS, top_yuv[0].u, 8); - memcpy(v_dst - BPS, top_yuv[0].v, 8); - } - - // predict and add residuals - if (block->is_i4x4_) { // 4x4 - uint32_t* const top_right = (uint32_t*)(y_dst - BPS + 16); - - if (mb_y > 0) { - if (mb_x >= dec->mb_w_ - 1) { // on rightmost border - memset(top_right, top_yuv[0].y[15], sizeof(*top_right)); - } else { - memcpy(top_right, top_yuv[1].y, sizeof(*top_right)); - } - } - // replicate the top-right pixels below - top_right[BPS] = top_right[2 * BPS] = top_right[3 * BPS] = top_right[0]; - - // predict and add residuals for all 4x4 blocks in turn. - for (n = 0; n < 16; ++n, bits <<= 2) { - uint8_t* const dst = y_dst + kScan[n]; - VP8PredLuma4[block->imodes_[n]](dst); - DoTransform(bits, coeffs + n * 16, dst); - } - } else { // 16x16 - const int pred_func = CheckMode(mb_x, mb_y, block->imodes_[0]); - VP8PredLuma16[pred_func](y_dst); - if (bits != 0) { - for (n = 0; n < 16; ++n, bits <<= 2) { - DoTransform(bits, coeffs + n * 16, y_dst + kScan[n]); - } - } - } - { - // Chroma - const uint32_t bits_uv = block->non_zero_uv_; - const int pred_func = CheckMode(mb_x, mb_y, block->uvmode_); - VP8PredChroma8[pred_func](u_dst); - VP8PredChroma8[pred_func](v_dst); - DoUVTransform(bits_uv >> 0, coeffs + 16 * 16, u_dst); - DoUVTransform(bits_uv >> 8, coeffs + 20 * 16, v_dst); - } - - // stash away top samples for next block - if (mb_y < dec->mb_h_ - 1) { - memcpy(top_yuv[0].y, y_dst + 15 * BPS, 16); - memcpy(top_yuv[0].u, u_dst + 7 * BPS, 8); - memcpy(top_yuv[0].v, v_dst + 7 * BPS, 8); - } - } - // Transfer reconstructed samples from yuv_b_ cache to final destination. - { - const int y_offset = cache_id * 16 * dec->cache_y_stride_; - const int uv_offset = cache_id * 8 * dec->cache_uv_stride_; - uint8_t* const y_out = dec->cache_y_ + mb_x * 16 + y_offset; - uint8_t* const u_out = dec->cache_u_ + mb_x * 8 + uv_offset; - uint8_t* const v_out = dec->cache_v_ + mb_x * 8 + uv_offset; - for (j = 0; j < 16; ++j) { - memcpy(y_out + j * dec->cache_y_stride_, y_dst + j * BPS, 16); - } - for (j = 0; j < 8; ++j) { - memcpy(u_out + j * dec->cache_uv_stride_, u_dst + j * BPS, 8); - memcpy(v_out + j * dec->cache_uv_stride_, v_dst + j * BPS, 8); - } - } - } -} - -//------------------------------------------------------------------------------ -// Filtering - -// kFilterExtraRows[] = How many extra lines are needed on the MB boundary -// for caching, given a filtering level. -// Simple filter: up to 2 luma samples are read and 1 is written. -// Complex filter: up to 4 luma samples are read and 3 are written. Same for -// U/V, so it's 8 samples total (because of the 2x upsampling). -static const uint8_t kFilterExtraRows[3] = { 0, 2, 8 }; - -static void DoFilter(const VP8Decoder* const dec, int mb_x, int mb_y) { - const VP8ThreadContext* const ctx = &dec->thread_ctx_; - const int cache_id = ctx->id_; - const int y_bps = dec->cache_y_stride_; - const VP8FInfo* const f_info = ctx->f_info_ + mb_x; - uint8_t* const y_dst = dec->cache_y_ + cache_id * 16 * y_bps + mb_x * 16; - const int ilevel = f_info->f_ilevel_; - const int limit = f_info->f_limit_; - if (limit == 0) { - return; - } - assert(limit >= 3); - if (dec->filter_type_ == 1) { // simple - if (mb_x > 0) { - VP8SimpleHFilter16(y_dst, y_bps, limit + 4); - } - if (f_info->f_inner_) { - VP8SimpleHFilter16i(y_dst, y_bps, limit); - } - if (mb_y > 0) { - VP8SimpleVFilter16(y_dst, y_bps, limit + 4); - } - if (f_info->f_inner_) { - VP8SimpleVFilter16i(y_dst, y_bps, limit); - } - } else { // complex - const int uv_bps = dec->cache_uv_stride_; - uint8_t* const u_dst = dec->cache_u_ + cache_id * 8 * uv_bps + mb_x * 8; - uint8_t* const v_dst = dec->cache_v_ + cache_id * 8 * uv_bps + mb_x * 8; - const int hev_thresh = f_info->hev_thresh_; - if (mb_x > 0) { - VP8HFilter16(y_dst, y_bps, limit + 4, ilevel, hev_thresh); - VP8HFilter8(u_dst, v_dst, uv_bps, limit + 4, ilevel, hev_thresh); - } - if (f_info->f_inner_) { - VP8HFilter16i(y_dst, y_bps, limit, ilevel, hev_thresh); - VP8HFilter8i(u_dst, v_dst, uv_bps, limit, ilevel, hev_thresh); - } - if (mb_y > 0) { - VP8VFilter16(y_dst, y_bps, limit + 4, ilevel, hev_thresh); - VP8VFilter8(u_dst, v_dst, uv_bps, limit + 4, ilevel, hev_thresh); - } - if (f_info->f_inner_) { - VP8VFilter16i(y_dst, y_bps, limit, ilevel, hev_thresh); - VP8VFilter8i(u_dst, v_dst, uv_bps, limit, ilevel, hev_thresh); - } - } -} - -// Filter the decoded macroblock row (if needed) -static void FilterRow(const VP8Decoder* const dec) { - int mb_x; - const int mb_y = dec->thread_ctx_.mb_y_; - assert(dec->thread_ctx_.filter_row_); - for (mb_x = dec->tl_mb_x_; mb_x < dec->br_mb_x_; ++mb_x) { - DoFilter(dec, mb_x, mb_y); - } -} - -//------------------------------------------------------------------------------ -// Precompute the filtering strength for each segment and each i4x4/i16x16 mode. - -static void PrecomputeFilterStrengths(VP8Decoder* const dec) { - if (dec->filter_type_ > 0) { - int s; - const VP8FilterHeader* const hdr = &dec->filter_hdr_; - for (s = 0; s < NUM_MB_SEGMENTS; ++s) { - int i4x4; - // First, compute the initial level - int base_level; - if (dec->segment_hdr_.use_segment_) { - base_level = dec->segment_hdr_.filter_strength_[s]; - if (!dec->segment_hdr_.absolute_delta_) { - base_level += hdr->level_; - } - } else { - base_level = hdr->level_; - } - for (i4x4 = 0; i4x4 <= 1; ++i4x4) { - VP8FInfo* const info = &dec->fstrengths_[s][i4x4]; - int level = base_level; - if (hdr->use_lf_delta_) { - level += hdr->ref_lf_delta_[0]; - if (i4x4) { - level += hdr->mode_lf_delta_[0]; - } - } - level = (level < 0) ? 0 : (level > 63) ? 63 : level; - if (level > 0) { - int ilevel = level; - if (hdr->sharpness_ > 0) { - if (hdr->sharpness_ > 4) { - ilevel >>= 2; - } else { - ilevel >>= 1; - } - if (ilevel > 9 - hdr->sharpness_) { - ilevel = 9 - hdr->sharpness_; - } - } - if (ilevel < 1) ilevel = 1; - info->f_ilevel_ = ilevel; - info->f_limit_ = 2 * level + ilevel; - info->hev_thresh_ = (level >= 40) ? 2 : (level >= 15) ? 1 : 0; - } else { - info->f_limit_ = 0; // no filtering - } - info->f_inner_ = i4x4; - } - } - } -} - -//------------------------------------------------------------------------------ -// Dithering - -#define DITHER_AMP_TAB_SIZE 12 -static const int kQuantToDitherAmp[DITHER_AMP_TAB_SIZE] = { - // roughly, it's dqm->uv_mat_[1] - 8, 7, 6, 4, 4, 2, 2, 2, 1, 1, 1, 1 -}; - -void VP8InitDithering(const WebPDecoderOptions* const options, - VP8Decoder* const dec) { - assert(dec != NULL); - if (options != NULL) { - const int d = options->dithering_strength; - const int max_amp = (1 << VP8_RANDOM_DITHER_FIX) - 1; - const int f = (d < 0) ? 0 : (d > 100) ? max_amp : (d * max_amp / 100); - if (f > 0) { - int s; - int all_amp = 0; - for (s = 0; s < NUM_MB_SEGMENTS; ++s) { - VP8QuantMatrix* const dqm = &dec->dqm_[s]; - if (dqm->uv_quant_ < DITHER_AMP_TAB_SIZE) { - // TODO(skal): should we specially dither more for uv_quant_ < 0? - const int idx = (dqm->uv_quant_ < 0) ? 0 : dqm->uv_quant_; - dqm->dither_ = (f * kQuantToDitherAmp[idx]) >> 3; - } - all_amp |= dqm->dither_; - } - if (all_amp != 0) { - VP8InitRandom(&dec->dithering_rg_, 1.0f); - dec->dither_ = 1; - } - } - // potentially allow alpha dithering - dec->alpha_dithering_ = options->alpha_dithering_strength; - if (dec->alpha_dithering_ > 100) { - dec->alpha_dithering_ = 100; - } else if (dec->alpha_dithering_ < 0) { - dec->alpha_dithering_ = 0; - } - } -} - -// minimal amp that will provide a non-zero dithering effect -#define MIN_DITHER_AMP 4 -#define DITHER_DESCALE 4 -#define DITHER_DESCALE_ROUNDER (1 << (DITHER_DESCALE - 1)) -#define DITHER_AMP_BITS 8 -#define DITHER_AMP_CENTER (1 << DITHER_AMP_BITS) - -static void Dither8x8(VP8Random* const rg, uint8_t* dst, int bps, int amp) { - int i, j; - for (j = 0; j < 8; ++j) { - for (i = 0; i < 8; ++i) { - // TODO: could be made faster with SSE2 - const int bits = - VP8RandomBits2(rg, DITHER_AMP_BITS + 1, amp) - DITHER_AMP_CENTER; - // Convert to range: [-2,2] for dither=50, [-4,4] for dither=100 - const int delta = (bits + DITHER_DESCALE_ROUNDER) >> DITHER_DESCALE; - const int v = (int)dst[i] + delta; - dst[i] = (v < 0) ? 0 : (v > 255) ? 255u : (uint8_t)v; - } - dst += bps; - } -} - -static void DitherRow(VP8Decoder* const dec) { - int mb_x; - assert(dec->dither_); - for (mb_x = dec->tl_mb_x_; mb_x < dec->br_mb_x_; ++mb_x) { - const VP8ThreadContext* const ctx = &dec->thread_ctx_; - const VP8MBData* const data = ctx->mb_data_ + mb_x; - const int cache_id = ctx->id_; - const int uv_bps = dec->cache_uv_stride_; - if (data->dither_ >= MIN_DITHER_AMP) { - uint8_t* const u_dst = dec->cache_u_ + cache_id * 8 * uv_bps + mb_x * 8; - uint8_t* const v_dst = dec->cache_v_ + cache_id * 8 * uv_bps + mb_x * 8; - Dither8x8(&dec->dithering_rg_, u_dst, uv_bps, data->dither_); - Dither8x8(&dec->dithering_rg_, v_dst, uv_bps, data->dither_); - } - } -} - -//------------------------------------------------------------------------------ -// This function is called after a row of macroblocks is finished decoding. -// It also takes into account the following restrictions: -// * In case of in-loop filtering, we must hold off sending some of the bottom -// pixels as they are yet unfiltered. They will be when the next macroblock -// row is decoded. Meanwhile, we must preserve them by rotating them in the -// cache area. This doesn't hold for the very bottom row of the uncropped -// picture of course. -// * we must clip the remaining pixels against the cropping area. The VP8Io -// struct must have the following fields set correctly before calling put(): - -#define MACROBLOCK_VPOS(mb_y) ((mb_y) * 16) // vertical position of a MB - -// Finalize and transmit a complete row. Return false in case of user-abort. -static int FinishRow(VP8Decoder* const dec, VP8Io* const io) { - int ok = 1; - const VP8ThreadContext* const ctx = &dec->thread_ctx_; - const int cache_id = ctx->id_; - const int extra_y_rows = kFilterExtraRows[dec->filter_type_]; - const int ysize = extra_y_rows * dec->cache_y_stride_; - const int uvsize = (extra_y_rows / 2) * dec->cache_uv_stride_; - const int y_offset = cache_id * 16 * dec->cache_y_stride_; - const int uv_offset = cache_id * 8 * dec->cache_uv_stride_; - uint8_t* const ydst = dec->cache_y_ - ysize + y_offset; - uint8_t* const udst = dec->cache_u_ - uvsize + uv_offset; - uint8_t* const vdst = dec->cache_v_ - uvsize + uv_offset; - const int mb_y = ctx->mb_y_; - const int is_first_row = (mb_y == 0); - const int is_last_row = (mb_y >= dec->br_mb_y_ - 1); - - if (dec->mt_method_ == 2) { - ReconstructRow(dec, ctx); - } - - if (ctx->filter_row_) { - FilterRow(dec); - } - - if (dec->dither_) { - DitherRow(dec); - } - - if (io->put != NULL) { - int y_start = MACROBLOCK_VPOS(mb_y); - int y_end = MACROBLOCK_VPOS(mb_y + 1); - if (!is_first_row) { - y_start -= extra_y_rows; - io->y = ydst; - io->u = udst; - io->v = vdst; - } else { - io->y = dec->cache_y_ + y_offset; - io->u = dec->cache_u_ + uv_offset; - io->v = dec->cache_v_ + uv_offset; - } - - if (!is_last_row) { - y_end -= extra_y_rows; - } - if (y_end > io->crop_bottom) { - y_end = io->crop_bottom; // make sure we don't overflow on last row. - } - io->a = NULL; - if (dec->alpha_data_ != NULL && y_start < y_end) { - // TODO(skal): testing presence of alpha with dec->alpha_data_ is not a - // good idea. - io->a = VP8DecompressAlphaRows(dec, y_start, y_end - y_start); - if (io->a == NULL) { - return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, - "Could not decode alpha data."); - } - } - if (y_start < io->crop_top) { - const int delta_y = io->crop_top - y_start; - y_start = io->crop_top; - assert(!(delta_y & 1)); - io->y += dec->cache_y_stride_ * delta_y; - io->u += dec->cache_uv_stride_ * (delta_y >> 1); - io->v += dec->cache_uv_stride_ * (delta_y >> 1); - if (io->a != NULL) { - io->a += io->width * delta_y; - } - } - if (y_start < y_end) { - io->y += io->crop_left; - io->u += io->crop_left >> 1; - io->v += io->crop_left >> 1; - if (io->a != NULL) { - io->a += io->crop_left; - } - io->mb_y = y_start - io->crop_top; - io->mb_w = io->crop_right - io->crop_left; - io->mb_h = y_end - y_start; - ok = io->put(io); - } - } - // rotate top samples if needed - if (cache_id + 1 == dec->num_caches_) { - if (!is_last_row) { - memcpy(dec->cache_y_ - ysize, ydst + 16 * dec->cache_y_stride_, ysize); - memcpy(dec->cache_u_ - uvsize, udst + 8 * dec->cache_uv_stride_, uvsize); - memcpy(dec->cache_v_ - uvsize, vdst + 8 * dec->cache_uv_stride_, uvsize); - } - } - - return ok; -} - -#undef MACROBLOCK_VPOS - -//------------------------------------------------------------------------------ - -int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io) { - int ok = 1; - VP8ThreadContext* const ctx = &dec->thread_ctx_; - const int filter_row = - (dec->filter_type_ > 0) && - (dec->mb_y_ >= dec->tl_mb_y_) && (dec->mb_y_ <= dec->br_mb_y_); - if (dec->mt_method_ == 0) { - // ctx->id_ and ctx->f_info_ are already set - ctx->mb_y_ = dec->mb_y_; - ctx->filter_row_ = filter_row; - ReconstructRow(dec, ctx); - ok = FinishRow(dec, io); - } else { - WebPWorker* const worker = &dec->worker_; - // Finish previous job *before* updating context - ok &= WebPGetWorkerInterface()->Sync(worker); - assert(worker->status_ == OK); - if (ok) { // spawn a new deblocking/output job - ctx->io_ = *io; - ctx->id_ = dec->cache_id_; - ctx->mb_y_ = dec->mb_y_; - ctx->filter_row_ = filter_row; - if (dec->mt_method_ == 2) { // swap macroblock data - VP8MBData* const tmp = ctx->mb_data_; - ctx->mb_data_ = dec->mb_data_; - dec->mb_data_ = tmp; - } else { - // perform reconstruction directly in main thread - ReconstructRow(dec, ctx); - } - if (filter_row) { // swap filter info - VP8FInfo* const tmp = ctx->f_info_; - ctx->f_info_ = dec->f_info_; - dec->f_info_ = tmp; - } - // (reconstruct)+filter in parallel - WebPGetWorkerInterface()->Launch(worker); - if (++dec->cache_id_ == dec->num_caches_) { - dec->cache_id_ = 0; - } - } - } - return ok; -} - -//------------------------------------------------------------------------------ -// Finish setting up the decoding parameter once user's setup() is called. - -VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io) { - // Call setup() first. This may trigger additional decoding features on 'io'. - // Note: Afterward, we must call teardown() no matter what. - if (io->setup != NULL && !io->setup(io)) { - VP8SetError(dec, VP8_STATUS_USER_ABORT, "Frame setup failed"); - return dec->status_; - } - - // Disable filtering per user request - if (io->bypass_filtering) { - dec->filter_type_ = 0; - } - // TODO(skal): filter type / strength / sharpness forcing - - // Define the area where we can skip in-loop filtering, in case of cropping. - // - // 'Simple' filter reads two luma samples outside of the macroblock - // and filters one. It doesn't filter the chroma samples. Hence, we can - // avoid doing the in-loop filtering before crop_top/crop_left position. - // For the 'Complex' filter, 3 samples are read and up to 3 are filtered. - // Means: there's a dependency chain that goes all the way up to the - // top-left corner of the picture (MB #0). We must filter all the previous - // macroblocks. - // TODO(skal): add an 'approximate_decoding' option, that won't produce - // a 1:1 bit-exactness for complex filtering? - { - const int extra_pixels = kFilterExtraRows[dec->filter_type_]; - if (dec->filter_type_ == 2) { - // For complex filter, we need to preserve the dependency chain. - dec->tl_mb_x_ = 0; - dec->tl_mb_y_ = 0; - } else { - // For simple filter, we can filter only the cropped region. - // We include 'extra_pixels' on the other side of the boundary, since - // vertical or horizontal filtering of the previous macroblock can - // modify some abutting pixels. - dec->tl_mb_x_ = (io->crop_left - extra_pixels) >> 4; - dec->tl_mb_y_ = (io->crop_top - extra_pixels) >> 4; - if (dec->tl_mb_x_ < 0) dec->tl_mb_x_ = 0; - if (dec->tl_mb_y_ < 0) dec->tl_mb_y_ = 0; - } - // We need some 'extra' pixels on the right/bottom. - dec->br_mb_y_ = (io->crop_bottom + 15 + extra_pixels) >> 4; - dec->br_mb_x_ = (io->crop_right + 15 + extra_pixels) >> 4; - if (dec->br_mb_x_ > dec->mb_w_) { - dec->br_mb_x_ = dec->mb_w_; - } - if (dec->br_mb_y_ > dec->mb_h_) { - dec->br_mb_y_ = dec->mb_h_; - } - } - PrecomputeFilterStrengths(dec); - return VP8_STATUS_OK; -} - -int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io) { - int ok = 1; - if (dec->mt_method_ > 0) { - ok = WebPGetWorkerInterface()->Sync(&dec->worker_); - } - - if (io->teardown != NULL) { - io->teardown(io); - } - return ok; -} - -//------------------------------------------------------------------------------ -// For multi-threaded decoding we need to use 3 rows of 16 pixels as delay line. -// -// Reason is: the deblocking filter cannot deblock the bottom horizontal edges -// immediately, and needs to wait for first few rows of the next macroblock to -// be decoded. Hence, deblocking is lagging behind by 4 or 8 pixels (depending -// on strength). -// With two threads, the vertical positions of the rows being decoded are: -// Decode: [ 0..15][16..31][32..47][48..63][64..79][... -// Deblock: [ 0..11][12..27][28..43][44..59][... -// If we use two threads and two caches of 16 pixels, the sequence would be: -// Decode: [ 0..15][16..31][ 0..15!!][16..31][ 0..15][... -// Deblock: [ 0..11][12..27!!][-4..11][12..27][... -// The problem occurs during row [12..15!!] that both the decoding and -// deblocking threads are writing simultaneously. -// With 3 cache lines, one get a safe write pattern: -// Decode: [ 0..15][16..31][32..47][ 0..15][16..31][32..47][0.. -// Deblock: [ 0..11][12..27][28..43][-4..11][12..27][28... -// Note that multi-threaded output _without_ deblocking can make use of two -// cache lines of 16 pixels only, since there's no lagging behind. The decoding -// and output process have non-concurrent writing: -// Decode: [ 0..15][16..31][ 0..15][16..31][... -// io->put: [ 0..15][16..31][ 0..15][... - -#define MT_CACHE_LINES 3 -#define ST_CACHE_LINES 1 // 1 cache row only for single-threaded case - -// Initialize multi/single-thread worker -static int InitThreadContext(VP8Decoder* const dec) { - dec->cache_id_ = 0; - if (dec->mt_method_ > 0) { - WebPWorker* const worker = &dec->worker_; - if (!WebPGetWorkerInterface()->Reset(worker)) { - return VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY, - "thread initialization failed."); - } - worker->data1 = dec; - worker->data2 = (void*)&dec->thread_ctx_.io_; - worker->hook = (WebPWorkerHook)FinishRow; - dec->num_caches_ = - (dec->filter_type_ > 0) ? MT_CACHE_LINES : MT_CACHE_LINES - 1; - } else { - dec->num_caches_ = ST_CACHE_LINES; - } - return 1; -} - -int VP8GetThreadMethod(const WebPDecoderOptions* const options, - const WebPHeaderStructure* const headers, - int width, int height) { - if (options == NULL || options->use_threads == 0) { - return 0; - } - (void)headers; - (void)width; - (void)height; - assert(headers == NULL || !headers->is_lossless); -#if defined(WEBP_USE_THREAD) - if (width < MIN_WIDTH_FOR_THREADS) return 0; - // TODO(skal): tune the heuristic further -#if 0 - if (height < 2 * width) return 2; -#endif - return 2; -#else // !WEBP_USE_THREAD - return 0; -#endif -} - -#undef MT_CACHE_LINES -#undef ST_CACHE_LINES - -//------------------------------------------------------------------------------ -// Memory setup - -static int AllocateMemory(VP8Decoder* const dec) { - const int num_caches = dec->num_caches_; - const int mb_w = dec->mb_w_; - // Note: we use 'size_t' when there's no overflow risk, uint64_t otherwise. - const size_t intra_pred_mode_size = 4 * mb_w * sizeof(uint8_t); - const size_t top_size = sizeof(VP8TopSamples) * mb_w; - const size_t mb_info_size = (mb_w + 1) * sizeof(VP8MB); - const size_t f_info_size = - (dec->filter_type_ > 0) ? - mb_w * (dec->mt_method_ > 0 ? 2 : 1) * sizeof(VP8FInfo) - : 0; - const size_t yuv_size = YUV_SIZE * sizeof(*dec->yuv_b_); - const size_t mb_data_size = - (dec->mt_method_ == 2 ? 2 : 1) * mb_w * sizeof(*dec->mb_data_); - const size_t cache_height = (16 * num_caches - + kFilterExtraRows[dec->filter_type_]) * 3 / 2; - const size_t cache_size = top_size * cache_height; - // alpha_size is the only one that scales as width x height. - const uint64_t alpha_size = (dec->alpha_data_ != NULL) ? - (uint64_t)dec->pic_hdr_.width_ * dec->pic_hdr_.height_ : 0ULL; - const uint64_t needed = (uint64_t)intra_pred_mode_size - + top_size + mb_info_size + f_info_size - + yuv_size + mb_data_size - + cache_size + alpha_size + WEBP_ALIGN_CST; - uint8_t* mem; - - if (needed != (size_t)needed) return 0; // check for overflow - if (needed > dec->mem_size_) { - WebPSafeFree(dec->mem_); - dec->mem_size_ = 0; - dec->mem_ = WebPSafeMalloc(needed, sizeof(uint8_t)); - if (dec->mem_ == NULL) { - return VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY, - "no memory during frame initialization."); - } - // down-cast is ok, thanks to WebPSafeAlloc() above. - dec->mem_size_ = (size_t)needed; - } - - mem = (uint8_t*)dec->mem_; - dec->intra_t_ = (uint8_t*)mem; - mem += intra_pred_mode_size; - - dec->yuv_t_ = (VP8TopSamples*)mem; - mem += top_size; - - dec->mb_info_ = ((VP8MB*)mem) + 1; - mem += mb_info_size; - - dec->f_info_ = f_info_size ? (VP8FInfo*)mem : NULL; - mem += f_info_size; - dec->thread_ctx_.id_ = 0; - dec->thread_ctx_.f_info_ = dec->f_info_; - if (dec->mt_method_ > 0) { - // secondary cache line. The deblocking process need to make use of the - // filtering strength from previous macroblock row, while the new ones - // are being decoded in parallel. We'll just swap the pointers. - dec->thread_ctx_.f_info_ += mb_w; - } - - mem = (uint8_t*)WEBP_ALIGN(mem); - assert((yuv_size & WEBP_ALIGN_CST) == 0); - dec->yuv_b_ = (uint8_t*)mem; - mem += yuv_size; - - dec->mb_data_ = (VP8MBData*)mem; - dec->thread_ctx_.mb_data_ = (VP8MBData*)mem; - if (dec->mt_method_ == 2) { - dec->thread_ctx_.mb_data_ += mb_w; - } - mem += mb_data_size; - - dec->cache_y_stride_ = 16 * mb_w; - dec->cache_uv_stride_ = 8 * mb_w; - { - const int extra_rows = kFilterExtraRows[dec->filter_type_]; - const int extra_y = extra_rows * dec->cache_y_stride_; - const int extra_uv = (extra_rows / 2) * dec->cache_uv_stride_; - dec->cache_y_ = ((uint8_t*)mem) + extra_y; - dec->cache_u_ = dec->cache_y_ - + 16 * num_caches * dec->cache_y_stride_ + extra_uv; - dec->cache_v_ = dec->cache_u_ - + 8 * num_caches * dec->cache_uv_stride_ + extra_uv; - dec->cache_id_ = 0; - } - mem += cache_size; - - // alpha plane - dec->alpha_plane_ = alpha_size ? (uint8_t*)mem : NULL; - mem += alpha_size; - assert(mem <= (uint8_t*)dec->mem_ + dec->mem_size_); - - // note: left/top-info is initialized once for all. - memset(dec->mb_info_ - 1, 0, mb_info_size); - VP8InitScanline(dec); // initialize left too. - - // initialize top - memset(dec->intra_t_, B_DC_PRED, intra_pred_mode_size); - - return 1; -} - -static void InitIo(VP8Decoder* const dec, VP8Io* io) { - // prepare 'io' - io->mb_y = 0; - io->y = dec->cache_y_; - io->u = dec->cache_u_; - io->v = dec->cache_v_; - io->y_stride = dec->cache_y_stride_; - io->uv_stride = dec->cache_uv_stride_; - io->a = NULL; -} - -int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io) { - if (!InitThreadContext(dec)) return 0; // call first. Sets dec->num_caches_. - if (!AllocateMemory(dec)) return 0; - InitIo(dec, io); - VP8DspInit(); // Init critical function pointers and look-up tables. - return 1; -} - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/dec/idec.c b/Example/Pods/libwebp/src/dec/idec.c deleted file mode 100644 index e0cf0c9c..00000000 --- a/Example/Pods/libwebp/src/dec/idec.c +++ /dev/null @@ -1,859 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Incremental decoding -// -// Author: somnath@google.com (Somnath Banerjee) - -#include -#include -#include - -#include "./alphai.h" -#include "./webpi.h" -#include "./vp8i.h" -#include "../utils/utils.h" - -// In append mode, buffer allocations increase as multiples of this value. -// Needs to be a power of 2. -#define CHUNK_SIZE 4096 -#define MAX_MB_SIZE 4096 - -//------------------------------------------------------------------------------ -// Data structures for memory and states - -// Decoding states. State normally flows as: -// WEBP_HEADER->VP8_HEADER->VP8_PARTS0->VP8_DATA->DONE for a lossy image, and -// WEBP_HEADER->VP8L_HEADER->VP8L_DATA->DONE for a lossless image. -// If there is any error the decoder goes into state ERROR. -typedef enum { - STATE_WEBP_HEADER, // All the data before that of the VP8/VP8L chunk. - STATE_VP8_HEADER, // The VP8 Frame header (within the VP8 chunk). - STATE_VP8_PARTS0, - STATE_VP8_DATA, - STATE_VP8L_HEADER, - STATE_VP8L_DATA, - STATE_DONE, - STATE_ERROR -} DecState; - -// Operating state for the MemBuffer -typedef enum { - MEM_MODE_NONE = 0, - MEM_MODE_APPEND, - MEM_MODE_MAP -} MemBufferMode; - -// storage for partition #0 and partial data (in a rolling fashion) -typedef struct { - MemBufferMode mode_; // Operation mode - size_t start_; // start location of the data to be decoded - size_t end_; // end location - size_t buf_size_; // size of the allocated buffer - uint8_t* buf_; // We don't own this buffer in case WebPIUpdate() - - size_t part0_size_; // size of partition #0 - const uint8_t* part0_buf_; // buffer to store partition #0 -} MemBuffer; - -struct WebPIDecoder { - DecState state_; // current decoding state - WebPDecParams params_; // Params to store output info - int is_lossless_; // for down-casting 'dec_'. - void* dec_; // either a VP8Decoder or a VP8LDecoder instance - VP8Io io_; - - MemBuffer mem_; // input memory buffer. - WebPDecBuffer output_; // output buffer (when no external one is supplied) - size_t chunk_size_; // Compressed VP8/VP8L size extracted from Header. - - int last_mb_y_; // last row reached for intra-mode decoding -}; - -// MB context to restore in case VP8DecodeMB() fails -typedef struct { - VP8MB left_; - VP8MB info_; - VP8BitReader token_br_; -} MBContext; - -//------------------------------------------------------------------------------ -// MemBuffer: incoming data handling - -static WEBP_INLINE size_t MemDataSize(const MemBuffer* mem) { - return (mem->end_ - mem->start_); -} - -// Check if we need to preserve the compressed alpha data, as it may not have -// been decoded yet. -static int NeedCompressedAlpha(const WebPIDecoder* const idec) { - if (idec->state_ == STATE_WEBP_HEADER) { - // We haven't parsed the headers yet, so we don't know whether the image is - // lossy or lossless. This also means that we haven't parsed the ALPH chunk. - return 0; - } - if (idec->is_lossless_) { - return 0; // ALPH chunk is not present for lossless images. - } else { - const VP8Decoder* const dec = (VP8Decoder*)idec->dec_; - assert(dec != NULL); // Must be true as idec->state_ != STATE_WEBP_HEADER. - return (dec->alpha_data_ != NULL) && !dec->is_alpha_decoded_; - } -} - -static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) { - MemBuffer* const mem = &idec->mem_; - const uint8_t* const new_base = mem->buf_ + mem->start_; - // note: for VP8, setting up idec->io_ is only really needed at the beginning - // of the decoding, till partition #0 is complete. - idec->io_.data = new_base; - idec->io_.data_size = MemDataSize(mem); - - if (idec->dec_ != NULL) { - if (!idec->is_lossless_) { - VP8Decoder* const dec = (VP8Decoder*)idec->dec_; - const int last_part = dec->num_parts_ - 1; - if (offset != 0) { - int p; - for (p = 0; p <= last_part; ++p) { - VP8RemapBitReader(dec->parts_ + p, offset); - } - // Remap partition #0 data pointer to new offset, but only in MAP - // mode (in APPEND mode, partition #0 is copied into a fixed memory). - if (mem->mode_ == MEM_MODE_MAP) { - VP8RemapBitReader(&dec->br_, offset); - } - } - { - const uint8_t* const last_start = dec->parts_[last_part].buf_; - assert(last_part >= 0); - VP8BitReaderSetBuffer(&dec->parts_[last_part], last_start, - mem->buf_ + mem->end_ - last_start); - } - if (NeedCompressedAlpha(idec)) { - ALPHDecoder* const alph_dec = dec->alph_dec_; - dec->alpha_data_ += offset; - if (alph_dec != NULL) { - if (alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION) { - VP8LDecoder* const alph_vp8l_dec = alph_dec->vp8l_dec_; - assert(alph_vp8l_dec != NULL); - assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN); - VP8LBitReaderSetBuffer(&alph_vp8l_dec->br_, - dec->alpha_data_ + ALPHA_HEADER_LEN, - dec->alpha_data_size_ - ALPHA_HEADER_LEN); - } else { // alph_dec->method_ == ALPHA_NO_COMPRESSION - // Nothing special to do in this case. - } - } - } - } else { // Resize lossless bitreader - VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; - VP8LBitReaderSetBuffer(&dec->br_, new_base, MemDataSize(mem)); - } - } -} - -// Appends data to the end of MemBuffer->buf_. It expands the allocated memory -// size if required and also updates VP8BitReader's if new memory is allocated. -static int AppendToMemBuffer(WebPIDecoder* const idec, - const uint8_t* const data, size_t data_size) { - VP8Decoder* const dec = (VP8Decoder*)idec->dec_; - MemBuffer* const mem = &idec->mem_; - const int need_compressed_alpha = NeedCompressedAlpha(idec); - const uint8_t* const old_start = mem->buf_ + mem->start_; - const uint8_t* const old_base = - need_compressed_alpha ? dec->alpha_data_ : old_start; - assert(mem->mode_ == MEM_MODE_APPEND); - if (data_size > MAX_CHUNK_PAYLOAD) { - // security safeguard: trying to allocate more than what the format - // allows for a chunk should be considered a smoke smell. - return 0; - } - - if (mem->end_ + data_size > mem->buf_size_) { // Need some free memory - const size_t new_mem_start = old_start - old_base; - const size_t current_size = MemDataSize(mem) + new_mem_start; - const uint64_t new_size = (uint64_t)current_size + data_size; - const uint64_t extra_size = (new_size + CHUNK_SIZE - 1) & ~(CHUNK_SIZE - 1); - uint8_t* const new_buf = - (uint8_t*)WebPSafeMalloc(extra_size, sizeof(*new_buf)); - if (new_buf == NULL) return 0; - memcpy(new_buf, old_base, current_size); - WebPSafeFree(mem->buf_); - mem->buf_ = new_buf; - mem->buf_size_ = (size_t)extra_size; - mem->start_ = new_mem_start; - mem->end_ = current_size; - } - - memcpy(mem->buf_ + mem->end_, data, data_size); - mem->end_ += data_size; - assert(mem->end_ <= mem->buf_size_); - - DoRemap(idec, mem->buf_ + mem->start_ - old_start); - return 1; -} - -static int RemapMemBuffer(WebPIDecoder* const idec, - const uint8_t* const data, size_t data_size) { - MemBuffer* const mem = &idec->mem_; - const uint8_t* const old_buf = mem->buf_; - const uint8_t* const old_start = old_buf + mem->start_; - assert(mem->mode_ == MEM_MODE_MAP); - - if (data_size < mem->buf_size_) return 0; // can't remap to a shorter buffer! - - mem->buf_ = (uint8_t*)data; - mem->end_ = mem->buf_size_ = data_size; - - DoRemap(idec, mem->buf_ + mem->start_ - old_start); - return 1; -} - -static void InitMemBuffer(MemBuffer* const mem) { - mem->mode_ = MEM_MODE_NONE; - mem->buf_ = NULL; - mem->buf_size_ = 0; - mem->part0_buf_ = NULL; - mem->part0_size_ = 0; -} - -static void ClearMemBuffer(MemBuffer* const mem) { - assert(mem); - if (mem->mode_ == MEM_MODE_APPEND) { - WebPSafeFree(mem->buf_); - WebPSafeFree((void*)mem->part0_buf_); - } -} - -static int CheckMemBufferMode(MemBuffer* const mem, MemBufferMode expected) { - if (mem->mode_ == MEM_MODE_NONE) { - mem->mode_ = expected; // switch to the expected mode - } else if (mem->mode_ != expected) { - return 0; // we mixed the modes => error - } - assert(mem->mode_ == expected); // mode is ok - return 1; -} - -// To be called last. -static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) { - const WebPDecoderOptions* const options = idec->params_.options; - WebPDecBuffer* const output = idec->params_.output; - - idec->state_ = STATE_DONE; - if (options != NULL && options->flip) { - return WebPFlipBuffer(output); - } else { - return VP8_STATUS_OK; - } -} - -//------------------------------------------------------------------------------ -// Macroblock-decoding contexts - -static void SaveContext(const VP8Decoder* dec, const VP8BitReader* token_br, - MBContext* const context) { - context->left_ = dec->mb_info_[-1]; - context->info_ = dec->mb_info_[dec->mb_x_]; - context->token_br_ = *token_br; -} - -static void RestoreContext(const MBContext* context, VP8Decoder* const dec, - VP8BitReader* const token_br) { - dec->mb_info_[-1] = context->left_; - dec->mb_info_[dec->mb_x_] = context->info_; - *token_br = context->token_br_; -} - -//------------------------------------------------------------------------------ - -static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) { - if (idec->state_ == STATE_VP8_DATA) { - VP8Io* const io = &idec->io_; - if (io->teardown != NULL) { - io->teardown(io); - } - } - idec->state_ = STATE_ERROR; - return error; -} - -static void ChangeState(WebPIDecoder* const idec, DecState new_state, - size_t consumed_bytes) { - MemBuffer* const mem = &idec->mem_; - idec->state_ = new_state; - mem->start_ += consumed_bytes; - assert(mem->start_ <= mem->end_); - idec->io_.data = mem->buf_ + mem->start_; - idec->io_.data_size = MemDataSize(mem); -} - -// Headers -static VP8StatusCode DecodeWebPHeaders(WebPIDecoder* const idec) { - MemBuffer* const mem = &idec->mem_; - const uint8_t* data = mem->buf_ + mem->start_; - size_t curr_size = MemDataSize(mem); - VP8StatusCode status; - WebPHeaderStructure headers; - - headers.data = data; - headers.data_size = curr_size; - headers.have_all_data = 0; - status = WebPParseHeaders(&headers); - if (status == VP8_STATUS_NOT_ENOUGH_DATA) { - return VP8_STATUS_SUSPENDED; // We haven't found a VP8 chunk yet. - } else if (status != VP8_STATUS_OK) { - return IDecError(idec, status); - } - - idec->chunk_size_ = headers.compressed_size; - idec->is_lossless_ = headers.is_lossless; - if (!idec->is_lossless_) { - VP8Decoder* const dec = VP8New(); - if (dec == NULL) { - return VP8_STATUS_OUT_OF_MEMORY; - } - idec->dec_ = dec; - dec->alpha_data_ = headers.alpha_data; - dec->alpha_data_size_ = headers.alpha_data_size; - ChangeState(idec, STATE_VP8_HEADER, headers.offset); - } else { - VP8LDecoder* const dec = VP8LNew(); - if (dec == NULL) { - return VP8_STATUS_OUT_OF_MEMORY; - } - idec->dec_ = dec; - ChangeState(idec, STATE_VP8L_HEADER, headers.offset); - } - return VP8_STATUS_OK; -} - -static VP8StatusCode DecodeVP8FrameHeader(WebPIDecoder* const idec) { - const uint8_t* data = idec->mem_.buf_ + idec->mem_.start_; - const size_t curr_size = MemDataSize(&idec->mem_); - int width, height; - uint32_t bits; - - if (curr_size < VP8_FRAME_HEADER_SIZE) { - // Not enough data bytes to extract VP8 Frame Header. - return VP8_STATUS_SUSPENDED; - } - if (!VP8GetInfo(data, curr_size, idec->chunk_size_, &width, &height)) { - return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); - } - - bits = data[0] | (data[1] << 8) | (data[2] << 16); - idec->mem_.part0_size_ = (bits >> 5) + VP8_FRAME_HEADER_SIZE; - - idec->io_.data = data; - idec->io_.data_size = curr_size; - idec->state_ = STATE_VP8_PARTS0; - return VP8_STATUS_OK; -} - -// Partition #0 -static VP8StatusCode CopyParts0Data(WebPIDecoder* const idec) { - VP8Decoder* const dec = (VP8Decoder*)idec->dec_; - VP8BitReader* const br = &dec->br_; - const size_t part_size = br->buf_end_ - br->buf_; - MemBuffer* const mem = &idec->mem_; - assert(!idec->is_lossless_); - assert(mem->part0_buf_ == NULL); - // the following is a format limitation, no need for runtime check: - assert(part_size <= mem->part0_size_); - if (part_size == 0) { // can't have zero-size partition #0 - return VP8_STATUS_BITSTREAM_ERROR; - } - if (mem->mode_ == MEM_MODE_APPEND) { - // We copy and grab ownership of the partition #0 data. - uint8_t* const part0_buf = (uint8_t*)WebPSafeMalloc(1ULL, part_size); - if (part0_buf == NULL) { - return VP8_STATUS_OUT_OF_MEMORY; - } - memcpy(part0_buf, br->buf_, part_size); - mem->part0_buf_ = part0_buf; - VP8BitReaderSetBuffer(br, part0_buf, part_size); - } else { - // Else: just keep pointers to the partition #0's data in dec_->br_. - } - mem->start_ += part_size; - return VP8_STATUS_OK; -} - -static VP8StatusCode DecodePartition0(WebPIDecoder* const idec) { - VP8Decoder* const dec = (VP8Decoder*)idec->dec_; - VP8Io* const io = &idec->io_; - const WebPDecParams* const params = &idec->params_; - WebPDecBuffer* const output = params->output; - - // Wait till we have enough data for the whole partition #0 - if (MemDataSize(&idec->mem_) < idec->mem_.part0_size_) { - return VP8_STATUS_SUSPENDED; - } - - if (!VP8GetHeaders(dec, io)) { - const VP8StatusCode status = dec->status_; - if (status == VP8_STATUS_SUSPENDED || - status == VP8_STATUS_NOT_ENOUGH_DATA) { - // treating NOT_ENOUGH_DATA as SUSPENDED state - return VP8_STATUS_SUSPENDED; - } - return IDecError(idec, status); - } - - // Allocate/Verify output buffer now - dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options, - output); - if (dec->status_ != VP8_STATUS_OK) { - return IDecError(idec, dec->status_); - } - // This change must be done before calling VP8InitFrame() - dec->mt_method_ = VP8GetThreadMethod(params->options, NULL, - io->width, io->height); - VP8InitDithering(params->options, dec); - - dec->status_ = CopyParts0Data(idec); - if (dec->status_ != VP8_STATUS_OK) { - return IDecError(idec, dec->status_); - } - - // Finish setting up the decoding parameters. Will call io->setup(). - if (VP8EnterCritical(dec, io) != VP8_STATUS_OK) { - return IDecError(idec, dec->status_); - } - - // Note: past this point, teardown() must always be called - // in case of error. - idec->state_ = STATE_VP8_DATA; - // Allocate memory and prepare everything. - if (!VP8InitFrame(dec, io)) { - return IDecError(idec, dec->status_); - } - return VP8_STATUS_OK; -} - -// Remaining partitions -static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) { - VP8Decoder* const dec = (VP8Decoder*)idec->dec_; - VP8Io* const io = &idec->io_; - - assert(dec->ready_); - for (; dec->mb_y_ < dec->mb_h_; ++dec->mb_y_) { - if (idec->last_mb_y_ != dec->mb_y_) { - if (!VP8ParseIntraModeRow(&dec->br_, dec)) { - // note: normally, error shouldn't occur since we already have the whole - // partition0 available here in DecodeRemaining(). Reaching EOF while - // reading intra modes really means a BITSTREAM_ERROR. - return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); - } - idec->last_mb_y_ = dec->mb_y_; - } - for (; dec->mb_x_ < dec->mb_w_; ++dec->mb_x_) { - VP8BitReader* const token_br = - &dec->parts_[dec->mb_y_ & (dec->num_parts_ - 1)]; - MBContext context; - SaveContext(dec, token_br, &context); - if (!VP8DecodeMB(dec, token_br)) { - // We shouldn't fail when MAX_MB data was available - if (dec->num_parts_ == 1 && MemDataSize(&idec->mem_) > MAX_MB_SIZE) { - return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); - } - RestoreContext(&context, dec, token_br); - return VP8_STATUS_SUSPENDED; - } - // Release buffer only if there is only one partition - if (dec->num_parts_ == 1) { - idec->mem_.start_ = token_br->buf_ - idec->mem_.buf_; - assert(idec->mem_.start_ <= idec->mem_.end_); - } - } - VP8InitScanline(dec); // Prepare for next scanline - - // Reconstruct, filter and emit the row. - if (!VP8ProcessRow(dec, io)) { - return IDecError(idec, VP8_STATUS_USER_ABORT); - } - } - // Synchronize the thread and check for errors. - if (!VP8ExitCritical(dec, io)) { - return IDecError(idec, VP8_STATUS_USER_ABORT); - } - dec->ready_ = 0; - return FinishDecoding(idec); -} - -static VP8StatusCode ErrorStatusLossless(WebPIDecoder* const idec, - VP8StatusCode status) { - if (status == VP8_STATUS_SUSPENDED || status == VP8_STATUS_NOT_ENOUGH_DATA) { - return VP8_STATUS_SUSPENDED; - } - return IDecError(idec, status); -} - -static VP8StatusCode DecodeVP8LHeader(WebPIDecoder* const idec) { - VP8Io* const io = &idec->io_; - VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; - const WebPDecParams* const params = &idec->params_; - WebPDecBuffer* const output = params->output; - size_t curr_size = MemDataSize(&idec->mem_); - assert(idec->is_lossless_); - - // Wait until there's enough data for decoding header. - if (curr_size < (idec->chunk_size_ >> 3)) { - dec->status_ = VP8_STATUS_SUSPENDED; - return ErrorStatusLossless(idec, dec->status_); - } - - if (!VP8LDecodeHeader(dec, io)) { - if (dec->status_ == VP8_STATUS_BITSTREAM_ERROR && - curr_size < idec->chunk_size_) { - dec->status_ = VP8_STATUS_SUSPENDED; - } - return ErrorStatusLossless(idec, dec->status_); - } - // Allocate/verify output buffer now. - dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options, - output); - if (dec->status_ != VP8_STATUS_OK) { - return IDecError(idec, dec->status_); - } - - idec->state_ = STATE_VP8L_DATA; - return VP8_STATUS_OK; -} - -static VP8StatusCode DecodeVP8LData(WebPIDecoder* const idec) { - VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; - const size_t curr_size = MemDataSize(&idec->mem_); - assert(idec->is_lossless_); - - // Switch to incremental decoding if we don't have all the bytes available. - dec->incremental_ = (curr_size < idec->chunk_size_); - - if (!VP8LDecodeImage(dec)) { - return ErrorStatusLossless(idec, dec->status_); - } - assert(dec->status_ == VP8_STATUS_OK || dec->status_ == VP8_STATUS_SUSPENDED); - return (dec->status_ == VP8_STATUS_SUSPENDED) ? dec->status_ - : FinishDecoding(idec); -} - - // Main decoding loop -static VP8StatusCode IDecode(WebPIDecoder* idec) { - VP8StatusCode status = VP8_STATUS_SUSPENDED; - - if (idec->state_ == STATE_WEBP_HEADER) { - status = DecodeWebPHeaders(idec); - } else { - if (idec->dec_ == NULL) { - return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder. - } - } - if (idec->state_ == STATE_VP8_HEADER) { - status = DecodeVP8FrameHeader(idec); - } - if (idec->state_ == STATE_VP8_PARTS0) { - status = DecodePartition0(idec); - } - if (idec->state_ == STATE_VP8_DATA) { - status = DecodeRemaining(idec); - } - if (idec->state_ == STATE_VP8L_HEADER) { - status = DecodeVP8LHeader(idec); - } - if (idec->state_ == STATE_VP8L_DATA) { - status = DecodeVP8LData(idec); - } - return status; -} - -//------------------------------------------------------------------------------ -// Public functions - -WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer) { - WebPIDecoder* idec = (WebPIDecoder*)WebPSafeCalloc(1ULL, sizeof(*idec)); - if (idec == NULL) { - return NULL; - } - - idec->state_ = STATE_WEBP_HEADER; - idec->chunk_size_ = 0; - - idec->last_mb_y_ = -1; - - InitMemBuffer(&idec->mem_); - WebPInitDecBuffer(&idec->output_); - VP8InitIo(&idec->io_); - - WebPResetDecParams(&idec->params_); - idec->params_.output = (output_buffer != NULL) ? output_buffer - : &idec->output_; - WebPInitCustomIo(&idec->params_, &idec->io_); // Plug the I/O functions. - - return idec; -} - -WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size, - WebPDecoderConfig* config) { - WebPIDecoder* idec; - - // Parse the bitstream's features, if requested: - if (data != NULL && data_size > 0 && config != NULL) { - if (WebPGetFeatures(data, data_size, &config->input) != VP8_STATUS_OK) { - return NULL; - } - } - // Create an instance of the incremental decoder - idec = WebPINewDecoder(config ? &config->output : NULL); - if (idec == NULL) { - return NULL; - } - // Finish initialization - if (config != NULL) { - idec->params_.options = &config->options; - } - return idec; -} - -void WebPIDelete(WebPIDecoder* idec) { - if (idec == NULL) return; - if (idec->dec_ != NULL) { - if (!idec->is_lossless_) { - if (idec->state_ == STATE_VP8_DATA) { - // Synchronize the thread, clean-up and check for errors. - VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_); - } - VP8Delete((VP8Decoder*)idec->dec_); - } else { - VP8LDelete((VP8LDecoder*)idec->dec_); - } - } - ClearMemBuffer(&idec->mem_); - WebPFreeDecBuffer(&idec->output_); - WebPSafeFree(idec); -} - -//------------------------------------------------------------------------------ -// Wrapper toward WebPINewDecoder - -WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE mode, uint8_t* output_buffer, - size_t output_buffer_size, int output_stride) { - const int is_external_memory = (output_buffer != NULL); - WebPIDecoder* idec; - - if (mode >= MODE_YUV) return NULL; - if (!is_external_memory) { // Overwrite parameters to sane values. - output_buffer_size = 0; - output_stride = 0; - } else { // A buffer was passed. Validate the other params. - if (output_stride == 0 || output_buffer_size == 0) { - return NULL; // invalid parameter. - } - } - idec = WebPINewDecoder(NULL); - if (idec == NULL) return NULL; - idec->output_.colorspace = mode; - idec->output_.is_external_memory = is_external_memory; - idec->output_.u.RGBA.rgba = output_buffer; - idec->output_.u.RGBA.stride = output_stride; - idec->output_.u.RGBA.size = output_buffer_size; - return idec; -} - -WebPIDecoder* WebPINewYUVA(uint8_t* luma, size_t luma_size, int luma_stride, - uint8_t* u, size_t u_size, int u_stride, - uint8_t* v, size_t v_size, int v_stride, - uint8_t* a, size_t a_size, int a_stride) { - const int is_external_memory = (luma != NULL); - WebPIDecoder* idec; - WEBP_CSP_MODE colorspace; - - if (!is_external_memory) { // Overwrite parameters to sane values. - luma_size = u_size = v_size = a_size = 0; - luma_stride = u_stride = v_stride = a_stride = 0; - u = v = a = NULL; - colorspace = MODE_YUVA; - } else { // A luma buffer was passed. Validate the other parameters. - if (u == NULL || v == NULL) return NULL; - if (luma_size == 0 || u_size == 0 || v_size == 0) return NULL; - if (luma_stride == 0 || u_stride == 0 || v_stride == 0) return NULL; - if (a != NULL) { - if (a_size == 0 || a_stride == 0) return NULL; - } - colorspace = (a == NULL) ? MODE_YUV : MODE_YUVA; - } - - idec = WebPINewDecoder(NULL); - if (idec == NULL) return NULL; - - idec->output_.colorspace = colorspace; - idec->output_.is_external_memory = is_external_memory; - idec->output_.u.YUVA.y = luma; - idec->output_.u.YUVA.y_stride = luma_stride; - idec->output_.u.YUVA.y_size = luma_size; - idec->output_.u.YUVA.u = u; - idec->output_.u.YUVA.u_stride = u_stride; - idec->output_.u.YUVA.u_size = u_size; - idec->output_.u.YUVA.v = v; - idec->output_.u.YUVA.v_stride = v_stride; - idec->output_.u.YUVA.v_size = v_size; - idec->output_.u.YUVA.a = a; - idec->output_.u.YUVA.a_stride = a_stride; - idec->output_.u.YUVA.a_size = a_size; - return idec; -} - -WebPIDecoder* WebPINewYUV(uint8_t* luma, size_t luma_size, int luma_stride, - uint8_t* u, size_t u_size, int u_stride, - uint8_t* v, size_t v_size, int v_stride) { - return WebPINewYUVA(luma, luma_size, luma_stride, - u, u_size, u_stride, - v, v_size, v_stride, - NULL, 0, 0); -} - -//------------------------------------------------------------------------------ - -static VP8StatusCode IDecCheckStatus(const WebPIDecoder* const idec) { - assert(idec); - if (idec->state_ == STATE_ERROR) { - return VP8_STATUS_BITSTREAM_ERROR; - } - if (idec->state_ == STATE_DONE) { - return VP8_STATUS_OK; - } - return VP8_STATUS_SUSPENDED; -} - -VP8StatusCode WebPIAppend(WebPIDecoder* idec, - const uint8_t* data, size_t data_size) { - VP8StatusCode status; - if (idec == NULL || data == NULL) { - return VP8_STATUS_INVALID_PARAM; - } - status = IDecCheckStatus(idec); - if (status != VP8_STATUS_SUSPENDED) { - return status; - } - // Check mixed calls between RemapMemBuffer and AppendToMemBuffer. - if (!CheckMemBufferMode(&idec->mem_, MEM_MODE_APPEND)) { - return VP8_STATUS_INVALID_PARAM; - } - // Append data to memory buffer - if (!AppendToMemBuffer(idec, data, data_size)) { - return VP8_STATUS_OUT_OF_MEMORY; - } - return IDecode(idec); -} - -VP8StatusCode WebPIUpdate(WebPIDecoder* idec, - const uint8_t* data, size_t data_size) { - VP8StatusCode status; - if (idec == NULL || data == NULL) { - return VP8_STATUS_INVALID_PARAM; - } - status = IDecCheckStatus(idec); - if (status != VP8_STATUS_SUSPENDED) { - return status; - } - // Check mixed calls between RemapMemBuffer and AppendToMemBuffer. - if (!CheckMemBufferMode(&idec->mem_, MEM_MODE_MAP)) { - return VP8_STATUS_INVALID_PARAM; - } - // Make the memory buffer point to the new buffer - if (!RemapMemBuffer(idec, data, data_size)) { - return VP8_STATUS_INVALID_PARAM; - } - return IDecode(idec); -} - -//------------------------------------------------------------------------------ - -static const WebPDecBuffer* GetOutputBuffer(const WebPIDecoder* const idec) { - if (idec == NULL || idec->dec_ == NULL) { - return NULL; - } - if (idec->state_ <= STATE_VP8_PARTS0) { - return NULL; - } - return idec->params_.output; -} - -const WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec, - int* left, int* top, - int* width, int* height) { - const WebPDecBuffer* const src = GetOutputBuffer(idec); - if (left != NULL) *left = 0; - if (top != NULL) *top = 0; - if (src) { - if (width != NULL) *width = src->width; - if (height != NULL) *height = idec->params_.last_y; - } else { - if (width != NULL) *width = 0; - if (height != NULL) *height = 0; - } - return src; -} - -uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y, - int* width, int* height, int* stride) { - const WebPDecBuffer* const src = GetOutputBuffer(idec); - if (src == NULL) return NULL; - if (src->colorspace >= MODE_YUV) { - return NULL; - } - - if (last_y != NULL) *last_y = idec->params_.last_y; - if (width != NULL) *width = src->width; - if (height != NULL) *height = src->height; - if (stride != NULL) *stride = src->u.RGBA.stride; - - return src->u.RGBA.rgba; -} - -uint8_t* WebPIDecGetYUVA(const WebPIDecoder* idec, int* last_y, - uint8_t** u, uint8_t** v, uint8_t** a, - int* width, int* height, - int* stride, int* uv_stride, int* a_stride) { - const WebPDecBuffer* const src = GetOutputBuffer(idec); - if (src == NULL) return NULL; - if (src->colorspace < MODE_YUV) { - return NULL; - } - - if (last_y != NULL) *last_y = idec->params_.last_y; - if (u != NULL) *u = src->u.YUVA.u; - if (v != NULL) *v = src->u.YUVA.v; - if (a != NULL) *a = src->u.YUVA.a; - if (width != NULL) *width = src->width; - if (height != NULL) *height = src->height; - if (stride != NULL) *stride = src->u.YUVA.y_stride; - if (uv_stride != NULL) *uv_stride = src->u.YUVA.u_stride; - if (a_stride != NULL) *a_stride = src->u.YUVA.a_stride; - - return src->u.YUVA.y; -} - -int WebPISetIOHooks(WebPIDecoder* const idec, - VP8IoPutHook put, - VP8IoSetupHook setup, - VP8IoTeardownHook teardown, - void* user_data) { - if (idec == NULL || idec->state_ > STATE_WEBP_HEADER) { - return 0; - } - - idec->io_.put = put; - idec->io_.setup = setup; - idec->io_.teardown = teardown; - idec->io_.opaque = user_data; - - return 1; -} diff --git a/Example/Pods/libwebp/src/dec/io.c b/Example/Pods/libwebp/src/dec/io.c deleted file mode 100644 index 13e469ab..00000000 --- a/Example/Pods/libwebp/src/dec/io.c +++ /dev/null @@ -1,614 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// functions for sample output. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include -#include "../dec/vp8i.h" -#include "./webpi.h" -#include "../dsp/dsp.h" -#include "../dsp/yuv.h" -#include "../utils/utils.h" - -//------------------------------------------------------------------------------ -// Main YUV<->RGB conversion functions - -static int EmitYUV(const VP8Io* const io, WebPDecParams* const p) { - WebPDecBuffer* output = p->output; - const WebPYUVABuffer* const buf = &output->u.YUVA; - uint8_t* const y_dst = buf->y + io->mb_y * buf->y_stride; - uint8_t* const u_dst = buf->u + (io->mb_y >> 1) * buf->u_stride; - uint8_t* const v_dst = buf->v + (io->mb_y >> 1) * buf->v_stride; - const int mb_w = io->mb_w; - const int mb_h = io->mb_h; - const int uv_w = (mb_w + 1) / 2; - const int uv_h = (mb_h + 1) / 2; - int j; - for (j = 0; j < mb_h; ++j) { - memcpy(y_dst + j * buf->y_stride, io->y + j * io->y_stride, mb_w); - } - for (j = 0; j < uv_h; ++j) { - memcpy(u_dst + j * buf->u_stride, io->u + j * io->uv_stride, uv_w); - memcpy(v_dst + j * buf->v_stride, io->v + j * io->uv_stride, uv_w); - } - return io->mb_h; -} - -// Point-sampling U/V sampler. -static int EmitSampledRGB(const VP8Io* const io, WebPDecParams* const p) { - WebPDecBuffer* const output = p->output; - WebPRGBABuffer* const buf = &output->u.RGBA; - uint8_t* const dst = buf->rgba + io->mb_y * buf->stride; - WebPSamplerProcessPlane(io->y, io->y_stride, - io->u, io->v, io->uv_stride, - dst, buf->stride, io->mb_w, io->mb_h, - WebPSamplers[output->colorspace]); - return io->mb_h; -} - -//------------------------------------------------------------------------------ -// Fancy upsampling - -#ifdef FANCY_UPSAMPLING -static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) { - int num_lines_out = io->mb_h; // a priori guess - const WebPRGBABuffer* const buf = &p->output->u.RGBA; - uint8_t* dst = buf->rgba + io->mb_y * buf->stride; - WebPUpsampleLinePairFunc upsample = WebPUpsamplers[p->output->colorspace]; - const uint8_t* cur_y = io->y; - const uint8_t* cur_u = io->u; - const uint8_t* cur_v = io->v; - const uint8_t* top_u = p->tmp_u; - const uint8_t* top_v = p->tmp_v; - int y = io->mb_y; - const int y_end = io->mb_y + io->mb_h; - const int mb_w = io->mb_w; - const int uv_w = (mb_w + 1) / 2; - - if (y == 0) { - // First line is special cased. We mirror the u/v samples at boundary. - upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, mb_w); - } else { - // We can finish the left-over line from previous call. - upsample(p->tmp_y, cur_y, top_u, top_v, cur_u, cur_v, - dst - buf->stride, dst, mb_w); - ++num_lines_out; - } - // Loop over each output pairs of row. - for (; y + 2 < y_end; y += 2) { - top_u = cur_u; - top_v = cur_v; - cur_u += io->uv_stride; - cur_v += io->uv_stride; - dst += 2 * buf->stride; - cur_y += 2 * io->y_stride; - upsample(cur_y - io->y_stride, cur_y, - top_u, top_v, cur_u, cur_v, - dst - buf->stride, dst, mb_w); - } - // move to last row - cur_y += io->y_stride; - if (io->crop_top + y_end < io->crop_bottom) { - // Save the unfinished samples for next call (as we're not done yet). - memcpy(p->tmp_y, cur_y, mb_w * sizeof(*p->tmp_y)); - memcpy(p->tmp_u, cur_u, uv_w * sizeof(*p->tmp_u)); - memcpy(p->tmp_v, cur_v, uv_w * sizeof(*p->tmp_v)); - // The fancy upsampler leaves a row unfinished behind - // (except for the very last row) - num_lines_out--; - } else { - // Process the very last row of even-sized picture - if (!(y_end & 1)) { - upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, - dst + buf->stride, NULL, mb_w); - } - } - return num_lines_out; -} - -#endif /* FANCY_UPSAMPLING */ - -//------------------------------------------------------------------------------ - -static int EmitAlphaYUV(const VP8Io* const io, WebPDecParams* const p, - int expected_num_lines_out) { - const uint8_t* alpha = io->a; - const WebPYUVABuffer* const buf = &p->output->u.YUVA; - const int mb_w = io->mb_w; - const int mb_h = io->mb_h; - uint8_t* dst = buf->a + io->mb_y * buf->a_stride; - int j; - (void)expected_num_lines_out; - assert(expected_num_lines_out == mb_h); - if (alpha != NULL) { - for (j = 0; j < mb_h; ++j) { - memcpy(dst, alpha, mb_w * sizeof(*dst)); - alpha += io->width; - dst += buf->a_stride; - } - } else if (buf->a != NULL) { - // the user requested alpha, but there is none, set it to opaque. - for (j = 0; j < mb_h; ++j) { - memset(dst, 0xff, mb_w * sizeof(*dst)); - dst += buf->a_stride; - } - } - return 0; -} - -static int GetAlphaSourceRow(const VP8Io* const io, - const uint8_t** alpha, int* const num_rows) { - int start_y = io->mb_y; - *num_rows = io->mb_h; - - // Compensate for the 1-line delay of the fancy upscaler. - // This is similar to EmitFancyRGB(). - if (io->fancy_upsampling) { - if (start_y == 0) { - // We don't process the last row yet. It'll be done during the next call. - --*num_rows; - } else { - --start_y; - // Fortunately, *alpha data is persistent, so we can go back - // one row and finish alpha blending, now that the fancy upscaler - // completed the YUV->RGB interpolation. - *alpha -= io->width; - } - if (io->crop_top + io->mb_y + io->mb_h == io->crop_bottom) { - // If it's the very last call, we process all the remaining rows! - *num_rows = io->crop_bottom - io->crop_top - start_y; - } - } - return start_y; -} - -static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p, - int expected_num_lines_out) { - const uint8_t* alpha = io->a; - if (alpha != NULL) { - const int mb_w = io->mb_w; - const WEBP_CSP_MODE colorspace = p->output->colorspace; - const int alpha_first = - (colorspace == MODE_ARGB || colorspace == MODE_Argb); - const WebPRGBABuffer* const buf = &p->output->u.RGBA; - int num_rows; - const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows); - uint8_t* const base_rgba = buf->rgba + start_y * buf->stride; - uint8_t* const dst = base_rgba + (alpha_first ? 0 : 3); - const int has_alpha = WebPDispatchAlpha(alpha, io->width, mb_w, - num_rows, dst, buf->stride); - (void)expected_num_lines_out; - assert(expected_num_lines_out == num_rows); - // has_alpha is true if there's non-trivial alpha to premultiply with. - if (has_alpha && WebPIsPremultipliedMode(colorspace)) { - WebPApplyAlphaMultiply(base_rgba, alpha_first, - mb_w, num_rows, buf->stride); - } - } - return 0; -} - -static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p, - int expected_num_lines_out) { - const uint8_t* alpha = io->a; - if (alpha != NULL) { - const int mb_w = io->mb_w; - const WEBP_CSP_MODE colorspace = p->output->colorspace; - const WebPRGBABuffer* const buf = &p->output->u.RGBA; - int num_rows; - const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows); - uint8_t* const base_rgba = buf->rgba + start_y * buf->stride; -#ifdef WEBP_SWAP_16BIT_CSP - uint8_t* alpha_dst = base_rgba; -#else - uint8_t* alpha_dst = base_rgba + 1; -#endif - uint32_t alpha_mask = 0x0f; - int i, j; - for (j = 0; j < num_rows; ++j) { - for (i = 0; i < mb_w; ++i) { - // Fill in the alpha value (converted to 4 bits). - const uint32_t alpha_value = alpha[i] >> 4; - alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value; - alpha_mask &= alpha_value; - } - alpha += io->width; - alpha_dst += buf->stride; - } - (void)expected_num_lines_out; - assert(expected_num_lines_out == num_rows); - if (alpha_mask != 0x0f && WebPIsPremultipliedMode(colorspace)) { - WebPApplyAlphaMultiply4444(base_rgba, mb_w, num_rows, buf->stride); - } - } - return 0; -} - -//------------------------------------------------------------------------------ -// YUV rescaling (no final RGB conversion needed) - -static int Rescale(const uint8_t* src, int src_stride, - int new_lines, WebPRescaler* const wrk) { - int num_lines_out = 0; - while (new_lines > 0) { // import new contributions of source rows. - const int lines_in = WebPRescalerImport(wrk, new_lines, src, src_stride); - src += lines_in * src_stride; - new_lines -= lines_in; - num_lines_out += WebPRescalerExport(wrk); // emit output row(s) - } - return num_lines_out; -} - -static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) { - const int mb_h = io->mb_h; - const int uv_mb_h = (mb_h + 1) >> 1; - WebPRescaler* const scaler = &p->scaler_y; - int num_lines_out = 0; - if (WebPIsAlphaMode(p->output->colorspace) && io->a != NULL) { - // Before rescaling, we premultiply the luma directly into the io->y - // internal buffer. This is OK since these samples are not used for - // intra-prediction (the top samples are saved in cache_y_/u_/v_). - // But we need to cast the const away, though. - WebPMultRows((uint8_t*)io->y, io->y_stride, - io->a, io->width, io->mb_w, mb_h, 0); - } - num_lines_out = Rescale(io->y, io->y_stride, mb_h, scaler); - Rescale(io->u, io->uv_stride, uv_mb_h, &p->scaler_u); - Rescale(io->v, io->uv_stride, uv_mb_h, &p->scaler_v); - return num_lines_out; -} - -static int EmitRescaledAlphaYUV(const VP8Io* const io, WebPDecParams* const p, - int expected_num_lines_out) { - if (io->a != NULL) { - const WebPYUVABuffer* const buf = &p->output->u.YUVA; - uint8_t* dst_y = buf->y + p->last_y * buf->y_stride; - const uint8_t* src_a = buf->a + p->last_y * buf->a_stride; - const int num_lines_out = Rescale(io->a, io->width, io->mb_h, &p->scaler_a); - (void)expected_num_lines_out; - assert(expected_num_lines_out == num_lines_out); - if (num_lines_out > 0) { // unmultiply the Y - WebPMultRows(dst_y, buf->y_stride, src_a, buf->a_stride, - p->scaler_a.dst_width, num_lines_out, 1); - } - } - return 0; -} - -static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) { - const int has_alpha = WebPIsAlphaMode(p->output->colorspace); - const WebPYUVABuffer* const buf = &p->output->u.YUVA; - const int out_width = io->scaled_width; - const int out_height = io->scaled_height; - const int uv_out_width = (out_width + 1) >> 1; - const int uv_out_height = (out_height + 1) >> 1; - const int uv_in_width = (io->mb_w + 1) >> 1; - const int uv_in_height = (io->mb_h + 1) >> 1; - const size_t work_size = 2 * out_width; // scratch memory for luma rescaler - const size_t uv_work_size = 2 * uv_out_width; // and for each u/v ones - size_t tmp_size; - rescaler_t* work; - - tmp_size = (work_size + 2 * uv_work_size) * sizeof(*work); - if (has_alpha) { - tmp_size += work_size * sizeof(*work); - } - p->memory = WebPSafeMalloc(1ULL, tmp_size); - if (p->memory == NULL) { - return 0; // memory error - } - work = (rescaler_t*)p->memory; - WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h, - buf->y, out_width, out_height, buf->y_stride, 1, - work); - WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height, - buf->u, uv_out_width, uv_out_height, buf->u_stride, 1, - work + work_size); - WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height, - buf->v, uv_out_width, uv_out_height, buf->v_stride, 1, - work + work_size + uv_work_size); - p->emit = EmitRescaledYUV; - - if (has_alpha) { - WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h, - buf->a, out_width, out_height, buf->a_stride, 1, - work + work_size + 2 * uv_work_size); - p->emit_alpha = EmitRescaledAlphaYUV; - WebPInitAlphaProcessing(); - } - return 1; -} - -//------------------------------------------------------------------------------ -// RGBA rescaling - -static int ExportRGB(WebPDecParams* const p, int y_pos) { - const WebPYUV444Converter convert = - WebPYUV444Converters[p->output->colorspace]; - const WebPRGBABuffer* const buf = &p->output->u.RGBA; - uint8_t* dst = buf->rgba + y_pos * buf->stride; - int num_lines_out = 0; - // For RGB rescaling, because of the YUV420, current scan position - // U/V can be +1/-1 line from the Y one. Hence the double test. - while (WebPRescalerHasPendingOutput(&p->scaler_y) && - WebPRescalerHasPendingOutput(&p->scaler_u)) { - assert(y_pos + num_lines_out < p->output->height); - assert(p->scaler_u.y_accum == p->scaler_v.y_accum); - WebPRescalerExportRow(&p->scaler_y); - WebPRescalerExportRow(&p->scaler_u); - WebPRescalerExportRow(&p->scaler_v); - convert(p->scaler_y.dst, p->scaler_u.dst, p->scaler_v.dst, - dst, p->scaler_y.dst_width); - dst += buf->stride; - ++num_lines_out; - } - return num_lines_out; -} - -static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) { - const int mb_h = io->mb_h; - const int uv_mb_h = (mb_h + 1) >> 1; - int j = 0, uv_j = 0; - int num_lines_out = 0; - while (j < mb_h) { - const int y_lines_in = - WebPRescalerImport(&p->scaler_y, mb_h - j, - io->y + j * io->y_stride, io->y_stride); - j += y_lines_in; - if (WebPRescaleNeededLines(&p->scaler_u, uv_mb_h - uv_j)) { - const int u_lines_in = - WebPRescalerImport(&p->scaler_u, uv_mb_h - uv_j, - io->u + uv_j * io->uv_stride, io->uv_stride); - const int v_lines_in = - WebPRescalerImport(&p->scaler_v, uv_mb_h - uv_j, - io->v + uv_j * io->uv_stride, io->uv_stride); - (void)v_lines_in; // remove a gcc warning - assert(u_lines_in == v_lines_in); - uv_j += u_lines_in; - } - num_lines_out += ExportRGB(p, p->last_y + num_lines_out); - } - return num_lines_out; -} - -static int ExportAlpha(WebPDecParams* const p, int y_pos, int max_lines_out) { - const WebPRGBABuffer* const buf = &p->output->u.RGBA; - uint8_t* const base_rgba = buf->rgba + y_pos * buf->stride; - const WEBP_CSP_MODE colorspace = p->output->colorspace; - const int alpha_first = - (colorspace == MODE_ARGB || colorspace == MODE_Argb); - uint8_t* dst = base_rgba + (alpha_first ? 0 : 3); - int num_lines_out = 0; - const int is_premult_alpha = WebPIsPremultipliedMode(colorspace); - uint32_t non_opaque = 0; - const int width = p->scaler_a.dst_width; - - while (WebPRescalerHasPendingOutput(&p->scaler_a) && - num_lines_out < max_lines_out) { - assert(y_pos + num_lines_out < p->output->height); - WebPRescalerExportRow(&p->scaler_a); - non_opaque |= WebPDispatchAlpha(p->scaler_a.dst, 0, width, 1, dst, 0); - dst += buf->stride; - ++num_lines_out; - } - if (is_premult_alpha && non_opaque) { - WebPApplyAlphaMultiply(base_rgba, alpha_first, - width, num_lines_out, buf->stride); - } - return num_lines_out; -} - -static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos, - int max_lines_out) { - const WebPRGBABuffer* const buf = &p->output->u.RGBA; - uint8_t* const base_rgba = buf->rgba + y_pos * buf->stride; -#ifdef WEBP_SWAP_16BIT_CSP - uint8_t* alpha_dst = base_rgba; -#else - uint8_t* alpha_dst = base_rgba + 1; -#endif - int num_lines_out = 0; - const WEBP_CSP_MODE colorspace = p->output->colorspace; - const int width = p->scaler_a.dst_width; - const int is_premult_alpha = WebPIsPremultipliedMode(colorspace); - uint32_t alpha_mask = 0x0f; - - while (WebPRescalerHasPendingOutput(&p->scaler_a) && - num_lines_out < max_lines_out) { - int i; - assert(y_pos + num_lines_out < p->output->height); - WebPRescalerExportRow(&p->scaler_a); - for (i = 0; i < width; ++i) { - // Fill in the alpha value (converted to 4 bits). - const uint32_t alpha_value = p->scaler_a.dst[i] >> 4; - alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value; - alpha_mask &= alpha_value; - } - alpha_dst += buf->stride; - ++num_lines_out; - } - if (is_premult_alpha && alpha_mask != 0x0f) { - WebPApplyAlphaMultiply4444(base_rgba, width, num_lines_out, buf->stride); - } - return num_lines_out; -} - -static int EmitRescaledAlphaRGB(const VP8Io* const io, WebPDecParams* const p, - int expected_num_out_lines) { - if (io->a != NULL) { - WebPRescaler* const scaler = &p->scaler_a; - int lines_left = expected_num_out_lines; - const int y_end = p->last_y + lines_left; - while (lines_left > 0) { - const int row_offset = scaler->src_y - io->mb_y; - WebPRescalerImport(scaler, io->mb_h + io->mb_y - scaler->src_y, - io->a + row_offset * io->width, io->width); - lines_left -= p->emit_alpha_row(p, y_end - lines_left, lines_left); - } - } - return 0; -} - -static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) { - const int has_alpha = WebPIsAlphaMode(p->output->colorspace); - const int out_width = io->scaled_width; - const int out_height = io->scaled_height; - const int uv_in_width = (io->mb_w + 1) >> 1; - const int uv_in_height = (io->mb_h + 1) >> 1; - const size_t work_size = 2 * out_width; // scratch memory for one rescaler - rescaler_t* work; // rescalers work area - uint8_t* tmp; // tmp storage for scaled YUV444 samples before RGB conversion - size_t tmp_size1, tmp_size2, total_size; - - tmp_size1 = 3 * work_size; - tmp_size2 = 3 * out_width; - if (has_alpha) { - tmp_size1 += work_size; - tmp_size2 += out_width; - } - total_size = tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp); - p->memory = WebPSafeMalloc(1ULL, total_size); - if (p->memory == NULL) { - return 0; // memory error - } - work = (rescaler_t*)p->memory; - tmp = (uint8_t*)(work + tmp_size1); - WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h, - tmp + 0 * out_width, out_width, out_height, 0, 1, - work + 0 * work_size); - WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height, - tmp + 1 * out_width, out_width, out_height, 0, 1, - work + 1 * work_size); - WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height, - tmp + 2 * out_width, out_width, out_height, 0, 1, - work + 2 * work_size); - p->emit = EmitRescaledRGB; - WebPInitYUV444Converters(); - - if (has_alpha) { - WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h, - tmp + 3 * out_width, out_width, out_height, 0, 1, - work + 3 * work_size); - p->emit_alpha = EmitRescaledAlphaRGB; - if (p->output->colorspace == MODE_RGBA_4444 || - p->output->colorspace == MODE_rgbA_4444) { - p->emit_alpha_row = ExportAlphaRGBA4444; - } else { - p->emit_alpha_row = ExportAlpha; - } - WebPInitAlphaProcessing(); - } - return 1; -} - -//------------------------------------------------------------------------------ -// Default custom functions - -static int CustomSetup(VP8Io* io) { - WebPDecParams* const p = (WebPDecParams*)io->opaque; - const WEBP_CSP_MODE colorspace = p->output->colorspace; - const int is_rgb = WebPIsRGBMode(colorspace); - const int is_alpha = WebPIsAlphaMode(colorspace); - - p->memory = NULL; - p->emit = NULL; - p->emit_alpha = NULL; - p->emit_alpha_row = NULL; - if (!WebPIoInitFromOptions(p->options, io, is_alpha ? MODE_YUV : MODE_YUVA)) { - return 0; - } - if (is_alpha && WebPIsPremultipliedMode(colorspace)) { - WebPInitUpsamplers(); - } - if (io->use_scaling) { - const int ok = is_rgb ? InitRGBRescaler(io, p) : InitYUVRescaler(io, p); - if (!ok) { - return 0; // memory error - } - } else { - if (is_rgb) { - WebPInitSamplers(); - p->emit = EmitSampledRGB; // default - if (io->fancy_upsampling) { -#ifdef FANCY_UPSAMPLING - const int uv_width = (io->mb_w + 1) >> 1; - p->memory = WebPSafeMalloc(1ULL, (size_t)(io->mb_w + 2 * uv_width)); - if (p->memory == NULL) { - return 0; // memory error. - } - p->tmp_y = (uint8_t*)p->memory; - p->tmp_u = p->tmp_y + io->mb_w; - p->tmp_v = p->tmp_u + uv_width; - p->emit = EmitFancyRGB; - WebPInitUpsamplers(); -#endif - } - } else { - p->emit = EmitYUV; - } - if (is_alpha) { // need transparency output - p->emit_alpha = - (colorspace == MODE_RGBA_4444 || colorspace == MODE_rgbA_4444) ? - EmitAlphaRGBA4444 - : is_rgb ? EmitAlphaRGB - : EmitAlphaYUV; - if (is_rgb) { - WebPInitAlphaProcessing(); - } - } - } - - if (is_rgb) { - VP8YUVInit(); - } - return 1; -} - -//------------------------------------------------------------------------------ - -static int CustomPut(const VP8Io* io) { - WebPDecParams* const p = (WebPDecParams*)io->opaque; - const int mb_w = io->mb_w; - const int mb_h = io->mb_h; - int num_lines_out; - assert(!(io->mb_y & 1)); - - if (mb_w <= 0 || mb_h <= 0) { - return 0; - } - num_lines_out = p->emit(io, p); - if (p->emit_alpha != NULL) { - p->emit_alpha(io, p, num_lines_out); - } - p->last_y += num_lines_out; - return 1; -} - -//------------------------------------------------------------------------------ - -static void CustomTeardown(const VP8Io* io) { - WebPDecParams* const p = (WebPDecParams*)io->opaque; - WebPSafeFree(p->memory); - p->memory = NULL; -} - -//------------------------------------------------------------------------------ -// Main entry point - -void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io) { - io->put = CustomPut; - io->setup = CustomSetup; - io->teardown = CustomTeardown; - io->opaque = params; -} - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/dec/quant.c b/Example/Pods/libwebp/src/dec/quant.c deleted file mode 100644 index 5b648f94..00000000 --- a/Example/Pods/libwebp/src/dec/quant.c +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Quantizer initialization -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./vp8i.h" - -static WEBP_INLINE int clip(int v, int M) { - return v < 0 ? 0 : v > M ? M : v; -} - -// Paragraph 14.1 -static const uint8_t kDcTable[128] = { - 4, 5, 6, 7, 8, 9, 10, 10, - 11, 12, 13, 14, 15, 16, 17, 17, - 18, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 25, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, - 37, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, - 91, 93, 95, 96, 98, 100, 101, 102, - 104, 106, 108, 110, 112, 114, 116, 118, - 122, 124, 126, 128, 130, 132, 134, 136, - 138, 140, 143, 145, 148, 151, 154, 157 -}; - -static const uint16_t kAcTable[128] = { - 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 60, - 62, 64, 66, 68, 70, 72, 74, 76, - 78, 80, 82, 84, 86, 88, 90, 92, - 94, 96, 98, 100, 102, 104, 106, 108, - 110, 112, 114, 116, 119, 122, 125, 128, - 131, 134, 137, 140, 143, 146, 149, 152, - 155, 158, 161, 164, 167, 170, 173, 177, - 181, 185, 189, 193, 197, 201, 205, 209, - 213, 217, 221, 225, 229, 234, 239, 245, - 249, 254, 259, 264, 269, 274, 279, 284 -}; - -//------------------------------------------------------------------------------ -// Paragraph 9.6 - -void VP8ParseQuant(VP8Decoder* const dec) { - VP8BitReader* const br = &dec->br_; - const int base_q0 = VP8GetValue(br, 7); - const int dqy1_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0; - const int dqy2_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0; - const int dqy2_ac = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0; - const int dquv_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0; - const int dquv_ac = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0; - - const VP8SegmentHeader* const hdr = &dec->segment_hdr_; - int i; - - for (i = 0; i < NUM_MB_SEGMENTS; ++i) { - int q; - if (hdr->use_segment_) { - q = hdr->quantizer_[i]; - if (!hdr->absolute_delta_) { - q += base_q0; - } - } else { - if (i > 0) { - dec->dqm_[i] = dec->dqm_[0]; - continue; - } else { - q = base_q0; - } - } - { - VP8QuantMatrix* const m = &dec->dqm_[i]; - m->y1_mat_[0] = kDcTable[clip(q + dqy1_dc, 127)]; - m->y1_mat_[1] = kAcTable[clip(q + 0, 127)]; - - m->y2_mat_[0] = kDcTable[clip(q + dqy2_dc, 127)] * 2; - // For all x in [0..284], x*155/100 is bitwise equal to (x*101581) >> 16. - // The smallest precision for that is '(x*6349) >> 12' but 16 is a good - // word size. - m->y2_mat_[1] = (kAcTable[clip(q + dqy2_ac, 127)] * 101581) >> 16; - if (m->y2_mat_[1] < 8) m->y2_mat_[1] = 8; - - m->uv_mat_[0] = kDcTable[clip(q + dquv_dc, 117)]; - m->uv_mat_[1] = kAcTable[clip(q + dquv_ac, 127)]; - - m->uv_quant_ = q + dquv_ac; // for dithering strength evaluation - } - } -} - -//------------------------------------------------------------------------------ - diff --git a/Example/Pods/libwebp/src/dec/tree.c b/Example/Pods/libwebp/src/dec/tree.c deleted file mode 100644 index c2007ea7..00000000 --- a/Example/Pods/libwebp/src/dec/tree.c +++ /dev/null @@ -1,525 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Coding trees and probas -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./vp8i.h" -#include "../utils/bit_reader_inl.h" - -#define USE_GENERIC_TREE - -#ifdef USE_GENERIC_TREE -static const int8_t kYModesIntra4[18] = { - -B_DC_PRED, 1, - -B_TM_PRED, 2, - -B_VE_PRED, 3, - 4, 6, - -B_HE_PRED, 5, - -B_RD_PRED, -B_VR_PRED, - -B_LD_PRED, 7, - -B_VL_PRED, 8, - -B_HD_PRED, -B_HU_PRED -}; -#endif - -//------------------------------------------------------------------------------ -// Default probabilities - -// Paragraph 13.5 -static const uint8_t - CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = { - { { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } - }, - { { 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128 }, - { 189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128 }, - { 106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128 } - }, - { { 1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128 }, - { 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128 }, - { 78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128 }, - }, - { { 1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128 }, - { 184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128 }, - { 77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128 }, - }, - { { 1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128 }, - { 170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128 }, - { 37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128 } - }, - { { 1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128 }, - { 207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128 }, - { 102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128 } - }, - { { 1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128 }, - { 177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128 }, - { 80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128 } - }, - { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } - } - }, - { { { 198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62 }, - { 131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1 }, - { 68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128 } - }, - { { 1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128 }, - { 184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128 }, - { 81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128 } - }, - { { 1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128 }, - { 99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128 }, - { 23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128 } - }, - { { 1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128 }, - { 109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128 }, - { 44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128 } - }, - { { 1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128 }, - { 94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128 }, - { 22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128 } - }, - { { 1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128 }, - { 124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128 }, - { 35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128 } - }, - { { 1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128 }, - { 121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128 }, - { 45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128 } - }, - { { 1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128 }, - { 203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128 } - } - }, - { { { 253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128 }, - { 175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128 }, - { 73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128 } - }, - { { 1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128 }, - { 239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128 }, - { 155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128 } - }, - { { 1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128 }, - { 201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128 }, - { 69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128 } - }, - { { 1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128 }, - { 141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128 } - }, - { { 1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128 }, - { 149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 } - }, - { { 1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128 } - }, - { { 1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128 } - }, - { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } - } - }, - { { { 202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255 }, - { 126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128 }, - { 61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128 } - }, - { { 1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128 }, - { 166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128 }, - { 39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128 } - }, - { { 1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128 }, - { 124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128 }, - { 24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128 } - }, - { { 1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128 }, - { 149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128 }, - { 28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128 } - }, - { { 1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128 }, - { 123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128 }, - { 20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128 } - }, - { { 1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128 }, - { 168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128 }, - { 47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128 } - }, - { { 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128 }, - { 141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128 }, - { 42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128 } - }, - { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 } - } - } -}; - -// Paragraph 11.5 -static const uint8_t kBModesProba[NUM_BMODES][NUM_BMODES][NUM_BMODES - 1] = { - { { 231, 120, 48, 89, 115, 113, 120, 152, 112 }, - { 152, 179, 64, 126, 170, 118, 46, 70, 95 }, - { 175, 69, 143, 80, 85, 82, 72, 155, 103 }, - { 56, 58, 10, 171, 218, 189, 17, 13, 152 }, - { 114, 26, 17, 163, 44, 195, 21, 10, 173 }, - { 121, 24, 80, 195, 26, 62, 44, 64, 85 }, - { 144, 71, 10, 38, 171, 213, 144, 34, 26 }, - { 170, 46, 55, 19, 136, 160, 33, 206, 71 }, - { 63, 20, 8, 114, 114, 208, 12, 9, 226 }, - { 81, 40, 11, 96, 182, 84, 29, 16, 36 } }, - { { 134, 183, 89, 137, 98, 101, 106, 165, 148 }, - { 72, 187, 100, 130, 157, 111, 32, 75, 80 }, - { 66, 102, 167, 99, 74, 62, 40, 234, 128 }, - { 41, 53, 9, 178, 241, 141, 26, 8, 107 }, - { 74, 43, 26, 146, 73, 166, 49, 23, 157 }, - { 65, 38, 105, 160, 51, 52, 31, 115, 128 }, - { 104, 79, 12, 27, 217, 255, 87, 17, 7 }, - { 87, 68, 71, 44, 114, 51, 15, 186, 23 }, - { 47, 41, 14, 110, 182, 183, 21, 17, 194 }, - { 66, 45, 25, 102, 197, 189, 23, 18, 22 } }, - { { 88, 88, 147, 150, 42, 46, 45, 196, 205 }, - { 43, 97, 183, 117, 85, 38, 35, 179, 61 }, - { 39, 53, 200, 87, 26, 21, 43, 232, 171 }, - { 56, 34, 51, 104, 114, 102, 29, 93, 77 }, - { 39, 28, 85, 171, 58, 165, 90, 98, 64 }, - { 34, 22, 116, 206, 23, 34, 43, 166, 73 }, - { 107, 54, 32, 26, 51, 1, 81, 43, 31 }, - { 68, 25, 106, 22, 64, 171, 36, 225, 114 }, - { 34, 19, 21, 102, 132, 188, 16, 76, 124 }, - { 62, 18, 78, 95, 85, 57, 50, 48, 51 } }, - { { 193, 101, 35, 159, 215, 111, 89, 46, 111 }, - { 60, 148, 31, 172, 219, 228, 21, 18, 111 }, - { 112, 113, 77, 85, 179, 255, 38, 120, 114 }, - { 40, 42, 1, 196, 245, 209, 10, 25, 109 }, - { 88, 43, 29, 140, 166, 213, 37, 43, 154 }, - { 61, 63, 30, 155, 67, 45, 68, 1, 209 }, - { 100, 80, 8, 43, 154, 1, 51, 26, 71 }, - { 142, 78, 78, 16, 255, 128, 34, 197, 171 }, - { 41, 40, 5, 102, 211, 183, 4, 1, 221 }, - { 51, 50, 17, 168, 209, 192, 23, 25, 82 } }, - { { 138, 31, 36, 171, 27, 166, 38, 44, 229 }, - { 67, 87, 58, 169, 82, 115, 26, 59, 179 }, - { 63, 59, 90, 180, 59, 166, 93, 73, 154 }, - { 40, 40, 21, 116, 143, 209, 34, 39, 175 }, - { 47, 15, 16, 183, 34, 223, 49, 45, 183 }, - { 46, 17, 33, 183, 6, 98, 15, 32, 183 }, - { 57, 46, 22, 24, 128, 1, 54, 17, 37 }, - { 65, 32, 73, 115, 28, 128, 23, 128, 205 }, - { 40, 3, 9, 115, 51, 192, 18, 6, 223 }, - { 87, 37, 9, 115, 59, 77, 64, 21, 47 } }, - { { 104, 55, 44, 218, 9, 54, 53, 130, 226 }, - { 64, 90, 70, 205, 40, 41, 23, 26, 57 }, - { 54, 57, 112, 184, 5, 41, 38, 166, 213 }, - { 30, 34, 26, 133, 152, 116, 10, 32, 134 }, - { 39, 19, 53, 221, 26, 114, 32, 73, 255 }, - { 31, 9, 65, 234, 2, 15, 1, 118, 73 }, - { 75, 32, 12, 51, 192, 255, 160, 43, 51 }, - { 88, 31, 35, 67, 102, 85, 55, 186, 85 }, - { 56, 21, 23, 111, 59, 205, 45, 37, 192 }, - { 55, 38, 70, 124, 73, 102, 1, 34, 98 } }, - { { 125, 98, 42, 88, 104, 85, 117, 175, 82 }, - { 95, 84, 53, 89, 128, 100, 113, 101, 45 }, - { 75, 79, 123, 47, 51, 128, 81, 171, 1 }, - { 57, 17, 5, 71, 102, 57, 53, 41, 49 }, - { 38, 33, 13, 121, 57, 73, 26, 1, 85 }, - { 41, 10, 67, 138, 77, 110, 90, 47, 114 }, - { 115, 21, 2, 10, 102, 255, 166, 23, 6 }, - { 101, 29, 16, 10, 85, 128, 101, 196, 26 }, - { 57, 18, 10, 102, 102, 213, 34, 20, 43 }, - { 117, 20, 15, 36, 163, 128, 68, 1, 26 } }, - { { 102, 61, 71, 37, 34, 53, 31, 243, 192 }, - { 69, 60, 71, 38, 73, 119, 28, 222, 37 }, - { 68, 45, 128, 34, 1, 47, 11, 245, 171 }, - { 62, 17, 19, 70, 146, 85, 55, 62, 70 }, - { 37, 43, 37, 154, 100, 163, 85, 160, 1 }, - { 63, 9, 92, 136, 28, 64, 32, 201, 85 }, - { 75, 15, 9, 9, 64, 255, 184, 119, 16 }, - { 86, 6, 28, 5, 64, 255, 25, 248, 1 }, - { 56, 8, 17, 132, 137, 255, 55, 116, 128 }, - { 58, 15, 20, 82, 135, 57, 26, 121, 40 } }, - { { 164, 50, 31, 137, 154, 133, 25, 35, 218 }, - { 51, 103, 44, 131, 131, 123, 31, 6, 158 }, - { 86, 40, 64, 135, 148, 224, 45, 183, 128 }, - { 22, 26, 17, 131, 240, 154, 14, 1, 209 }, - { 45, 16, 21, 91, 64, 222, 7, 1, 197 }, - { 56, 21, 39, 155, 60, 138, 23, 102, 213 }, - { 83, 12, 13, 54, 192, 255, 68, 47, 28 }, - { 85, 26, 85, 85, 128, 128, 32, 146, 171 }, - { 18, 11, 7, 63, 144, 171, 4, 4, 246 }, - { 35, 27, 10, 146, 174, 171, 12, 26, 128 } }, - { { 190, 80, 35, 99, 180, 80, 126, 54, 45 }, - { 85, 126, 47, 87, 176, 51, 41, 20, 32 }, - { 101, 75, 128, 139, 118, 146, 116, 128, 85 }, - { 56, 41, 15, 176, 236, 85, 37, 9, 62 }, - { 71, 30, 17, 119, 118, 255, 17, 18, 138 }, - { 101, 38, 60, 138, 55, 70, 43, 26, 142 }, - { 146, 36, 19, 30, 171, 255, 97, 27, 20 }, - { 138, 45, 61, 62, 219, 1, 81, 188, 64 }, - { 32, 41, 20, 117, 151, 142, 20, 21, 163 }, - { 112, 19, 12, 61, 195, 128, 48, 4, 24 } } -}; - -void VP8ResetProba(VP8Proba* const proba) { - memset(proba->segments_, 255u, sizeof(proba->segments_)); - // proba->bands_[][] is initialized later -} - -static void ParseIntraMode(VP8BitReader* const br, - VP8Decoder* const dec, int mb_x) { - uint8_t* const top = dec->intra_t_ + 4 * mb_x; - uint8_t* const left = dec->intra_l_; - VP8MBData* const block = dec->mb_data_ + mb_x; - - // Note: we don't save segment map (yet), as we don't expect - // to decode more than 1 keyframe. - if (dec->segment_hdr_.update_map_) { - // Hardcoded tree parsing - block->segment_ = !VP8GetBit(br, dec->proba_.segments_[0]) - ? VP8GetBit(br, dec->proba_.segments_[1]) - : 2 + VP8GetBit(br, dec->proba_.segments_[2]); - } else { - block->segment_ = 0; // default for intra - } - if (dec->use_skip_proba_) block->skip_ = VP8GetBit(br, dec->skip_p_); - - block->is_i4x4_ = !VP8GetBit(br, 145); // decide for B_PRED first - if (!block->is_i4x4_) { - // Hardcoded 16x16 intra-mode decision tree. - const int ymode = - VP8GetBit(br, 156) ? (VP8GetBit(br, 128) ? TM_PRED : H_PRED) - : (VP8GetBit(br, 163) ? V_PRED : DC_PRED); - block->imodes_[0] = ymode; - memset(top, ymode, 4 * sizeof(*top)); - memset(left, ymode, 4 * sizeof(*left)); - } else { - uint8_t* modes = block->imodes_; - int y; - for (y = 0; y < 4; ++y) { - int ymode = left[y]; - int x; - for (x = 0; x < 4; ++x) { - const uint8_t* const prob = kBModesProba[top[x]][ymode]; -#ifdef USE_GENERIC_TREE - // Generic tree-parsing - int i = kYModesIntra4[VP8GetBit(br, prob[0])]; - while (i > 0) { - i = kYModesIntra4[2 * i + VP8GetBit(br, prob[i])]; - } - ymode = -i; -#else - // Hardcoded tree parsing - ymode = !VP8GetBit(br, prob[0]) ? B_DC_PRED : - !VP8GetBit(br, prob[1]) ? B_TM_PRED : - !VP8GetBit(br, prob[2]) ? B_VE_PRED : - !VP8GetBit(br, prob[3]) ? - (!VP8GetBit(br, prob[4]) ? B_HE_PRED : - (!VP8GetBit(br, prob[5]) ? B_RD_PRED : B_VR_PRED)) : - (!VP8GetBit(br, prob[6]) ? B_LD_PRED : - (!VP8GetBit(br, prob[7]) ? B_VL_PRED : - (!VP8GetBit(br, prob[8]) ? B_HD_PRED : B_HU_PRED))); -#endif // USE_GENERIC_TREE - top[x] = ymode; - } - memcpy(modes, top, 4 * sizeof(*top)); - modes += 4; - left[y] = ymode; - } - } - // Hardcoded UVMode decision tree - block->uvmode_ = !VP8GetBit(br, 142) ? DC_PRED - : !VP8GetBit(br, 114) ? V_PRED - : VP8GetBit(br, 183) ? TM_PRED : H_PRED; -} - -int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec) { - int mb_x; - for (mb_x = 0; mb_x < dec->mb_w_; ++mb_x) { - ParseIntraMode(br, dec, mb_x); - } - return !dec->br_.eof_; -} - -//------------------------------------------------------------------------------ -// Paragraph 13 - -static const uint8_t - CoeffsUpdateProba[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = { - { { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255 }, - { 250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - } - }, - { { { 217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255 }, - { 234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255 } - }, - { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - } - }, - { { { 186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255 }, - { 251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255 } - }, - { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - } - }, - { { { 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255 }, - { 248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - } - } -}; - -// Paragraph 9.9 - -static const int kBands[16 + 1] = { - 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, - 0 // extra entry as sentinel -}; - -void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) { - VP8Proba* const proba = &dec->proba_; - int t, b, c, p; - for (t = 0; t < NUM_TYPES; ++t) { - for (b = 0; b < NUM_BANDS; ++b) { - for (c = 0; c < NUM_CTX; ++c) { - for (p = 0; p < NUM_PROBAS; ++p) { - const int v = VP8GetBit(br, CoeffsUpdateProba[t][b][c][p]) ? - VP8GetValue(br, 8) : CoeffsProba0[t][b][c][p]; - proba->bands_[t][b].probas_[c][p] = v; - } - } - } - for (b = 0; b < 16 + 1; ++b) { - proba->bands_ptr_[t][b] = &proba->bands_[t][kBands[b]]; - } - } - dec->use_skip_proba_ = VP8Get(br); - if (dec->use_skip_proba_) { - dec->skip_p_ = VP8GetValue(br, 8); - } -} - diff --git a/Example/Pods/libwebp/src/dec/vp8.c b/Example/Pods/libwebp/src/dec/vp8.c deleted file mode 100644 index d89eb1c5..00000000 --- a/Example/Pods/libwebp/src/dec/vp8.c +++ /dev/null @@ -1,662 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// main entry for the decoder -// -// Author: Skal (pascal.massimino@gmail.com) - -#include - -#include "./alphai.h" -#include "./vp8i.h" -#include "./vp8li.h" -#include "./webpi.h" -#include "../utils/bit_reader_inl.h" -#include "../utils/utils.h" - -//------------------------------------------------------------------------------ - -int WebPGetDecoderVersion(void) { - return (DEC_MAJ_VERSION << 16) | (DEC_MIN_VERSION << 8) | DEC_REV_VERSION; -} - -//------------------------------------------------------------------------------ -// VP8Decoder - -static void SetOk(VP8Decoder* const dec) { - dec->status_ = VP8_STATUS_OK; - dec->error_msg_ = "OK"; -} - -int VP8InitIoInternal(VP8Io* const io, int version) { - if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { - return 0; // mismatch error - } - if (io != NULL) { - memset(io, 0, sizeof(*io)); - } - return 1; -} - -VP8Decoder* VP8New(void) { - VP8Decoder* const dec = (VP8Decoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); - if (dec != NULL) { - SetOk(dec); - WebPGetWorkerInterface()->Init(&dec->worker_); - dec->ready_ = 0; - dec->num_parts_ = 1; - } - return dec; -} - -VP8StatusCode VP8Status(VP8Decoder* const dec) { - if (!dec) return VP8_STATUS_INVALID_PARAM; - return dec->status_; -} - -const char* VP8StatusMessage(VP8Decoder* const dec) { - if (dec == NULL) return "no object"; - if (!dec->error_msg_) return "OK"; - return dec->error_msg_; -} - -void VP8Delete(VP8Decoder* const dec) { - if (dec != NULL) { - VP8Clear(dec); - WebPSafeFree(dec); - } -} - -int VP8SetError(VP8Decoder* const dec, - VP8StatusCode error, const char* const msg) { - // The oldest error reported takes precedence over the new one. - if (dec->status_ == VP8_STATUS_OK) { - dec->status_ = error; - dec->error_msg_ = msg; - dec->ready_ = 0; - } - return 0; -} - -//------------------------------------------------------------------------------ - -int VP8CheckSignature(const uint8_t* const data, size_t data_size) { - return (data_size >= 3 && - data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a); -} - -int VP8GetInfo(const uint8_t* data, size_t data_size, size_t chunk_size, - int* const width, int* const height) { - if (data == NULL || data_size < VP8_FRAME_HEADER_SIZE) { - return 0; // not enough data - } - // check signature - if (!VP8CheckSignature(data + 3, data_size - 3)) { - return 0; // Wrong signature. - } else { - const uint32_t bits = data[0] | (data[1] << 8) | (data[2] << 16); - const int key_frame = !(bits & 1); - const int w = ((data[7] << 8) | data[6]) & 0x3fff; - const int h = ((data[9] << 8) | data[8]) & 0x3fff; - - if (!key_frame) { // Not a keyframe. - return 0; - } - - if (((bits >> 1) & 7) > 3) { - return 0; // unknown profile - } - if (!((bits >> 4) & 1)) { - return 0; // first frame is invisible! - } - if (((bits >> 5)) >= chunk_size) { // partition_length - return 0; // inconsistent size information. - } - if (w == 0 || h == 0) { - return 0; // We don't support both width and height to be zero. - } - - if (width) { - *width = w; - } - if (height) { - *height = h; - } - - return 1; - } -} - -//------------------------------------------------------------------------------ -// Header parsing - -static void ResetSegmentHeader(VP8SegmentHeader* const hdr) { - assert(hdr != NULL); - hdr->use_segment_ = 0; - hdr->update_map_ = 0; - hdr->absolute_delta_ = 1; - memset(hdr->quantizer_, 0, sizeof(hdr->quantizer_)); - memset(hdr->filter_strength_, 0, sizeof(hdr->filter_strength_)); -} - -// Paragraph 9.3 -static int ParseSegmentHeader(VP8BitReader* br, - VP8SegmentHeader* hdr, VP8Proba* proba) { - assert(br != NULL); - assert(hdr != NULL); - hdr->use_segment_ = VP8Get(br); - if (hdr->use_segment_) { - hdr->update_map_ = VP8Get(br); - if (VP8Get(br)) { // update data - int s; - hdr->absolute_delta_ = VP8Get(br); - for (s = 0; s < NUM_MB_SEGMENTS; ++s) { - hdr->quantizer_[s] = VP8Get(br) ? VP8GetSignedValue(br, 7) : 0; - } - for (s = 0; s < NUM_MB_SEGMENTS; ++s) { - hdr->filter_strength_[s] = VP8Get(br) ? VP8GetSignedValue(br, 6) : 0; - } - } - if (hdr->update_map_) { - int s; - for (s = 0; s < MB_FEATURE_TREE_PROBS; ++s) { - proba->segments_[s] = VP8Get(br) ? VP8GetValue(br, 8) : 255u; - } - } - } else { - hdr->update_map_ = 0; - } - return !br->eof_; -} - -// Paragraph 9.5 -// This function returns VP8_STATUS_SUSPENDED if we don't have all the -// necessary data in 'buf'. -// This case is not necessarily an error (for incremental decoding). -// Still, no bitreader is ever initialized to make it possible to read -// unavailable memory. -// If we don't even have the partitions' sizes, than VP8_STATUS_NOT_ENOUGH_DATA -// is returned, and this is an unrecoverable error. -// If the partitions were positioned ok, VP8_STATUS_OK is returned. -static VP8StatusCode ParsePartitions(VP8Decoder* const dec, - const uint8_t* buf, size_t size) { - VP8BitReader* const br = &dec->br_; - const uint8_t* sz = buf; - const uint8_t* buf_end = buf + size; - const uint8_t* part_start; - size_t size_left = size; - size_t last_part; - size_t p; - - dec->num_parts_ = 1 << VP8GetValue(br, 2); - last_part = dec->num_parts_ - 1; - if (size < 3 * last_part) { - // we can't even read the sizes with sz[]! That's a failure. - return VP8_STATUS_NOT_ENOUGH_DATA; - } - part_start = buf + last_part * 3; - size_left -= last_part * 3; - for (p = 0; p < last_part; ++p) { - size_t psize = sz[0] | (sz[1] << 8) | (sz[2] << 16); - if (psize > size_left) psize = size_left; - VP8InitBitReader(dec->parts_ + p, part_start, psize); - part_start += psize; - size_left -= psize; - sz += 3; - } - VP8InitBitReader(dec->parts_ + last_part, part_start, size_left); - return (part_start < buf_end) ? VP8_STATUS_OK : - VP8_STATUS_SUSPENDED; // Init is ok, but there's not enough data -} - -// Paragraph 9.4 -static int ParseFilterHeader(VP8BitReader* br, VP8Decoder* const dec) { - VP8FilterHeader* const hdr = &dec->filter_hdr_; - hdr->simple_ = VP8Get(br); - hdr->level_ = VP8GetValue(br, 6); - hdr->sharpness_ = VP8GetValue(br, 3); - hdr->use_lf_delta_ = VP8Get(br); - if (hdr->use_lf_delta_) { - if (VP8Get(br)) { // update lf-delta? - int i; - for (i = 0; i < NUM_REF_LF_DELTAS; ++i) { - if (VP8Get(br)) { - hdr->ref_lf_delta_[i] = VP8GetSignedValue(br, 6); - } - } - for (i = 0; i < NUM_MODE_LF_DELTAS; ++i) { - if (VP8Get(br)) { - hdr->mode_lf_delta_[i] = VP8GetSignedValue(br, 6); - } - } - } - } - dec->filter_type_ = (hdr->level_ == 0) ? 0 : hdr->simple_ ? 1 : 2; - return !br->eof_; -} - -// Topmost call -int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) { - const uint8_t* buf; - size_t buf_size; - VP8FrameHeader* frm_hdr; - VP8PictureHeader* pic_hdr; - VP8BitReader* br; - VP8StatusCode status; - - if (dec == NULL) { - return 0; - } - SetOk(dec); - if (io == NULL) { - return VP8SetError(dec, VP8_STATUS_INVALID_PARAM, - "null VP8Io passed to VP8GetHeaders()"); - } - buf = io->data; - buf_size = io->data_size; - if (buf_size < 4) { - return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, - "Truncated header."); - } - - // Paragraph 9.1 - { - const uint32_t bits = buf[0] | (buf[1] << 8) | (buf[2] << 16); - frm_hdr = &dec->frm_hdr_; - frm_hdr->key_frame_ = !(bits & 1); - frm_hdr->profile_ = (bits >> 1) & 7; - frm_hdr->show_ = (bits >> 4) & 1; - frm_hdr->partition_length_ = (bits >> 5); - if (frm_hdr->profile_ > 3) - return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, - "Incorrect keyframe parameters."); - if (!frm_hdr->show_) - return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE, - "Frame not displayable."); - buf += 3; - buf_size -= 3; - } - - pic_hdr = &dec->pic_hdr_; - if (frm_hdr->key_frame_) { - // Paragraph 9.2 - if (buf_size < 7) { - return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, - "cannot parse picture header"); - } - if (!VP8CheckSignature(buf, buf_size)) { - return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, - "Bad code word"); - } - pic_hdr->width_ = ((buf[4] << 8) | buf[3]) & 0x3fff; - pic_hdr->xscale_ = buf[4] >> 6; // ratio: 1, 5/4 5/3 or 2 - pic_hdr->height_ = ((buf[6] << 8) | buf[5]) & 0x3fff; - pic_hdr->yscale_ = buf[6] >> 6; - buf += 7; - buf_size -= 7; - - dec->mb_w_ = (pic_hdr->width_ + 15) >> 4; - dec->mb_h_ = (pic_hdr->height_ + 15) >> 4; - // Setup default output area (can be later modified during io->setup()) - io->width = pic_hdr->width_; - io->height = pic_hdr->height_; - io->use_scaling = 0; - io->use_cropping = 0; - io->crop_top = 0; - io->crop_left = 0; - io->crop_right = io->width; - io->crop_bottom = io->height; - io->mb_w = io->width; // sanity check - io->mb_h = io->height; // ditto - - VP8ResetProba(&dec->proba_); - ResetSegmentHeader(&dec->segment_hdr_); - } - - // Check if we have all the partition #0 available, and initialize dec->br_ - // to read this partition (and this partition only). - if (frm_hdr->partition_length_ > buf_size) { - return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, - "bad partition length"); - } - - br = &dec->br_; - VP8InitBitReader(br, buf, frm_hdr->partition_length_); - buf += frm_hdr->partition_length_; - buf_size -= frm_hdr->partition_length_; - - if (frm_hdr->key_frame_) { - pic_hdr->colorspace_ = VP8Get(br); - pic_hdr->clamp_type_ = VP8Get(br); - } - if (!ParseSegmentHeader(br, &dec->segment_hdr_, &dec->proba_)) { - return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, - "cannot parse segment header"); - } - // Filter specs - if (!ParseFilterHeader(br, dec)) { - return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, - "cannot parse filter header"); - } - status = ParsePartitions(dec, buf, buf_size); - if (status != VP8_STATUS_OK) { - return VP8SetError(dec, status, "cannot parse partitions"); - } - - // quantizer change - VP8ParseQuant(dec); - - // Frame buffer marking - if (!frm_hdr->key_frame_) { - return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE, - "Not a key frame."); - } - - VP8Get(br); // ignore the value of update_proba_ - - VP8ParseProba(br, dec); - - // sanitized state - dec->ready_ = 1; - return 1; -} - -//------------------------------------------------------------------------------ -// Residual decoding (Paragraph 13.2 / 13.3) - -static const uint8_t kCat3[] = { 173, 148, 140, 0 }; -static const uint8_t kCat4[] = { 176, 155, 140, 135, 0 }; -static const uint8_t kCat5[] = { 180, 157, 141, 134, 130, 0 }; -static const uint8_t kCat6[] = - { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0 }; -static const uint8_t* const kCat3456[] = { kCat3, kCat4, kCat5, kCat6 }; -static const uint8_t kZigzag[16] = { - 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 -}; - -// See section 13-2: http://tools.ietf.org/html/rfc6386#section-13.2 -static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) { - int v; - if (!VP8GetBit(br, p[3])) { - if (!VP8GetBit(br, p[4])) { - v = 2; - } else { - v = 3 + VP8GetBit(br, p[5]); - } - } else { - if (!VP8GetBit(br, p[6])) { - if (!VP8GetBit(br, p[7])) { - v = 5 + VP8GetBit(br, 159); - } else { - v = 7 + 2 * VP8GetBit(br, 165); - v += VP8GetBit(br, 145); - } - } else { - const uint8_t* tab; - const int bit1 = VP8GetBit(br, p[8]); - const int bit0 = VP8GetBit(br, p[9 + bit1]); - const int cat = 2 * bit1 + bit0; - v = 0; - for (tab = kCat3456[cat]; *tab; ++tab) { - v += v + VP8GetBit(br, *tab); - } - v += 3 + (8 << cat); - } - } - return v; -} - -// Returns the position of the last non-zero coeff plus one -static int GetCoeffs(VP8BitReader* const br, const VP8BandProbas* const prob[], - int ctx, const quant_t dq, int n, int16_t* out) { - const uint8_t* p = prob[n]->probas_[ctx]; - for (; n < 16; ++n) { - if (!VP8GetBit(br, p[0])) { - return n; // previous coeff was last non-zero coeff - } - while (!VP8GetBit(br, p[1])) { // sequence of zero coeffs - p = prob[++n]->probas_[0]; - if (n == 16) return 16; - } - { // non zero coeff - const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0]; - int v; - if (!VP8GetBit(br, p[2])) { - v = 1; - p = p_ctx[1]; - } else { - v = GetLargeValue(br, p); - p = p_ctx[2]; - } - out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0]; - } - } - return 16; -} - -static WEBP_INLINE uint32_t NzCodeBits(uint32_t nz_coeffs, int nz, int dc_nz) { - nz_coeffs <<= 2; - nz_coeffs |= (nz > 3) ? 3 : (nz > 1) ? 2 : dc_nz; - return nz_coeffs; -} - -static int ParseResiduals(VP8Decoder* const dec, - VP8MB* const mb, VP8BitReader* const token_br) { - const VP8BandProbas* (* const bands)[16 + 1] = dec->proba_.bands_ptr_; - const VP8BandProbas* const * ac_proba; - VP8MBData* const block = dec->mb_data_ + dec->mb_x_; - const VP8QuantMatrix* const q = &dec->dqm_[block->segment_]; - int16_t* dst = block->coeffs_; - VP8MB* const left_mb = dec->mb_info_ - 1; - uint8_t tnz, lnz; - uint32_t non_zero_y = 0; - uint32_t non_zero_uv = 0; - int x, y, ch; - uint32_t out_t_nz, out_l_nz; - int first; - - memset(dst, 0, 384 * sizeof(*dst)); - if (!block->is_i4x4_) { // parse DC - int16_t dc[16] = { 0 }; - const int ctx = mb->nz_dc_ + left_mb->nz_dc_; - const int nz = GetCoeffs(token_br, bands[1], ctx, q->y2_mat_, 0, dc); - mb->nz_dc_ = left_mb->nz_dc_ = (nz > 0); - if (nz > 1) { // more than just the DC -> perform the full transform - VP8TransformWHT(dc, dst); - } else { // only DC is non-zero -> inlined simplified transform - int i; - const int dc0 = (dc[0] + 3) >> 3; - for (i = 0; i < 16 * 16; i += 16) dst[i] = dc0; - } - first = 1; - ac_proba = bands[0]; - } else { - first = 0; - ac_proba = bands[3]; - } - - tnz = mb->nz_ & 0x0f; - lnz = left_mb->nz_ & 0x0f; - for (y = 0; y < 4; ++y) { - int l = lnz & 1; - uint32_t nz_coeffs = 0; - for (x = 0; x < 4; ++x) { - const int ctx = l + (tnz & 1); - const int nz = GetCoeffs(token_br, ac_proba, ctx, q->y1_mat_, first, dst); - l = (nz > first); - tnz = (tnz >> 1) | (l << 7); - nz_coeffs = NzCodeBits(nz_coeffs, nz, dst[0] != 0); - dst += 16; - } - tnz >>= 4; - lnz = (lnz >> 1) | (l << 7); - non_zero_y = (non_zero_y << 8) | nz_coeffs; - } - out_t_nz = tnz; - out_l_nz = lnz >> 4; - - for (ch = 0; ch < 4; ch += 2) { - uint32_t nz_coeffs = 0; - tnz = mb->nz_ >> (4 + ch); - lnz = left_mb->nz_ >> (4 + ch); - for (y = 0; y < 2; ++y) { - int l = lnz & 1; - for (x = 0; x < 2; ++x) { - const int ctx = l + (tnz & 1); - const int nz = GetCoeffs(token_br, bands[2], ctx, q->uv_mat_, 0, dst); - l = (nz > 0); - tnz = (tnz >> 1) | (l << 3); - nz_coeffs = NzCodeBits(nz_coeffs, nz, dst[0] != 0); - dst += 16; - } - tnz >>= 2; - lnz = (lnz >> 1) | (l << 5); - } - // Note: we don't really need the per-4x4 details for U/V blocks. - non_zero_uv |= nz_coeffs << (4 * ch); - out_t_nz |= (tnz << 4) << ch; - out_l_nz |= (lnz & 0xf0) << ch; - } - mb->nz_ = out_t_nz; - left_mb->nz_ = out_l_nz; - - block->non_zero_y_ = non_zero_y; - block->non_zero_uv_ = non_zero_uv; - - // We look at the mode-code of each block and check if some blocks have less - // than three non-zero coeffs (code < 2). This is to avoid dithering flat and - // empty blocks. - block->dither_ = (non_zero_uv & 0xaaaa) ? 0 : q->dither_; - - return !(non_zero_y | non_zero_uv); // will be used for further optimization -} - -//------------------------------------------------------------------------------ -// Main loop - -int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br) { - VP8MB* const left = dec->mb_info_ - 1; - VP8MB* const mb = dec->mb_info_ + dec->mb_x_; - VP8MBData* const block = dec->mb_data_ + dec->mb_x_; - int skip = dec->use_skip_proba_ ? block->skip_ : 0; - - if (!skip) { - skip = ParseResiduals(dec, mb, token_br); - } else { - left->nz_ = mb->nz_ = 0; - if (!block->is_i4x4_) { - left->nz_dc_ = mb->nz_dc_ = 0; - } - block->non_zero_y_ = 0; - block->non_zero_uv_ = 0; - block->dither_ = 0; - } - - if (dec->filter_type_ > 0) { // store filter info - VP8FInfo* const finfo = dec->f_info_ + dec->mb_x_; - *finfo = dec->fstrengths_[block->segment_][block->is_i4x4_]; - finfo->f_inner_ |= !skip; - } - - return !token_br->eof_; -} - -void VP8InitScanline(VP8Decoder* const dec) { - VP8MB* const left = dec->mb_info_ - 1; - left->nz_ = 0; - left->nz_dc_ = 0; - memset(dec->intra_l_, B_DC_PRED, sizeof(dec->intra_l_)); - dec->mb_x_ = 0; -} - -static int ParseFrame(VP8Decoder* const dec, VP8Io* io) { - for (dec->mb_y_ = 0; dec->mb_y_ < dec->br_mb_y_; ++dec->mb_y_) { - // Parse bitstream for this row. - VP8BitReader* const token_br = - &dec->parts_[dec->mb_y_ & (dec->num_parts_ - 1)]; - if (!VP8ParseIntraModeRow(&dec->br_, dec)) { - return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, - "Premature end-of-partition0 encountered."); - } - for (; dec->mb_x_ < dec->mb_w_; ++dec->mb_x_) { - if (!VP8DecodeMB(dec, token_br)) { - return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, - "Premature end-of-file encountered."); - } - } - VP8InitScanline(dec); // Prepare for next scanline - - // Reconstruct, filter and emit the row. - if (!VP8ProcessRow(dec, io)) { - return VP8SetError(dec, VP8_STATUS_USER_ABORT, "Output aborted."); - } - } - if (dec->mt_method_ > 0) { - if (!WebPGetWorkerInterface()->Sync(&dec->worker_)) return 0; - } - - return 1; -} - -// Main entry point -int VP8Decode(VP8Decoder* const dec, VP8Io* const io) { - int ok = 0; - if (dec == NULL) { - return 0; - } - if (io == NULL) { - return VP8SetError(dec, VP8_STATUS_INVALID_PARAM, - "NULL VP8Io parameter in VP8Decode()."); - } - - if (!dec->ready_) { - if (!VP8GetHeaders(dec, io)) { - return 0; - } - } - assert(dec->ready_); - - // Finish setting up the decoding parameter. Will call io->setup(). - ok = (VP8EnterCritical(dec, io) == VP8_STATUS_OK); - if (ok) { // good to go. - // Will allocate memory and prepare everything. - if (ok) ok = VP8InitFrame(dec, io); - - // Main decoding loop - if (ok) ok = ParseFrame(dec, io); - - // Exit. - ok &= VP8ExitCritical(dec, io); - } - - if (!ok) { - VP8Clear(dec); - return 0; - } - - dec->ready_ = 0; - return ok; -} - -void VP8Clear(VP8Decoder* const dec) { - if (dec == NULL) { - return; - } - WebPGetWorkerInterface()->End(&dec->worker_); - ALPHDelete(dec->alph_dec_); - dec->alph_dec_ = NULL; - WebPSafeFree(dec->mem_); - dec->mem_ = NULL; - dec->mem_size_ = 0; - memset(&dec->br_, 0, sizeof(dec->br_)); - dec->ready_ = 0; -} - -//------------------------------------------------------------------------------ - diff --git a/Example/Pods/libwebp/src/dec/vp8i.h b/Example/Pods/libwebp/src/dec/vp8i.h deleted file mode 100644 index 0104f255..00000000 --- a/Example/Pods/libwebp/src/dec/vp8i.h +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// VP8 decoder: internal header. -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_DEC_VP8I_H_ -#define WEBP_DEC_VP8I_H_ - -#include // for memcpy() -#include "./common.h" -#include "./vp8li.h" -#include "../utils/bit_reader.h" -#include "../utils/random.h" -#include "../utils/thread.h" -#include "../dsp/dsp.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//------------------------------------------------------------------------------ -// Various defines and enums - -// version numbers -#define DEC_MAJ_VERSION 0 -#define DEC_MIN_VERSION 5 -#define DEC_REV_VERSION 0 - -// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline). -// Constraints are: We need to store one 16x16 block of luma samples (y), -// and two 8x8 chroma blocks (u/v). These are better be 16-bytes aligned, -// in order to be SIMD-friendly. We also need to store the top, left and -// top-left samples (from previously decoded blocks), along with four -// extra top-right samples for luma (intra4x4 prediction only). -// One possible layout is, using 32 * (17 + 9) bytes: -// -// .+------ <- only 1 pixel high -// .|yyyyt. -// .|yyyyt. -// .|yyyyt. -// .|yyyy.. -// .+--.+-- <- only 1 pixel high -// .|uu.|vv -// .|uu.|vv -// -// Every character is a 4x4 block, with legend: -// '.' = unused -// 'y' = y-samples 'u' = u-samples 'v' = u-samples -// '|' = left sample, '-' = top sample, '+' = top-left sample -// 't' = extra top-right sample for 4x4 modes -#define YUV_SIZE (BPS * 17 + BPS * 9) -#define Y_SIZE (BPS * 17) -#define Y_OFF (BPS * 1 + 8) -#define U_OFF (Y_OFF + BPS * 16 + BPS) -#define V_OFF (U_OFF + 16) - -// minimal width under which lossy multi-threading is always disabled -#define MIN_WIDTH_FOR_THREADS 512 - -//------------------------------------------------------------------------------ -// Headers - -typedef struct { - uint8_t key_frame_; - uint8_t profile_; - uint8_t show_; - uint32_t partition_length_; -} VP8FrameHeader; - -typedef struct { - uint16_t width_; - uint16_t height_; - uint8_t xscale_; - uint8_t yscale_; - uint8_t colorspace_; // 0 = YCbCr - uint8_t clamp_type_; -} VP8PictureHeader; - -// segment features -typedef struct { - int use_segment_; - int update_map_; // whether to update the segment map or not - int absolute_delta_; // absolute or delta values for quantizer and filter - int8_t quantizer_[NUM_MB_SEGMENTS]; // quantization changes - int8_t filter_strength_[NUM_MB_SEGMENTS]; // filter strength for segments -} VP8SegmentHeader; - -// probas associated to one of the contexts -typedef uint8_t VP8ProbaArray[NUM_PROBAS]; - -typedef struct { // all the probas associated to one band - VP8ProbaArray probas_[NUM_CTX]; -} VP8BandProbas; - -// Struct collecting all frame-persistent probabilities. -typedef struct { - uint8_t segments_[MB_FEATURE_TREE_PROBS]; - // Type: 0:Intra16-AC 1:Intra16-DC 2:Chroma 3:Intra4 - VP8BandProbas bands_[NUM_TYPES][NUM_BANDS]; - const VP8BandProbas* bands_ptr_[NUM_TYPES][16 + 1]; -} VP8Proba; - -// Filter parameters -typedef struct { - int simple_; // 0=complex, 1=simple - int level_; // [0..63] - int sharpness_; // [0..7] - int use_lf_delta_; - int ref_lf_delta_[NUM_REF_LF_DELTAS]; - int mode_lf_delta_[NUM_MODE_LF_DELTAS]; -} VP8FilterHeader; - -//------------------------------------------------------------------------------ -// Informations about the macroblocks. - -typedef struct { // filter specs - uint8_t f_limit_; // filter limit in [3..189], or 0 if no filtering - uint8_t f_ilevel_; // inner limit in [1..63] - uint8_t f_inner_; // do inner filtering? - uint8_t hev_thresh_; // high edge variance threshold in [0..2] -} VP8FInfo; - -typedef struct { // Top/Left Contexts used for syntax-parsing - uint8_t nz_; // non-zero AC/DC coeffs (4bit for luma + 4bit for chroma) - uint8_t nz_dc_; // non-zero DC coeff (1bit) -} VP8MB; - -// Dequantization matrices -typedef int quant_t[2]; // [DC / AC]. Can be 'uint16_t[2]' too (~slower). -typedef struct { - quant_t y1_mat_, y2_mat_, uv_mat_; - - int uv_quant_; // U/V quantizer value - int dither_; // dithering amplitude (0 = off, max=255) -} VP8QuantMatrix; - -// Data needed to reconstruct a macroblock -typedef struct { - int16_t coeffs_[384]; // 384 coeffs = (16+4+4) * 4*4 - uint8_t is_i4x4_; // true if intra4x4 - uint8_t imodes_[16]; // one 16x16 mode (#0) or sixteen 4x4 modes - uint8_t uvmode_; // chroma prediction mode - // bit-wise info about the content of each sub-4x4 blocks (in decoding order). - // Each of the 4x4 blocks for y/u/v is associated with a 2b code according to: - // code=0 -> no coefficient - // code=1 -> only DC - // code=2 -> first three coefficients are non-zero - // code=3 -> more than three coefficients are non-zero - // This allows to call specialized transform functions. - uint32_t non_zero_y_; - uint32_t non_zero_uv_; - uint8_t dither_; // local dithering strength (deduced from non_zero_*) - uint8_t skip_; - uint8_t segment_; -} VP8MBData; - -// Persistent information needed by the parallel processing -typedef struct { - int id_; // cache row to process (in [0..2]) - int mb_y_; // macroblock position of the row - int filter_row_; // true if row-filtering is needed - VP8FInfo* f_info_; // filter strengths (swapped with dec->f_info_) - VP8MBData* mb_data_; // reconstruction data (swapped with dec->mb_data_) - VP8Io io_; // copy of the VP8Io to pass to put() -} VP8ThreadContext; - -// Saved top samples, per macroblock. Fits into a cache-line. -typedef struct { - uint8_t y[16], u[8], v[8]; -} VP8TopSamples; - -//------------------------------------------------------------------------------ -// VP8Decoder: the main opaque structure handed over to user - -struct VP8Decoder { - VP8StatusCode status_; - int ready_; // true if ready to decode a picture with VP8Decode() - const char* error_msg_; // set when status_ is not OK. - - // Main data source - VP8BitReader br_; - - // headers - VP8FrameHeader frm_hdr_; - VP8PictureHeader pic_hdr_; - VP8FilterHeader filter_hdr_; - VP8SegmentHeader segment_hdr_; - - // Worker - WebPWorker worker_; - int mt_method_; // multi-thread method: 0=off, 1=[parse+recon][filter] - // 2=[parse][recon+filter] - int cache_id_; // current cache row - int num_caches_; // number of cached rows of 16 pixels (1, 2 or 3) - VP8ThreadContext thread_ctx_; // Thread context - - // dimension, in macroblock units. - int mb_w_, mb_h_; - - // Macroblock to process/filter, depending on cropping and filter_type. - int tl_mb_x_, tl_mb_y_; // top-left MB that must be in-loop filtered - int br_mb_x_, br_mb_y_; // last bottom-right MB that must be decoded - - // number of partitions. - int num_parts_; - // per-partition boolean decoders. - VP8BitReader parts_[MAX_NUM_PARTITIONS]; - - // Dithering strength, deduced from decoding options - int dither_; // whether to use dithering or not - VP8Random dithering_rg_; // random generator for dithering - - // dequantization (one set of DC/AC dequant factor per segment) - VP8QuantMatrix dqm_[NUM_MB_SEGMENTS]; - - // probabilities - VP8Proba proba_; - int use_skip_proba_; - uint8_t skip_p_; - - // Boundary data cache and persistent buffers. - uint8_t* intra_t_; // top intra modes values: 4 * mb_w_ - uint8_t intra_l_[4]; // left intra modes values - - VP8TopSamples* yuv_t_; // top y/u/v samples - - VP8MB* mb_info_; // contextual macroblock info (mb_w_ + 1) - VP8FInfo* f_info_; // filter strength info - uint8_t* yuv_b_; // main block for Y/U/V (size = YUV_SIZE) - - uint8_t* cache_y_; // macroblock row for storing unfiltered samples - uint8_t* cache_u_; - uint8_t* cache_v_; - int cache_y_stride_; - int cache_uv_stride_; - - // main memory chunk for the above data. Persistent. - void* mem_; - size_t mem_size_; - - // Per macroblock non-persistent infos. - int mb_x_, mb_y_; // current position, in macroblock units - VP8MBData* mb_data_; // parsed reconstruction data - - // Filtering side-info - int filter_type_; // 0=off, 1=simple, 2=complex - VP8FInfo fstrengths_[NUM_MB_SEGMENTS][2]; // precalculated per-segment/type - - // Alpha - struct ALPHDecoder* alph_dec_; // alpha-plane decoder object - const uint8_t* alpha_data_; // compressed alpha data (if present) - size_t alpha_data_size_; - int is_alpha_decoded_; // true if alpha_data_ is decoded in alpha_plane_ - uint8_t* alpha_plane_; // output. Persistent, contains the whole data. - int alpha_dithering_; // derived from decoding options (0=off, 100=full). -}; - -//------------------------------------------------------------------------------ -// internal functions. Not public. - -// in vp8.c -int VP8SetError(VP8Decoder* const dec, - VP8StatusCode error, const char* const msg); - -// in tree.c -void VP8ResetProba(VP8Proba* const proba); -void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec); -// parses one row of intra mode data in partition 0, returns !eof -int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec); - -// in quant.c -void VP8ParseQuant(VP8Decoder* const dec); - -// in frame.c -int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io); -// Call io->setup() and finish setting up scan parameters. -// After this call returns, one must always call VP8ExitCritical() with the -// same parameters. Both functions should be used in pair. Returns VP8_STATUS_OK -// if ok, otherwise sets and returns the error status on *dec. -VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io); -// Must always be called in pair with VP8EnterCritical(). -// Returns false in case of error. -int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io); -// Return the multi-threading method to use (0=off), depending -// on options and bitstream size. Only for lossy decoding. -int VP8GetThreadMethod(const WebPDecoderOptions* const options, - const WebPHeaderStructure* const headers, - int width, int height); -// Initialize dithering post-process if needed. -void VP8InitDithering(const WebPDecoderOptions* const options, - VP8Decoder* const dec); -// Process the last decoded row (filtering + output). -int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io); -// To be called at the start of a new scanline, to initialize predictors. -void VP8InitScanline(VP8Decoder* const dec); -// Decode one macroblock. Returns false if there is not enough data. -int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br); - -// in alpha.c -const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, - int row, int num_rows); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_DEC_VP8I_H_ */ diff --git a/Example/Pods/libwebp/src/dec/vp8l.c b/Example/Pods/libwebp/src/dec/vp8l.c deleted file mode 100644 index a76ad6a1..00000000 --- a/Example/Pods/libwebp/src/dec/vp8l.c +++ /dev/null @@ -1,1627 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// main entry for the decoder -// -// Authors: Vikas Arora (vikaas.arora@gmail.com) -// Jyrki Alakuijala (jyrki@google.com) - -#include - -#include "./alphai.h" -#include "./vp8li.h" -#include "../dsp/dsp.h" -#include "../dsp/lossless.h" -#include "../dsp/yuv.h" -#include "../utils/endian_inl.h" -#include "../utils/huffman.h" -#include "../utils/utils.h" - -#define NUM_ARGB_CACHE_ROWS 16 - -static const int kCodeLengthLiterals = 16; -static const int kCodeLengthRepeatCode = 16; -static const int kCodeLengthExtraBits[3] = { 2, 3, 7 }; -static const int kCodeLengthRepeatOffsets[3] = { 3, 3, 11 }; - -// ----------------------------------------------------------------------------- -// Five Huffman codes are used at each meta code: -// 1. green + length prefix codes + color cache codes, -// 2. alpha, -// 3. red, -// 4. blue, and, -// 5. distance prefix codes. -typedef enum { - GREEN = 0, - RED = 1, - BLUE = 2, - ALPHA = 3, - DIST = 4 -} HuffIndex; - -static const uint16_t kAlphabetSize[HUFFMAN_CODES_PER_META_CODE] = { - NUM_LITERAL_CODES + NUM_LENGTH_CODES, - NUM_LITERAL_CODES, NUM_LITERAL_CODES, NUM_LITERAL_CODES, - NUM_DISTANCE_CODES -}; - -static const uint8_t kLiteralMap[HUFFMAN_CODES_PER_META_CODE] = { - 0, 1, 1, 1, 0 -}; - -#define NUM_CODE_LENGTH_CODES 19 -static const uint8_t kCodeLengthCodeOrder[NUM_CODE_LENGTH_CODES] = { - 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 -}; - -#define CODE_TO_PLANE_CODES 120 -static const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = { - 0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a, - 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a, - 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b, - 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03, - 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c, - 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e, - 0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b, - 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f, - 0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b, - 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41, - 0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f, - 0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70 -}; - -// Memory needed for lookup tables of one Huffman tree group. Red, blue, alpha -// and distance alphabets are constant (256 for red, blue and alpha, 40 for -// distance) and lookup table sizes for them in worst case are 630 and 410 -// respectively. Size of green alphabet depends on color cache size and is equal -// to 256 (green component values) + 24 (length prefix values) -// + color_cache_size (between 0 and 2048). -// All values computed for 8-bit first level lookup with Mark Adler's tool: -// http://www.hdfgroup.org/ftp/lib-external/zlib/zlib-1.2.5/examples/enough.c -#define FIXED_TABLE_SIZE (630 * 3 + 410) -static const int kTableSize[12] = { - FIXED_TABLE_SIZE + 654, - FIXED_TABLE_SIZE + 656, - FIXED_TABLE_SIZE + 658, - FIXED_TABLE_SIZE + 662, - FIXED_TABLE_SIZE + 670, - FIXED_TABLE_SIZE + 686, - FIXED_TABLE_SIZE + 718, - FIXED_TABLE_SIZE + 782, - FIXED_TABLE_SIZE + 912, - FIXED_TABLE_SIZE + 1168, - FIXED_TABLE_SIZE + 1680, - FIXED_TABLE_SIZE + 2704 -}; - -static int DecodeImageStream(int xsize, int ysize, - int is_level0, - VP8LDecoder* const dec, - uint32_t** const decoded_data); - -//------------------------------------------------------------------------------ - -int VP8LCheckSignature(const uint8_t* const data, size_t size) { - return (size >= VP8L_FRAME_HEADER_SIZE && - data[0] == VP8L_MAGIC_BYTE && - (data[4] >> 5) == 0); // version -} - -static int ReadImageInfo(VP8LBitReader* const br, - int* const width, int* const height, - int* const has_alpha) { - if (VP8LReadBits(br, 8) != VP8L_MAGIC_BYTE) return 0; - *width = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1; - *height = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1; - *has_alpha = VP8LReadBits(br, 1); - if (VP8LReadBits(br, VP8L_VERSION_BITS) != 0) return 0; - return !br->eos_; -} - -int VP8LGetInfo(const uint8_t* data, size_t data_size, - int* const width, int* const height, int* const has_alpha) { - if (data == NULL || data_size < VP8L_FRAME_HEADER_SIZE) { - return 0; // not enough data - } else if (!VP8LCheckSignature(data, data_size)) { - return 0; // bad signature - } else { - int w, h, a; - VP8LBitReader br; - VP8LInitBitReader(&br, data, data_size); - if (!ReadImageInfo(&br, &w, &h, &a)) { - return 0; - } - if (width != NULL) *width = w; - if (height != NULL) *height = h; - if (has_alpha != NULL) *has_alpha = a; - return 1; - } -} - -//------------------------------------------------------------------------------ - -static WEBP_INLINE int GetCopyDistance(int distance_symbol, - VP8LBitReader* const br) { - int extra_bits, offset; - if (distance_symbol < 4) { - return distance_symbol + 1; - } - extra_bits = (distance_symbol - 2) >> 1; - offset = (2 + (distance_symbol & 1)) << extra_bits; - return offset + VP8LReadBits(br, extra_bits) + 1; -} - -static WEBP_INLINE int GetCopyLength(int length_symbol, - VP8LBitReader* const br) { - // Length and distance prefixes are encoded the same way. - return GetCopyDistance(length_symbol, br); -} - -static WEBP_INLINE int PlaneCodeToDistance(int xsize, int plane_code) { - if (plane_code > CODE_TO_PLANE_CODES) { - return plane_code - CODE_TO_PLANE_CODES; - } else { - const int dist_code = kCodeToPlane[plane_code - 1]; - const int yoffset = dist_code >> 4; - const int xoffset = 8 - (dist_code & 0xf); - const int dist = yoffset * xsize + xoffset; - return (dist >= 1) ? dist : 1; // dist<1 can happen if xsize is very small - } -} - -//------------------------------------------------------------------------------ -// Decodes the next Huffman code from bit-stream. -// FillBitWindow(br) needs to be called at minimum every second call -// to ReadSymbol, in order to pre-fetch enough bits. -static WEBP_INLINE int ReadSymbol(const HuffmanCode* table, - VP8LBitReader* const br) { - int nbits; - uint32_t val = VP8LPrefetchBits(br); - table += val & HUFFMAN_TABLE_MASK; - nbits = table->bits - HUFFMAN_TABLE_BITS; - if (nbits > 0) { - VP8LSetBitPos(br, br->bit_pos_ + HUFFMAN_TABLE_BITS); - val = VP8LPrefetchBits(br); - table += table->value; - table += val & ((1 << nbits) - 1); - } - VP8LSetBitPos(br, br->bit_pos_ + table->bits); - return table->value; -} - -// Reads packed symbol depending on GREEN channel -#define BITS_SPECIAL_MARKER 0x100 // something large enough (and a bit-mask) -#define PACKED_NON_LITERAL_CODE 0 // must be < NUM_LITERAL_CODES -static WEBP_INLINE int ReadPackedSymbols(const HTreeGroup* group, - VP8LBitReader* const br, - uint32_t* const dst) { - const uint32_t val = VP8LPrefetchBits(br) & (HUFFMAN_PACKED_TABLE_SIZE - 1); - const HuffmanCode32 code = group->packed_table[val]; - assert(group->use_packed_table); - if (code.bits < BITS_SPECIAL_MARKER) { - VP8LSetBitPos(br, br->bit_pos_ + code.bits); - *dst = code.value; - return PACKED_NON_LITERAL_CODE; - } else { - VP8LSetBitPos(br, br->bit_pos_ + code.bits - BITS_SPECIAL_MARKER); - assert(code.value >= NUM_LITERAL_CODES); - return code.value; - } -} - -static int AccumulateHCode(HuffmanCode hcode, int shift, - HuffmanCode32* const huff) { - huff->bits += hcode.bits; - huff->value |= (uint32_t)hcode.value << shift; - assert(huff->bits <= HUFFMAN_TABLE_BITS); - return hcode.bits; -} - -static void BuildPackedTable(HTreeGroup* const htree_group) { - uint32_t code; - for (code = 0; code < HUFFMAN_PACKED_TABLE_SIZE; ++code) { - uint32_t bits = code; - HuffmanCode32* const huff = &htree_group->packed_table[bits]; - HuffmanCode hcode = htree_group->htrees[GREEN][bits]; - if (hcode.value >= NUM_LITERAL_CODES) { - huff->bits = hcode.bits + BITS_SPECIAL_MARKER; - huff->value = hcode.value; - } else { - huff->bits = 0; - huff->value = 0; - bits >>= AccumulateHCode(hcode, 8, huff); - bits >>= AccumulateHCode(htree_group->htrees[RED][bits], 16, huff); - bits >>= AccumulateHCode(htree_group->htrees[BLUE][bits], 0, huff); - bits >>= AccumulateHCode(htree_group->htrees[ALPHA][bits], 24, huff); - (void)bits; - } - } -} - -static int ReadHuffmanCodeLengths( - VP8LDecoder* const dec, const int* const code_length_code_lengths, - int num_symbols, int* const code_lengths) { - int ok = 0; - VP8LBitReader* const br = &dec->br_; - int symbol; - int max_symbol; - int prev_code_len = DEFAULT_CODE_LENGTH; - HuffmanCode table[1 << LENGTHS_TABLE_BITS]; - - if (!VP8LBuildHuffmanTable(table, LENGTHS_TABLE_BITS, - code_length_code_lengths, - NUM_CODE_LENGTH_CODES)) { - goto End; - } - - if (VP8LReadBits(br, 1)) { // use length - const int length_nbits = 2 + 2 * VP8LReadBits(br, 3); - max_symbol = 2 + VP8LReadBits(br, length_nbits); - if (max_symbol > num_symbols) { - goto End; - } - } else { - max_symbol = num_symbols; - } - - symbol = 0; - while (symbol < num_symbols) { - const HuffmanCode* p; - int code_len; - if (max_symbol-- == 0) break; - VP8LFillBitWindow(br); - p = &table[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK]; - VP8LSetBitPos(br, br->bit_pos_ + p->bits); - code_len = p->value; - if (code_len < kCodeLengthLiterals) { - code_lengths[symbol++] = code_len; - if (code_len != 0) prev_code_len = code_len; - } else { - const int use_prev = (code_len == kCodeLengthRepeatCode); - const int slot = code_len - kCodeLengthLiterals; - const int extra_bits = kCodeLengthExtraBits[slot]; - const int repeat_offset = kCodeLengthRepeatOffsets[slot]; - int repeat = VP8LReadBits(br, extra_bits) + repeat_offset; - if (symbol + repeat > num_symbols) { - goto End; - } else { - const int length = use_prev ? prev_code_len : 0; - while (repeat-- > 0) code_lengths[symbol++] = length; - } - } - } - ok = 1; - - End: - if (!ok) dec->status_ = VP8_STATUS_BITSTREAM_ERROR; - return ok; -} - -// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman -// tree. -static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec, - int* const code_lengths, HuffmanCode* const table) { - int ok = 0; - int size = 0; - VP8LBitReader* const br = &dec->br_; - const int simple_code = VP8LReadBits(br, 1); - - memset(code_lengths, 0, alphabet_size * sizeof(*code_lengths)); - - if (simple_code) { // Read symbols, codes & code lengths directly. - const int num_symbols = VP8LReadBits(br, 1) + 1; - const int first_symbol_len_code = VP8LReadBits(br, 1); - // The first code is either 1 bit or 8 bit code. - int symbol = VP8LReadBits(br, (first_symbol_len_code == 0) ? 1 : 8); - code_lengths[symbol] = 1; - // The second code (if present), is always 8 bit long. - if (num_symbols == 2) { - symbol = VP8LReadBits(br, 8); - code_lengths[symbol] = 1; - } - ok = 1; - } else { // Decode Huffman-coded code lengths. - int i; - int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 }; - const int num_codes = VP8LReadBits(br, 4) + 4; - if (num_codes > NUM_CODE_LENGTH_CODES) { - dec->status_ = VP8_STATUS_BITSTREAM_ERROR; - return 0; - } - - for (i = 0; i < num_codes; ++i) { - code_length_code_lengths[kCodeLengthCodeOrder[i]] = VP8LReadBits(br, 3); - } - ok = ReadHuffmanCodeLengths(dec, code_length_code_lengths, alphabet_size, - code_lengths); - } - - ok = ok && !br->eos_; - if (ok) { - size = VP8LBuildHuffmanTable(table, HUFFMAN_TABLE_BITS, - code_lengths, alphabet_size); - } - if (!ok || size == 0) { - dec->status_ = VP8_STATUS_BITSTREAM_ERROR; - return 0; - } - return size; -} - -static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, - int color_cache_bits, int allow_recursion) { - int i, j; - VP8LBitReader* const br = &dec->br_; - VP8LMetadata* const hdr = &dec->hdr_; - uint32_t* huffman_image = NULL; - HTreeGroup* htree_groups = NULL; - HuffmanCode* huffman_tables = NULL; - HuffmanCode* next = NULL; - int num_htree_groups = 1; - int max_alphabet_size = 0; - int* code_lengths = NULL; - const int table_size = kTableSize[color_cache_bits]; - - if (allow_recursion && VP8LReadBits(br, 1)) { - // use meta Huffman codes. - const int huffman_precision = VP8LReadBits(br, 3) + 2; - const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision); - const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision); - const int huffman_pixs = huffman_xsize * huffman_ysize; - if (!DecodeImageStream(huffman_xsize, huffman_ysize, 0, dec, - &huffman_image)) { - goto Error; - } - hdr->huffman_subsample_bits_ = huffman_precision; - for (i = 0; i < huffman_pixs; ++i) { - // The huffman data is stored in red and green bytes. - const int group = (huffman_image[i] >> 8) & 0xffff; - huffman_image[i] = group; - if (group >= num_htree_groups) { - num_htree_groups = group + 1; - } - } - } - - if (br->eos_) goto Error; - - // Find maximum alphabet size for the htree group. - for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { - int alphabet_size = kAlphabetSize[j]; - if (j == 0 && color_cache_bits > 0) { - alphabet_size += 1 << color_cache_bits; - } - if (max_alphabet_size < alphabet_size) { - max_alphabet_size = alphabet_size; - } - } - - huffman_tables = (HuffmanCode*)WebPSafeMalloc(num_htree_groups * table_size, - sizeof(*huffman_tables)); - htree_groups = VP8LHtreeGroupsNew(num_htree_groups); - code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size, - sizeof(*code_lengths)); - - if (htree_groups == NULL || code_lengths == NULL || huffman_tables == NULL) { - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; - goto Error; - } - - next = huffman_tables; - for (i = 0; i < num_htree_groups; ++i) { - HTreeGroup* const htree_group = &htree_groups[i]; - HuffmanCode** const htrees = htree_group->htrees; - int size; - int total_size = 0; - int is_trivial_literal = 1; - int max_bits = 0; - for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { - int alphabet_size = kAlphabetSize[j]; - htrees[j] = next; - if (j == 0 && color_cache_bits > 0) { - alphabet_size += 1 << color_cache_bits; - } - size = ReadHuffmanCode(alphabet_size, dec, code_lengths, next); - if (size == 0) { - goto Error; - } - if (is_trivial_literal && kLiteralMap[j] == 1) { - is_trivial_literal = (next->bits == 0); - } - total_size += next->bits; - next += size; - if (j <= ALPHA) { - int local_max_bits = code_lengths[0]; - int k; - for (k = 1; k < alphabet_size; ++k) { - if (code_lengths[k] > local_max_bits) { - local_max_bits = code_lengths[k]; - } - } - max_bits += local_max_bits; - } - } - htree_group->is_trivial_literal = is_trivial_literal; - htree_group->is_trivial_code = 0; - if (is_trivial_literal) { - const int red = htrees[RED][0].value; - const int blue = htrees[BLUE][0].value; - const int alpha = htrees[ALPHA][0].value; - htree_group->literal_arb = - ((uint32_t)alpha << 24) | (red << 16) | blue; - if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) { - htree_group->is_trivial_code = 1; - htree_group->literal_arb |= htrees[GREEN][0].value << 8; - } - } - htree_group->use_packed_table = !htree_group->is_trivial_code && - (max_bits < HUFFMAN_PACKED_BITS); - if (htree_group->use_packed_table) BuildPackedTable(htree_group); - } - WebPSafeFree(code_lengths); - - // All OK. Finalize pointers and return. - hdr->huffman_image_ = huffman_image; - hdr->num_htree_groups_ = num_htree_groups; - hdr->htree_groups_ = htree_groups; - hdr->huffman_tables_ = huffman_tables; - return 1; - - Error: - WebPSafeFree(code_lengths); - WebPSafeFree(huffman_image); - WebPSafeFree(huffman_tables); - VP8LHtreeGroupsFree(htree_groups); - return 0; -} - -//------------------------------------------------------------------------------ -// Scaling. - -static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) { - const int num_channels = 4; - const int in_width = io->mb_w; - const int out_width = io->scaled_width; - const int in_height = io->mb_h; - const int out_height = io->scaled_height; - const uint64_t work_size = 2 * num_channels * (uint64_t)out_width; - rescaler_t* work; // Rescaler work area. - const uint64_t scaled_data_size = (uint64_t)out_width; - uint32_t* scaled_data; // Temporary storage for scaled BGRA data. - const uint64_t memory_size = sizeof(*dec->rescaler) + - work_size * sizeof(*work) + - scaled_data_size * sizeof(*scaled_data); - uint8_t* memory = (uint8_t*)WebPSafeMalloc(memory_size, sizeof(*memory)); - if (memory == NULL) { - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; - return 0; - } - assert(dec->rescaler_memory == NULL); - dec->rescaler_memory = memory; - - dec->rescaler = (WebPRescaler*)memory; - memory += sizeof(*dec->rescaler); - work = (rescaler_t*)memory; - memory += work_size * sizeof(*work); - scaled_data = (uint32_t*)memory; - - WebPRescalerInit(dec->rescaler, in_width, in_height, (uint8_t*)scaled_data, - out_width, out_height, 0, num_channels, work); - return 1; -} - -//------------------------------------------------------------------------------ -// Export to ARGB - -// We have special "export" function since we need to convert from BGRA -static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace, - int rgba_stride, uint8_t* const rgba) { - uint32_t* const src = (uint32_t*)rescaler->dst; - const int dst_width = rescaler->dst_width; - int num_lines_out = 0; - while (WebPRescalerHasPendingOutput(rescaler)) { - uint8_t* const dst = rgba + num_lines_out * rgba_stride; - WebPRescalerExportRow(rescaler); - WebPMultARGBRow(src, dst_width, 1); - VP8LConvertFromBGRA(src, dst_width, colorspace, dst); - ++num_lines_out; - } - return num_lines_out; -} - -// Emit scaled rows. -static int EmitRescaledRowsRGBA(const VP8LDecoder* const dec, - uint8_t* in, int in_stride, int mb_h, - uint8_t* const out, int out_stride) { - const WEBP_CSP_MODE colorspace = dec->output_->colorspace; - int num_lines_in = 0; - int num_lines_out = 0; - while (num_lines_in < mb_h) { - uint8_t* const row_in = in + num_lines_in * in_stride; - uint8_t* const row_out = out + num_lines_out * out_stride; - const int lines_left = mb_h - num_lines_in; - const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left); - assert(needed_lines > 0 && needed_lines <= lines_left); - WebPMultARGBRows(row_in, in_stride, - dec->rescaler->src_width, needed_lines, 0); - WebPRescalerImport(dec->rescaler, lines_left, row_in, in_stride); - num_lines_in += needed_lines; - num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out); - } - return num_lines_out; -} - -// Emit rows without any scaling. -static int EmitRows(WEBP_CSP_MODE colorspace, - const uint8_t* row_in, int in_stride, - int mb_w, int mb_h, - uint8_t* const out, int out_stride) { - int lines = mb_h; - uint8_t* row_out = out; - while (lines-- > 0) { - VP8LConvertFromBGRA((const uint32_t*)row_in, mb_w, colorspace, row_out); - row_in += in_stride; - row_out += out_stride; - } - return mb_h; // Num rows out == num rows in. -} - -//------------------------------------------------------------------------------ -// Export to YUVA - -static void ConvertToYUVA(const uint32_t* const src, int width, int y_pos, - const WebPDecBuffer* const output) { - const WebPYUVABuffer* const buf = &output->u.YUVA; - - // first, the luma plane - WebPConvertARGBToY(src, buf->y + y_pos * buf->y_stride, width); - - // then U/V planes - { - uint8_t* const u = buf->u + (y_pos >> 1) * buf->u_stride; - uint8_t* const v = buf->v + (y_pos >> 1) * buf->v_stride; - // even lines: store values - // odd lines: average with previous values - WebPConvertARGBToUV(src, u, v, width, !(y_pos & 1)); - } - // Lastly, store alpha if needed. - if (buf->a != NULL) { - uint8_t* const a = buf->a + y_pos * buf->a_stride; -#if defined(WORDS_BIGENDIAN) - WebPExtractAlpha((uint8_t*)src + 0, 0, width, 1, a, 0); -#else - WebPExtractAlpha((uint8_t*)src + 3, 0, width, 1, a, 0); -#endif - } -} - -static int ExportYUVA(const VP8LDecoder* const dec, int y_pos) { - WebPRescaler* const rescaler = dec->rescaler; - uint32_t* const src = (uint32_t*)rescaler->dst; - const int dst_width = rescaler->dst_width; - int num_lines_out = 0; - while (WebPRescalerHasPendingOutput(rescaler)) { - WebPRescalerExportRow(rescaler); - WebPMultARGBRow(src, dst_width, 1); - ConvertToYUVA(src, dst_width, y_pos, dec->output_); - ++y_pos; - ++num_lines_out; - } - return num_lines_out; -} - -static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec, - uint8_t* in, int in_stride, int mb_h) { - int num_lines_in = 0; - int y_pos = dec->last_out_row_; - while (num_lines_in < mb_h) { - const int lines_left = mb_h - num_lines_in; - const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left); - WebPMultARGBRows(in, in_stride, dec->rescaler->src_width, needed_lines, 0); - WebPRescalerImport(dec->rescaler, lines_left, in, in_stride); - num_lines_in += needed_lines; - in += needed_lines * in_stride; - y_pos += ExportYUVA(dec, y_pos); - } - return y_pos; -} - -static int EmitRowsYUVA(const VP8LDecoder* const dec, - const uint8_t* in, int in_stride, - int mb_w, int num_rows) { - int y_pos = dec->last_out_row_; - while (num_rows-- > 0) { - ConvertToYUVA((const uint32_t*)in, mb_w, y_pos, dec->output_); - in += in_stride; - ++y_pos; - } - return y_pos; -} - -//------------------------------------------------------------------------------ -// Cropping. - -// Sets io->mb_y, io->mb_h & io->mb_w according to start row, end row and -// crop options. Also updates the input data pointer, so that it points to the -// start of the cropped window. Note that pixels are in ARGB format even if -// 'in_data' is uint8_t*. -// Returns true if the crop window is not empty. -static int SetCropWindow(VP8Io* const io, int y_start, int y_end, - uint8_t** const in_data, int pixel_stride) { - assert(y_start < y_end); - assert(io->crop_left < io->crop_right); - if (y_end > io->crop_bottom) { - y_end = io->crop_bottom; // make sure we don't overflow on last row. - } - if (y_start < io->crop_top) { - const int delta = io->crop_top - y_start; - y_start = io->crop_top; - *in_data += delta * pixel_stride; - } - if (y_start >= y_end) return 0; // Crop window is empty. - - *in_data += io->crop_left * sizeof(uint32_t); - - io->mb_y = y_start - io->crop_top; - io->mb_w = io->crop_right - io->crop_left; - io->mb_h = y_end - y_start; - return 1; // Non-empty crop window. -} - -//------------------------------------------------------------------------------ - -static WEBP_INLINE int GetMetaIndex( - const uint32_t* const image, int xsize, int bits, int x, int y) { - if (bits == 0) return 0; - return image[xsize * (y >> bits) + (x >> bits)]; -} - -static WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr, - int x, int y) { - const int meta_index = GetMetaIndex(hdr->huffman_image_, hdr->huffman_xsize_, - hdr->huffman_subsample_bits_, x, y); - assert(meta_index < hdr->num_htree_groups_); - return hdr->htree_groups_ + meta_index; -} - -//------------------------------------------------------------------------------ -// Main loop, with custom row-processing function - -typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row); - -static void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows, - const uint32_t* const rows) { - int n = dec->next_transform_; - const int cache_pixs = dec->width_ * num_rows; - const int start_row = dec->last_row_; - const int end_row = start_row + num_rows; - const uint32_t* rows_in = rows; - uint32_t* const rows_out = dec->argb_cache_; - - // Inverse transforms. - // TODO: most transforms only need to operate on the cropped region only. - memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out)); - while (n-- > 0) { - VP8LTransform* const transform = &dec->transforms_[n]; - VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out); - rows_in = rows_out; - } -} - -// Special method for paletted alpha data. -static void ApplyInverseTransformsAlpha(VP8LDecoder* const dec, int num_rows, - const uint8_t* const rows) { - const int start_row = dec->last_row_; - const int end_row = start_row + num_rows; - const uint8_t* rows_in = rows; - uint8_t* rows_out = (uint8_t*)dec->io_->opaque + dec->io_->width * start_row; - VP8LTransform* const transform = &dec->transforms_[0]; - assert(dec->next_transform_ == 1); - assert(transform->type_ == COLOR_INDEXING_TRANSFORM); - VP8LColorIndexInverseTransformAlpha(transform, start_row, end_row, rows_in, - rows_out); -} - -// Processes (transforms, scales & color-converts) the rows decoded after the -// last call. -static void ProcessRows(VP8LDecoder* const dec, int row) { - const uint32_t* const rows = dec->pixels_ + dec->width_ * dec->last_row_; - const int num_rows = row - dec->last_row_; - - if (num_rows <= 0) return; // Nothing to be done. - ApplyInverseTransforms(dec, num_rows, rows); - - // Emit output. - { - VP8Io* const io = dec->io_; - uint8_t* rows_data = (uint8_t*)dec->argb_cache_; - const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA - if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) { - // Nothing to output (this time). - } else { - const WebPDecBuffer* const output = dec->output_; - if (WebPIsRGBMode(output->colorspace)) { // convert to RGBA - const WebPRGBABuffer* const buf = &output->u.RGBA; - uint8_t* const rgba = buf->rgba + dec->last_out_row_ * buf->stride; - const int num_rows_out = io->use_scaling ? - EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h, - rgba, buf->stride) : - EmitRows(output->colorspace, rows_data, in_stride, - io->mb_w, io->mb_h, rgba, buf->stride); - // Update 'last_out_row_'. - dec->last_out_row_ += num_rows_out; - } else { // convert to YUVA - dec->last_out_row_ = io->use_scaling ? - EmitRescaledRowsYUVA(dec, rows_data, in_stride, io->mb_h) : - EmitRowsYUVA(dec, rows_data, in_stride, io->mb_w, io->mb_h); - } - assert(dec->last_out_row_ <= output->height); - } - } - - // Update 'last_row_'. - dec->last_row_ = row; - assert(dec->last_row_ <= dec->height_); -} - -// Row-processing for the special case when alpha data contains only one -// transform (color indexing), and trivial non-green literals. -static int Is8bOptimizable(const VP8LMetadata* const hdr) { - int i; - if (hdr->color_cache_size_ > 0) return 0; - // When the Huffman tree contains only one symbol, we can skip the - // call to ReadSymbol() for red/blue/alpha channels. - for (i = 0; i < hdr->num_htree_groups_; ++i) { - HuffmanCode** const htrees = hdr->htree_groups_[i].htrees; - if (htrees[RED][0].bits > 0) return 0; - if (htrees[BLUE][0].bits > 0) return 0; - if (htrees[ALPHA][0].bits > 0) return 0; - } - return 1; -} - -static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int row) { - const int num_rows = row - dec->last_row_; - const uint8_t* const in = - (uint8_t*)dec->pixels_ + dec->width_ * dec->last_row_; - if (num_rows > 0) { - ApplyInverseTransformsAlpha(dec, num_rows, in); - } - dec->last_row_ = dec->last_out_row_ = row; -} - -//------------------------------------------------------------------------------ -// Helper functions for fast pattern copy (8b and 32b) - -// cyclic rotation of pattern word -static WEBP_INLINE uint32_t Rotate8b(uint32_t V) { -#if defined(WORDS_BIGENDIAN) - return ((V & 0xff000000u) >> 24) | (V << 8); -#else - return ((V & 0xffu) << 24) | (V >> 8); -#endif -} - -// copy 1, 2 or 4-bytes pattern -static WEBP_INLINE void CopySmallPattern8b(const uint8_t* src, uint8_t* dst, - int length, uint32_t pattern) { - int i; - // align 'dst' to 4-bytes boundary. Adjust the pattern along the way. - while ((uintptr_t)dst & 3) { - *dst++ = *src++; - pattern = Rotate8b(pattern); - --length; - } - // Copy the pattern 4 bytes at a time. - for (i = 0; i < (length >> 2); ++i) { - ((uint32_t*)dst)[i] = pattern; - } - // Finish with left-overs. 'pattern' is still correctly positioned, - // so no Rotate8b() call is needed. - for (i <<= 2; i < length; ++i) { - dst[i] = src[i]; - } -} - -static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) { - const uint8_t* src = dst - dist; - if (length >= 8) { - uint32_t pattern = 0; - switch (dist) { - case 1: - pattern = src[0]; -#if defined(__arm__) || defined(_M_ARM) // arm doesn't like multiply that much - pattern |= pattern << 8; - pattern |= pattern << 16; -#elif defined(WEBP_USE_MIPS_DSP_R2) - __asm__ volatile ("replv.qb %0, %0" : "+r"(pattern)); -#else - pattern = 0x01010101u * pattern; -#endif - break; - case 2: - memcpy(&pattern, src, sizeof(uint16_t)); -#if defined(__arm__) || defined(_M_ARM) - pattern |= pattern << 16; -#elif defined(WEBP_USE_MIPS_DSP_R2) - __asm__ volatile ("replv.ph %0, %0" : "+r"(pattern)); -#else - pattern = 0x00010001u * pattern; -#endif - break; - case 4: - memcpy(&pattern, src, sizeof(uint32_t)); - break; - default: - goto Copy; - break; - } - CopySmallPattern8b(src, dst, length, pattern); - return; - } - Copy: - if (dist >= length) { // no overlap -> use memcpy() - memcpy(dst, src, length * sizeof(*dst)); - } else { - int i; - for (i = 0; i < length; ++i) dst[i] = src[i]; - } -} - -// copy pattern of 1 or 2 uint32_t's -static WEBP_INLINE void CopySmallPattern32b(const uint32_t* src, - uint32_t* dst, - int length, uint64_t pattern) { - int i; - if ((uintptr_t)dst & 4) { // Align 'dst' to 8-bytes boundary. - *dst++ = *src++; - pattern = (pattern >> 32) | (pattern << 32); - --length; - } - assert(0 == ((uintptr_t)dst & 7)); - for (i = 0; i < (length >> 1); ++i) { - ((uint64_t*)dst)[i] = pattern; // Copy the pattern 8 bytes at a time. - } - if (length & 1) { // Finish with left-over. - dst[i << 1] = src[i << 1]; - } -} - -static WEBP_INLINE void CopyBlock32b(uint32_t* const dst, - int dist, int length) { - const uint32_t* const src = dst - dist; - if (dist <= 2 && length >= 4 && ((uintptr_t)dst & 3) == 0) { - uint64_t pattern; - if (dist == 1) { - pattern = (uint64_t)src[0]; - pattern |= pattern << 32; - } else { - memcpy(&pattern, src, sizeof(pattern)); - } - CopySmallPattern32b(src, dst, length, pattern); - } else if (dist >= length) { // no overlap - memcpy(dst, src, length * sizeof(*dst)); - } else { - int i; - for (i = 0; i < length; ++i) dst[i] = src[i]; - } -} - -//------------------------------------------------------------------------------ - -static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data, - int width, int height, int last_row) { - int ok = 1; - int row = dec->last_pixel_ / width; - int col = dec->last_pixel_ % width; - VP8LBitReader* const br = &dec->br_; - VP8LMetadata* const hdr = &dec->hdr_; - const HTreeGroup* htree_group = GetHtreeGroupForPos(hdr, col, row); - int pos = dec->last_pixel_; // current position - const int end = width * height; // End of data - const int last = width * last_row; // Last pixel to decode - const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES; - const int mask = hdr->huffman_mask_; - assert(htree_group != NULL); - assert(pos < end); - assert(last_row <= height); - assert(Is8bOptimizable(hdr)); - - while (!br->eos_ && pos < last) { - int code; - // Only update when changing tile. - if ((col & mask) == 0) { - htree_group = GetHtreeGroupForPos(hdr, col, row); - } - VP8LFillBitWindow(br); - code = ReadSymbol(htree_group->htrees[GREEN], br); - if (code < NUM_LITERAL_CODES) { // Literal - data[pos] = code; - ++pos; - ++col; - if (col >= width) { - col = 0; - ++row; - if (row % NUM_ARGB_CACHE_ROWS == 0) { - ExtractPalettedAlphaRows(dec, row); - } - } - } else if (code < len_code_limit) { // Backward reference - int dist_code, dist; - const int length_sym = code - NUM_LITERAL_CODES; - const int length = GetCopyLength(length_sym, br); - const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br); - VP8LFillBitWindow(br); - dist_code = GetCopyDistance(dist_symbol, br); - dist = PlaneCodeToDistance(width, dist_code); - if (pos >= dist && end - pos >= length) { - CopyBlock8b(data + pos, dist, length); - } else { - ok = 0; - goto End; - } - pos += length; - col += length; - while (col >= width) { - col -= width; - ++row; - if (row % NUM_ARGB_CACHE_ROWS == 0) { - ExtractPalettedAlphaRows(dec, row); - } - } - if (pos < last && (col & mask)) { - htree_group = GetHtreeGroupForPos(hdr, col, row); - } - } else { // Not reached - ok = 0; - goto End; - } - assert(br->eos_ == VP8LIsEndOfStream(br)); - } - // Process the remaining rows corresponding to last row-block. - ExtractPalettedAlphaRows(dec, row); - - End: - if (!ok || (br->eos_ && pos < end)) { - ok = 0; - dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED - : VP8_STATUS_BITSTREAM_ERROR; - } else { - dec->last_pixel_ = pos; - } - return ok; -} - -static void SaveState(VP8LDecoder* const dec, int last_pixel) { - assert(dec->incremental_); - dec->saved_br_ = dec->br_; - dec->saved_last_pixel_ = last_pixel; - if (dec->hdr_.color_cache_size_ > 0) { - VP8LColorCacheCopy(&dec->hdr_.color_cache_, &dec->hdr_.saved_color_cache_); - } -} - -static void RestoreState(VP8LDecoder* const dec) { - assert(dec->br_.eos_); - dec->status_ = VP8_STATUS_SUSPENDED; - dec->br_ = dec->saved_br_; - dec->last_pixel_ = dec->saved_last_pixel_; - if (dec->hdr_.color_cache_size_ > 0) { - VP8LColorCacheCopy(&dec->hdr_.saved_color_cache_, &dec->hdr_.color_cache_); - } -} - -#define SYNC_EVERY_N_ROWS 8 // minimum number of rows between check-points -static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, - int width, int height, int last_row, - ProcessRowsFunc process_func) { - int row = dec->last_pixel_ / width; - int col = dec->last_pixel_ % width; - VP8LBitReader* const br = &dec->br_; - VP8LMetadata* const hdr = &dec->hdr_; - HTreeGroup* htree_group = GetHtreeGroupForPos(hdr, col, row); - uint32_t* src = data + dec->last_pixel_; - uint32_t* last_cached = src; - uint32_t* const src_end = data + width * height; // End of data - uint32_t* const src_last = data + width * last_row; // Last pixel to decode - const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES; - const int color_cache_limit = len_code_limit + hdr->color_cache_size_; - int next_sync_row = dec->incremental_ ? row : 1 << 24; - VP8LColorCache* const color_cache = - (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL; - const int mask = hdr->huffman_mask_; - assert(htree_group != NULL); - assert(src < src_end); - assert(src_last <= src_end); - - while (src < src_last) { - int code; - if (row >= next_sync_row) { - SaveState(dec, (int)(src - data)); - next_sync_row = row + SYNC_EVERY_N_ROWS; - } - // Only update when changing tile. Note we could use this test: - // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed - // but that's actually slower and needs storing the previous col/row. - if ((col & mask) == 0) htree_group = GetHtreeGroupForPos(hdr, col, row); - if (htree_group->is_trivial_code) { - *src = htree_group->literal_arb; - goto AdvanceByOne; - } - VP8LFillBitWindow(br); - if (htree_group->use_packed_table) { - code = ReadPackedSymbols(htree_group, br, src); - if (code == PACKED_NON_LITERAL_CODE) goto AdvanceByOne; - } else { - code = ReadSymbol(htree_group->htrees[GREEN], br); - } - if (br->eos_) break; // early out - if (code < NUM_LITERAL_CODES) { // Literal - if (htree_group->is_trivial_literal) { - *src = htree_group->literal_arb | (code << 8); - } else { - int red, blue, alpha; - red = ReadSymbol(htree_group->htrees[RED], br); - VP8LFillBitWindow(br); - blue = ReadSymbol(htree_group->htrees[BLUE], br); - alpha = ReadSymbol(htree_group->htrees[ALPHA], br); - if (br->eos_) break; - *src = ((uint32_t)alpha << 24) | (red << 16) | (code << 8) | blue; - } - AdvanceByOne: - ++src; - ++col; - if (col >= width) { - col = 0; - ++row; - if ((row % NUM_ARGB_CACHE_ROWS == 0) && (process_func != NULL)) { - process_func(dec, row); - } - if (color_cache != NULL) { - while (last_cached < src) { - VP8LColorCacheInsert(color_cache, *last_cached++); - } - } - } - } else if (code < len_code_limit) { // Backward reference - int dist_code, dist; - const int length_sym = code - NUM_LITERAL_CODES; - const int length = GetCopyLength(length_sym, br); - const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br); - VP8LFillBitWindow(br); - dist_code = GetCopyDistance(dist_symbol, br); - dist = PlaneCodeToDistance(width, dist_code); - if (br->eos_) break; - if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) { - goto Error; - } else { - CopyBlock32b(src, dist, length); - } - src += length; - col += length; - while (col >= width) { - col -= width; - ++row; - if ((row % NUM_ARGB_CACHE_ROWS == 0) && (process_func != NULL)) { - process_func(dec, row); - } - } - // Because of the check done above (before 'src' was incremented by - // 'length'), the following holds true. - assert(src <= src_end); - if (col & mask) htree_group = GetHtreeGroupForPos(hdr, col, row); - if (color_cache != NULL) { - while (last_cached < src) { - VP8LColorCacheInsert(color_cache, *last_cached++); - } - } - } else if (code < color_cache_limit) { // Color cache - const int key = code - len_code_limit; - assert(color_cache != NULL); - while (last_cached < src) { - VP8LColorCacheInsert(color_cache, *last_cached++); - } - *src = VP8LColorCacheLookup(color_cache, key); - goto AdvanceByOne; - } else { // Not reached - goto Error; - } - assert(br->eos_ == VP8LIsEndOfStream(br)); - } - - if (dec->incremental_ && br->eos_ && src < src_end) { - RestoreState(dec); - } else if (!br->eos_) { - // Process the remaining rows corresponding to last row-block. - if (process_func != NULL) { - process_func(dec, row); - } - dec->status_ = VP8_STATUS_OK; - dec->last_pixel_ = (int)(src - data); // end-of-scan marker - } else { - // if not incremental, and we are past the end of buffer (eos_=1), then this - // is a real bitstream error. - goto Error; - } - return 1; - - Error: - dec->status_ = VP8_STATUS_BITSTREAM_ERROR; - return 0; -} - -// ----------------------------------------------------------------------------- -// VP8LTransform - -static void ClearTransform(VP8LTransform* const transform) { - WebPSafeFree(transform->data_); - transform->data_ = NULL; -} - -// For security reason, we need to remap the color map to span -// the total possible bundled values, and not just the num_colors. -static int ExpandColorMap(int num_colors, VP8LTransform* const transform) { - int i; - const int final_num_colors = 1 << (8 >> transform->bits_); - uint32_t* const new_color_map = - (uint32_t*)WebPSafeMalloc((uint64_t)final_num_colors, - sizeof(*new_color_map)); - if (new_color_map == NULL) { - return 0; - } else { - uint8_t* const data = (uint8_t*)transform->data_; - uint8_t* const new_data = (uint8_t*)new_color_map; - new_color_map[0] = transform->data_[0]; - for (i = 4; i < 4 * num_colors; ++i) { - // Equivalent to AddPixelEq(), on a byte-basis. - new_data[i] = (data[i] + new_data[i - 4]) & 0xff; - } - for (; i < 4 * final_num_colors; ++i) - new_data[i] = 0; // black tail. - WebPSafeFree(transform->data_); - transform->data_ = new_color_map; - } - return 1; -} - -static int ReadTransform(int* const xsize, int const* ysize, - VP8LDecoder* const dec) { - int ok = 1; - VP8LBitReader* const br = &dec->br_; - VP8LTransform* transform = &dec->transforms_[dec->next_transform_]; - const VP8LImageTransformType type = - (VP8LImageTransformType)VP8LReadBits(br, 2); - - // Each transform type can only be present once in the stream. - if (dec->transforms_seen_ & (1U << type)) { - return 0; // Already there, let's not accept the second same transform. - } - dec->transforms_seen_ |= (1U << type); - - transform->type_ = type; - transform->xsize_ = *xsize; - transform->ysize_ = *ysize; - transform->data_ = NULL; - ++dec->next_transform_; - assert(dec->next_transform_ <= NUM_TRANSFORMS); - - switch (type) { - case PREDICTOR_TRANSFORM: - case CROSS_COLOR_TRANSFORM: - transform->bits_ = VP8LReadBits(br, 3) + 2; - ok = DecodeImageStream(VP8LSubSampleSize(transform->xsize_, - transform->bits_), - VP8LSubSampleSize(transform->ysize_, - transform->bits_), - 0, dec, &transform->data_); - break; - case COLOR_INDEXING_TRANSFORM: { - const int num_colors = VP8LReadBits(br, 8) + 1; - const int bits = (num_colors > 16) ? 0 - : (num_colors > 4) ? 1 - : (num_colors > 2) ? 2 - : 3; - *xsize = VP8LSubSampleSize(transform->xsize_, bits); - transform->bits_ = bits; - ok = DecodeImageStream(num_colors, 1, 0, dec, &transform->data_); - ok = ok && ExpandColorMap(num_colors, transform); - break; - } - case SUBTRACT_GREEN: - break; - default: - assert(0); // can't happen - break; - } - - return ok; -} - -// ----------------------------------------------------------------------------- -// VP8LMetadata - -static void InitMetadata(VP8LMetadata* const hdr) { - assert(hdr != NULL); - memset(hdr, 0, sizeof(*hdr)); -} - -static void ClearMetadata(VP8LMetadata* const hdr) { - assert(hdr != NULL); - - WebPSafeFree(hdr->huffman_image_); - WebPSafeFree(hdr->huffman_tables_); - VP8LHtreeGroupsFree(hdr->htree_groups_); - VP8LColorCacheClear(&hdr->color_cache_); - VP8LColorCacheClear(&hdr->saved_color_cache_); - InitMetadata(hdr); -} - -// ----------------------------------------------------------------------------- -// VP8LDecoder - -VP8LDecoder* VP8LNew(void) { - VP8LDecoder* const dec = (VP8LDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); - if (dec == NULL) return NULL; - dec->status_ = VP8_STATUS_OK; - dec->state_ = READ_DIM; - - VP8LDspInit(); // Init critical function pointers. - - return dec; -} - -void VP8LClear(VP8LDecoder* const dec) { - int i; - if (dec == NULL) return; - ClearMetadata(&dec->hdr_); - - WebPSafeFree(dec->pixels_); - dec->pixels_ = NULL; - for (i = 0; i < dec->next_transform_; ++i) { - ClearTransform(&dec->transforms_[i]); - } - dec->next_transform_ = 0; - dec->transforms_seen_ = 0; - - WebPSafeFree(dec->rescaler_memory); - dec->rescaler_memory = NULL; - - dec->output_ = NULL; // leave no trace behind -} - -void VP8LDelete(VP8LDecoder* const dec) { - if (dec != NULL) { - VP8LClear(dec); - WebPSafeFree(dec); - } -} - -static void UpdateDecoder(VP8LDecoder* const dec, int width, int height) { - VP8LMetadata* const hdr = &dec->hdr_; - const int num_bits = hdr->huffman_subsample_bits_; - dec->width_ = width; - dec->height_ = height; - - hdr->huffman_xsize_ = VP8LSubSampleSize(width, num_bits); - hdr->huffman_mask_ = (num_bits == 0) ? ~0 : (1 << num_bits) - 1; -} - -static int DecodeImageStream(int xsize, int ysize, - int is_level0, - VP8LDecoder* const dec, - uint32_t** const decoded_data) { - int ok = 1; - int transform_xsize = xsize; - int transform_ysize = ysize; - VP8LBitReader* const br = &dec->br_; - VP8LMetadata* const hdr = &dec->hdr_; - uint32_t* data = NULL; - int color_cache_bits = 0; - - // Read the transforms (may recurse). - if (is_level0) { - while (ok && VP8LReadBits(br, 1)) { - ok = ReadTransform(&transform_xsize, &transform_ysize, dec); - } - } - - // Color cache - if (ok && VP8LReadBits(br, 1)) { - color_cache_bits = VP8LReadBits(br, 4); - ok = (color_cache_bits >= 1 && color_cache_bits <= MAX_CACHE_BITS); - if (!ok) { - dec->status_ = VP8_STATUS_BITSTREAM_ERROR; - goto End; - } - } - - // Read the Huffman codes (may recurse). - ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize, - color_cache_bits, is_level0); - if (!ok) { - dec->status_ = VP8_STATUS_BITSTREAM_ERROR; - goto End; - } - - // Finish setting up the color-cache - if (color_cache_bits > 0) { - hdr->color_cache_size_ = 1 << color_cache_bits; - if (!VP8LColorCacheInit(&hdr->color_cache_, color_cache_bits)) { - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; - ok = 0; - goto End; - } - } else { - hdr->color_cache_size_ = 0; - } - UpdateDecoder(dec, transform_xsize, transform_ysize); - - if (is_level0) { // level 0 complete - dec->state_ = READ_HDR; - goto End; - } - - { - const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize; - data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data)); - if (data == NULL) { - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; - ok = 0; - goto End; - } - } - - // Use the Huffman trees to decode the LZ77 encoded data. - ok = DecodeImageData(dec, data, transform_xsize, transform_ysize, - transform_ysize, NULL); - ok = ok && !br->eos_; - - End: - if (!ok) { - WebPSafeFree(data); - ClearMetadata(hdr); - } else { - if (decoded_data != NULL) { - *decoded_data = data; - } else { - // We allocate image data in this function only for transforms. At level 0 - // (that is: not the transforms), we shouldn't have allocated anything. - assert(data == NULL); - assert(is_level0); - } - dec->last_pixel_ = 0; // Reset for future DECODE_DATA_FUNC() calls. - if (!is_level0) ClearMetadata(hdr); // Clean up temporary data behind. - } - return ok; -} - -//------------------------------------------------------------------------------ -// Allocate internal buffers dec->pixels_ and dec->argb_cache_. -static int AllocateInternalBuffers32b(VP8LDecoder* const dec, int final_width) { - const uint64_t num_pixels = (uint64_t)dec->width_ * dec->height_; - // Scratch buffer corresponding to top-prediction row for transforming the - // first row in the row-blocks. Not needed for paletted alpha. - const uint64_t cache_top_pixels = (uint16_t)final_width; - // Scratch buffer for temporary BGRA storage. Not needed for paletted alpha. - const uint64_t cache_pixels = (uint64_t)final_width * NUM_ARGB_CACHE_ROWS; - const uint64_t total_num_pixels = - num_pixels + cache_top_pixels + cache_pixels; - - assert(dec->width_ <= final_width); - dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint32_t)); - if (dec->pixels_ == NULL) { - dec->argb_cache_ = NULL; // for sanity check - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; - return 0; - } - dec->argb_cache_ = dec->pixels_ + num_pixels + cache_top_pixels; - return 1; -} - -static int AllocateInternalBuffers8b(VP8LDecoder* const dec) { - const uint64_t total_num_pixels = (uint64_t)dec->width_ * dec->height_; - dec->argb_cache_ = NULL; // for sanity check - dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint8_t)); - if (dec->pixels_ == NULL) { - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; - return 0; - } - return 1; -} - -//------------------------------------------------------------------------------ - -// Special row-processing that only stores the alpha data. -static void ExtractAlphaRows(VP8LDecoder* const dec, int row) { - const int num_rows = row - dec->last_row_; - const uint32_t* const in = dec->pixels_ + dec->width_ * dec->last_row_; - - if (num_rows <= 0) return; // Nothing to be done. - ApplyInverseTransforms(dec, num_rows, in); - - // Extract alpha (which is stored in the green plane). - { - const int width = dec->io_->width; // the final width (!= dec->width_) - const int cache_pixs = width * num_rows; - uint8_t* const dst = (uint8_t*)dec->io_->opaque + width * dec->last_row_; - const uint32_t* const src = dec->argb_cache_; - int i; - for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff; - } - dec->last_row_ = dec->last_out_row_ = row; -} - -int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec, - const uint8_t* const data, size_t data_size, - uint8_t* const output) { - int ok = 0; - VP8LDecoder* dec; - VP8Io* io; - assert(alph_dec != NULL); - alph_dec->vp8l_dec_ = VP8LNew(); - if (alph_dec->vp8l_dec_ == NULL) return 0; - dec = alph_dec->vp8l_dec_; - - dec->width_ = alph_dec->width_; - dec->height_ = alph_dec->height_; - dec->io_ = &alph_dec->io_; - io = dec->io_; - - VP8InitIo(io); - WebPInitCustomIo(NULL, io); // Just a sanity Init. io won't be used. - io->opaque = output; - io->width = alph_dec->width_; - io->height = alph_dec->height_; - - dec->status_ = VP8_STATUS_OK; - VP8LInitBitReader(&dec->br_, data, data_size); - - if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, 1, dec, NULL)) { - goto Err; - } - - // Special case: if alpha data uses only the color indexing transform and - // doesn't use color cache (a frequent case), we will use DecodeAlphaData() - // method that only needs allocation of 1 byte per pixel (alpha channel). - if (dec->next_transform_ == 1 && - dec->transforms_[0].type_ == COLOR_INDEXING_TRANSFORM && - Is8bOptimizable(&dec->hdr_)) { - alph_dec->use_8b_decode = 1; - ok = AllocateInternalBuffers8b(dec); - } else { - // Allocate internal buffers (note that dec->width_ may have changed here). - alph_dec->use_8b_decode = 0; - ok = AllocateInternalBuffers32b(dec, alph_dec->width_); - } - - if (!ok) goto Err; - - return 1; - - Err: - VP8LDelete(alph_dec->vp8l_dec_); - alph_dec->vp8l_dec_ = NULL; - return 0; -} - -int VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) { - VP8LDecoder* const dec = alph_dec->vp8l_dec_; - assert(dec != NULL); - assert(last_row <= dec->height_); - - if (dec->last_pixel_ == dec->width_ * dec->height_) { - return 1; // done - } - - // Decode (with special row processing). - return alph_dec->use_8b_decode ? - DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_, - last_row) : - DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, - last_row, ExtractAlphaRows); -} - -//------------------------------------------------------------------------------ - -int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) { - int width, height, has_alpha; - - if (dec == NULL) return 0; - if (io == NULL) { - dec->status_ = VP8_STATUS_INVALID_PARAM; - return 0; - } - - dec->io_ = io; - dec->status_ = VP8_STATUS_OK; - VP8LInitBitReader(&dec->br_, io->data, io->data_size); - if (!ReadImageInfo(&dec->br_, &width, &height, &has_alpha)) { - dec->status_ = VP8_STATUS_BITSTREAM_ERROR; - goto Error; - } - dec->state_ = READ_DIM; - io->width = width; - io->height = height; - - if (!DecodeImageStream(width, height, 1, dec, NULL)) goto Error; - return 1; - - Error: - VP8LClear(dec); - assert(dec->status_ != VP8_STATUS_OK); - return 0; -} - -int VP8LDecodeImage(VP8LDecoder* const dec) { - VP8Io* io = NULL; - WebPDecParams* params = NULL; - - // Sanity checks. - if (dec == NULL) return 0; - - assert(dec->hdr_.huffman_tables_ != NULL); - assert(dec->hdr_.htree_groups_ != NULL); - assert(dec->hdr_.num_htree_groups_ > 0); - - io = dec->io_; - assert(io != NULL); - params = (WebPDecParams*)io->opaque; - assert(params != NULL); - - // Initialization. - if (dec->state_ != READ_DATA) { - dec->output_ = params->output; - assert(dec->output_ != NULL); - - if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) { - dec->status_ = VP8_STATUS_INVALID_PARAM; - goto Err; - } - - if (!AllocateInternalBuffers32b(dec, io->width)) goto Err; - - if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err; - - if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) { - // need the alpha-multiply functions for premultiplied output or rescaling - WebPInitAlphaProcessing(); - } - if (!WebPIsRGBMode(dec->output_->colorspace)) { - WebPInitConvertARGBToYUV(); - if (dec->output_->u.YUVA.a != NULL) WebPInitAlphaProcessing(); - } - if (dec->incremental_) { - if (dec->hdr_.color_cache_size_ > 0 && - dec->hdr_.saved_color_cache_.colors_ == NULL) { - if (!VP8LColorCacheInit(&dec->hdr_.saved_color_cache_, - dec->hdr_.color_cache_.hash_bits_)) { - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; - goto Err; - } - } - } - dec->state_ = READ_DATA; - } - - // Decode. - if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, - dec->height_, ProcessRows)) { - goto Err; - } - - params->last_y = dec->last_out_row_; - return 1; - - Err: - VP8LClear(dec); - assert(dec->status_ != VP8_STATUS_OK); - return 0; -} - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/dec/vp8li.h b/Example/Pods/libwebp/src/dec/vp8li.h deleted file mode 100644 index 8886e47f..00000000 --- a/Example/Pods/libwebp/src/dec/vp8li.h +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Lossless decoder: internal header. -// -// Author: Skal (pascal.massimino@gmail.com) -// Vikas Arora(vikaas.arora@gmail.com) - -#ifndef WEBP_DEC_VP8LI_H_ -#define WEBP_DEC_VP8LI_H_ - -#include // for memcpy() -#include "./webpi.h" -#include "../utils/bit_reader.h" -#include "../utils/color_cache.h" -#include "../utils/huffman.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - READ_DATA = 0, - READ_HDR = 1, - READ_DIM = 2 -} VP8LDecodeState; - -typedef struct VP8LTransform VP8LTransform; -struct VP8LTransform { - VP8LImageTransformType type_; // transform type. - int bits_; // subsampling bits defining transform window. - int xsize_; // transform window X index. - int ysize_; // transform window Y index. - uint32_t *data_; // transform data. -}; - -typedef struct { - int color_cache_size_; - VP8LColorCache color_cache_; - VP8LColorCache saved_color_cache_; // for incremental - - int huffman_mask_; - int huffman_subsample_bits_; - int huffman_xsize_; - uint32_t *huffman_image_; - int num_htree_groups_; - HTreeGroup *htree_groups_; - HuffmanCode *huffman_tables_; -} VP8LMetadata; - -typedef struct VP8LDecoder VP8LDecoder; -struct VP8LDecoder { - VP8StatusCode status_; - VP8LDecodeState state_; - VP8Io *io_; - - const WebPDecBuffer *output_; // shortcut to io->opaque->output - - uint32_t *pixels_; // Internal data: either uint8_t* for alpha - // or uint32_t* for BGRA. - uint32_t *argb_cache_; // Scratch buffer for temporary BGRA storage. - - VP8LBitReader br_; - int incremental_; // if true, incremental decoding is expected - VP8LBitReader saved_br_; // note: could be local variables too - int saved_last_pixel_; - - int width_; - int height_; - int last_row_; // last input row decoded so far. - int last_pixel_; // last pixel decoded so far. However, it may - // not be transformed, scaled and - // color-converted yet. - int last_out_row_; // last row output so far. - - VP8LMetadata hdr_; - - int next_transform_; - VP8LTransform transforms_[NUM_TRANSFORMS]; - // or'd bitset storing the transforms types. - uint32_t transforms_seen_; - - uint8_t *rescaler_memory; // Working memory for rescaling work. - WebPRescaler *rescaler; // Common rescaler for all channels. -}; - -//------------------------------------------------------------------------------ -// internal functions. Not public. - -struct ALPHDecoder; // Defined in dec/alphai.h. - -// in vp8l.c - -// Decodes image header for alpha data stored using lossless compression. -// Returns false in case of error. -int VP8LDecodeAlphaHeader(struct ALPHDecoder* const alph_dec, - const uint8_t* const data, size_t data_size, - uint8_t* const output); - -// Decodes *at least* 'last_row' rows of alpha. If some of the initial rows are -// already decoded in previous call(s), it will resume decoding from where it -// was paused. -// Returns false in case of bitstream error. -int VP8LDecodeAlphaImageStream(struct ALPHDecoder* const alph_dec, - int last_row); - -// Allocates and initialize a new lossless decoder instance. -VP8LDecoder* VP8LNew(void); - -// Decodes the image header. Returns false in case of error. -int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io); - -// Decodes an image. It's required to decode the lossless header before calling -// this function. Returns false in case of error, with updated dec->status_. -int VP8LDecodeImage(VP8LDecoder* const dec); - -// Resets the decoder in its initial state, reclaiming memory. -// Preserves the dec->status_ value. -void VP8LClear(VP8LDecoder* const dec); - -// Clears and deallocate a lossless decoder instance. -void VP8LDelete(VP8LDecoder* const dec); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_DEC_VP8LI_H_ */ diff --git a/Example/Pods/libwebp/src/dec/webp.c b/Example/Pods/libwebp/src/dec/webp.c deleted file mode 100644 index 952178fa..00000000 --- a/Example/Pods/libwebp/src/dec/webp.c +++ /dev/null @@ -1,829 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Main decoding functions for WEBP images. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include - -#include "./vp8i.h" -#include "./vp8li.h" -#include "./webpi.h" -#include "../utils/utils.h" -#include "../webp/mux_types.h" // ALPHA_FLAG - -//------------------------------------------------------------------------------ -// RIFF layout is: -// Offset tag -// 0...3 "RIFF" 4-byte tag -// 4...7 size of image data (including metadata) starting at offset 8 -// 8...11 "WEBP" our form-type signature -// The RIFF container (12 bytes) is followed by appropriate chunks: -// 12..15 "VP8 ": 4-bytes tags, signaling the use of VP8 video format -// 16..19 size of the raw VP8 image data, starting at offset 20 -// 20.... the VP8 bytes -// Or, -// 12..15 "VP8L": 4-bytes tags, signaling the use of VP8L lossless format -// 16..19 size of the raw VP8L image data, starting at offset 20 -// 20.... the VP8L bytes -// Or, -// 12..15 "VP8X": 4-bytes tags, describing the extended-VP8 chunk. -// 16..19 size of the VP8X chunk starting at offset 20. -// 20..23 VP8X flags bit-map corresponding to the chunk-types present. -// 24..26 Width of the Canvas Image. -// 27..29 Height of the Canvas Image. -// There can be extra chunks after the "VP8X" chunk (ICCP, FRGM, ANMF, VP8, -// VP8L, XMP, EXIF ...) -// All sizes are in little-endian order. -// Note: chunk data size must be padded to multiple of 2 when written. - -// Validates the RIFF container (if detected) and skips over it. -// If a RIFF container is detected, returns: -// VP8_STATUS_BITSTREAM_ERROR for invalid header, -// VP8_STATUS_NOT_ENOUGH_DATA for truncated data if have_all_data is true, -// and VP8_STATUS_OK otherwise. -// In case there are not enough bytes (partial RIFF container), return 0 for -// *riff_size. Else return the RIFF size extracted from the header. -static VP8StatusCode ParseRIFF(const uint8_t** const data, - size_t* const data_size, int have_all_data, - size_t* const riff_size) { - assert(data != NULL); - assert(data_size != NULL); - assert(riff_size != NULL); - - *riff_size = 0; // Default: no RIFF present. - if (*data_size >= RIFF_HEADER_SIZE && !memcmp(*data, "RIFF", TAG_SIZE)) { - if (memcmp(*data + 8, "WEBP", TAG_SIZE)) { - return VP8_STATUS_BITSTREAM_ERROR; // Wrong image file signature. - } else { - const uint32_t size = GetLE32(*data + TAG_SIZE); - // Check that we have at least one chunk (i.e "WEBP" + "VP8?nnnn"). - if (size < TAG_SIZE + CHUNK_HEADER_SIZE) { - return VP8_STATUS_BITSTREAM_ERROR; - } - if (size > MAX_CHUNK_PAYLOAD) { - return VP8_STATUS_BITSTREAM_ERROR; - } - if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) { - return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream. - } - // We have a RIFF container. Skip it. - *riff_size = size; - *data += RIFF_HEADER_SIZE; - *data_size -= RIFF_HEADER_SIZE; - } - } - return VP8_STATUS_OK; -} - -// Validates the VP8X header and skips over it. -// Returns VP8_STATUS_BITSTREAM_ERROR for invalid VP8X header, -// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and -// VP8_STATUS_OK otherwise. -// If a VP8X chunk is found, found_vp8x is set to true and *width_ptr, -// *height_ptr and *flags_ptr are set to the corresponding values extracted -// from the VP8X chunk. -static VP8StatusCode ParseVP8X(const uint8_t** const data, - size_t* const data_size, - int* const found_vp8x, - int* const width_ptr, int* const height_ptr, - uint32_t* const flags_ptr) { - const uint32_t vp8x_size = CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE; - assert(data != NULL); - assert(data_size != NULL); - assert(found_vp8x != NULL); - - *found_vp8x = 0; - - if (*data_size < CHUNK_HEADER_SIZE) { - return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. - } - - if (!memcmp(*data, "VP8X", TAG_SIZE)) { - int width, height; - uint32_t flags; - const uint32_t chunk_size = GetLE32(*data + TAG_SIZE); - if (chunk_size != VP8X_CHUNK_SIZE) { - return VP8_STATUS_BITSTREAM_ERROR; // Wrong chunk size. - } - - // Verify if enough data is available to validate the VP8X chunk. - if (*data_size < vp8x_size) { - return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. - } - flags = GetLE32(*data + 8); - width = 1 + GetLE24(*data + 12); - height = 1 + GetLE24(*data + 15); - if (width * (uint64_t)height >= MAX_IMAGE_AREA) { - return VP8_STATUS_BITSTREAM_ERROR; // image is too large - } - - if (flags_ptr != NULL) *flags_ptr = flags; - if (width_ptr != NULL) *width_ptr = width; - if (height_ptr != NULL) *height_ptr = height; - // Skip over VP8X header bytes. - *data += vp8x_size; - *data_size -= vp8x_size; - *found_vp8x = 1; - } - return VP8_STATUS_OK; -} - -// Skips to the next VP8/VP8L chunk header in the data given the size of the -// RIFF chunk 'riff_size'. -// Returns VP8_STATUS_BITSTREAM_ERROR if any invalid chunk size is encountered, -// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and -// VP8_STATUS_OK otherwise. -// If an alpha chunk is found, *alpha_data and *alpha_size are set -// appropriately. -static VP8StatusCode ParseOptionalChunks(const uint8_t** const data, - size_t* const data_size, - size_t const riff_size, - const uint8_t** const alpha_data, - size_t* const alpha_size) { - const uint8_t* buf; - size_t buf_size; - uint32_t total_size = TAG_SIZE + // "WEBP". - CHUNK_HEADER_SIZE + // "VP8Xnnnn". - VP8X_CHUNK_SIZE; // data. - assert(data != NULL); - assert(data_size != NULL); - buf = *data; - buf_size = *data_size; - - assert(alpha_data != NULL); - assert(alpha_size != NULL); - *alpha_data = NULL; - *alpha_size = 0; - - while (1) { - uint32_t chunk_size; - uint32_t disk_chunk_size; // chunk_size with padding - - *data = buf; - *data_size = buf_size; - - if (buf_size < CHUNK_HEADER_SIZE) { // Insufficient data. - return VP8_STATUS_NOT_ENOUGH_DATA; - } - - chunk_size = GetLE32(buf + TAG_SIZE); - if (chunk_size > MAX_CHUNK_PAYLOAD) { - return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. - } - // For odd-sized chunk-payload, there's one byte padding at the end. - disk_chunk_size = (CHUNK_HEADER_SIZE + chunk_size + 1) & ~1; - total_size += disk_chunk_size; - - // Check that total bytes skipped so far does not exceed riff_size. - if (riff_size > 0 && (total_size > riff_size)) { - return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. - } - - // Start of a (possibly incomplete) VP8/VP8L chunk implies that we have - // parsed all the optional chunks. - // Note: This check must occur before the check 'buf_size < disk_chunk_size' - // below to allow incomplete VP8/VP8L chunks. - if (!memcmp(buf, "VP8 ", TAG_SIZE) || - !memcmp(buf, "VP8L", TAG_SIZE)) { - return VP8_STATUS_OK; - } - - if (buf_size < disk_chunk_size) { // Insufficient data. - return VP8_STATUS_NOT_ENOUGH_DATA; - } - - if (!memcmp(buf, "ALPH", TAG_SIZE)) { // A valid ALPH header. - *alpha_data = buf + CHUNK_HEADER_SIZE; - *alpha_size = chunk_size; - } - - // We have a full and valid chunk; skip it. - buf += disk_chunk_size; - buf_size -= disk_chunk_size; - } -} - -// Validates the VP8/VP8L Header ("VP8 nnnn" or "VP8L nnnn") and skips over it. -// Returns VP8_STATUS_BITSTREAM_ERROR for invalid (chunk larger than -// riff_size) VP8/VP8L header, -// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and -// VP8_STATUS_OK otherwise. -// If a VP8/VP8L chunk is found, *chunk_size is set to the total number of bytes -// extracted from the VP8/VP8L chunk header. -// The flag '*is_lossless' is set to 1 in case of VP8L chunk / raw VP8L data. -static VP8StatusCode ParseVP8Header(const uint8_t** const data_ptr, - size_t* const data_size, int have_all_data, - size_t riff_size, size_t* const chunk_size, - int* const is_lossless) { - const uint8_t* const data = *data_ptr; - const int is_vp8 = !memcmp(data, "VP8 ", TAG_SIZE); - const int is_vp8l = !memcmp(data, "VP8L", TAG_SIZE); - const uint32_t minimal_size = - TAG_SIZE + CHUNK_HEADER_SIZE; // "WEBP" + "VP8 nnnn" OR - // "WEBP" + "VP8Lnnnn" - assert(data != NULL); - assert(data_size != NULL); - assert(chunk_size != NULL); - assert(is_lossless != NULL); - - if (*data_size < CHUNK_HEADER_SIZE) { - return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. - } - - if (is_vp8 || is_vp8l) { - // Bitstream contains VP8/VP8L header. - const uint32_t size = GetLE32(data + TAG_SIZE); - if ((riff_size >= minimal_size) && (size > riff_size - minimal_size)) { - return VP8_STATUS_BITSTREAM_ERROR; // Inconsistent size information. - } - if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) { - return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream. - } - // Skip over CHUNK_HEADER_SIZE bytes from VP8/VP8L Header. - *chunk_size = size; - *data_ptr += CHUNK_HEADER_SIZE; - *data_size -= CHUNK_HEADER_SIZE; - *is_lossless = is_vp8l; - } else { - // Raw VP8/VP8L bitstream (no header). - *is_lossless = VP8LCheckSignature(data, *data_size); - *chunk_size = *data_size; - } - - return VP8_STATUS_OK; -} - -//------------------------------------------------------------------------------ - -// Fetch '*width', '*height', '*has_alpha' and fill out 'headers' based on -// 'data'. All the output parameters may be NULL. If 'headers' is NULL only the -// minimal amount will be read to fetch the remaining parameters. -// If 'headers' is non-NULL this function will attempt to locate both alpha -// data (with or without a VP8X chunk) and the bitstream chunk (VP8/VP8L). -// Note: The following chunk sequences (before the raw VP8/VP8L data) are -// considered valid by this function: -// RIFF + VP8(L) -// RIFF + VP8X + (optional chunks) + VP8(L) -// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose. -// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose. -static VP8StatusCode ParseHeadersInternal(const uint8_t* data, - size_t data_size, - int* const width, - int* const height, - int* const has_alpha, - int* const has_animation, - int* const format, - WebPHeaderStructure* const headers) { - int canvas_width = 0; - int canvas_height = 0; - int image_width = 0; - int image_height = 0; - int found_riff = 0; - int found_vp8x = 0; - int animation_present = 0; - int fragments_present = 0; - const int have_all_data = (headers != NULL) ? headers->have_all_data : 0; - - VP8StatusCode status; - WebPHeaderStructure hdrs; - - if (data == NULL || data_size < RIFF_HEADER_SIZE) { - return VP8_STATUS_NOT_ENOUGH_DATA; - } - memset(&hdrs, 0, sizeof(hdrs)); - hdrs.data = data; - hdrs.data_size = data_size; - - // Skip over RIFF header. - status = ParseRIFF(&data, &data_size, have_all_data, &hdrs.riff_size); - if (status != VP8_STATUS_OK) { - return status; // Wrong RIFF header / insufficient data. - } - found_riff = (hdrs.riff_size > 0); - - // Skip over VP8X. - { - uint32_t flags = 0; - status = ParseVP8X(&data, &data_size, &found_vp8x, - &canvas_width, &canvas_height, &flags); - if (status != VP8_STATUS_OK) { - return status; // Wrong VP8X / insufficient data. - } - animation_present = !!(flags & ANIMATION_FLAG); - fragments_present = !!(flags & FRAGMENTS_FLAG); - if (!found_riff && found_vp8x) { - // Note: This restriction may be removed in the future, if it becomes - // necessary to send VP8X chunk to the decoder. - return VP8_STATUS_BITSTREAM_ERROR; - } - if (has_alpha != NULL) *has_alpha = !!(flags & ALPHA_FLAG); - if (has_animation != NULL) *has_animation = animation_present; - if (format != NULL) *format = 0; // default = undefined - - image_width = canvas_width; - image_height = canvas_height; - if (found_vp8x && (animation_present || fragments_present) && - headers == NULL) { - status = VP8_STATUS_OK; - goto ReturnWidthHeight; // Just return features from VP8X header. - } - } - - if (data_size < TAG_SIZE) { - status = VP8_STATUS_NOT_ENOUGH_DATA; - goto ReturnWidthHeight; - } - - // Skip over optional chunks if data started with "RIFF + VP8X" or "ALPH". - if ((found_riff && found_vp8x) || - (!found_riff && !found_vp8x && !memcmp(data, "ALPH", TAG_SIZE))) { - status = ParseOptionalChunks(&data, &data_size, hdrs.riff_size, - &hdrs.alpha_data, &hdrs.alpha_data_size); - if (status != VP8_STATUS_OK) { - goto ReturnWidthHeight; // Invalid chunk size / insufficient data. - } - } - - // Skip over VP8/VP8L header. - status = ParseVP8Header(&data, &data_size, have_all_data, hdrs.riff_size, - &hdrs.compressed_size, &hdrs.is_lossless); - if (status != VP8_STATUS_OK) { - goto ReturnWidthHeight; // Wrong VP8/VP8L chunk-header / insufficient data. - } - if (hdrs.compressed_size > MAX_CHUNK_PAYLOAD) { - return VP8_STATUS_BITSTREAM_ERROR; - } - - if (format != NULL && !(animation_present || fragments_present)) { - *format = hdrs.is_lossless ? 2 : 1; - } - - if (!hdrs.is_lossless) { - if (data_size < VP8_FRAME_HEADER_SIZE) { - status = VP8_STATUS_NOT_ENOUGH_DATA; - goto ReturnWidthHeight; - } - // Validates raw VP8 data. - if (!VP8GetInfo(data, data_size, (uint32_t)hdrs.compressed_size, - &image_width, &image_height)) { - return VP8_STATUS_BITSTREAM_ERROR; - } - } else { - if (data_size < VP8L_FRAME_HEADER_SIZE) { - status = VP8_STATUS_NOT_ENOUGH_DATA; - goto ReturnWidthHeight; - } - // Validates raw VP8L data. - if (!VP8LGetInfo(data, data_size, &image_width, &image_height, has_alpha)) { - return VP8_STATUS_BITSTREAM_ERROR; - } - } - // Validates image size coherency. - if (found_vp8x) { - if (canvas_width != image_width || canvas_height != image_height) { - return VP8_STATUS_BITSTREAM_ERROR; - } - } - if (headers != NULL) { - *headers = hdrs; - headers->offset = data - headers->data; - assert((uint64_t)(data - headers->data) < MAX_CHUNK_PAYLOAD); - assert(headers->offset == headers->data_size - data_size); - } - ReturnWidthHeight: - if (status == VP8_STATUS_OK || - (status == VP8_STATUS_NOT_ENOUGH_DATA && found_vp8x && headers == NULL)) { - if (has_alpha != NULL) { - // If the data did not contain a VP8X/VP8L chunk the only definitive way - // to set this is by looking for alpha data (from an ALPH chunk). - *has_alpha |= (hdrs.alpha_data != NULL); - } - if (width != NULL) *width = image_width; - if (height != NULL) *height = image_height; - return VP8_STATUS_OK; - } else { - return status; - } -} - -VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers) { - VP8StatusCode status; - int has_animation = 0; - assert(headers != NULL); - // fill out headers, ignore width/height/has_alpha. - status = ParseHeadersInternal(headers->data, headers->data_size, - NULL, NULL, NULL, &has_animation, - NULL, headers); - if (status == VP8_STATUS_OK || status == VP8_STATUS_NOT_ENOUGH_DATA) { - // TODO(jzern): full support of animation frames will require API additions. - if (has_animation) { - status = VP8_STATUS_UNSUPPORTED_FEATURE; - } - } - return status; -} - -//------------------------------------------------------------------------------ -// WebPDecParams - -void WebPResetDecParams(WebPDecParams* const params) { - if (params != NULL) { - memset(params, 0, sizeof(*params)); - } -} - -//------------------------------------------------------------------------------ -// "Into" decoding variants - -// Main flow -static VP8StatusCode DecodeInto(const uint8_t* const data, size_t data_size, - WebPDecParams* const params) { - VP8StatusCode status; - VP8Io io; - WebPHeaderStructure headers; - - headers.data = data; - headers.data_size = data_size; - headers.have_all_data = 1; - status = WebPParseHeaders(&headers); // Process Pre-VP8 chunks. - if (status != VP8_STATUS_OK) { - return status; - } - - assert(params != NULL); - VP8InitIo(&io); - io.data = headers.data + headers.offset; - io.data_size = headers.data_size - headers.offset; - WebPInitCustomIo(params, &io); // Plug the I/O functions. - - if (!headers.is_lossless) { - VP8Decoder* const dec = VP8New(); - if (dec == NULL) { - return VP8_STATUS_OUT_OF_MEMORY; - } - dec->alpha_data_ = headers.alpha_data; - dec->alpha_data_size_ = headers.alpha_data_size; - - // Decode bitstream header, update io->width/io->height. - if (!VP8GetHeaders(dec, &io)) { - status = dec->status_; // An error occurred. Grab error status. - } else { - // Allocate/check output buffers. - status = WebPAllocateDecBuffer(io.width, io.height, params->options, - params->output); - if (status == VP8_STATUS_OK) { // Decode - // This change must be done before calling VP8Decode() - dec->mt_method_ = VP8GetThreadMethod(params->options, &headers, - io.width, io.height); - VP8InitDithering(params->options, dec); - if (!VP8Decode(dec, &io)) { - status = dec->status_; - } - } - } - VP8Delete(dec); - } else { - VP8LDecoder* const dec = VP8LNew(); - if (dec == NULL) { - return VP8_STATUS_OUT_OF_MEMORY; - } - if (!VP8LDecodeHeader(dec, &io)) { - status = dec->status_; // An error occurred. Grab error status. - } else { - // Allocate/check output buffers. - status = WebPAllocateDecBuffer(io.width, io.height, params->options, - params->output); - if (status == VP8_STATUS_OK) { // Decode - if (!VP8LDecodeImage(dec)) { - status = dec->status_; - } - } - } - VP8LDelete(dec); - } - - if (status != VP8_STATUS_OK) { - WebPFreeDecBuffer(params->output); - } - - if (params->options != NULL && params->options->flip) { - status = WebPFlipBuffer(params->output); - } - return status; -} - -// Helpers -static uint8_t* DecodeIntoRGBABuffer(WEBP_CSP_MODE colorspace, - const uint8_t* const data, - size_t data_size, - uint8_t* const rgba, - int stride, size_t size) { - WebPDecParams params; - WebPDecBuffer buf; - if (rgba == NULL) { - return NULL; - } - WebPInitDecBuffer(&buf); - WebPResetDecParams(¶ms); - params.output = &buf; - buf.colorspace = colorspace; - buf.u.RGBA.rgba = rgba; - buf.u.RGBA.stride = stride; - buf.u.RGBA.size = size; - buf.is_external_memory = 1; - if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { - return NULL; - } - return rgba; -} - -uint8_t* WebPDecodeRGBInto(const uint8_t* data, size_t data_size, - uint8_t* output, size_t size, int stride) { - return DecodeIntoRGBABuffer(MODE_RGB, data, data_size, output, stride, size); -} - -uint8_t* WebPDecodeRGBAInto(const uint8_t* data, size_t data_size, - uint8_t* output, size_t size, int stride) { - return DecodeIntoRGBABuffer(MODE_RGBA, data, data_size, output, stride, size); -} - -uint8_t* WebPDecodeARGBInto(const uint8_t* data, size_t data_size, - uint8_t* output, size_t size, int stride) { - return DecodeIntoRGBABuffer(MODE_ARGB, data, data_size, output, stride, size); -} - -uint8_t* WebPDecodeBGRInto(const uint8_t* data, size_t data_size, - uint8_t* output, size_t size, int stride) { - return DecodeIntoRGBABuffer(MODE_BGR, data, data_size, output, stride, size); -} - -uint8_t* WebPDecodeBGRAInto(const uint8_t* data, size_t data_size, - uint8_t* output, size_t size, int stride) { - return DecodeIntoRGBABuffer(MODE_BGRA, data, data_size, output, stride, size); -} - -uint8_t* WebPDecodeYUVInto(const uint8_t* data, size_t data_size, - uint8_t* luma, size_t luma_size, int luma_stride, - uint8_t* u, size_t u_size, int u_stride, - uint8_t* v, size_t v_size, int v_stride) { - WebPDecParams params; - WebPDecBuffer output; - if (luma == NULL) return NULL; - WebPInitDecBuffer(&output); - WebPResetDecParams(¶ms); - params.output = &output; - output.colorspace = MODE_YUV; - output.u.YUVA.y = luma; - output.u.YUVA.y_stride = luma_stride; - output.u.YUVA.y_size = luma_size; - output.u.YUVA.u = u; - output.u.YUVA.u_stride = u_stride; - output.u.YUVA.u_size = u_size; - output.u.YUVA.v = v; - output.u.YUVA.v_stride = v_stride; - output.u.YUVA.v_size = v_size; - output.is_external_memory = 1; - if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { - return NULL; - } - return luma; -} - -//------------------------------------------------------------------------------ - -static uint8_t* Decode(WEBP_CSP_MODE mode, const uint8_t* const data, - size_t data_size, int* const width, int* const height, - WebPDecBuffer* const keep_info) { - WebPDecParams params; - WebPDecBuffer output; - - WebPInitDecBuffer(&output); - WebPResetDecParams(¶ms); - params.output = &output; - output.colorspace = mode; - - // Retrieve (and report back) the required dimensions from bitstream. - if (!WebPGetInfo(data, data_size, &output.width, &output.height)) { - return NULL; - } - if (width != NULL) *width = output.width; - if (height != NULL) *height = output.height; - - // Decode - if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { - return NULL; - } - if (keep_info != NULL) { // keep track of the side-info - WebPCopyDecBuffer(&output, keep_info); - } - // return decoded samples (don't clear 'output'!) - return WebPIsRGBMode(mode) ? output.u.RGBA.rgba : output.u.YUVA.y; -} - -uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size, - int* width, int* height) { - return Decode(MODE_RGB, data, data_size, width, height, NULL); -} - -uint8_t* WebPDecodeRGBA(const uint8_t* data, size_t data_size, - int* width, int* height) { - return Decode(MODE_RGBA, data, data_size, width, height, NULL); -} - -uint8_t* WebPDecodeARGB(const uint8_t* data, size_t data_size, - int* width, int* height) { - return Decode(MODE_ARGB, data, data_size, width, height, NULL); -} - -uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size, - int* width, int* height) { - return Decode(MODE_BGR, data, data_size, width, height, NULL); -} - -uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size, - int* width, int* height) { - return Decode(MODE_BGRA, data, data_size, width, height, NULL); -} - -uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size, - int* width, int* height, uint8_t** u, uint8_t** v, - int* stride, int* uv_stride) { - WebPDecBuffer output; // only to preserve the side-infos - uint8_t* const out = Decode(MODE_YUV, data, data_size, - width, height, &output); - - if (out != NULL) { - const WebPYUVABuffer* const buf = &output.u.YUVA; - *u = buf->u; - *v = buf->v; - *stride = buf->y_stride; - *uv_stride = buf->u_stride; - assert(buf->u_stride == buf->v_stride); - } - return out; -} - -static void DefaultFeatures(WebPBitstreamFeatures* const features) { - assert(features != NULL); - memset(features, 0, sizeof(*features)); -} - -static VP8StatusCode GetFeatures(const uint8_t* const data, size_t data_size, - WebPBitstreamFeatures* const features) { - if (features == NULL || data == NULL) { - return VP8_STATUS_INVALID_PARAM; - } - DefaultFeatures(features); - - // Only parse enough of the data to retrieve the features. - return ParseHeadersInternal(data, data_size, - &features->width, &features->height, - &features->has_alpha, &features->has_animation, - &features->format, NULL); -} - -//------------------------------------------------------------------------------ -// WebPGetInfo() - -int WebPGetInfo(const uint8_t* data, size_t data_size, - int* width, int* height) { - WebPBitstreamFeatures features; - - if (GetFeatures(data, data_size, &features) != VP8_STATUS_OK) { - return 0; - } - - if (width != NULL) { - *width = features.width; - } - if (height != NULL) { - *height = features.height; - } - - return 1; -} - -//------------------------------------------------------------------------------ -// Advance decoding API - -int WebPInitDecoderConfigInternal(WebPDecoderConfig* config, - int version) { - if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { - return 0; // version mismatch - } - if (config == NULL) { - return 0; - } - memset(config, 0, sizeof(*config)); - DefaultFeatures(&config->input); - WebPInitDecBuffer(&config->output); - return 1; -} - -VP8StatusCode WebPGetFeaturesInternal(const uint8_t* data, size_t data_size, - WebPBitstreamFeatures* features, - int version) { - if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { - return VP8_STATUS_INVALID_PARAM; // version mismatch - } - if (features == NULL) { - return VP8_STATUS_INVALID_PARAM; - } - return GetFeatures(data, data_size, features); -} - -VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size, - WebPDecoderConfig* config) { - WebPDecParams params; - VP8StatusCode status; - - if (config == NULL) { - return VP8_STATUS_INVALID_PARAM; - } - - status = GetFeatures(data, data_size, &config->input); - if (status != VP8_STATUS_OK) { - if (status == VP8_STATUS_NOT_ENOUGH_DATA) { - return VP8_STATUS_BITSTREAM_ERROR; // Not-enough-data treated as error. - } - return status; - } - - WebPResetDecParams(¶ms); - params.output = &config->output; - params.options = &config->options; - status = DecodeInto(data, data_size, ¶ms); - - return status; -} - -//------------------------------------------------------------------------------ -// Cropping and rescaling. - -int WebPIoInitFromOptions(const WebPDecoderOptions* const options, - VP8Io* const io, WEBP_CSP_MODE src_colorspace) { - const int W = io->width; - const int H = io->height; - int x = 0, y = 0, w = W, h = H; - - // Cropping - io->use_cropping = (options != NULL) && (options->use_cropping > 0); - if (io->use_cropping) { - w = options->crop_width; - h = options->crop_height; - x = options->crop_left; - y = options->crop_top; - if (!WebPIsRGBMode(src_colorspace)) { // only snap for YUV420 - x &= ~1; - y &= ~1; - } - if (x < 0 || y < 0 || w <= 0 || h <= 0 || x + w > W || y + h > H) { - return 0; // out of frame boundary error - } - } - io->crop_left = x; - io->crop_top = y; - io->crop_right = x + w; - io->crop_bottom = y + h; - io->mb_w = w; - io->mb_h = h; - - // Scaling - io->use_scaling = (options != NULL) && (options->use_scaling > 0); - if (io->use_scaling) { - int scaled_width = options->scaled_width; - int scaled_height = options->scaled_height; - if (!WebPRescalerGetScaledDimensions(w, h, &scaled_width, &scaled_height)) { - return 0; - } - io->scaled_width = scaled_width; - io->scaled_height = scaled_height; - } - - // Filter - io->bypass_filtering = options && options->bypass_filtering; - - // Fancy upsampler -#ifdef FANCY_UPSAMPLING - io->fancy_upsampling = (options == NULL) || (!options->no_fancy_upsampling); -#endif - - if (io->use_scaling) { - // disable filter (only for large downscaling ratio). - io->bypass_filtering = (io->scaled_width < W * 3 / 4) && - (io->scaled_height < H * 3 / 4); - io->fancy_upsampling = 0; - } - return 1; -} - -//------------------------------------------------------------------------------ - diff --git a/Example/Pods/libwebp/src/dec/webpi.h b/Example/Pods/libwebp/src/dec/webpi.h deleted file mode 100644 index c75a2e4a..00000000 --- a/Example/Pods/libwebp/src/dec/webpi.h +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Internal header: WebP decoding parameters and custom IO on buffer -// -// Author: somnath@google.com (Somnath Banerjee) - -#ifndef WEBP_DEC_WEBPI_H_ -#define WEBP_DEC_WEBPI_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "../utils/rescaler.h" -#include "./decode_vp8.h" - -//------------------------------------------------------------------------------ -// WebPDecParams: Decoding output parameters. Transient internal object. - -typedef struct WebPDecParams WebPDecParams; -typedef int (*OutputFunc)(const VP8Io* const io, WebPDecParams* const p); -typedef int (*OutputAlphaFunc)(const VP8Io* const io, WebPDecParams* const p, - int expected_num_out_lines); -typedef int (*OutputRowFunc)(WebPDecParams* const p, int y_pos, - int max_out_lines); - -struct WebPDecParams { - WebPDecBuffer* output; // output buffer. - uint8_t* tmp_y, *tmp_u, *tmp_v; // cache for the fancy upsampler - // or used for tmp rescaling - - int last_y; // coordinate of the line that was last output - const WebPDecoderOptions* options; // if not NULL, use alt decoding features - // rescalers - WebPRescaler scaler_y, scaler_u, scaler_v, scaler_a; - void* memory; // overall scratch memory for the output work. - - OutputFunc emit; // output RGB or YUV samples - OutputAlphaFunc emit_alpha; // output alpha channel - OutputRowFunc emit_alpha_row; // output one line of rescaled alpha values -}; - -// Should be called first, before any use of the WebPDecParams object. -void WebPResetDecParams(WebPDecParams* const params); - -//------------------------------------------------------------------------------ -// Header parsing helpers - -// Structure storing a description of the RIFF headers. -typedef struct { - const uint8_t* data; // input buffer - size_t data_size; // input buffer size - int have_all_data; // true if all data is known to be available - size_t offset; // offset to main data chunk (VP8 or VP8L) - const uint8_t* alpha_data; // points to alpha chunk (if present) - size_t alpha_data_size; // alpha chunk size - size_t compressed_size; // VP8/VP8L compressed data size - size_t riff_size; // size of the riff payload (or 0 if absent) - int is_lossless; // true if a VP8L chunk is present -} WebPHeaderStructure; - -// Skips over all valid chunks prior to the first VP8/VP8L frame header. -// Returns: VP8_STATUS_OK, VP8_STATUS_BITSTREAM_ERROR (invalid header/chunk), -// VP8_STATUS_NOT_ENOUGH_DATA (partial input) or VP8_STATUS_UNSUPPORTED_FEATURE -// in the case of non-decodable features (animation for instance). -// In 'headers', compressed_size, offset, alpha_data, alpha_size, and lossless -// fields are updated appropriately upon success. -VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers); - -//------------------------------------------------------------------------------ -// Misc utils - -// Initializes VP8Io with custom setup, io and teardown functions. The default -// hooks will use the supplied 'params' as io->opaque handle. -void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io); - -// Setup crop_xxx fields, mb_w and mb_h in io. 'src_colorspace' refers -// to the *compressed* format, not the output one. -int WebPIoInitFromOptions(const WebPDecoderOptions* const options, - VP8Io* const io, WEBP_CSP_MODE src_colorspace); - -//------------------------------------------------------------------------------ -// Internal functions regarding WebPDecBuffer memory (in buffer.c). -// Don't really need to be externally visible for now. - -// Prepare 'buffer' with the requested initial dimensions width/height. -// If no external storage is supplied, initializes buffer by allocating output -// memory and setting up the stride information. Validate the parameters. Return -// an error code in case of problem (no memory, or invalid stride / size / -// dimension / etc.). If *options is not NULL, also verify that the options' -// parameters are valid and apply them to the width/height dimensions of the -// output buffer. This takes cropping / scaling / rotation into account. -// Also incorporates the options->flip flag to flip the buffer parameters if -// needed. -VP8StatusCode WebPAllocateDecBuffer(int width, int height, - const WebPDecoderOptions* const options, - WebPDecBuffer* const buffer); - -// Flip buffer vertically by negating the various strides. -VP8StatusCode WebPFlipBuffer(WebPDecBuffer* const buffer); - -// Copy 'src' into 'dst' buffer, making sure 'dst' is not marked as owner of the -// memory (still held by 'src'). -void WebPCopyDecBuffer(const WebPDecBuffer* const src, - WebPDecBuffer* const dst); - -// Copy and transfer ownership from src to dst (beware of parameter order!) -void WebPGrabDecBuffer(WebPDecBuffer* const src, WebPDecBuffer* const dst); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_DEC_WEBPI_H_ */ diff --git a/Example/Pods/libwebp/src/demux/anim_decode.c b/Example/Pods/libwebp/src/demux/anim_decode.c deleted file mode 100644 index 1989eb4a..00000000 --- a/Example/Pods/libwebp/src/demux/anim_decode.c +++ /dev/null @@ -1,442 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// AnimDecoder implementation. -// - -#ifdef HAVE_CONFIG_H -#include "../webp/config.h" -#endif - -#include -#include - -#include "../utils/utils.h" -#include "../webp/decode.h" -#include "../webp/demux.h" - -#define NUM_CHANNELS 4 - -typedef void (*BlendRowFunc)(uint32_t* const, const uint32_t* const, int); -static void BlendPixelRowNonPremult(uint32_t* const src, - const uint32_t* const dst, int num_pixels); -static void BlendPixelRowPremult(uint32_t* const src, const uint32_t* const dst, - int num_pixels); - -struct WebPAnimDecoder { - WebPDemuxer* demux_; // Demuxer created from given WebP bitstream. - WebPDecoderConfig config_; // Decoder config. - // Note: we use a pointer to a function blending multiple pixels at a time to - // allow possible inlining of per-pixel blending function. - BlendRowFunc blend_func_; // Pointer to the chose blend row function. - WebPAnimInfo info_; // Global info about the animation. - uint8_t* curr_frame_; // Current canvas (not disposed). - uint8_t* prev_frame_disposed_; // Previous canvas (properly disposed). - int prev_frame_timestamp_; // Previous frame timestamp (milliseconds). - WebPIterator prev_iter_; // Iterator object for previous frame. - int prev_frame_was_keyframe_; // True if previous frame was a keyframe. - int next_frame_; // Index of the next frame to be decoded - // (starting from 1). -}; - -static void DefaultDecoderOptions(WebPAnimDecoderOptions* const dec_options) { - dec_options->color_mode = MODE_RGBA; - dec_options->use_threads = 0; -} - -int WebPAnimDecoderOptionsInitInternal(WebPAnimDecoderOptions* dec_options, - int abi_version) { - if (dec_options == NULL || - WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_DEMUX_ABI_VERSION)) { - return 0; - } - DefaultDecoderOptions(dec_options); - return 1; -} - -static int ApplyDecoderOptions(const WebPAnimDecoderOptions* const dec_options, - WebPAnimDecoder* const dec) { - WEBP_CSP_MODE mode; - WebPDecoderConfig* config = &dec->config_; - assert(dec_options != NULL); - - mode = dec_options->color_mode; - if (mode != MODE_RGBA && mode != MODE_BGRA && - mode != MODE_rgbA && mode != MODE_bgrA) { - return 0; - } - dec->blend_func_ = (mode == MODE_RGBA || mode == MODE_BGRA) - ? &BlendPixelRowNonPremult - : &BlendPixelRowPremult; - WebPInitDecoderConfig(config); - config->output.colorspace = mode; - config->output.is_external_memory = 1; - config->options.use_threads = dec_options->use_threads; - // Note: config->output.u.RGBA is set at the time of decoding each frame. - return 1; -} - -WebPAnimDecoder* WebPAnimDecoderNewInternal( - const WebPData* webp_data, const WebPAnimDecoderOptions* dec_options, - int abi_version) { - WebPAnimDecoderOptions options; - WebPAnimDecoder* dec = NULL; - if (webp_data == NULL || - WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_DEMUX_ABI_VERSION)) { - return NULL; - } - - // Note: calloc() so that the pointer members are initialized to NULL. - dec = (WebPAnimDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); - if (dec == NULL) goto Error; - - if (dec_options != NULL) { - options = *dec_options; - } else { - DefaultDecoderOptions(&options); - } - if (!ApplyDecoderOptions(&options, dec)) goto Error; - - dec->demux_ = WebPDemux(webp_data); - if (dec->demux_ == NULL) goto Error; - - dec->info_.canvas_width = WebPDemuxGetI(dec->demux_, WEBP_FF_CANVAS_WIDTH); - dec->info_.canvas_height = WebPDemuxGetI(dec->demux_, WEBP_FF_CANVAS_HEIGHT); - dec->info_.loop_count = WebPDemuxGetI(dec->demux_, WEBP_FF_LOOP_COUNT); - dec->info_.bgcolor = WebPDemuxGetI(dec->demux_, WEBP_FF_BACKGROUND_COLOR); - dec->info_.frame_count = WebPDemuxGetI(dec->demux_, WEBP_FF_FRAME_COUNT); - - { - const int canvas_bytes = - dec->info_.canvas_width * NUM_CHANNELS * dec->info_.canvas_height; - // Note: calloc() because we fill frame with zeroes as well. - dec->curr_frame_ = WebPSafeCalloc(1ULL, canvas_bytes); - if (dec->curr_frame_ == NULL) goto Error; - dec->prev_frame_disposed_ = WebPSafeCalloc(1ULL, canvas_bytes); - if (dec->prev_frame_disposed_ == NULL) goto Error; - } - - WebPAnimDecoderReset(dec); - - return dec; - - Error: - WebPAnimDecoderDelete(dec); - return NULL; -} - -int WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec, WebPAnimInfo* info) { - if (dec == NULL || info == NULL) return 0; - *info = dec->info_; - return 1; -} - -// Returns true if the frame covers the full canvas. -static int IsFullFrame(int width, int height, int canvas_width, - int canvas_height) { - return (width == canvas_width && height == canvas_height); -} - -// Clear the canvas to transparent. -static void ZeroFillCanvas(uint8_t* buf, uint32_t canvas_width, - uint32_t canvas_height) { - memset(buf, 0, canvas_width * NUM_CHANNELS * canvas_height); -} - -// Clear given frame rectangle to transparent. -static void ZeroFillFrameRect(uint8_t* buf, int buf_stride, int x_offset, - int y_offset, int width, int height) { - int j; - assert(width * NUM_CHANNELS <= buf_stride); - buf += y_offset * buf_stride + x_offset * NUM_CHANNELS; - for (j = 0; j < height; ++j) { - memset(buf, 0, width * NUM_CHANNELS); - buf += buf_stride; - } -} - -// Copy width * height pixels from 'src' to 'dst'. -static void CopyCanvas(const uint8_t* src, uint8_t* dst, - uint32_t width, uint32_t height) { - assert(src != NULL && dst != NULL); - memcpy(dst, src, width * NUM_CHANNELS * height); -} - -// Returns true if the current frame is a key-frame. -static int IsKeyFrame(const WebPIterator* const curr, - const WebPIterator* const prev, - int prev_frame_was_key_frame, - int canvas_width, int canvas_height) { - if (curr->frame_num == 1) { - return 1; - } else if ((!curr->has_alpha || curr->blend_method == WEBP_MUX_NO_BLEND) && - IsFullFrame(curr->width, curr->height, - canvas_width, canvas_height)) { - return 1; - } else { - return (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) && - (IsFullFrame(prev->width, prev->height, canvas_width, - canvas_height) || - prev_frame_was_key_frame); - } -} - - -// Blend a single channel of 'src' over 'dst', given their alpha channel values. -// 'src' and 'dst' are assumed to be NOT pre-multiplied by alpha. -static uint8_t BlendChannelNonPremult(uint32_t src, uint8_t src_a, - uint32_t dst, uint8_t dst_a, - uint32_t scale, int shift) { - const uint8_t src_channel = (src >> shift) & 0xff; - const uint8_t dst_channel = (dst >> shift) & 0xff; - const uint32_t blend_unscaled = src_channel * src_a + dst_channel * dst_a; - assert(blend_unscaled < (1ULL << 32) / scale); - return (blend_unscaled * scale) >> 24; -} - -// Blend 'src' over 'dst' assuming they are NOT pre-multiplied by alpha. -static uint32_t BlendPixelNonPremult(uint32_t src, uint32_t dst) { - const uint8_t src_a = (src >> 24) & 0xff; - - if (src_a == 0) { - return dst; - } else { - const uint8_t dst_a = (dst >> 24) & 0xff; - // This is the approximate integer arithmetic for the actual formula: - // dst_factor_a = (dst_a * (255 - src_a)) / 255. - const uint8_t dst_factor_a = (dst_a * (256 - src_a)) >> 8; - const uint8_t blend_a = src_a + dst_factor_a; - const uint32_t scale = (1UL << 24) / blend_a; - - const uint8_t blend_r = - BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 0); - const uint8_t blend_g = - BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 8); - const uint8_t blend_b = - BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 16); - assert(src_a + dst_factor_a < 256); - - return (blend_r << 0) | - (blend_g << 8) | - (blend_b << 16) | - ((uint32_t)blend_a << 24); - } -} - -// Blend 'num_pixels' in 'src' over 'dst' assuming they are NOT pre-multiplied -// by alpha. -static void BlendPixelRowNonPremult(uint32_t* const src, - const uint32_t* const dst, int num_pixels) { - int i; - for (i = 0; i < num_pixels; ++i) { - const uint8_t src_alpha = (src[i] >> 24) & 0xff; - if (src_alpha != 0xff) { - src[i] = BlendPixelNonPremult(src[i], dst[i]); - } - } -} - -// Individually multiply each channel in 'pix' by 'scale'. -static WEBP_INLINE uint32_t ChannelwiseMultiply(uint32_t pix, uint32_t scale) { - uint32_t mask = 0x00FF00FF; - uint32_t rb = ((pix & mask) * scale) >> 8; - uint32_t ag = ((pix >> 8) & mask) * scale; - return (rb & mask) | (ag & ~mask); -} - -// Blend 'src' over 'dst' assuming they are pre-multiplied by alpha. -static uint32_t BlendPixelPremult(uint32_t src, uint32_t dst) { - const uint8_t src_a = (src >> 24) & 0xff; - return src + ChannelwiseMultiply(dst, 256 - src_a); -} - -// Blend 'num_pixels' in 'src' over 'dst' assuming they are pre-multiplied by -// alpha. -static void BlendPixelRowPremult(uint32_t* const src, const uint32_t* const dst, - int num_pixels) { - int i; - for (i = 0; i < num_pixels; ++i) { - const uint8_t src_alpha = (src[i] >> 24) & 0xff; - if (src_alpha != 0xff) { - src[i] = BlendPixelPremult(src[i], dst[i]); - } - } -} - -// Returns two ranges ( pairs) at row 'canvas_y', that belong to -// 'src' but not 'dst'. A point range is empty if the corresponding width is 0. -static void FindBlendRangeAtRow(const WebPIterator* const src, - const WebPIterator* const dst, int canvas_y, - int* const left1, int* const width1, - int* const left2, int* const width2) { - const int src_max_x = src->x_offset + src->width; - const int dst_max_x = dst->x_offset + dst->width; - const int dst_max_y = dst->y_offset + dst->height; - assert(canvas_y >= src->y_offset && canvas_y < (src->y_offset + src->height)); - *left1 = -1; - *width1 = 0; - *left2 = -1; - *width2 = 0; - - if (canvas_y < dst->y_offset || canvas_y >= dst_max_y || - src->x_offset >= dst_max_x || src_max_x <= dst->x_offset) { - *left1 = src->x_offset; - *width1 = src->width; - return; - } - - if (src->x_offset < dst->x_offset) { - *left1 = src->x_offset; - *width1 = dst->x_offset - src->x_offset; - } - - if (src_max_x > dst_max_x) { - *left2 = dst_max_x; - *width2 = src_max_x - dst_max_x; - } -} - -int WebPAnimDecoderGetNext(WebPAnimDecoder* dec, - uint8_t** buf_ptr, int* timestamp_ptr) { - WebPIterator iter; - uint32_t width; - uint32_t height; - int is_key_frame; - int timestamp; - BlendRowFunc blend_row; - - if (dec == NULL || buf_ptr == NULL || timestamp_ptr == NULL) return 0; - if (!WebPAnimDecoderHasMoreFrames(dec)) return 0; - - width = dec->info_.canvas_width; - height = dec->info_.canvas_height; - blend_row = dec->blend_func_; - - // Get compressed frame. - if (!WebPDemuxGetFrame(dec->demux_, dec->next_frame_, &iter)) { - return 0; - } - timestamp = dec->prev_frame_timestamp_ + iter.duration; - - // Initialize. - is_key_frame = IsKeyFrame(&iter, &dec->prev_iter_, - dec->prev_frame_was_keyframe_, width, height); - if (is_key_frame) { - ZeroFillCanvas(dec->curr_frame_, width, height); - } else { - CopyCanvas(dec->prev_frame_disposed_, dec->curr_frame_, width, height); - } - - // Decode. - { - const uint8_t* in = iter.fragment.bytes; - const size_t in_size = iter.fragment.size; - const size_t out_offset = - (iter.y_offset * width + iter.x_offset) * NUM_CHANNELS; - WebPDecoderConfig* const config = &dec->config_; - WebPRGBABuffer* const buf = &config->output.u.RGBA; - buf->stride = NUM_CHANNELS * width; - buf->size = buf->stride * iter.height; - buf->rgba = dec->curr_frame_ + out_offset; - - if (WebPDecode(in, in_size, config) != VP8_STATUS_OK) { - goto Error; - } - } - - // During the decoding of current frame, we may have set some pixels to be - // transparent (i.e. alpha < 255). However, the value of each of these - // pixels should have been determined by blending it against the value of - // that pixel in the previous frame if blending method of is WEBP_MUX_BLEND. - if (iter.frame_num > 1 && iter.blend_method == WEBP_MUX_BLEND && - !is_key_frame) { - if (dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_NONE) { - int y; - // Blend transparent pixels with pixels in previous canvas. - for (y = 0; y < iter.height; ++y) { - const size_t offset = - (iter.y_offset + y) * width + iter.x_offset; - blend_row((uint32_t*)dec->curr_frame_ + offset, - (uint32_t*)dec->prev_frame_disposed_ + offset, iter.width); - } - } else { - int y; - assert(dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND); - // We need to blend a transparent pixel with its value just after - // initialization. That is, blend it with: - // * Fully transparent pixel if it belongs to prevRect <-- No-op. - // * The pixel in the previous canvas otherwise <-- Need alpha-blending. - for (y = 0; y < iter.height; ++y) { - const int canvas_y = iter.y_offset + y; - int left1, width1, left2, width2; - FindBlendRangeAtRow(&iter, &dec->prev_iter_, canvas_y, &left1, &width1, - &left2, &width2); - if (width1 > 0) { - const size_t offset1 = canvas_y * width + left1; - blend_row((uint32_t*)dec->curr_frame_ + offset1, - (uint32_t*)dec->prev_frame_disposed_ + offset1, width1); - } - if (width2 > 0) { - const size_t offset2 = canvas_y * width + left2; - blend_row((uint32_t*)dec->curr_frame_ + offset2, - (uint32_t*)dec->prev_frame_disposed_ + offset2, width2); - } - } - } - } - - // Update info of the previous frame and dispose it for the next iteration. - dec->prev_frame_timestamp_ = timestamp; - dec->prev_iter_ = iter; - dec->prev_frame_was_keyframe_ = is_key_frame; - CopyCanvas(dec->curr_frame_, dec->prev_frame_disposed_, width, height); - if (dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { - ZeroFillFrameRect(dec->prev_frame_disposed_, width * NUM_CHANNELS, - dec->prev_iter_.x_offset, dec->prev_iter_.y_offset, - dec->prev_iter_.width, dec->prev_iter_.height); - } - ++dec->next_frame_; - - // All OK, fill in the values. - *buf_ptr = dec->curr_frame_; - *timestamp_ptr = timestamp; - return 1; - - Error: - WebPDemuxReleaseIterator(&iter); - return 0; -} - -int WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec) { - if (dec == NULL) return 0; - return (dec->next_frame_ <= (int)dec->info_.frame_count); -} - -void WebPAnimDecoderReset(WebPAnimDecoder* dec) { - if (dec != NULL) { - dec->prev_frame_timestamp_ = 0; - memset(&dec->prev_iter_, 0, sizeof(dec->prev_iter_)); - dec->prev_frame_was_keyframe_ = 0; - dec->next_frame_ = 1; - } -} - -const WebPDemuxer* WebPAnimDecoderGetDemuxer(const WebPAnimDecoder* dec) { - if (dec == NULL) return NULL; - return dec->demux_; -} - -void WebPAnimDecoderDelete(WebPAnimDecoder* dec) { - if (dec != NULL) { - WebPDemuxDelete(dec->demux_); - WebPSafeFree(dec->curr_frame_); - WebPSafeFree(dec->prev_frame_disposed_); - WebPSafeFree(dec); - } -} diff --git a/Example/Pods/libwebp/src/demux/demux.c b/Example/Pods/libwebp/src/demux/demux.c deleted file mode 100644 index 0d2989f6..00000000 --- a/Example/Pods/libwebp/src/demux/demux.c +++ /dev/null @@ -1,966 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// WebP container demux. -// - -#ifdef HAVE_CONFIG_H -#include "../webp/config.h" -#endif - -#include -#include -#include - -#include "../utils/utils.h" -#include "../webp/decode.h" // WebPGetFeatures -#include "../webp/demux.h" -#include "../webp/format_constants.h" - -#define DMUX_MAJ_VERSION 0 -#define DMUX_MIN_VERSION 3 -#define DMUX_REV_VERSION 0 - -typedef struct { - size_t start_; // start location of the data - size_t end_; // end location - size_t riff_end_; // riff chunk end location, can be > end_. - size_t buf_size_; // size of the buffer - const uint8_t* buf_; -} MemBuffer; - -typedef struct { - size_t offset_; - size_t size_; -} ChunkData; - -typedef struct Frame { - int x_offset_, y_offset_; - int width_, height_; - int has_alpha_; - int duration_; - WebPMuxAnimDispose dispose_method_; - WebPMuxAnimBlend blend_method_; - int frame_num_; - int complete_; // img_components_ contains a full image. - ChunkData img_components_[2]; // 0=VP8{,L} 1=ALPH - struct Frame* next_; -} Frame; - -typedef struct Chunk { - ChunkData data_; - struct Chunk* next_; -} Chunk; - -struct WebPDemuxer { - MemBuffer mem_; - WebPDemuxState state_; - int is_ext_format_; - uint32_t feature_flags_; - int canvas_width_, canvas_height_; - int loop_count_; - uint32_t bgcolor_; - int num_frames_; - Frame* frames_; - Frame** frames_tail_; - Chunk* chunks_; // non-image chunks - Chunk** chunks_tail_; -}; - -typedef enum { - PARSE_OK, - PARSE_NEED_MORE_DATA, - PARSE_ERROR -} ParseStatus; - -typedef struct ChunkParser { - uint8_t id[4]; - ParseStatus (*parse)(WebPDemuxer* const dmux); - int (*valid)(const WebPDemuxer* const dmux); -} ChunkParser; - -static ParseStatus ParseSingleImage(WebPDemuxer* const dmux); -static ParseStatus ParseVP8X(WebPDemuxer* const dmux); -static int IsValidSimpleFormat(const WebPDemuxer* const dmux); -static int IsValidExtendedFormat(const WebPDemuxer* const dmux); - -static const ChunkParser kMasterChunks[] = { - { { 'V', 'P', '8', ' ' }, ParseSingleImage, IsValidSimpleFormat }, - { { 'V', 'P', '8', 'L' }, ParseSingleImage, IsValidSimpleFormat }, - { { 'V', 'P', '8', 'X' }, ParseVP8X, IsValidExtendedFormat }, - { { '0', '0', '0', '0' }, NULL, NULL }, -}; - -//------------------------------------------------------------------------------ - -int WebPGetDemuxVersion(void) { - return (DMUX_MAJ_VERSION << 16) | (DMUX_MIN_VERSION << 8) | DMUX_REV_VERSION; -} - -// ----------------------------------------------------------------------------- -// MemBuffer - -static int RemapMemBuffer(MemBuffer* const mem, - const uint8_t* data, size_t size) { - if (size < mem->buf_size_) return 0; // can't remap to a shorter buffer! - - mem->buf_ = data; - mem->end_ = mem->buf_size_ = size; - return 1; -} - -static int InitMemBuffer(MemBuffer* const mem, - const uint8_t* data, size_t size) { - memset(mem, 0, sizeof(*mem)); - return RemapMemBuffer(mem, data, size); -} - -// Return the remaining data size available in 'mem'. -static WEBP_INLINE size_t MemDataSize(const MemBuffer* const mem) { - return (mem->end_ - mem->start_); -} - -// Return true if 'size' exceeds the end of the RIFF chunk. -static WEBP_INLINE int SizeIsInvalid(const MemBuffer* const mem, size_t size) { - return (size > mem->riff_end_ - mem->start_); -} - -static WEBP_INLINE void Skip(MemBuffer* const mem, size_t size) { - mem->start_ += size; -} - -static WEBP_INLINE void Rewind(MemBuffer* const mem, size_t size) { - mem->start_ -= size; -} - -static WEBP_INLINE const uint8_t* GetBuffer(MemBuffer* const mem) { - return mem->buf_ + mem->start_; -} - -// Read from 'mem' and skip the read bytes. -static WEBP_INLINE uint8_t ReadByte(MemBuffer* const mem) { - const uint8_t byte = mem->buf_[mem->start_]; - Skip(mem, 1); - return byte; -} - -static WEBP_INLINE int ReadLE16s(MemBuffer* const mem) { - const uint8_t* const data = mem->buf_ + mem->start_; - const int val = GetLE16(data); - Skip(mem, 2); - return val; -} - -static WEBP_INLINE int ReadLE24s(MemBuffer* const mem) { - const uint8_t* const data = mem->buf_ + mem->start_; - const int val = GetLE24(data); - Skip(mem, 3); - return val; -} - -static WEBP_INLINE uint32_t ReadLE32(MemBuffer* const mem) { - const uint8_t* const data = mem->buf_ + mem->start_; - const uint32_t val = GetLE32(data); - Skip(mem, 4); - return val; -} - -// ----------------------------------------------------------------------------- -// Secondary chunk parsing - -static void AddChunk(WebPDemuxer* const dmux, Chunk* const chunk) { - *dmux->chunks_tail_ = chunk; - chunk->next_ = NULL; - dmux->chunks_tail_ = &chunk->next_; -} - -// Add a frame to the end of the list, ensuring the last frame is complete. -// Returns true on success, false otherwise. -static int AddFrame(WebPDemuxer* const dmux, Frame* const frame) { - const Frame* const last_frame = *dmux->frames_tail_; - if (last_frame != NULL && !last_frame->complete_) return 0; - - *dmux->frames_tail_ = frame; - frame->next_ = NULL; - dmux->frames_tail_ = &frame->next_; - return 1; -} - -static void SetFrameInfo(size_t start_offset, size_t size, - int frame_num, int complete, - const WebPBitstreamFeatures* const features, - Frame* const frame) { - frame->img_components_[0].offset_ = start_offset; - frame->img_components_[0].size_ = size; - frame->width_ = features->width; - frame->height_ = features->height; - frame->has_alpha_ |= features->has_alpha; - frame->frame_num_ = frame_num; - frame->complete_ = complete; -} - -// Store image bearing chunks to 'frame'. -static ParseStatus StoreFrame(int frame_num, uint32_t min_size, - MemBuffer* const mem, Frame* const frame) { - int alpha_chunks = 0; - int image_chunks = 0; - int done = (MemDataSize(mem) < min_size); - ParseStatus status = PARSE_OK; - - if (done) return PARSE_NEED_MORE_DATA; - - do { - const size_t chunk_start_offset = mem->start_; - const uint32_t fourcc = ReadLE32(mem); - const uint32_t payload_size = ReadLE32(mem); - const uint32_t payload_size_padded = payload_size + (payload_size & 1); - const size_t payload_available = (payload_size_padded > MemDataSize(mem)) - ? MemDataSize(mem) : payload_size_padded; - const size_t chunk_size = CHUNK_HEADER_SIZE + payload_available; - - if (payload_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; - if (SizeIsInvalid(mem, payload_size_padded)) return PARSE_ERROR; - if (payload_size_padded > MemDataSize(mem)) status = PARSE_NEED_MORE_DATA; - - switch (fourcc) { - case MKFOURCC('A', 'L', 'P', 'H'): - if (alpha_chunks == 0) { - ++alpha_chunks; - frame->img_components_[1].offset_ = chunk_start_offset; - frame->img_components_[1].size_ = chunk_size; - frame->has_alpha_ = 1; - frame->frame_num_ = frame_num; - Skip(mem, payload_available); - } else { - goto Done; - } - break; - case MKFOURCC('V', 'P', '8', 'L'): - if (alpha_chunks > 0) return PARSE_ERROR; // VP8L has its own alpha - // fall through - case MKFOURCC('V', 'P', '8', ' '): - if (image_chunks == 0) { - // Extract the bitstream features, tolerating failures when the data - // is incomplete. - WebPBitstreamFeatures features; - const VP8StatusCode vp8_status = - WebPGetFeatures(mem->buf_ + chunk_start_offset, chunk_size, - &features); - if (status == PARSE_NEED_MORE_DATA && - vp8_status == VP8_STATUS_NOT_ENOUGH_DATA) { - return PARSE_NEED_MORE_DATA; - } else if (vp8_status != VP8_STATUS_OK) { - // We have enough data, and yet WebPGetFeatures() failed. - return PARSE_ERROR; - } - ++image_chunks; - SetFrameInfo(chunk_start_offset, chunk_size, frame_num, - status == PARSE_OK, &features, frame); - Skip(mem, payload_available); - } else { - goto Done; - } - break; - Done: - default: - // Restore fourcc/size when moving up one level in parsing. - Rewind(mem, CHUNK_HEADER_SIZE); - done = 1; - break; - } - - if (mem->start_ == mem->riff_end_) { - done = 1; - } else if (MemDataSize(mem) < CHUNK_HEADER_SIZE) { - status = PARSE_NEED_MORE_DATA; - } - } while (!done && status == PARSE_OK); - - return status; -} - -// Creates a new Frame if 'actual_size' is within bounds and 'mem' contains -// enough data ('min_size') to parse the payload. -// Returns PARSE_OK on success with *frame pointing to the new Frame. -// Returns PARSE_NEED_MORE_DATA with insufficient data, PARSE_ERROR otherwise. -static ParseStatus NewFrame(const MemBuffer* const mem, - uint32_t min_size, uint32_t actual_size, - Frame** frame) { - if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR; - if (actual_size < min_size) return PARSE_ERROR; - if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA; - - *frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(**frame)); - return (*frame == NULL) ? PARSE_ERROR : PARSE_OK; -} - -// Parse a 'ANMF' chunk and any image bearing chunks that immediately follow. -// 'frame_chunk_size' is the previously validated, padded chunk size. -static ParseStatus ParseAnimationFrame( - WebPDemuxer* const dmux, uint32_t frame_chunk_size) { - const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG); - const uint32_t anmf_payload_size = frame_chunk_size - ANMF_CHUNK_SIZE; - int added_frame = 0; - int bits; - MemBuffer* const mem = &dmux->mem_; - Frame* frame; - ParseStatus status = - NewFrame(mem, ANMF_CHUNK_SIZE, frame_chunk_size, &frame); - if (status != PARSE_OK) return status; - - frame->x_offset_ = 2 * ReadLE24s(mem); - frame->y_offset_ = 2 * ReadLE24s(mem); - frame->width_ = 1 + ReadLE24s(mem); - frame->height_ = 1 + ReadLE24s(mem); - frame->duration_ = ReadLE24s(mem); - bits = ReadByte(mem); - frame->dispose_method_ = - (bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE; - frame->blend_method_ = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND; - if (frame->width_ * (uint64_t)frame->height_ >= MAX_IMAGE_AREA) { - WebPSafeFree(frame); - return PARSE_ERROR; - } - - // Store a frame only if the animation flag is set there is some data for - // this frame is available. - status = StoreFrame(dmux->num_frames_ + 1, anmf_payload_size, mem, frame); - if (status != PARSE_ERROR && is_animation && frame->frame_num_ > 0) { - added_frame = AddFrame(dmux, frame); - if (added_frame) { - ++dmux->num_frames_; - } else { - status = PARSE_ERROR; - } - } - - if (!added_frame) WebPSafeFree(frame); - return status; -} - -// General chunk storage, starting with the header at 'start_offset', allowing -// the user to request the payload via a fourcc string. 'size' includes the -// header and the unpadded payload size. -// Returns true on success, false otherwise. -static int StoreChunk(WebPDemuxer* const dmux, - size_t start_offset, uint32_t size) { - Chunk* const chunk = (Chunk*)WebPSafeCalloc(1ULL, sizeof(*chunk)); - if (chunk == NULL) return 0; - - chunk->data_.offset_ = start_offset; - chunk->data_.size_ = size; - AddChunk(dmux, chunk); - return 1; -} - -// ----------------------------------------------------------------------------- -// Primary chunk parsing - -static ParseStatus ReadHeader(MemBuffer* const mem) { - const size_t min_size = RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE; - uint32_t riff_size; - - // Basic file level validation. - if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA; - if (memcmp(GetBuffer(mem), "RIFF", CHUNK_SIZE_BYTES) || - memcmp(GetBuffer(mem) + CHUNK_HEADER_SIZE, "WEBP", CHUNK_SIZE_BYTES)) { - return PARSE_ERROR; - } - - riff_size = GetLE32(GetBuffer(mem) + TAG_SIZE); - if (riff_size < CHUNK_HEADER_SIZE) return PARSE_ERROR; - if (riff_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; - - // There's no point in reading past the end of the RIFF chunk - mem->riff_end_ = riff_size + CHUNK_HEADER_SIZE; - if (mem->buf_size_ > mem->riff_end_) { - mem->buf_size_ = mem->end_ = mem->riff_end_; - } - - Skip(mem, RIFF_HEADER_SIZE); - return PARSE_OK; -} - -static ParseStatus ParseSingleImage(WebPDemuxer* const dmux) { - const size_t min_size = CHUNK_HEADER_SIZE; - MemBuffer* const mem = &dmux->mem_; - Frame* frame; - ParseStatus status; - int image_added = 0; - - if (dmux->frames_ != NULL) return PARSE_ERROR; - if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR; - if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA; - - frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame)); - if (frame == NULL) return PARSE_ERROR; - - // For the single image case we allow parsing of a partial frame, but we need - // at least CHUNK_HEADER_SIZE for parsing. - status = StoreFrame(1, CHUNK_HEADER_SIZE, &dmux->mem_, frame); - if (status != PARSE_ERROR) { - const int has_alpha = !!(dmux->feature_flags_ & ALPHA_FLAG); - // Clear any alpha when the alpha flag is missing. - if (!has_alpha && frame->img_components_[1].size_ > 0) { - frame->img_components_[1].offset_ = 0; - frame->img_components_[1].size_ = 0; - frame->has_alpha_ = 0; - } - - // Use the frame width/height as the canvas values for non-vp8x files. - // Also, set ALPHA_FLAG if this is a lossless image with alpha. - if (!dmux->is_ext_format_ && frame->width_ > 0 && frame->height_ > 0) { - dmux->state_ = WEBP_DEMUX_PARSED_HEADER; - dmux->canvas_width_ = frame->width_; - dmux->canvas_height_ = frame->height_; - dmux->feature_flags_ |= frame->has_alpha_ ? ALPHA_FLAG : 0; - } - if (!AddFrame(dmux, frame)) { - status = PARSE_ERROR; // last frame was left incomplete - } else { - image_added = 1; - dmux->num_frames_ = 1; - } - } - - if (!image_added) WebPSafeFree(frame); - return status; -} - -static ParseStatus ParseVP8XChunks(WebPDemuxer* const dmux) { - const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG); - MemBuffer* const mem = &dmux->mem_; - int anim_chunks = 0; - ParseStatus status = PARSE_OK; - - do { - int store_chunk = 1; - const size_t chunk_start_offset = mem->start_; - const uint32_t fourcc = ReadLE32(mem); - const uint32_t chunk_size = ReadLE32(mem); - const uint32_t chunk_size_padded = chunk_size + (chunk_size & 1); - - if (chunk_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; - if (SizeIsInvalid(mem, chunk_size_padded)) return PARSE_ERROR; - - switch (fourcc) { - case MKFOURCC('V', 'P', '8', 'X'): { - return PARSE_ERROR; - } - case MKFOURCC('A', 'L', 'P', 'H'): - case MKFOURCC('V', 'P', '8', ' '): - case MKFOURCC('V', 'P', '8', 'L'): { - // check that this isn't an animation (all frames should be in an ANMF). - if (anim_chunks > 0 || is_animation) return PARSE_ERROR; - - Rewind(mem, CHUNK_HEADER_SIZE); - status = ParseSingleImage(dmux); - break; - } - case MKFOURCC('A', 'N', 'I', 'M'): { - if (chunk_size_padded < ANIM_CHUNK_SIZE) return PARSE_ERROR; - - if (MemDataSize(mem) < chunk_size_padded) { - status = PARSE_NEED_MORE_DATA; - } else if (anim_chunks == 0) { - ++anim_chunks; - dmux->bgcolor_ = ReadLE32(mem); - dmux->loop_count_ = ReadLE16s(mem); - Skip(mem, chunk_size_padded - ANIM_CHUNK_SIZE); - } else { - store_chunk = 0; - goto Skip; - } - break; - } - case MKFOURCC('A', 'N', 'M', 'F'): { - if (anim_chunks == 0) return PARSE_ERROR; // 'ANIM' precedes frames. - status = ParseAnimationFrame(dmux, chunk_size_padded); - break; - } - case MKFOURCC('I', 'C', 'C', 'P'): { - store_chunk = !!(dmux->feature_flags_ & ICCP_FLAG); - goto Skip; - } - case MKFOURCC('E', 'X', 'I', 'F'): { - store_chunk = !!(dmux->feature_flags_ & EXIF_FLAG); - goto Skip; - } - case MKFOURCC('X', 'M', 'P', ' '): { - store_chunk = !!(dmux->feature_flags_ & XMP_FLAG); - goto Skip; - } - Skip: - default: { - if (chunk_size_padded <= MemDataSize(mem)) { - if (store_chunk) { - // Store only the chunk header and unpadded size as only the payload - // will be returned to the user. - if (!StoreChunk(dmux, chunk_start_offset, - CHUNK_HEADER_SIZE + chunk_size)) { - return PARSE_ERROR; - } - } - Skip(mem, chunk_size_padded); - } else { - status = PARSE_NEED_MORE_DATA; - } - } - } - - if (mem->start_ == mem->riff_end_) { - break; - } else if (MemDataSize(mem) < CHUNK_HEADER_SIZE) { - status = PARSE_NEED_MORE_DATA; - } - } while (status == PARSE_OK); - - return status; -} - -static ParseStatus ParseVP8X(WebPDemuxer* const dmux) { - MemBuffer* const mem = &dmux->mem_; - uint32_t vp8x_size; - - if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA; - - dmux->is_ext_format_ = 1; - Skip(mem, TAG_SIZE); // VP8X - vp8x_size = ReadLE32(mem); - if (vp8x_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; - if (vp8x_size < VP8X_CHUNK_SIZE) return PARSE_ERROR; - vp8x_size += vp8x_size & 1; - if (SizeIsInvalid(mem, vp8x_size)) return PARSE_ERROR; - if (MemDataSize(mem) < vp8x_size) return PARSE_NEED_MORE_DATA; - - dmux->feature_flags_ = ReadByte(mem); - Skip(mem, 3); // Reserved. - dmux->canvas_width_ = 1 + ReadLE24s(mem); - dmux->canvas_height_ = 1 + ReadLE24s(mem); - if (dmux->canvas_width_ * (uint64_t)dmux->canvas_height_ >= MAX_IMAGE_AREA) { - return PARSE_ERROR; // image final dimension is too large - } - Skip(mem, vp8x_size - VP8X_CHUNK_SIZE); // skip any trailing data. - dmux->state_ = WEBP_DEMUX_PARSED_HEADER; - - if (SizeIsInvalid(mem, CHUNK_HEADER_SIZE)) return PARSE_ERROR; - if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA; - - return ParseVP8XChunks(dmux); -} - -// ----------------------------------------------------------------------------- -// Format validation - -static int IsValidSimpleFormat(const WebPDemuxer* const dmux) { - const Frame* const frame = dmux->frames_; - if (dmux->state_ == WEBP_DEMUX_PARSING_HEADER) return 1; - - if (dmux->canvas_width_ <= 0 || dmux->canvas_height_ <= 0) return 0; - if (dmux->state_ == WEBP_DEMUX_DONE && frame == NULL) return 0; - - if (frame->width_ <= 0 || frame->height_ <= 0) return 0; - return 1; -} - -// If 'exact' is true, check that the image resolution matches the canvas. -// If 'exact' is false, check that the x/y offsets do not exceed the canvas. -static int CheckFrameBounds(const Frame* const frame, int exact, - int canvas_width, int canvas_height) { - if (exact) { - if (frame->x_offset_ != 0 || frame->y_offset_ != 0) { - return 0; - } - if (frame->width_ != canvas_width || frame->height_ != canvas_height) { - return 0; - } - } else { - if (frame->x_offset_ < 0 || frame->y_offset_ < 0) return 0; - if (frame->width_ + frame->x_offset_ > canvas_width) return 0; - if (frame->height_ + frame->y_offset_ > canvas_height) return 0; - } - return 1; -} - -static int IsValidExtendedFormat(const WebPDemuxer* const dmux) { - const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG); - const int is_fragmented = !!(dmux->feature_flags_ & FRAGMENTS_FLAG); - const Frame* f = dmux->frames_; - - if (dmux->state_ == WEBP_DEMUX_PARSING_HEADER) return 1; - - if (dmux->canvas_width_ <= 0 || dmux->canvas_height_ <= 0) return 0; - if (dmux->loop_count_ < 0) return 0; - if (dmux->state_ == WEBP_DEMUX_DONE && dmux->frames_ == NULL) return 0; - if (is_fragmented) return 0; - - while (f != NULL) { - const int cur_frame_set = f->frame_num_; - int frame_count = 0; - - // Check frame properties. - for (; f != NULL && f->frame_num_ == cur_frame_set; f = f->next_) { - const ChunkData* const image = f->img_components_; - const ChunkData* const alpha = f->img_components_ + 1; - - if (!is_animation && f->frame_num_ > 1) return 0; - - if (f->complete_) { - if (alpha->size_ == 0 && image->size_ == 0) return 0; - // Ensure alpha precedes image bitstream. - if (alpha->size_ > 0 && alpha->offset_ > image->offset_) { - return 0; - } - - if (f->width_ <= 0 || f->height_ <= 0) return 0; - } else { - // There shouldn't be a partial frame in a complete file. - if (dmux->state_ == WEBP_DEMUX_DONE) return 0; - - // Ensure alpha precedes image bitstream. - if (alpha->size_ > 0 && image->size_ > 0 && - alpha->offset_ > image->offset_) { - return 0; - } - // There shouldn't be any frames after an incomplete one. - if (f->next_ != NULL) return 0; - } - - if (f->width_ > 0 && f->height_ > 0 && - !CheckFrameBounds(f, !is_animation, - dmux->canvas_width_, dmux->canvas_height_)) { - return 0; - } - - ++frame_count; - } - } - return 1; -} - -// ----------------------------------------------------------------------------- -// WebPDemuxer object - -static void InitDemux(WebPDemuxer* const dmux, const MemBuffer* const mem) { - dmux->state_ = WEBP_DEMUX_PARSING_HEADER; - dmux->loop_count_ = 1; - dmux->bgcolor_ = 0xFFFFFFFF; // White background by default. - dmux->canvas_width_ = -1; - dmux->canvas_height_ = -1; - dmux->frames_tail_ = &dmux->frames_; - dmux->chunks_tail_ = &dmux->chunks_; - dmux->mem_ = *mem; -} - -static ParseStatus CreateRawImageDemuxer(MemBuffer* const mem, - WebPDemuxer** demuxer) { - WebPBitstreamFeatures features; - const VP8StatusCode status = - WebPGetFeatures(mem->buf_, mem->buf_size_, &features); - *demuxer = NULL; - if (status != VP8_STATUS_OK) { - return (status == VP8_STATUS_NOT_ENOUGH_DATA) ? PARSE_NEED_MORE_DATA - : PARSE_ERROR; - } - - { - WebPDemuxer* const dmux = (WebPDemuxer*)WebPSafeCalloc(1ULL, sizeof(*dmux)); - Frame* const frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame)); - if (dmux == NULL || frame == NULL) goto Error; - InitDemux(dmux, mem); - SetFrameInfo(0, mem->buf_size_, 1 /*frame_num*/, 1 /*complete*/, &features, - frame); - if (!AddFrame(dmux, frame)) goto Error; - dmux->state_ = WEBP_DEMUX_DONE; - dmux->canvas_width_ = frame->width_; - dmux->canvas_height_ = frame->height_; - dmux->feature_flags_ |= frame->has_alpha_ ? ALPHA_FLAG : 0; - dmux->num_frames_ = 1; - assert(IsValidSimpleFormat(dmux)); - *demuxer = dmux; - return PARSE_OK; - - Error: - WebPSafeFree(dmux); - WebPSafeFree(frame); - return PARSE_ERROR; - } -} - -WebPDemuxer* WebPDemuxInternal(const WebPData* data, int allow_partial, - WebPDemuxState* state, int version) { - const ChunkParser* parser; - int partial; - ParseStatus status = PARSE_ERROR; - MemBuffer mem; - WebPDemuxer* dmux; - - if (state != NULL) *state = WEBP_DEMUX_PARSE_ERROR; - - if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DEMUX_ABI_VERSION)) return NULL; - if (data == NULL || data->bytes == NULL || data->size == 0) return NULL; - - if (!InitMemBuffer(&mem, data->bytes, data->size)) return NULL; - status = ReadHeader(&mem); - if (status != PARSE_OK) { - // If parsing of the webp file header fails attempt to handle a raw - // VP8/VP8L frame. Note 'allow_partial' is ignored in this case. - if (status == PARSE_ERROR) { - status = CreateRawImageDemuxer(&mem, &dmux); - if (status == PARSE_OK) { - if (state != NULL) *state = WEBP_DEMUX_DONE; - return dmux; - } - } - if (state != NULL) { - *state = (status == PARSE_NEED_MORE_DATA) ? WEBP_DEMUX_PARSING_HEADER - : WEBP_DEMUX_PARSE_ERROR; - } - return NULL; - } - - partial = (mem.buf_size_ < mem.riff_end_); - if (!allow_partial && partial) return NULL; - - dmux = (WebPDemuxer*)WebPSafeCalloc(1ULL, sizeof(*dmux)); - if (dmux == NULL) return NULL; - InitDemux(dmux, &mem); - - status = PARSE_ERROR; - for (parser = kMasterChunks; parser->parse != NULL; ++parser) { - if (!memcmp(parser->id, GetBuffer(&dmux->mem_), TAG_SIZE)) { - status = parser->parse(dmux); - if (status == PARSE_OK) dmux->state_ = WEBP_DEMUX_DONE; - if (status == PARSE_NEED_MORE_DATA && !partial) status = PARSE_ERROR; - if (status != PARSE_ERROR && !parser->valid(dmux)) status = PARSE_ERROR; - if (status == PARSE_ERROR) dmux->state_ = WEBP_DEMUX_PARSE_ERROR; - break; - } - } - if (state != NULL) *state = dmux->state_; - - if (status == PARSE_ERROR) { - WebPDemuxDelete(dmux); - return NULL; - } - return dmux; -} - -void WebPDemuxDelete(WebPDemuxer* dmux) { - Chunk* c; - Frame* f; - if (dmux == NULL) return; - - for (f = dmux->frames_; f != NULL;) { - Frame* const cur_frame = f; - f = f->next_; - WebPSafeFree(cur_frame); - } - for (c = dmux->chunks_; c != NULL;) { - Chunk* const cur_chunk = c; - c = c->next_; - WebPSafeFree(cur_chunk); - } - WebPSafeFree(dmux); -} - -// ----------------------------------------------------------------------------- - -uint32_t WebPDemuxGetI(const WebPDemuxer* dmux, WebPFormatFeature feature) { - if (dmux == NULL) return 0; - - switch (feature) { - case WEBP_FF_FORMAT_FLAGS: return dmux->feature_flags_; - case WEBP_FF_CANVAS_WIDTH: return (uint32_t)dmux->canvas_width_; - case WEBP_FF_CANVAS_HEIGHT: return (uint32_t)dmux->canvas_height_; - case WEBP_FF_LOOP_COUNT: return (uint32_t)dmux->loop_count_; - case WEBP_FF_BACKGROUND_COLOR: return dmux->bgcolor_; - case WEBP_FF_FRAME_COUNT: return (uint32_t)dmux->num_frames_; - } - return 0; -} - -// ----------------------------------------------------------------------------- -// Frame iteration - -static const Frame* GetFrame(const WebPDemuxer* const dmux, int frame_num) { - const Frame* f; - for (f = dmux->frames_; f != NULL; f = f->next_) { - if (frame_num == f->frame_num_) break; - } - return f; -} - -static const uint8_t* GetFramePayload(const uint8_t* const mem_buf, - const Frame* const frame, - size_t* const data_size) { - *data_size = 0; - if (frame != NULL) { - const ChunkData* const image = frame->img_components_; - const ChunkData* const alpha = frame->img_components_ + 1; - size_t start_offset = image->offset_; - *data_size = image->size_; - - // if alpha exists it precedes image, update the size allowing for - // intervening chunks. - if (alpha->size_ > 0) { - const size_t inter_size = (image->offset_ > 0) - ? image->offset_ - (alpha->offset_ + alpha->size_) - : 0; - start_offset = alpha->offset_; - *data_size += alpha->size_ + inter_size; - } - return mem_buf + start_offset; - } - return NULL; -} - -// Create a whole 'frame' from VP8 (+ alpha) or lossless. -static int SynthesizeFrame(const WebPDemuxer* const dmux, - const Frame* const frame, - WebPIterator* const iter) { - const uint8_t* const mem_buf = dmux->mem_.buf_; - size_t payload_size = 0; - const uint8_t* const payload = GetFramePayload(mem_buf, frame, &payload_size); - if (payload == NULL) return 0; - assert(frame != NULL); - - iter->frame_num = frame->frame_num_; - iter->num_frames = dmux->num_frames_; - iter->x_offset = frame->x_offset_; - iter->y_offset = frame->y_offset_; - iter->width = frame->width_; - iter->height = frame->height_; - iter->has_alpha = frame->has_alpha_; - iter->duration = frame->duration_; - iter->dispose_method = frame->dispose_method_; - iter->blend_method = frame->blend_method_; - iter->complete = frame->complete_; - iter->fragment.bytes = payload; - iter->fragment.size = payload_size; - return 1; -} - -static int SetFrame(int frame_num, WebPIterator* const iter) { - const Frame* frame; - const WebPDemuxer* const dmux = (WebPDemuxer*)iter->private_; - if (dmux == NULL || frame_num < 0) return 0; - if (frame_num > dmux->num_frames_) return 0; - if (frame_num == 0) frame_num = dmux->num_frames_; - - frame = GetFrame(dmux, frame_num); - if (frame == NULL) return 0; - - return SynthesizeFrame(dmux, frame, iter); -} - -int WebPDemuxGetFrame(const WebPDemuxer* dmux, int frame, WebPIterator* iter) { - if (iter == NULL) return 0; - - memset(iter, 0, sizeof(*iter)); - iter->private_ = (void*)dmux; - return SetFrame(frame, iter); -} - -int WebPDemuxNextFrame(WebPIterator* iter) { - if (iter == NULL) return 0; - return SetFrame(iter->frame_num + 1, iter); -} - -int WebPDemuxPrevFrame(WebPIterator* iter) { - if (iter == NULL) return 0; - if (iter->frame_num <= 1) return 0; - return SetFrame(iter->frame_num - 1, iter); -} - -void WebPDemuxReleaseIterator(WebPIterator* iter) { - (void)iter; -} - -// ----------------------------------------------------------------------------- -// Chunk iteration - -static int ChunkCount(const WebPDemuxer* const dmux, const char fourcc[4]) { - const uint8_t* const mem_buf = dmux->mem_.buf_; - const Chunk* c; - int count = 0; - for (c = dmux->chunks_; c != NULL; c = c->next_) { - const uint8_t* const header = mem_buf + c->data_.offset_; - if (!memcmp(header, fourcc, TAG_SIZE)) ++count; - } - return count; -} - -static const Chunk* GetChunk(const WebPDemuxer* const dmux, - const char fourcc[4], int chunk_num) { - const uint8_t* const mem_buf = dmux->mem_.buf_; - const Chunk* c; - int count = 0; - for (c = dmux->chunks_; c != NULL; c = c->next_) { - const uint8_t* const header = mem_buf + c->data_.offset_; - if (!memcmp(header, fourcc, TAG_SIZE)) ++count; - if (count == chunk_num) break; - } - return c; -} - -static int SetChunk(const char fourcc[4], int chunk_num, - WebPChunkIterator* const iter) { - const WebPDemuxer* const dmux = (WebPDemuxer*)iter->private_; - int count; - - if (dmux == NULL || fourcc == NULL || chunk_num < 0) return 0; - count = ChunkCount(dmux, fourcc); - if (count == 0) return 0; - if (chunk_num == 0) chunk_num = count; - - if (chunk_num <= count) { - const uint8_t* const mem_buf = dmux->mem_.buf_; - const Chunk* const chunk = GetChunk(dmux, fourcc, chunk_num); - iter->chunk.bytes = mem_buf + chunk->data_.offset_ + CHUNK_HEADER_SIZE; - iter->chunk.size = chunk->data_.size_ - CHUNK_HEADER_SIZE; - iter->num_chunks = count; - iter->chunk_num = chunk_num; - return 1; - } - return 0; -} - -int WebPDemuxGetChunk(const WebPDemuxer* dmux, - const char fourcc[4], int chunk_num, - WebPChunkIterator* iter) { - if (iter == NULL) return 0; - - memset(iter, 0, sizeof(*iter)); - iter->private_ = (void*)dmux; - return SetChunk(fourcc, chunk_num, iter); -} - -int WebPDemuxNextChunk(WebPChunkIterator* iter) { - if (iter != NULL) { - const char* const fourcc = - (const char*)iter->chunk.bytes - CHUNK_HEADER_SIZE; - return SetChunk(fourcc, iter->chunk_num + 1, iter); - } - return 0; -} - -int WebPDemuxPrevChunk(WebPChunkIterator* iter) { - if (iter != NULL && iter->chunk_num > 1) { - const char* const fourcc = - (const char*)iter->chunk.bytes - CHUNK_HEADER_SIZE; - return SetChunk(fourcc, iter->chunk_num - 1, iter); - } - return 0; -} - -void WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter) { - (void)iter; -} - diff --git a/Example/Pods/libwebp/src/dsp/alpha_processing.c b/Example/Pods/libwebp/src/dsp/alpha_processing.c deleted file mode 100644 index 1716cace..00000000 --- a/Example/Pods/libwebp/src/dsp/alpha_processing.c +++ /dev/null @@ -1,383 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Utilities for processing transparent channel. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include "./dsp.h" - -// Tables can be faster on some platform but incur some extra binary size (~2k). -// #define USE_TABLES_FOR_ALPHA_MULT - -// ----------------------------------------------------------------------------- - -#define MFIX 24 // 24bit fixed-point arithmetic -#define HALF ((1u << MFIX) >> 1) -#define KINV_255 ((1u << MFIX) / 255u) - -static uint32_t Mult(uint8_t x, uint32_t mult) { - const uint32_t v = (x * mult + HALF) >> MFIX; - assert(v <= 255); // <- 24bit precision is enough to ensure that. - return v; -} - -#ifdef USE_TABLES_FOR_ALPHA_MULT - -static const uint32_t kMultTables[2][256] = { - { // (255u << MFIX) / alpha - 0x00000000, 0xff000000, 0x7f800000, 0x55000000, 0x3fc00000, 0x33000000, - 0x2a800000, 0x246db6db, 0x1fe00000, 0x1c555555, 0x19800000, 0x172e8ba2, - 0x15400000, 0x139d89d8, 0x1236db6d, 0x11000000, 0x0ff00000, 0x0f000000, - 0x0e2aaaaa, 0x0d6bca1a, 0x0cc00000, 0x0c249249, 0x0b9745d1, 0x0b1642c8, - 0x0aa00000, 0x0a333333, 0x09cec4ec, 0x0971c71c, 0x091b6db6, 0x08cb08d3, - 0x08800000, 0x0839ce73, 0x07f80000, 0x07ba2e8b, 0x07800000, 0x07492492, - 0x07155555, 0x06e45306, 0x06b5e50d, 0x0689d89d, 0x06600000, 0x063831f3, - 0x06124924, 0x05ee23b8, 0x05cba2e8, 0x05aaaaaa, 0x058b2164, 0x056cefa8, - 0x05500000, 0x05343eb1, 0x05199999, 0x05000000, 0x04e76276, 0x04cfb2b7, - 0x04b8e38e, 0x04a2e8ba, 0x048db6db, 0x0479435e, 0x04658469, 0x045270d0, - 0x04400000, 0x042e29f7, 0x041ce739, 0x040c30c3, 0x03fc0000, 0x03ec4ec4, - 0x03dd1745, 0x03ce540f, 0x03c00000, 0x03b21642, 0x03a49249, 0x03976fc6, - 0x038aaaaa, 0x037e3f1f, 0x03722983, 0x03666666, 0x035af286, 0x034fcace, - 0x0344ec4e, 0x033a5440, 0x03300000, 0x0325ed09, 0x031c18f9, 0x0312818a, - 0x03092492, 0x03000000, 0x02f711dc, 0x02ee5846, 0x02e5d174, 0x02dd7baf, - 0x02d55555, 0x02cd5cd5, 0x02c590b2, 0x02bdef7b, 0x02b677d4, 0x02af286b, - 0x02a80000, 0x02a0fd5c, 0x029a1f58, 0x029364d9, 0x028ccccc, 0x0286562d, - 0x02800000, 0x0279c952, 0x0273b13b, 0x026db6db, 0x0267d95b, 0x026217ec, - 0x025c71c7, 0x0256e62a, 0x0251745d, 0x024c1bac, 0x0246db6d, 0x0241b2f9, - 0x023ca1af, 0x0237a6f4, 0x0232c234, 0x022df2df, 0x02293868, 0x02249249, - 0x02200000, 0x021b810e, 0x021714fb, 0x0212bb51, 0x020e739c, 0x020a3d70, - 0x02061861, 0x02020408, 0x01fe0000, 0x01fa0be8, 0x01f62762, 0x01f25213, - 0x01ee8ba2, 0x01ead3ba, 0x01e72a07, 0x01e38e38, 0x01e00000, 0x01dc7f10, - 0x01d90b21, 0x01d5a3e9, 0x01d24924, 0x01cefa8d, 0x01cbb7e3, 0x01c880e5, - 0x01c55555, 0x01c234f7, 0x01bf1f8f, 0x01bc14e5, 0x01b914c1, 0x01b61eed, - 0x01b33333, 0x01b05160, 0x01ad7943, 0x01aaaaaa, 0x01a7e567, 0x01a5294a, - 0x01a27627, 0x019fcbd2, 0x019d2a20, 0x019a90e7, 0x01980000, 0x01957741, - 0x0192f684, 0x01907da4, 0x018e0c7c, 0x018ba2e8, 0x018940c5, 0x0186e5f0, - 0x01849249, 0x018245ae, 0x01800000, 0x017dc11f, 0x017b88ee, 0x0179574e, - 0x01772c23, 0x01750750, 0x0172e8ba, 0x0170d045, 0x016ebdd7, 0x016cb157, - 0x016aaaaa, 0x0168a9b9, 0x0166ae6a, 0x0164b8a7, 0x0162c859, 0x0160dd67, - 0x015ef7bd, 0x015d1745, 0x015b3bea, 0x01596596, 0x01579435, 0x0155c7b4, - 0x01540000, 0x01523d03, 0x01507eae, 0x014ec4ec, 0x014d0fac, 0x014b5edc, - 0x0149b26c, 0x01480a4a, 0x01466666, 0x0144c6af, 0x01432b16, 0x0141938b, - 0x01400000, 0x013e7063, 0x013ce4a9, 0x013b5cc0, 0x0139d89d, 0x01385830, - 0x0136db6d, 0x01356246, 0x0133ecad, 0x01327a97, 0x01310bf6, 0x012fa0be, - 0x012e38e3, 0x012cd459, 0x012b7315, 0x012a150a, 0x0128ba2e, 0x01276276, - 0x01260dd6, 0x0124bc44, 0x01236db6, 0x01222222, 0x0120d97c, 0x011f93bc, - 0x011e50d7, 0x011d10c4, 0x011bd37a, 0x011a98ef, 0x0119611a, 0x01182bf2, - 0x0116f96f, 0x0115c988, 0x01149c34, 0x0113716a, 0x01124924, 0x01112358, - 0x01100000, 0x010edf12, 0x010dc087, 0x010ca458, 0x010b8a7d, 0x010a72f0, - 0x01095da8, 0x01084a9f, 0x010739ce, 0x01062b2e, 0x01051eb8, 0x01041465, - 0x01030c30, 0x01020612, 0x01010204, 0x01000000 }, - { // alpha * KINV_255 - 0x00000000, 0x00010101, 0x00020202, 0x00030303, 0x00040404, 0x00050505, - 0x00060606, 0x00070707, 0x00080808, 0x00090909, 0x000a0a0a, 0x000b0b0b, - 0x000c0c0c, 0x000d0d0d, 0x000e0e0e, 0x000f0f0f, 0x00101010, 0x00111111, - 0x00121212, 0x00131313, 0x00141414, 0x00151515, 0x00161616, 0x00171717, - 0x00181818, 0x00191919, 0x001a1a1a, 0x001b1b1b, 0x001c1c1c, 0x001d1d1d, - 0x001e1e1e, 0x001f1f1f, 0x00202020, 0x00212121, 0x00222222, 0x00232323, - 0x00242424, 0x00252525, 0x00262626, 0x00272727, 0x00282828, 0x00292929, - 0x002a2a2a, 0x002b2b2b, 0x002c2c2c, 0x002d2d2d, 0x002e2e2e, 0x002f2f2f, - 0x00303030, 0x00313131, 0x00323232, 0x00333333, 0x00343434, 0x00353535, - 0x00363636, 0x00373737, 0x00383838, 0x00393939, 0x003a3a3a, 0x003b3b3b, - 0x003c3c3c, 0x003d3d3d, 0x003e3e3e, 0x003f3f3f, 0x00404040, 0x00414141, - 0x00424242, 0x00434343, 0x00444444, 0x00454545, 0x00464646, 0x00474747, - 0x00484848, 0x00494949, 0x004a4a4a, 0x004b4b4b, 0x004c4c4c, 0x004d4d4d, - 0x004e4e4e, 0x004f4f4f, 0x00505050, 0x00515151, 0x00525252, 0x00535353, - 0x00545454, 0x00555555, 0x00565656, 0x00575757, 0x00585858, 0x00595959, - 0x005a5a5a, 0x005b5b5b, 0x005c5c5c, 0x005d5d5d, 0x005e5e5e, 0x005f5f5f, - 0x00606060, 0x00616161, 0x00626262, 0x00636363, 0x00646464, 0x00656565, - 0x00666666, 0x00676767, 0x00686868, 0x00696969, 0x006a6a6a, 0x006b6b6b, - 0x006c6c6c, 0x006d6d6d, 0x006e6e6e, 0x006f6f6f, 0x00707070, 0x00717171, - 0x00727272, 0x00737373, 0x00747474, 0x00757575, 0x00767676, 0x00777777, - 0x00787878, 0x00797979, 0x007a7a7a, 0x007b7b7b, 0x007c7c7c, 0x007d7d7d, - 0x007e7e7e, 0x007f7f7f, 0x00808080, 0x00818181, 0x00828282, 0x00838383, - 0x00848484, 0x00858585, 0x00868686, 0x00878787, 0x00888888, 0x00898989, - 0x008a8a8a, 0x008b8b8b, 0x008c8c8c, 0x008d8d8d, 0x008e8e8e, 0x008f8f8f, - 0x00909090, 0x00919191, 0x00929292, 0x00939393, 0x00949494, 0x00959595, - 0x00969696, 0x00979797, 0x00989898, 0x00999999, 0x009a9a9a, 0x009b9b9b, - 0x009c9c9c, 0x009d9d9d, 0x009e9e9e, 0x009f9f9f, 0x00a0a0a0, 0x00a1a1a1, - 0x00a2a2a2, 0x00a3a3a3, 0x00a4a4a4, 0x00a5a5a5, 0x00a6a6a6, 0x00a7a7a7, - 0x00a8a8a8, 0x00a9a9a9, 0x00aaaaaa, 0x00ababab, 0x00acacac, 0x00adadad, - 0x00aeaeae, 0x00afafaf, 0x00b0b0b0, 0x00b1b1b1, 0x00b2b2b2, 0x00b3b3b3, - 0x00b4b4b4, 0x00b5b5b5, 0x00b6b6b6, 0x00b7b7b7, 0x00b8b8b8, 0x00b9b9b9, - 0x00bababa, 0x00bbbbbb, 0x00bcbcbc, 0x00bdbdbd, 0x00bebebe, 0x00bfbfbf, - 0x00c0c0c0, 0x00c1c1c1, 0x00c2c2c2, 0x00c3c3c3, 0x00c4c4c4, 0x00c5c5c5, - 0x00c6c6c6, 0x00c7c7c7, 0x00c8c8c8, 0x00c9c9c9, 0x00cacaca, 0x00cbcbcb, - 0x00cccccc, 0x00cdcdcd, 0x00cecece, 0x00cfcfcf, 0x00d0d0d0, 0x00d1d1d1, - 0x00d2d2d2, 0x00d3d3d3, 0x00d4d4d4, 0x00d5d5d5, 0x00d6d6d6, 0x00d7d7d7, - 0x00d8d8d8, 0x00d9d9d9, 0x00dadada, 0x00dbdbdb, 0x00dcdcdc, 0x00dddddd, - 0x00dedede, 0x00dfdfdf, 0x00e0e0e0, 0x00e1e1e1, 0x00e2e2e2, 0x00e3e3e3, - 0x00e4e4e4, 0x00e5e5e5, 0x00e6e6e6, 0x00e7e7e7, 0x00e8e8e8, 0x00e9e9e9, - 0x00eaeaea, 0x00ebebeb, 0x00ececec, 0x00ededed, 0x00eeeeee, 0x00efefef, - 0x00f0f0f0, 0x00f1f1f1, 0x00f2f2f2, 0x00f3f3f3, 0x00f4f4f4, 0x00f5f5f5, - 0x00f6f6f6, 0x00f7f7f7, 0x00f8f8f8, 0x00f9f9f9, 0x00fafafa, 0x00fbfbfb, - 0x00fcfcfc, 0x00fdfdfd, 0x00fefefe, 0x00ffffff } -}; - -static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) { - return kMultTables[!inverse][a]; -} - -#else - -static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) { - return inverse ? (255u << MFIX) / a : a * KINV_255; -} - -#endif // USE_TABLES_FOR_ALPHA_MULT - -void WebPMultARGBRowC(uint32_t* const ptr, int width, int inverse) { - int x; - for (x = 0; x < width; ++x) { - const uint32_t argb = ptr[x]; - if (argb < 0xff000000u) { // alpha < 255 - if (argb <= 0x00ffffffu) { // alpha == 0 - ptr[x] = 0; - } else { - const uint32_t alpha = (argb >> 24) & 0xff; - const uint32_t scale = GetScale(alpha, inverse); - uint32_t out = argb & 0xff000000u; - out |= Mult(argb >> 0, scale) << 0; - out |= Mult(argb >> 8, scale) << 8; - out |= Mult(argb >> 16, scale) << 16; - ptr[x] = out; - } - } - } -} - -void WebPMultRowC(uint8_t* const ptr, const uint8_t* const alpha, - int width, int inverse) { - int x; - for (x = 0; x < width; ++x) { - const uint32_t a = alpha[x]; - if (a != 255) { - if (a == 0) { - ptr[x] = 0; - } else { - const uint32_t scale = GetScale(a, inverse); - ptr[x] = Mult(ptr[x], scale); - } - } - } -} - -#undef KINV_255 -#undef HALF -#undef MFIX - -void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse); -void (*WebPMultRow)(uint8_t* const ptr, const uint8_t* const alpha, - int width, int inverse); - -//------------------------------------------------------------------------------ -// Generic per-plane calls - -void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows, - int inverse) { - int n; - for (n = 0; n < num_rows; ++n) { - WebPMultARGBRow((uint32_t*)ptr, width, inverse); - ptr += stride; - } -} - -void WebPMultRows(uint8_t* ptr, int stride, - const uint8_t* alpha, int alpha_stride, - int width, int num_rows, int inverse) { - int n; - for (n = 0; n < num_rows; ++n) { - WebPMultRow(ptr, alpha, width, inverse); - ptr += stride; - alpha += alpha_stride; - } -} - -//------------------------------------------------------------------------------ -// Premultiplied modes - -// non dithered-modes - -// (x * a * 32897) >> 23 is bit-wise equivalent to (int)(x * a / 255.) -// for all 8bit x or a. For bit-wise equivalence to (int)(x * a / 255. + .5), -// one can use instead: (x * a * 65793 + (1 << 23)) >> 24 -#if 1 // (int)(x * a / 255.) -#define MULTIPLIER(a) ((a) * 32897U) -#define PREMULTIPLY(x, m) (((x) * (m)) >> 23) -#else // (int)(x * a / 255. + .5) -#define MULTIPLIER(a) ((a) * 65793U) -#define PREMULTIPLY(x, m) (((x) * (m) + (1U << 23)) >> 24) -#endif - -static void ApplyAlphaMultiply(uint8_t* rgba, int alpha_first, - int w, int h, int stride) { - while (h-- > 0) { - uint8_t* const rgb = rgba + (alpha_first ? 1 : 0); - const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3); - int i; - for (i = 0; i < w; ++i) { - const uint32_t a = alpha[4 * i]; - if (a != 0xff) { - const uint32_t mult = MULTIPLIER(a); - rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult); - rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult); - rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult); - } - } - rgba += stride; - } -} -#undef MULTIPLIER -#undef PREMULTIPLY - -// rgbA4444 - -#define MULTIPLIER(a) ((a) * 0x1111) // 0x1111 ~= (1 << 16) / 15 - -static WEBP_INLINE uint8_t dither_hi(uint8_t x) { - return (x & 0xf0) | (x >> 4); -} - -static WEBP_INLINE uint8_t dither_lo(uint8_t x) { - return (x & 0x0f) | (x << 4); -} - -static WEBP_INLINE uint8_t multiply(uint8_t x, uint32_t m) { - return (x * m) >> 16; -} - -static WEBP_INLINE void ApplyAlphaMultiply4444(uint8_t* rgba4444, - int w, int h, int stride, - int rg_byte_pos /* 0 or 1 */) { - while (h-- > 0) { - int i; - for (i = 0; i < w; ++i) { - const uint32_t rg = rgba4444[2 * i + rg_byte_pos]; - const uint32_t ba = rgba4444[2 * i + (rg_byte_pos ^ 1)]; - const uint8_t a = ba & 0x0f; - const uint32_t mult = MULTIPLIER(a); - const uint8_t r = multiply(dither_hi(rg), mult); - const uint8_t g = multiply(dither_lo(rg), mult); - const uint8_t b = multiply(dither_hi(ba), mult); - rgba4444[2 * i + rg_byte_pos] = (r & 0xf0) | ((g >> 4) & 0x0f); - rgba4444[2 * i + (rg_byte_pos ^ 1)] = (b & 0xf0) | a; - } - rgba4444 += stride; - } -} -#undef MULTIPLIER - -static void ApplyAlphaMultiply_16b(uint8_t* rgba4444, - int w, int h, int stride) { -#ifdef WEBP_SWAP_16BIT_CSP - ApplyAlphaMultiply4444(rgba4444, w, h, stride, 1); -#else - ApplyAlphaMultiply4444(rgba4444, w, h, stride, 0); -#endif -} - -static int DispatchAlpha(const uint8_t* alpha, int alpha_stride, - int width, int height, - uint8_t* dst, int dst_stride) { - uint32_t alpha_mask = 0xff; - int i, j; - - for (j = 0; j < height; ++j) { - for (i = 0; i < width; ++i) { - const uint32_t alpha_value = alpha[i]; - dst[4 * i] = alpha_value; - alpha_mask &= alpha_value; - } - alpha += alpha_stride; - dst += dst_stride; - } - - return (alpha_mask != 0xff); -} - -static void DispatchAlphaToGreen(const uint8_t* alpha, int alpha_stride, - int width, int height, - uint32_t* dst, int dst_stride) { - int i, j; - for (j = 0; j < height; ++j) { - for (i = 0; i < width; ++i) { - dst[i] = alpha[i] << 8; // leave A/R/B channels zero'd. - } - alpha += alpha_stride; - dst += dst_stride; - } -} - -static int ExtractAlpha(const uint8_t* argb, int argb_stride, - int width, int height, - uint8_t* alpha, int alpha_stride) { - uint8_t alpha_mask = 0xff; - int i, j; - - for (j = 0; j < height; ++j) { - for (i = 0; i < width; ++i) { - const uint8_t alpha_value = argb[4 * i]; - alpha[i] = alpha_value; - alpha_mask &= alpha_value; - } - argb += argb_stride; - alpha += alpha_stride; - } - return (alpha_mask == 0xff); -} - -void (*WebPApplyAlphaMultiply)(uint8_t*, int, int, int, int); -void (*WebPApplyAlphaMultiply4444)(uint8_t*, int, int, int); -int (*WebPDispatchAlpha)(const uint8_t*, int, int, int, uint8_t*, int); -void (*WebPDispatchAlphaToGreen)(const uint8_t*, int, int, int, uint32_t*, int); -int (*WebPExtractAlpha)(const uint8_t*, int, int, int, uint8_t*, int); - -//------------------------------------------------------------------------------ -// Init function - -extern void WebPInitAlphaProcessingMIPSdspR2(void); -extern void WebPInitAlphaProcessingSSE2(void); -extern void WebPInitAlphaProcessingSSE41(void); - -static volatile VP8CPUInfo alpha_processing_last_cpuinfo_used = - (VP8CPUInfo)&alpha_processing_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessing(void) { - if (alpha_processing_last_cpuinfo_used == VP8GetCPUInfo) return; - - WebPMultARGBRow = WebPMultARGBRowC; - WebPMultRow = WebPMultRowC; - WebPApplyAlphaMultiply = ApplyAlphaMultiply; - WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b; - WebPDispatchAlpha = DispatchAlpha; - WebPDispatchAlphaToGreen = DispatchAlphaToGreen; - WebPExtractAlpha = ExtractAlpha; - - // If defined, use CPUInfo() to overwrite some pointers with faster versions. - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - WebPInitAlphaProcessingSSE2(); -#if defined(WEBP_USE_SSE41) - if (VP8GetCPUInfo(kSSE4_1)) { - WebPInitAlphaProcessingSSE41(); - } -#endif - } -#endif -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - WebPInitAlphaProcessingMIPSdspR2(); - } -#endif - } - alpha_processing_last_cpuinfo_used = VP8GetCPUInfo; -} diff --git a/Example/Pods/libwebp/src/dsp/alpha_processing_mips_dsp_r2.c b/Example/Pods/libwebp/src/dsp/alpha_processing_mips_dsp_r2.c deleted file mode 100644 index c631d789..00000000 --- a/Example/Pods/libwebp/src/dsp/alpha_processing_mips_dsp_r2.c +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Utilities for processing transparent channel. -// -// Author(s): Branimir Vasic (branimir.vasic@imgtec.com) -// Djordje Pesut (djordje.pesut@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS_DSP_R2) - -static int DispatchAlpha(const uint8_t* alpha, int alpha_stride, - int width, int height, - uint8_t* dst, int dst_stride) { - uint32_t alpha_mask = 0xffffffff; - int i, j, temp0; - - for (j = 0; j < height; ++j) { - uint8_t* pdst = dst; - const uint8_t* palpha = alpha; - for (i = 0; i < (width >> 2); ++i) { - int temp1, temp2, temp3; - - __asm__ volatile ( - "ulw %[temp0], 0(%[palpha]) \n\t" - "addiu %[palpha], %[palpha], 4 \n\t" - "addiu %[pdst], %[pdst], 16 \n\t" - "srl %[temp1], %[temp0], 8 \n\t" - "srl %[temp2], %[temp0], 16 \n\t" - "srl %[temp3], %[temp0], 24 \n\t" - "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t" - "sb %[temp0], -16(%[pdst]) \n\t" - "sb %[temp1], -12(%[pdst]) \n\t" - "sb %[temp2], -8(%[pdst]) \n\t" - "sb %[temp3], -4(%[pdst]) \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [palpha]"+r"(palpha), [pdst]"+r"(pdst), - [alpha_mask]"+r"(alpha_mask) - : - : "memory" - ); - } - - for (i = 0; i < (width & 3); ++i) { - __asm__ volatile ( - "lbu %[temp0], 0(%[palpha]) \n\t" - "addiu %[palpha], %[palpha], 1 \n\t" - "sb %[temp0], 0(%[pdst]) \n\t" - "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t" - "addiu %[pdst], %[pdst], 4 \n\t" - : [temp0]"=&r"(temp0), [palpha]"+r"(palpha), [pdst]"+r"(pdst), - [alpha_mask]"+r"(alpha_mask) - : - : "memory" - ); - } - alpha += alpha_stride; - dst += dst_stride; - } - - __asm__ volatile ( - "ext %[temp0], %[alpha_mask], 0, 16 \n\t" - "srl %[alpha_mask], %[alpha_mask], 16 \n\t" - "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t" - "ext %[temp0], %[alpha_mask], 0, 8 \n\t" - "srl %[alpha_mask], %[alpha_mask], 8 \n\t" - "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t" - : [temp0]"=&r"(temp0), [alpha_mask]"+r"(alpha_mask) - : - ); - - return (alpha_mask != 0xff); -} - -static void MultARGBRow(uint32_t* const ptr, int width, int inverse) { - int x; - const uint32_t c_00ffffff = 0x00ffffffu; - const uint32_t c_ff000000 = 0xff000000u; - const uint32_t c_8000000 = 0x00800000u; - const uint32_t c_8000080 = 0x00800080u; - for (x = 0; x < width; ++x) { - const uint32_t argb = ptr[x]; - if (argb < 0xff000000u) { // alpha < 255 - if (argb <= 0x00ffffffu) { // alpha == 0 - ptr[x] = 0; - } else { - int temp0, temp1, temp2, temp3, alpha; - __asm__ volatile ( - "srl %[alpha], %[argb], 24 \n\t" - "replv.qb %[temp0], %[alpha] \n\t" - "and %[temp0], %[temp0], %[c_00ffffff] \n\t" - "beqz %[inverse], 0f \n\t" - "divu $zero, %[c_ff000000], %[alpha] \n\t" - "mflo %[temp0] \n\t" - "0: \n\t" - "andi %[temp1], %[argb], 0xff \n\t" - "ext %[temp2], %[argb], 8, 8 \n\t" - "ext %[temp3], %[argb], 16, 8 \n\t" - "mul %[temp1], %[temp1], %[temp0] \n\t" - "mul %[temp2], %[temp2], %[temp0] \n\t" - "mul %[temp3], %[temp3], %[temp0] \n\t" - "precrq.ph.w %[temp1], %[temp2], %[temp1] \n\t" - "addu %[temp3], %[temp3], %[c_8000000] \n\t" - "addu %[temp1], %[temp1], %[c_8000080] \n\t" - "precrq.ph.w %[temp3], %[argb], %[temp3] \n\t" - "precrq.qb.ph %[temp1], %[temp3], %[temp1] \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [alpha]"=&r"(alpha) - : [inverse]"r"(inverse), [c_00ffffff]"r"(c_00ffffff), - [c_8000000]"r"(c_8000000), [c_8000080]"r"(c_8000080), - [c_ff000000]"r"(c_ff000000), [argb]"r"(argb) - : "memory", "hi", "lo" - ); - ptr[x] = temp1; - } - } - } -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void WebPInitAlphaProcessingMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingMIPSdspR2(void) { - WebPDispatchAlpha = DispatchAlpha; - WebPMultARGBRow = MultARGBRow; -} - -#else // !WEBP_USE_MIPS_DSP_R2 - -WEBP_DSP_INIT_STUB(WebPInitAlphaProcessingMIPSdspR2) - -#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/Example/Pods/libwebp/src/dsp/alpha_processing_sse2.c b/Example/Pods/libwebp/src/dsp/alpha_processing_sse2.c deleted file mode 100644 index 5acb481d..00000000 --- a/Example/Pods/libwebp/src/dsp/alpha_processing_sse2.c +++ /dev/null @@ -1,298 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Utilities for processing transparent channel. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE2) -#include - -//------------------------------------------------------------------------------ - -static int DispatchAlpha(const uint8_t* alpha, int alpha_stride, - int width, int height, - uint8_t* dst, int dst_stride) { - // alpha_and stores an 'and' operation of all the alpha[] values. The final - // value is not 0xff if any of the alpha[] is not equal to 0xff. - uint32_t alpha_and = 0xff; - int i, j; - const __m128i zero = _mm_setzero_si128(); - const __m128i rgb_mask = _mm_set1_epi32(0xffffff00u); // to preserve RGB - const __m128i all_0xff = _mm_set_epi32(0, 0, ~0u, ~0u); - __m128i all_alphas = all_0xff; - - // We must be able to access 3 extra bytes after the last written byte - // 'dst[4 * width - 4]', because we don't know if alpha is the first or the - // last byte of the quadruplet. - const int limit = (width - 1) & ~7; - - for (j = 0; j < height; ++j) { - __m128i* out = (__m128i*)dst; - for (i = 0; i < limit; i += 8) { - // load 8 alpha bytes - const __m128i a0 = _mm_loadl_epi64((const __m128i*)&alpha[i]); - const __m128i a1 = _mm_unpacklo_epi8(a0, zero); - const __m128i a2_lo = _mm_unpacklo_epi16(a1, zero); - const __m128i a2_hi = _mm_unpackhi_epi16(a1, zero); - // load 8 dst pixels (32 bytes) - const __m128i b0_lo = _mm_loadu_si128(out + 0); - const __m128i b0_hi = _mm_loadu_si128(out + 1); - // mask dst alpha values - const __m128i b1_lo = _mm_and_si128(b0_lo, rgb_mask); - const __m128i b1_hi = _mm_and_si128(b0_hi, rgb_mask); - // combine - const __m128i b2_lo = _mm_or_si128(b1_lo, a2_lo); - const __m128i b2_hi = _mm_or_si128(b1_hi, a2_hi); - // store - _mm_storeu_si128(out + 0, b2_lo); - _mm_storeu_si128(out + 1, b2_hi); - // accumulate eight alpha 'and' in parallel - all_alphas = _mm_and_si128(all_alphas, a0); - out += 2; - } - for (; i < width; ++i) { - const uint32_t alpha_value = alpha[i]; - dst[4 * i] = alpha_value; - alpha_and &= alpha_value; - } - alpha += alpha_stride; - dst += dst_stride; - } - // Combine the eight alpha 'and' into a 8-bit mask. - alpha_and &= _mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas, all_0xff)); - return (alpha_and != 0xff); -} - -static void DispatchAlphaToGreen(const uint8_t* alpha, int alpha_stride, - int width, int height, - uint32_t* dst, int dst_stride) { - int i, j; - const __m128i zero = _mm_setzero_si128(); - const int limit = width & ~15; - for (j = 0; j < height; ++j) { - for (i = 0; i < limit; i += 16) { // process 16 alpha bytes - const __m128i a0 = _mm_loadu_si128((const __m128i*)&alpha[i]); - const __m128i a1 = _mm_unpacklo_epi8(zero, a0); // note the 'zero' first! - const __m128i b1 = _mm_unpackhi_epi8(zero, a0); - const __m128i a2_lo = _mm_unpacklo_epi16(a1, zero); - const __m128i b2_lo = _mm_unpacklo_epi16(b1, zero); - const __m128i a2_hi = _mm_unpackhi_epi16(a1, zero); - const __m128i b2_hi = _mm_unpackhi_epi16(b1, zero); - _mm_storeu_si128((__m128i*)&dst[i + 0], a2_lo); - _mm_storeu_si128((__m128i*)&dst[i + 4], a2_hi); - _mm_storeu_si128((__m128i*)&dst[i + 8], b2_lo); - _mm_storeu_si128((__m128i*)&dst[i + 12], b2_hi); - } - for (; i < width; ++i) dst[i] = alpha[i] << 8; - alpha += alpha_stride; - dst += dst_stride; - } -} - -static int ExtractAlpha(const uint8_t* argb, int argb_stride, - int width, int height, - uint8_t* alpha, int alpha_stride) { - // alpha_and stores an 'and' operation of all the alpha[] values. The final - // value is not 0xff if any of the alpha[] is not equal to 0xff. - uint32_t alpha_and = 0xff; - int i, j; - const __m128i a_mask = _mm_set1_epi32(0xffu); // to preserve alpha - const __m128i all_0xff = _mm_set_epi32(0, 0, ~0u, ~0u); - __m128i all_alphas = all_0xff; - - // We must be able to access 3 extra bytes after the last written byte - // 'src[4 * width - 4]', because we don't know if alpha is the first or the - // last byte of the quadruplet. - const int limit = (width - 1) & ~7; - - for (j = 0; j < height; ++j) { - const __m128i* src = (const __m128i*)argb; - for (i = 0; i < limit; i += 8) { - // load 32 argb bytes - const __m128i a0 = _mm_loadu_si128(src + 0); - const __m128i a1 = _mm_loadu_si128(src + 1); - const __m128i b0 = _mm_and_si128(a0, a_mask); - const __m128i b1 = _mm_and_si128(a1, a_mask); - const __m128i c0 = _mm_packs_epi32(b0, b1); - const __m128i d0 = _mm_packus_epi16(c0, c0); - // store - _mm_storel_epi64((__m128i*)&alpha[i], d0); - // accumulate eight alpha 'and' in parallel - all_alphas = _mm_and_si128(all_alphas, d0); - src += 2; - } - for (; i < width; ++i) { - const uint32_t alpha_value = argb[4 * i]; - alpha[i] = alpha_value; - alpha_and &= alpha_value; - } - argb += argb_stride; - alpha += alpha_stride; - } - // Combine the eight alpha 'and' into a 8-bit mask. - alpha_and &= _mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas, all_0xff)); - return (alpha_and == 0xff); -} - -//------------------------------------------------------------------------------ -// Non-dither premultiplied modes - -#define MULTIPLIER(a) ((a) * 0x8081) -#define PREMULTIPLY(x, m) (((x) * (m)) >> 23) - -// We can't use a 'const int' for the SHUFFLE value, because it has to be an -// immediate in the _mm_shufflexx_epi16() instruction. We really a macro here. -#define APPLY_ALPHA(RGBX, SHUFFLE, MASK, MULT) do { \ - const __m128i argb0 = _mm_loadl_epi64((__m128i*)&(RGBX)); \ - const __m128i argb1 = _mm_unpacklo_epi8(argb0, zero); \ - const __m128i alpha0 = _mm_and_si128(argb1, MASK); \ - const __m128i alpha1 = _mm_shufflelo_epi16(alpha0, SHUFFLE); \ - const __m128i alpha2 = _mm_shufflehi_epi16(alpha1, SHUFFLE); \ - /* alpha2 = [0 a0 a0 a0][0 a1 a1 a1] */ \ - const __m128i scale0 = _mm_mullo_epi16(alpha2, MULT); \ - const __m128i scale1 = _mm_mulhi_epu16(alpha2, MULT); \ - const __m128i argb2 = _mm_mulhi_epu16(argb1, scale0); \ - const __m128i argb3 = _mm_mullo_epi16(argb1, scale1); \ - const __m128i argb4 = _mm_adds_epu16(argb2, argb3); \ - const __m128i argb5 = _mm_srli_epi16(argb4, 7); \ - const __m128i argb6 = _mm_or_si128(argb5, alpha0); \ - const __m128i argb7 = _mm_packus_epi16(argb6, zero); \ - _mm_storel_epi64((__m128i*)&(RGBX), argb7); \ -} while (0) - -static void ApplyAlphaMultiply(uint8_t* rgba, int alpha_first, - int w, int h, int stride) { - const __m128i zero = _mm_setzero_si128(); - const int kSpan = 2; - const int w2 = w & ~(kSpan - 1); - while (h-- > 0) { - uint32_t* const rgbx = (uint32_t*)rgba; - int i; - if (!alpha_first) { - const __m128i kMask = _mm_set_epi16(0xff, 0, 0, 0, 0xff, 0, 0, 0); - const __m128i kMult = - _mm_set_epi16(0, 0x8081, 0x8081, 0x8081, 0, 0x8081, 0x8081, 0x8081); - for (i = 0; i < w2; i += kSpan) { - APPLY_ALPHA(rgbx[i], _MM_SHUFFLE(0, 3, 3, 3), kMask, kMult); - } - } else { - const __m128i kMask = _mm_set_epi16(0, 0, 0, 0xff, 0, 0, 0, 0xff); - const __m128i kMult = - _mm_set_epi16(0x8081, 0x8081, 0x8081, 0, 0x8081, 0x8081, 0x8081, 0); - for (i = 0; i < w2; i += kSpan) { - APPLY_ALPHA(rgbx[i], _MM_SHUFFLE(0, 0, 0, 3), kMask, kMult); - } - } - // Finish with left-overs. - for (; i < w; ++i) { - uint8_t* const rgb = rgba + (alpha_first ? 1 : 0); - const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3); - const uint32_t a = alpha[4 * i]; - if (a != 0xff) { - const uint32_t mult = MULTIPLIER(a); - rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult); - rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult); - rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult); - } - } - rgba += stride; - } -} -#undef MULTIPLIER -#undef PREMULTIPLY - -// ----------------------------------------------------------------------------- -// Apply alpha value to rows - -// We use: kINV255 = (1 << 24) / 255 = 0x010101 -// So: a * kINV255 = (a << 16) | [(a << 8) | a] -// -> _mm_mulhi_epu16() takes care of the (a<<16) part, -// and _mm_mullo_epu16(a * 0x0101,...) takes care of the "(a << 8) | a" one. - -static void MultARGBRow(uint32_t* const ptr, int width, int inverse) { - int x = 0; - if (!inverse) { - const int kSpan = 2; - const __m128i zero = _mm_setzero_si128(); - const __m128i kRound = - _mm_set_epi16(0, 1 << 7, 1 << 7, 1 << 7, 0, 1 << 7, 1 << 7, 1 << 7); - const __m128i kMult = - _mm_set_epi16(0, 0x0101, 0x0101, 0x0101, 0, 0x0101, 0x0101, 0x0101); - const __m128i kOne64 = _mm_set_epi16(1u << 8, 0, 0, 0, 1u << 8, 0, 0, 0); - const int w2 = width & ~(kSpan - 1); - for (x = 0; x < w2; x += kSpan) { - const __m128i argb0 = _mm_loadl_epi64((__m128i*)&ptr[x]); - const __m128i argb1 = _mm_unpacklo_epi8(argb0, zero); - const __m128i tmp0 = _mm_shufflelo_epi16(argb1, _MM_SHUFFLE(3, 3, 3, 3)); - const __m128i tmp1 = _mm_shufflehi_epi16(tmp0, _MM_SHUFFLE(3, 3, 3, 3)); - const __m128i tmp2 = _mm_srli_epi64(tmp1, 16); - const __m128i scale0 = _mm_mullo_epi16(tmp1, kMult); - const __m128i scale1 = _mm_or_si128(tmp2, kOne64); - const __m128i argb2 = _mm_mulhi_epu16(argb1, scale0); - const __m128i argb3 = _mm_mullo_epi16(argb1, scale1); - const __m128i argb4 = _mm_adds_epu16(argb2, argb3); - const __m128i argb5 = _mm_adds_epu16(argb4, kRound); - const __m128i argb6 = _mm_srli_epi16(argb5, 8); - const __m128i argb7 = _mm_packus_epi16(argb6, zero); - _mm_storel_epi64((__m128i*)&ptr[x], argb7); - } - } - width -= x; - if (width > 0) WebPMultARGBRowC(ptr + x, width, inverse); -} - -static void MultRow(uint8_t* const ptr, const uint8_t* const alpha, - int width, int inverse) { - int x = 0; - if (!inverse) { - const int kSpan = 8; - const __m128i zero = _mm_setzero_si128(); - const __m128i kRound = _mm_set1_epi16(1 << 7); - const int w2 = width & ~(kSpan - 1); - for (x = 0; x < w2; x += kSpan) { - const __m128i v0 = _mm_loadl_epi64((__m128i*)&ptr[x]); - const __m128i v1 = _mm_unpacklo_epi8(v0, zero); - const __m128i alpha0 = _mm_loadl_epi64((const __m128i*)&alpha[x]); - const __m128i alpha1 = _mm_unpacklo_epi8(alpha0, zero); - const __m128i alpha2 = _mm_unpacklo_epi8(alpha0, alpha0); - const __m128i v2 = _mm_mulhi_epu16(v1, alpha2); - const __m128i v3 = _mm_mullo_epi16(v1, alpha1); - const __m128i v4 = _mm_adds_epu16(v2, v3); - const __m128i v5 = _mm_adds_epu16(v4, kRound); - const __m128i v6 = _mm_srli_epi16(v5, 8); - const __m128i v7 = _mm_packus_epi16(v6, zero); - _mm_storel_epi64((__m128i*)&ptr[x], v7); - } - } - width -= x; - if (width > 0) WebPMultRowC(ptr + x, alpha + x, width, inverse); -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void WebPInitAlphaProcessingSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingSSE2(void) { - WebPMultARGBRow = MultARGBRow; - WebPMultRow = MultRow; - WebPApplyAlphaMultiply = ApplyAlphaMultiply; - WebPDispatchAlpha = DispatchAlpha; - WebPDispatchAlphaToGreen = DispatchAlphaToGreen; - WebPExtractAlpha = ExtractAlpha; -} - -#else // !WEBP_USE_SSE2 - -WEBP_DSP_INIT_STUB(WebPInitAlphaProcessingSSE2) - -#endif // WEBP_USE_SSE2 diff --git a/Example/Pods/libwebp/src/dsp/alpha_processing_sse41.c b/Example/Pods/libwebp/src/dsp/alpha_processing_sse41.c deleted file mode 100644 index 986fde94..00000000 --- a/Example/Pods/libwebp/src/dsp/alpha_processing_sse41.c +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Utilities for processing transparent channel, SSE4.1 variant. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE41) - -#include - -//------------------------------------------------------------------------------ - -static int ExtractAlpha(const uint8_t* argb, int argb_stride, - int width, int height, - uint8_t* alpha, int alpha_stride) { - // alpha_and stores an 'and' operation of all the alpha[] values. The final - // value is not 0xff if any of the alpha[] is not equal to 0xff. - uint32_t alpha_and = 0xff; - int i, j; - const __m128i all_0xff = _mm_set1_epi32(~0u); - __m128i all_alphas = all_0xff; - - // We must be able to access 3 extra bytes after the last written byte - // 'src[4 * width - 4]', because we don't know if alpha is the first or the - // last byte of the quadruplet. - const int limit = (width - 1) & ~15; - const __m128i kCstAlpha0 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 12, 8, 4, 0); - const __m128i kCstAlpha1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, - 12, 8, 4, 0, -1, -1, -1, -1); - const __m128i kCstAlpha2 = _mm_set_epi8(-1, -1, -1, -1, 12, 8, 4, 0, - -1, -1, -1, -1, -1, -1, -1, -1); - const __m128i kCstAlpha3 = _mm_set_epi8(12, 8, 4, 0, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1); - for (j = 0; j < height; ++j) { - const __m128i* src = (const __m128i*)argb; - for (i = 0; i < limit; i += 16) { - // load 64 argb bytes - const __m128i a0 = _mm_loadu_si128(src + 0); - const __m128i a1 = _mm_loadu_si128(src + 1); - const __m128i a2 = _mm_loadu_si128(src + 2); - const __m128i a3 = _mm_loadu_si128(src + 3); - const __m128i b0 = _mm_shuffle_epi8(a0, kCstAlpha0); - const __m128i b1 = _mm_shuffle_epi8(a1, kCstAlpha1); - const __m128i b2 = _mm_shuffle_epi8(a2, kCstAlpha2); - const __m128i b3 = _mm_shuffle_epi8(a3, kCstAlpha3); - const __m128i c0 = _mm_or_si128(b0, b1); - const __m128i c1 = _mm_or_si128(b2, b3); - const __m128i d0 = _mm_or_si128(c0, c1); - // store - _mm_storeu_si128((__m128i*)&alpha[i], d0); - // accumulate sixteen alpha 'and' in parallel - all_alphas = _mm_and_si128(all_alphas, d0); - src += 4; - } - for (; i < width; ++i) { - const uint32_t alpha_value = argb[4 * i]; - alpha[i] = alpha_value; - alpha_and &= alpha_value; - } - argb += argb_stride; - alpha += alpha_stride; - } - // Combine the sixteen alpha 'and' into an 8-bit mask. - alpha_and |= 0xff00u; // pretend the upper bits [8..15] were tested ok. - alpha_and &= _mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas, all_0xff)); - return (alpha_and == 0xffffu); -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void WebPInitAlphaProcessingSSE41(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingSSE41(void) { - WebPExtractAlpha = ExtractAlpha; -} - -#else // !WEBP_USE_SSE41 - -WEBP_DSP_INIT_STUB(WebPInitAlphaProcessingSSE41) - -#endif // WEBP_USE_SSE41 diff --git a/Example/Pods/libwebp/src/dsp/argb.c b/Example/Pods/libwebp/src/dsp/argb.c deleted file mode 100644 index cc1f9a96..00000000 --- a/Example/Pods/libwebp/src/dsp/argb.c +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// ARGB making functions. -// -// Author: Djordje Pesut (djordje.pesut@imgtec.com) - -#include "./dsp.h" - -static WEBP_INLINE uint32_t MakeARGB32(int a, int r, int g, int b) { - return (((uint32_t)a << 24) | (r << 16) | (g << 8) | b); -} - -static void PackARGB(const uint8_t* a, const uint8_t* r, const uint8_t* g, - const uint8_t* b, int len, uint32_t* out) { - int i; - for (i = 0; i < len; ++i) { - out[i] = MakeARGB32(a[4 * i], r[4 * i], g[4 * i], b[4 * i]); - } -} - -static void PackRGB(const uint8_t* r, const uint8_t* g, const uint8_t* b, - int len, int step, uint32_t* out) { - int i, offset = 0; - for (i = 0; i < len; ++i) { - out[i] = MakeARGB32(0xff, r[offset], g[offset], b[offset]); - offset += step; - } -} - -void (*VP8PackARGB)(const uint8_t*, const uint8_t*, const uint8_t*, - const uint8_t*, int, uint32_t*); -void (*VP8PackRGB)(const uint8_t*, const uint8_t*, const uint8_t*, - int, int, uint32_t*); - -extern void VP8EncDspARGBInitMIPSdspR2(void); -extern void VP8EncDspARGBInitSSE2(void); - -static volatile VP8CPUInfo argb_last_cpuinfo_used = - (VP8CPUInfo)&argb_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspARGBInit(void) { - if (argb_last_cpuinfo_used == VP8GetCPUInfo) return; - - VP8PackARGB = PackARGB; - VP8PackRGB = PackRGB; - - // If defined, use CPUInfo() to overwrite some pointers with faster versions. - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - VP8EncDspARGBInitSSE2(); - } -#endif -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - VP8EncDspARGBInitMIPSdspR2(); - } -#endif - } - argb_last_cpuinfo_used = VP8GetCPUInfo; -} diff --git a/Example/Pods/libwebp/src/dsp/argb_mips_dsp_r2.c b/Example/Pods/libwebp/src/dsp/argb_mips_dsp_r2.c deleted file mode 100644 index af65acb8..00000000 --- a/Example/Pods/libwebp/src/dsp/argb_mips_dsp_r2.c +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// ARGB making functions (mips version). -// -// Author: Djordje Pesut (djordje.pesut@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS_DSP_R2) - -static void PackARGB(const uint8_t* a, const uint8_t* r, const uint8_t* g, - const uint8_t* b, int len, uint32_t* out) { - int temp0, temp1, temp2, temp3, offset; - const int rest = len & 1; - const uint32_t* const loop_end = out + len - rest; - const int step = 4; - __asm__ volatile ( - "xor %[offset], %[offset], %[offset] \n\t" - "beq %[loop_end], %[out], 0f \n\t" - "2: \n\t" - "lbux %[temp0], %[offset](%[a]) \n\t" - "lbux %[temp1], %[offset](%[r]) \n\t" - "lbux %[temp2], %[offset](%[g]) \n\t" - "lbux %[temp3], %[offset](%[b]) \n\t" - "ins %[temp1], %[temp0], 16, 16 \n\t" - "ins %[temp3], %[temp2], 16, 16 \n\t" - "addiu %[out], %[out], 4 \n\t" - "precr.qb.ph %[temp0], %[temp1], %[temp3] \n\t" - "sw %[temp0], -4(%[out]) \n\t" - "addu %[offset], %[offset], %[step] \n\t" - "bne %[loop_end], %[out], 2b \n\t" - "0: \n\t" - "beq %[rest], $zero, 1f \n\t" - "lbux %[temp0], %[offset](%[a]) \n\t" - "lbux %[temp1], %[offset](%[r]) \n\t" - "lbux %[temp2], %[offset](%[g]) \n\t" - "lbux %[temp3], %[offset](%[b]) \n\t" - "ins %[temp1], %[temp0], 16, 16 \n\t" - "ins %[temp3], %[temp2], 16, 16 \n\t" - "precr.qb.ph %[temp0], %[temp1], %[temp3] \n\t" - "sw %[temp0], 0(%[out]) \n\t" - "1: \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [offset]"=&r"(offset), [out]"+&r"(out) - : [a]"r"(a), [r]"r"(r), [g]"r"(g), [b]"r"(b), [step]"r"(step), - [loop_end]"r"(loop_end), [rest]"r"(rest) - : "memory" - ); -} - -static void PackRGB(const uint8_t* r, const uint8_t* g, const uint8_t* b, - int len, int step, uint32_t* out) { - int temp0, temp1, temp2, offset; - const int rest = len & 1; - const int a = 0xff; - const uint32_t* const loop_end = out + len - rest; - __asm__ volatile ( - "xor %[offset], %[offset], %[offset] \n\t" - "beq %[loop_end], %[out], 0f \n\t" - "2: \n\t" - "lbux %[temp0], %[offset](%[r]) \n\t" - "lbux %[temp1], %[offset](%[g]) \n\t" - "lbux %[temp2], %[offset](%[b]) \n\t" - "ins %[temp0], %[a], 16, 16 \n\t" - "ins %[temp2], %[temp1], 16, 16 \n\t" - "addiu %[out], %[out], 4 \n\t" - "precr.qb.ph %[temp0], %[temp0], %[temp2] \n\t" - "sw %[temp0], -4(%[out]) \n\t" - "addu %[offset], %[offset], %[step] \n\t" - "bne %[loop_end], %[out], 2b \n\t" - "0: \n\t" - "beq %[rest], $zero, 1f \n\t" - "lbux %[temp0], %[offset](%[r]) \n\t" - "lbux %[temp1], %[offset](%[g]) \n\t" - "lbux %[temp2], %[offset](%[b]) \n\t" - "ins %[temp0], %[a], 16, 16 \n\t" - "ins %[temp2], %[temp1], 16, 16 \n\t" - "precr.qb.ph %[temp0], %[temp0], %[temp2] \n\t" - "sw %[temp0], 0(%[out]) \n\t" - "1: \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [offset]"=&r"(offset), [out]"+&r"(out) - : [a]"r"(a), [r]"r"(r), [g]"r"(g), [b]"r"(b), [step]"r"(step), - [loop_end]"r"(loop_end), [rest]"r"(rest) - : "memory" - ); -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8EncDspARGBInitMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspARGBInitMIPSdspR2(void) { - VP8PackARGB = PackARGB; - VP8PackRGB = PackRGB; -} - -#else // !WEBP_USE_MIPS_DSP_R2 - -WEBP_DSP_INIT_STUB(VP8EncDspARGBInitMIPSdspR2) - -#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/Example/Pods/libwebp/src/dsp/argb_sse2.c b/Example/Pods/libwebp/src/dsp/argb_sse2.c deleted file mode 100644 index afcb1957..00000000 --- a/Example/Pods/libwebp/src/dsp/argb_sse2.c +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// ARGB making functions (SSE2 version). -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE2) - -#include -#include -#include - -static WEBP_INLINE uint32_t MakeARGB32(int a, int r, int g, int b) { - return (((uint32_t)a << 24) | (r << 16) | (g << 8) | b); -} - -static void PackARGB(const uint8_t* a, const uint8_t* r, const uint8_t* g, - const uint8_t* b, int len, uint32_t* out) { - if (g == r + 1) { // RGBA input order. Need to swap R and B. - int i = 0; - const int len_max = len & ~3; // max length processed in main loop - const __m128i red_blue_mask = _mm_set1_epi32(0x00ff00ffu); - assert(b == r + 2); - assert(a == r + 3); - for (; i < len_max; i += 4) { - const __m128i A = _mm_loadu_si128((const __m128i*)(r + 4 * i)); - const __m128i B = _mm_and_si128(A, red_blue_mask); // R 0 B 0 - const __m128i C = _mm_andnot_si128(red_blue_mask, A); // 0 G 0 A - const __m128i D = _mm_shufflelo_epi16(B, _MM_SHUFFLE(2, 3, 0, 1)); - const __m128i E = _mm_shufflehi_epi16(D, _MM_SHUFFLE(2, 3, 0, 1)); - const __m128i F = _mm_or_si128(E, C); - _mm_storeu_si128((__m128i*)(out + i), F); - } - for (; i < len; ++i) { - out[i] = MakeARGB32(a[4 * i], r[4 * i], g[4 * i], b[4 * i]); - } - } else { - assert(g == b + 1); - assert(r == b + 2); - assert(a == b + 3); - memcpy(out, b, len * 4); - } -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8EncDspARGBInitSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspARGBInitSSE2(void) { - VP8PackARGB = PackARGB; -} - -#else // !WEBP_USE_SSE2 - -WEBP_DSP_INIT_STUB(VP8EncDspARGBInitSSE2) - -#endif // WEBP_USE_SSE2 diff --git a/Example/Pods/libwebp/src/dsp/cost.c b/Example/Pods/libwebp/src/dsp/cost.c deleted file mode 100644 index fe72d26e..00000000 --- a/Example/Pods/libwebp/src/dsp/cost.c +++ /dev/null @@ -1,412 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" -#include "../enc/cost.h" - -//------------------------------------------------------------------------------ -// Boolean-cost cost table - -const uint16_t VP8EntropyCost[256] = { - 1792, 1792, 1792, 1536, 1536, 1408, 1366, 1280, 1280, 1216, - 1178, 1152, 1110, 1076, 1061, 1024, 1024, 992, 968, 951, - 939, 911, 896, 878, 871, 854, 838, 820, 811, 794, - 786, 768, 768, 752, 740, 732, 720, 709, 704, 690, - 683, 672, 666, 655, 647, 640, 631, 622, 615, 607, - 598, 592, 586, 576, 572, 564, 559, 555, 547, 541, - 534, 528, 522, 512, 512, 504, 500, 494, 488, 483, - 477, 473, 467, 461, 458, 452, 448, 443, 438, 434, - 427, 424, 419, 415, 410, 406, 403, 399, 394, 390, - 384, 384, 377, 374, 370, 366, 362, 359, 355, 351, - 347, 342, 342, 336, 333, 330, 326, 323, 320, 316, - 312, 308, 305, 302, 299, 296, 293, 288, 287, 283, - 280, 277, 274, 272, 268, 266, 262, 256, 256, 256, - 251, 248, 245, 242, 240, 237, 234, 232, 228, 226, - 223, 221, 218, 216, 214, 211, 208, 205, 203, 201, - 198, 196, 192, 191, 188, 187, 183, 181, 179, 176, - 175, 171, 171, 168, 165, 163, 160, 159, 156, 154, - 152, 150, 148, 146, 144, 142, 139, 138, 135, 133, - 131, 128, 128, 125, 123, 121, 119, 117, 115, 113, - 111, 110, 107, 105, 103, 102, 100, 98, 96, 94, - 92, 91, 89, 86, 86, 83, 82, 80, 77, 76, - 74, 73, 71, 69, 67, 66, 64, 63, 61, 59, - 57, 55, 54, 52, 51, 49, 47, 46, 44, 43, - 41, 40, 38, 36, 35, 33, 32, 30, 29, 27, - 25, 24, 22, 21, 19, 18, 16, 15, 13, 12, - 10, 9, 7, 6, 4, 3 -}; - -//------------------------------------------------------------------------------ -// Level cost tables - -// fixed costs for coding levels, deduce from the coding tree. -// This is only the part that doesn't depend on the probability state. -const uint16_t VP8LevelFixedCosts[MAX_LEVEL + 1] = { - 0, 256, 256, 256, 256, 432, 618, 630, - 731, 640, 640, 828, 901, 948, 1021, 1101, - 1174, 1221, 1294, 1042, 1085, 1115, 1158, 1202, - 1245, 1275, 1318, 1337, 1380, 1410, 1453, 1497, - 1540, 1570, 1613, 1280, 1295, 1317, 1332, 1358, - 1373, 1395, 1410, 1454, 1469, 1491, 1506, 1532, - 1547, 1569, 1584, 1601, 1616, 1638, 1653, 1679, - 1694, 1716, 1731, 1775, 1790, 1812, 1827, 1853, - 1868, 1890, 1905, 1727, 1733, 1742, 1748, 1759, - 1765, 1774, 1780, 1800, 1806, 1815, 1821, 1832, - 1838, 1847, 1853, 1878, 1884, 1893, 1899, 1910, - 1916, 1925, 1931, 1951, 1957, 1966, 1972, 1983, - 1989, 1998, 2004, 2027, 2033, 2042, 2048, 2059, - 2065, 2074, 2080, 2100, 2106, 2115, 2121, 2132, - 2138, 2147, 2153, 2178, 2184, 2193, 2199, 2210, - 2216, 2225, 2231, 2251, 2257, 2266, 2272, 2283, - 2289, 2298, 2304, 2168, 2174, 2183, 2189, 2200, - 2206, 2215, 2221, 2241, 2247, 2256, 2262, 2273, - 2279, 2288, 2294, 2319, 2325, 2334, 2340, 2351, - 2357, 2366, 2372, 2392, 2398, 2407, 2413, 2424, - 2430, 2439, 2445, 2468, 2474, 2483, 2489, 2500, - 2506, 2515, 2521, 2541, 2547, 2556, 2562, 2573, - 2579, 2588, 2594, 2619, 2625, 2634, 2640, 2651, - 2657, 2666, 2672, 2692, 2698, 2707, 2713, 2724, - 2730, 2739, 2745, 2540, 2546, 2555, 2561, 2572, - 2578, 2587, 2593, 2613, 2619, 2628, 2634, 2645, - 2651, 2660, 2666, 2691, 2697, 2706, 2712, 2723, - 2729, 2738, 2744, 2764, 2770, 2779, 2785, 2796, - 2802, 2811, 2817, 2840, 2846, 2855, 2861, 2872, - 2878, 2887, 2893, 2913, 2919, 2928, 2934, 2945, - 2951, 2960, 2966, 2991, 2997, 3006, 3012, 3023, - 3029, 3038, 3044, 3064, 3070, 3079, 3085, 3096, - 3102, 3111, 3117, 2981, 2987, 2996, 3002, 3013, - 3019, 3028, 3034, 3054, 3060, 3069, 3075, 3086, - 3092, 3101, 3107, 3132, 3138, 3147, 3153, 3164, - 3170, 3179, 3185, 3205, 3211, 3220, 3226, 3237, - 3243, 3252, 3258, 3281, 3287, 3296, 3302, 3313, - 3319, 3328, 3334, 3354, 3360, 3369, 3375, 3386, - 3392, 3401, 3407, 3432, 3438, 3447, 3453, 3464, - 3470, 3479, 3485, 3505, 3511, 3520, 3526, 3537, - 3543, 3552, 3558, 2816, 2822, 2831, 2837, 2848, - 2854, 2863, 2869, 2889, 2895, 2904, 2910, 2921, - 2927, 2936, 2942, 2967, 2973, 2982, 2988, 2999, - 3005, 3014, 3020, 3040, 3046, 3055, 3061, 3072, - 3078, 3087, 3093, 3116, 3122, 3131, 3137, 3148, - 3154, 3163, 3169, 3189, 3195, 3204, 3210, 3221, - 3227, 3236, 3242, 3267, 3273, 3282, 3288, 3299, - 3305, 3314, 3320, 3340, 3346, 3355, 3361, 3372, - 3378, 3387, 3393, 3257, 3263, 3272, 3278, 3289, - 3295, 3304, 3310, 3330, 3336, 3345, 3351, 3362, - 3368, 3377, 3383, 3408, 3414, 3423, 3429, 3440, - 3446, 3455, 3461, 3481, 3487, 3496, 3502, 3513, - 3519, 3528, 3534, 3557, 3563, 3572, 3578, 3589, - 3595, 3604, 3610, 3630, 3636, 3645, 3651, 3662, - 3668, 3677, 3683, 3708, 3714, 3723, 3729, 3740, - 3746, 3755, 3761, 3781, 3787, 3796, 3802, 3813, - 3819, 3828, 3834, 3629, 3635, 3644, 3650, 3661, - 3667, 3676, 3682, 3702, 3708, 3717, 3723, 3734, - 3740, 3749, 3755, 3780, 3786, 3795, 3801, 3812, - 3818, 3827, 3833, 3853, 3859, 3868, 3874, 3885, - 3891, 3900, 3906, 3929, 3935, 3944, 3950, 3961, - 3967, 3976, 3982, 4002, 4008, 4017, 4023, 4034, - 4040, 4049, 4055, 4080, 4086, 4095, 4101, 4112, - 4118, 4127, 4133, 4153, 4159, 4168, 4174, 4185, - 4191, 4200, 4206, 4070, 4076, 4085, 4091, 4102, - 4108, 4117, 4123, 4143, 4149, 4158, 4164, 4175, - 4181, 4190, 4196, 4221, 4227, 4236, 4242, 4253, - 4259, 4268, 4274, 4294, 4300, 4309, 4315, 4326, - 4332, 4341, 4347, 4370, 4376, 4385, 4391, 4402, - 4408, 4417, 4423, 4443, 4449, 4458, 4464, 4475, - 4481, 4490, 4496, 4521, 4527, 4536, 4542, 4553, - 4559, 4568, 4574, 4594, 4600, 4609, 4615, 4626, - 4632, 4641, 4647, 3515, 3521, 3530, 3536, 3547, - 3553, 3562, 3568, 3588, 3594, 3603, 3609, 3620, - 3626, 3635, 3641, 3666, 3672, 3681, 3687, 3698, - 3704, 3713, 3719, 3739, 3745, 3754, 3760, 3771, - 3777, 3786, 3792, 3815, 3821, 3830, 3836, 3847, - 3853, 3862, 3868, 3888, 3894, 3903, 3909, 3920, - 3926, 3935, 3941, 3966, 3972, 3981, 3987, 3998, - 4004, 4013, 4019, 4039, 4045, 4054, 4060, 4071, - 4077, 4086, 4092, 3956, 3962, 3971, 3977, 3988, - 3994, 4003, 4009, 4029, 4035, 4044, 4050, 4061, - 4067, 4076, 4082, 4107, 4113, 4122, 4128, 4139, - 4145, 4154, 4160, 4180, 4186, 4195, 4201, 4212, - 4218, 4227, 4233, 4256, 4262, 4271, 4277, 4288, - 4294, 4303, 4309, 4329, 4335, 4344, 4350, 4361, - 4367, 4376, 4382, 4407, 4413, 4422, 4428, 4439, - 4445, 4454, 4460, 4480, 4486, 4495, 4501, 4512, - 4518, 4527, 4533, 4328, 4334, 4343, 4349, 4360, - 4366, 4375, 4381, 4401, 4407, 4416, 4422, 4433, - 4439, 4448, 4454, 4479, 4485, 4494, 4500, 4511, - 4517, 4526, 4532, 4552, 4558, 4567, 4573, 4584, - 4590, 4599, 4605, 4628, 4634, 4643, 4649, 4660, - 4666, 4675, 4681, 4701, 4707, 4716, 4722, 4733, - 4739, 4748, 4754, 4779, 4785, 4794, 4800, 4811, - 4817, 4826, 4832, 4852, 4858, 4867, 4873, 4884, - 4890, 4899, 4905, 4769, 4775, 4784, 4790, 4801, - 4807, 4816, 4822, 4842, 4848, 4857, 4863, 4874, - 4880, 4889, 4895, 4920, 4926, 4935, 4941, 4952, - 4958, 4967, 4973, 4993, 4999, 5008, 5014, 5025, - 5031, 5040, 5046, 5069, 5075, 5084, 5090, 5101, - 5107, 5116, 5122, 5142, 5148, 5157, 5163, 5174, - 5180, 5189, 5195, 5220, 5226, 5235, 5241, 5252, - 5258, 5267, 5273, 5293, 5299, 5308, 5314, 5325, - 5331, 5340, 5346, 4604, 4610, 4619, 4625, 4636, - 4642, 4651, 4657, 4677, 4683, 4692, 4698, 4709, - 4715, 4724, 4730, 4755, 4761, 4770, 4776, 4787, - 4793, 4802, 4808, 4828, 4834, 4843, 4849, 4860, - 4866, 4875, 4881, 4904, 4910, 4919, 4925, 4936, - 4942, 4951, 4957, 4977, 4983, 4992, 4998, 5009, - 5015, 5024, 5030, 5055, 5061, 5070, 5076, 5087, - 5093, 5102, 5108, 5128, 5134, 5143, 5149, 5160, - 5166, 5175, 5181, 5045, 5051, 5060, 5066, 5077, - 5083, 5092, 5098, 5118, 5124, 5133, 5139, 5150, - 5156, 5165, 5171, 5196, 5202, 5211, 5217, 5228, - 5234, 5243, 5249, 5269, 5275, 5284, 5290, 5301, - 5307, 5316, 5322, 5345, 5351, 5360, 5366, 5377, - 5383, 5392, 5398, 5418, 5424, 5433, 5439, 5450, - 5456, 5465, 5471, 5496, 5502, 5511, 5517, 5528, - 5534, 5543, 5549, 5569, 5575, 5584, 5590, 5601, - 5607, 5616, 5622, 5417, 5423, 5432, 5438, 5449, - 5455, 5464, 5470, 5490, 5496, 5505, 5511, 5522, - 5528, 5537, 5543, 5568, 5574, 5583, 5589, 5600, - 5606, 5615, 5621, 5641, 5647, 5656, 5662, 5673, - 5679, 5688, 5694, 5717, 5723, 5732, 5738, 5749, - 5755, 5764, 5770, 5790, 5796, 5805, 5811, 5822, - 5828, 5837, 5843, 5868, 5874, 5883, 5889, 5900, - 5906, 5915, 5921, 5941, 5947, 5956, 5962, 5973, - 5979, 5988, 5994, 5858, 5864, 5873, 5879, 5890, - 5896, 5905, 5911, 5931, 5937, 5946, 5952, 5963, - 5969, 5978, 5984, 6009, 6015, 6024, 6030, 6041, - 6047, 6056, 6062, 6082, 6088, 6097, 6103, 6114, - 6120, 6129, 6135, 6158, 6164, 6173, 6179, 6190, - 6196, 6205, 6211, 6231, 6237, 6246, 6252, 6263, - 6269, 6278, 6284, 6309, 6315, 6324, 6330, 6341, - 6347, 6356, 6362, 6382, 6388, 6397, 6403, 6414, - 6420, 6429, 6435, 3515, 3521, 3530, 3536, 3547, - 3553, 3562, 3568, 3588, 3594, 3603, 3609, 3620, - 3626, 3635, 3641, 3666, 3672, 3681, 3687, 3698, - 3704, 3713, 3719, 3739, 3745, 3754, 3760, 3771, - 3777, 3786, 3792, 3815, 3821, 3830, 3836, 3847, - 3853, 3862, 3868, 3888, 3894, 3903, 3909, 3920, - 3926, 3935, 3941, 3966, 3972, 3981, 3987, 3998, - 4004, 4013, 4019, 4039, 4045, 4054, 4060, 4071, - 4077, 4086, 4092, 3956, 3962, 3971, 3977, 3988, - 3994, 4003, 4009, 4029, 4035, 4044, 4050, 4061, - 4067, 4076, 4082, 4107, 4113, 4122, 4128, 4139, - 4145, 4154, 4160, 4180, 4186, 4195, 4201, 4212, - 4218, 4227, 4233, 4256, 4262, 4271, 4277, 4288, - 4294, 4303, 4309, 4329, 4335, 4344, 4350, 4361, - 4367, 4376, 4382, 4407, 4413, 4422, 4428, 4439, - 4445, 4454, 4460, 4480, 4486, 4495, 4501, 4512, - 4518, 4527, 4533, 4328, 4334, 4343, 4349, 4360, - 4366, 4375, 4381, 4401, 4407, 4416, 4422, 4433, - 4439, 4448, 4454, 4479, 4485, 4494, 4500, 4511, - 4517, 4526, 4532, 4552, 4558, 4567, 4573, 4584, - 4590, 4599, 4605, 4628, 4634, 4643, 4649, 4660, - 4666, 4675, 4681, 4701, 4707, 4716, 4722, 4733, - 4739, 4748, 4754, 4779, 4785, 4794, 4800, 4811, - 4817, 4826, 4832, 4852, 4858, 4867, 4873, 4884, - 4890, 4899, 4905, 4769, 4775, 4784, 4790, 4801, - 4807, 4816, 4822, 4842, 4848, 4857, 4863, 4874, - 4880, 4889, 4895, 4920, 4926, 4935, 4941, 4952, - 4958, 4967, 4973, 4993, 4999, 5008, 5014, 5025, - 5031, 5040, 5046, 5069, 5075, 5084, 5090, 5101, - 5107, 5116, 5122, 5142, 5148, 5157, 5163, 5174, - 5180, 5189, 5195, 5220, 5226, 5235, 5241, 5252, - 5258, 5267, 5273, 5293, 5299, 5308, 5314, 5325, - 5331, 5340, 5346, 4604, 4610, 4619, 4625, 4636, - 4642, 4651, 4657, 4677, 4683, 4692, 4698, 4709, - 4715, 4724, 4730, 4755, 4761, 4770, 4776, 4787, - 4793, 4802, 4808, 4828, 4834, 4843, 4849, 4860, - 4866, 4875, 4881, 4904, 4910, 4919, 4925, 4936, - 4942, 4951, 4957, 4977, 4983, 4992, 4998, 5009, - 5015, 5024, 5030, 5055, 5061, 5070, 5076, 5087, - 5093, 5102, 5108, 5128, 5134, 5143, 5149, 5160, - 5166, 5175, 5181, 5045, 5051, 5060, 5066, 5077, - 5083, 5092, 5098, 5118, 5124, 5133, 5139, 5150, - 5156, 5165, 5171, 5196, 5202, 5211, 5217, 5228, - 5234, 5243, 5249, 5269, 5275, 5284, 5290, 5301, - 5307, 5316, 5322, 5345, 5351, 5360, 5366, 5377, - 5383, 5392, 5398, 5418, 5424, 5433, 5439, 5450, - 5456, 5465, 5471, 5496, 5502, 5511, 5517, 5528, - 5534, 5543, 5549, 5569, 5575, 5584, 5590, 5601, - 5607, 5616, 5622, 5417, 5423, 5432, 5438, 5449, - 5455, 5464, 5470, 5490, 5496, 5505, 5511, 5522, - 5528, 5537, 5543, 5568, 5574, 5583, 5589, 5600, - 5606, 5615, 5621, 5641, 5647, 5656, 5662, 5673, - 5679, 5688, 5694, 5717, 5723, 5732, 5738, 5749, - 5755, 5764, 5770, 5790, 5796, 5805, 5811, 5822, - 5828, 5837, 5843, 5868, 5874, 5883, 5889, 5900, - 5906, 5915, 5921, 5941, 5947, 5956, 5962, 5973, - 5979, 5988, 5994, 5858, 5864, 5873, 5879, 5890, - 5896, 5905, 5911, 5931, 5937, 5946, 5952, 5963, - 5969, 5978, 5984, 6009, 6015, 6024, 6030, 6041, - 6047, 6056, 6062, 6082, 6088, 6097, 6103, 6114, - 6120, 6129, 6135, 6158, 6164, 6173, 6179, 6190, - 6196, 6205, 6211, 6231, 6237, 6246, 6252, 6263, - 6269, 6278, 6284, 6309, 6315, 6324, 6330, 6341, - 6347, 6356, 6362, 6382, 6388, 6397, 6403, 6414, - 6420, 6429, 6435, 5303, 5309, 5318, 5324, 5335, - 5341, 5350, 5356, 5376, 5382, 5391, 5397, 5408, - 5414, 5423, 5429, 5454, 5460, 5469, 5475, 5486, - 5492, 5501, 5507, 5527, 5533, 5542, 5548, 5559, - 5565, 5574, 5580, 5603, 5609, 5618, 5624, 5635, - 5641, 5650, 5656, 5676, 5682, 5691, 5697, 5708, - 5714, 5723, 5729, 5754, 5760, 5769, 5775, 5786, - 5792, 5801, 5807, 5827, 5833, 5842, 5848, 5859, - 5865, 5874, 5880, 5744, 5750, 5759, 5765, 5776, - 5782, 5791, 5797, 5817, 5823, 5832, 5838, 5849, - 5855, 5864, 5870, 5895, 5901, 5910, 5916, 5927, - 5933, 5942, 5948, 5968, 5974, 5983, 5989, 6000, - 6006, 6015, 6021, 6044, 6050, 6059, 6065, 6076, - 6082, 6091, 6097, 6117, 6123, 6132, 6138, 6149, - 6155, 6164, 6170, 6195, 6201, 6210, 6216, 6227, - 6233, 6242, 6248, 6268, 6274, 6283, 6289, 6300, - 6306, 6315, 6321, 6116, 6122, 6131, 6137, 6148, - 6154, 6163, 6169, 6189, 6195, 6204, 6210, 6221, - 6227, 6236, 6242, 6267, 6273, 6282, 6288, 6299, - 6305, 6314, 6320, 6340, 6346, 6355, 6361, 6372, - 6378, 6387, 6393, 6416, 6422, 6431, 6437, 6448, - 6454, 6463, 6469, 6489, 6495, 6504, 6510, 6521, - 6527, 6536, 6542, 6567, 6573, 6582, 6588, 6599, - 6605, 6614, 6620, 6640, 6646, 6655, 6661, 6672, - 6678, 6687, 6693, 6557, 6563, 6572, 6578, 6589, - 6595, 6604, 6610, 6630, 6636, 6645, 6651, 6662, - 6668, 6677, 6683, 6708, 6714, 6723, 6729, 6740, - 6746, 6755, 6761, 6781, 6787, 6796, 6802, 6813, - 6819, 6828, 6834, 6857, 6863, 6872, 6878, 6889, - 6895, 6904, 6910, 6930, 6936, 6945, 6951, 6962, - 6968, 6977, 6983, 7008, 7014, 7023, 7029, 7040, - 7046, 7055, 7061, 7081, 7087, 7096, 7102, 7113, - 7119, 7128, 7134, 6392, 6398, 6407, 6413, 6424, - 6430, 6439, 6445, 6465, 6471, 6480, 6486, 6497, - 6503, 6512, 6518, 6543, 6549, 6558, 6564, 6575, - 6581, 6590, 6596, 6616, 6622, 6631, 6637, 6648, - 6654, 6663, 6669, 6692, 6698, 6707, 6713, 6724, - 6730, 6739, 6745, 6765, 6771, 6780, 6786, 6797, - 6803, 6812, 6818, 6843, 6849, 6858, 6864, 6875, - 6881, 6890, 6896, 6916, 6922, 6931, 6937, 6948, - 6954, 6963, 6969, 6833, 6839, 6848, 6854, 6865, - 6871, 6880, 6886, 6906, 6912, 6921, 6927, 6938, - 6944, 6953, 6959, 6984, 6990, 6999, 7005, 7016, - 7022, 7031, 7037, 7057, 7063, 7072, 7078, 7089, - 7095, 7104, 7110, 7133, 7139, 7148, 7154, 7165, - 7171, 7180, 7186, 7206, 7212, 7221, 7227, 7238, - 7244, 7253, 7259, 7284, 7290, 7299, 7305, 7316, - 7322, 7331, 7337, 7357, 7363, 7372, 7378, 7389, - 7395, 7404, 7410, 7205, 7211, 7220, 7226, 7237, - 7243, 7252, 7258, 7278, 7284, 7293, 7299, 7310, - 7316, 7325, 7331, 7356, 7362, 7371, 7377, 7388, - 7394, 7403, 7409, 7429, 7435, 7444, 7450, 7461, - 7467, 7476, 7482, 7505, 7511, 7520, 7526, 7537, - 7543, 7552, 7558, 7578, 7584, 7593, 7599, 7610, - 7616, 7625, 7631, 7656, 7662, 7671, 7677, 7688, - 7694, 7703, 7709, 7729, 7735, 7744, 7750, 7761 -}; - -//------------------------------------------------------------------------------ -// Tables for level coding - -const uint8_t VP8EncBands[16 + 1] = { - 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, - 0 // sentinel -}; - -//------------------------------------------------------------------------------ -// Mode costs - -static int GetResidualCost(int ctx0, const VP8Residual* const res) { - int n = res->first; - // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 - const int p0 = res->prob[n][ctx0][0]; - CostArrayPtr const costs = res->costs; - const uint16_t* t = costs[n][ctx0]; - // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0 - // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll - // be missing during the loop. - int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0; - - if (res->last < 0) { - return VP8BitCost(0, p0); - } - for (; n < res->last; ++n) { - const int v = abs(res->coeffs[n]); - const int ctx = (v >= 2) ? 2 : v; - cost += VP8LevelCost(t, v); - t = costs[n + 1][ctx]; - } - // Last coefficient is always non-zero - { - const int v = abs(res->coeffs[n]); - assert(v != 0); - cost += VP8LevelCost(t, v); - if (n < 15) { - const int b = VP8EncBands[n + 1]; - const int ctx = (v == 1) ? 1 : 2; - const int last_p0 = res->prob[b][ctx][0]; - cost += VP8BitCost(0, last_p0); - } - } - return cost; -} - -static void SetResidualCoeffs(const int16_t* const coeffs, - VP8Residual* const res) { - int n; - res->last = -1; - assert(res->first == 0 || coeffs[0] == 0); - for (n = 15; n >= 0; --n) { - if (coeffs[n]) { - res->last = n; - break; - } - } - res->coeffs = coeffs; -} - -//------------------------------------------------------------------------------ -// init function - -VP8GetResidualCostFunc VP8GetResidualCost; -VP8SetResidualCoeffsFunc VP8SetResidualCoeffs; - -extern void VP8EncDspCostInitMIPS32(void); -extern void VP8EncDspCostInitMIPSdspR2(void); -extern void VP8EncDspCostInitSSE2(void); - -static volatile VP8CPUInfo cost_last_cpuinfo_used = - (VP8CPUInfo)&cost_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInit(void) { - if (cost_last_cpuinfo_used == VP8GetCPUInfo) return; - - VP8GetResidualCost = GetResidualCost; - VP8SetResidualCoeffs = SetResidualCoeffs; - - // If defined, use CPUInfo() to overwrite some pointers with faster versions. - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_MIPS32) - if (VP8GetCPUInfo(kMIPS32)) { - VP8EncDspCostInitMIPS32(); - } -#endif -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - VP8EncDspCostInitMIPSdspR2(); - } -#endif -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - VP8EncDspCostInitSSE2(); - } -#endif - } - - cost_last_cpuinfo_used = VP8GetCPUInfo; -} - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/dsp/cost_mips32.c b/Example/Pods/libwebp/src/dsp/cost_mips32.c deleted file mode 100644 index d1e240e1..00000000 --- a/Example/Pods/libwebp/src/dsp/cost_mips32.c +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Djordje Pesut (djordje.pesut@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS32) - -#include "../enc/cost.h" - -static int GetResidualCost(int ctx0, const VP8Residual* const res) { - int temp0, temp1; - int v_reg, ctx_reg; - int n = res->first; - // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 - int p0 = res->prob[n][ctx0][0]; - CostArrayPtr const costs = res->costs; - const uint16_t* t = costs[n][ctx0]; - // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0 - // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll - // be missing during the loop. - int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0; - const int16_t* res_coeffs = res->coeffs; - const int res_last = res->last; - const int const_max_level = MAX_VARIABLE_LEVEL; - const int const_2 = 2; - const uint16_t** p_costs = &costs[n][0]; - const size_t inc_p_costs = NUM_CTX * sizeof(*p_costs); - - if (res->last < 0) { - return VP8BitCost(0, p0); - } - - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "subu %[temp1], %[res_last], %[n] \n\t" - "sll %[temp0], %[n], 1 \n\t" - "blez %[temp1], 2f \n\t" - " addu %[res_coeffs], %[res_coeffs], %[temp0] \n\t" - "1: \n\t" - "lh %[v_reg], 0(%[res_coeffs]) \n\t" - "addiu %[n], %[n], 1 \n\t" - "negu %[temp0], %[v_reg] \n\t" - "slti %[temp1], %[v_reg], 0 \n\t" - "movn %[v_reg], %[temp0], %[temp1] \n\t" - "sltiu %[temp0], %[v_reg], 2 \n\t" - "move %[ctx_reg], %[v_reg] \n\t" - "movz %[ctx_reg], %[const_2], %[temp0] \n\t" - "sll %[temp1], %[v_reg], 1 \n\t" - "addu %[temp1], %[temp1], %[VP8LevelFixedCosts] \n\t" - "lhu %[temp1], 0(%[temp1]) \n\t" - "slt %[temp0], %[v_reg], %[const_max_level] \n\t" - "movz %[v_reg], %[const_max_level], %[temp0] \n\t" - "addu %[cost], %[cost], %[temp1] \n\t" - "sll %[v_reg], %[v_reg], 1 \n\t" - "sll %[ctx_reg], %[ctx_reg], 2 \n\t" - "addu %[v_reg], %[v_reg], %[t] \n\t" - "lhu %[temp0], 0(%[v_reg]) \n\t" - "addu %[p_costs], %[p_costs], %[inc_p_costs] \n\t" - "addu %[t], %[p_costs], %[ctx_reg] \n\t" - "addu %[cost], %[cost], %[temp0] \n\t" - "addiu %[res_coeffs], %[res_coeffs], 2 \n\t" - "bne %[n], %[res_last], 1b \n\t" - " lw %[t], 0(%[t]) \n\t" - "2: \n\t" - ".set pop \n\t" - : [cost]"+&r"(cost), [t]"+&r"(t), [n]"+&r"(n), [v_reg]"=&r"(v_reg), - [ctx_reg]"=&r"(ctx_reg), [p_costs]"+&r"(p_costs), [temp0]"=&r"(temp0), - [temp1]"=&r"(temp1), [res_coeffs]"+&r"(res_coeffs) - : [const_2]"r"(const_2), [const_max_level]"r"(const_max_level), - [VP8LevelFixedCosts]"r"(VP8LevelFixedCosts), [res_last]"r"(res_last), - [inc_p_costs]"r"(inc_p_costs) - : "memory" - ); - - // Last coefficient is always non-zero - { - const int v = abs(res->coeffs[n]); - assert(v != 0); - cost += VP8LevelCost(t, v); - if (n < 15) { - const int b = VP8EncBands[n + 1]; - const int ctx = (v == 1) ? 1 : 2; - const int last_p0 = res->prob[b][ctx][0]; - cost += VP8BitCost(0, last_p0); - } - } - return cost; -} - -static void SetResidualCoeffs(const int16_t* const coeffs, - VP8Residual* const res) { - const int16_t* p_coeffs = (int16_t*)coeffs; - int temp0, temp1, temp2, n, n1; - assert(res->first == 0 || coeffs[0] == 0); - - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "addiu %[p_coeffs], %[p_coeffs], 28 \n\t" - "li %[n], 15 \n\t" - "li %[temp2], -1 \n\t" - "0: \n\t" - "ulw %[temp0], 0(%[p_coeffs]) \n\t" - "beqz %[temp0], 1f \n\t" -#if defined(WORDS_BIGENDIAN) - " sll %[temp1], %[temp0], 16 \n\t" -#else - " srl %[temp1], %[temp0], 16 \n\t" -#endif - "addiu %[n1], %[n], -1 \n\t" - "movz %[temp0], %[n1], %[temp1] \n\t" - "movn %[temp0], %[n], %[temp1] \n\t" - "j 2f \n\t" - " addiu %[temp2], %[temp0], 0 \n\t" - "1: \n\t" - "addiu %[n], %[n], -2 \n\t" - "bgtz %[n], 0b \n\t" - " addiu %[p_coeffs], %[p_coeffs], -4 \n\t" - "2: \n\t" - ".set pop \n\t" - : [p_coeffs]"+&r"(p_coeffs), [temp0]"=&r"(temp0), - [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [n]"=&r"(n), [n1]"=&r"(n1) - : - : "memory" - ); - res->last = temp2; - res->coeffs = coeffs; -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8EncDspCostInitMIPS32(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitMIPS32(void) { - VP8GetResidualCost = GetResidualCost; - VP8SetResidualCoeffs = SetResidualCoeffs; -} - -#else // !WEBP_USE_MIPS32 - -WEBP_DSP_INIT_STUB(VP8EncDspCostInitMIPS32) - -#endif // WEBP_USE_MIPS32 diff --git a/Example/Pods/libwebp/src/dsp/cost_mips_dsp_r2.c b/Example/Pods/libwebp/src/dsp/cost_mips_dsp_r2.c deleted file mode 100644 index ce640677..00000000 --- a/Example/Pods/libwebp/src/dsp/cost_mips_dsp_r2.c +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Djordje Pesut (djordje.pesut@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS_DSP_R2) - -#include "../enc/cost.h" - -static int GetResidualCost(int ctx0, const VP8Residual* const res) { - int temp0, temp1; - int v_reg, ctx_reg; - int n = res->first; - // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 - int p0 = res->prob[n][ctx0][0]; - CostArrayPtr const costs = res->costs; - const uint16_t* t = costs[n][ctx0]; - // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0 - // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll - // be missing during the loop. - int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0; - const int16_t* res_coeffs = res->coeffs; - const int res_last = res->last; - const int const_max_level = MAX_VARIABLE_LEVEL; - const int const_2 = 2; - const uint16_t** p_costs = &costs[n][0]; - const size_t inc_p_costs = NUM_CTX * sizeof(*p_costs); - - if (res->last < 0) { - return VP8BitCost(0, p0); - } - - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "subu %[temp1], %[res_last], %[n] \n\t" - "blez %[temp1], 2f \n\t" - " nop \n\t" - "1: \n\t" - "sll %[temp0], %[n], 1 \n\t" - "lhx %[v_reg], %[temp0](%[res_coeffs]) \n\t" - "addiu %[n], %[n], 1 \n\t" - "absq_s.w %[v_reg], %[v_reg] \n\t" - "sltiu %[temp0], %[v_reg], 2 \n\t" - "move %[ctx_reg], %[v_reg] \n\t" - "movz %[ctx_reg], %[const_2], %[temp0] \n\t" - "sll %[temp1], %[v_reg], 1 \n\t" - "lhx %[temp1], %[temp1](%[VP8LevelFixedCosts]) \n\t" - "slt %[temp0], %[v_reg], %[const_max_level] \n\t" - "movz %[v_reg], %[const_max_level], %[temp0] \n\t" - "addu %[cost], %[cost], %[temp1] \n\t" - "sll %[v_reg], %[v_reg], 1 \n\t" - "sll %[ctx_reg], %[ctx_reg], 2 \n\t" - "lhx %[temp0], %[v_reg](%[t]) \n\t" - "addu %[p_costs], %[p_costs], %[inc_p_costs] \n\t" - "addu %[t], %[p_costs], %[ctx_reg] \n\t" - "addu %[cost], %[cost], %[temp0] \n\t" - "bne %[n], %[res_last], 1b \n\t" - " lw %[t], 0(%[t]) \n\t" - "2: \n\t" - ".set pop \n\t" - : [cost]"+&r"(cost), [t]"+&r"(t), [n]"+&r"(n), [v_reg]"=&r"(v_reg), - [ctx_reg]"=&r"(ctx_reg), [p_costs]"+&r"(p_costs), [temp0]"=&r"(temp0), - [temp1]"=&r"(temp1) - : [const_2]"r"(const_2), [const_max_level]"r"(const_max_level), - [VP8LevelFixedCosts]"r"(VP8LevelFixedCosts), [res_last]"r"(res_last), - [res_coeffs]"r"(res_coeffs), [inc_p_costs]"r"(inc_p_costs) - : "memory" - ); - - // Last coefficient is always non-zero - { - const int v = abs(res->coeffs[n]); - assert(v != 0); - cost += VP8LevelCost(t, v); - if (n < 15) { - const int b = VP8EncBands[n + 1]; - const int ctx = (v == 1) ? 1 : 2; - const int last_p0 = res->prob[b][ctx][0]; - cost += VP8BitCost(0, last_p0); - } - } - return cost; -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8EncDspCostInitMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitMIPSdspR2(void) { - VP8GetResidualCost = GetResidualCost; -} - -#else // !WEBP_USE_MIPS_DSP_R2 - -WEBP_DSP_INIT_STUB(VP8EncDspCostInitMIPSdspR2) - -#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/Example/Pods/libwebp/src/dsp/cost_sse2.c b/Example/Pods/libwebp/src/dsp/cost_sse2.c deleted file mode 100644 index 0cb1c1fa..00000000 --- a/Example/Pods/libwebp/src/dsp/cost_sse2.c +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// SSE2 version of cost functions -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE2) -#include - -#include "../enc/cost.h" -#include "../enc/vp8enci.h" -#include "../utils/utils.h" - -//------------------------------------------------------------------------------ - -static void SetResidualCoeffsSSE2(const int16_t* const coeffs, - VP8Residual* const res) { - const __m128i c0 = _mm_loadu_si128((const __m128i*)(coeffs + 0)); - const __m128i c1 = _mm_loadu_si128((const __m128i*)(coeffs + 8)); - // Use SSE2 to compare 16 values with a single instruction. - const __m128i zero = _mm_setzero_si128(); - const __m128i m0 = _mm_packs_epi16(c0, c1); - const __m128i m1 = _mm_cmpeq_epi8(m0, zero); - // Get the comparison results as a bitmask into 16bits. Negate the mask to get - // the position of entries that are not equal to zero. We don't need to mask - // out least significant bits according to res->first, since coeffs[0] is 0 - // if res->first > 0. - const uint32_t mask = 0x0000ffffu ^ (uint32_t)_mm_movemask_epi8(m1); - // The position of the most significant non-zero bit indicates the position of - // the last non-zero value. - assert(res->first == 0 || coeffs[0] == 0); - res->last = mask ? BitsLog2Floor(mask) : -1; - res->coeffs = coeffs; -} - -static int GetResidualCostSSE2(int ctx0, const VP8Residual* const res) { - uint8_t levels[16], ctxs[16]; - uint16_t abs_levels[16]; - int n = res->first; - // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 - const int p0 = res->prob[n][ctx0][0]; - CostArrayPtr const costs = res->costs; - const uint16_t* t = costs[n][ctx0]; - // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0 - // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll - // be missing during the loop. - int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0; - - if (res->last < 0) { - return VP8BitCost(0, p0); - } - - { // precompute clamped levels and contexts, packed to 8b. - const __m128i zero = _mm_setzero_si128(); - const __m128i kCst2 = _mm_set1_epi8(2); - const __m128i kCst67 = _mm_set1_epi8(MAX_VARIABLE_LEVEL); - const __m128i c0 = _mm_loadu_si128((const __m128i*)&res->coeffs[0]); - const __m128i c1 = _mm_loadu_si128((const __m128i*)&res->coeffs[8]); - const __m128i D0 = _mm_sub_epi16(zero, c0); - const __m128i D1 = _mm_sub_epi16(zero, c1); - const __m128i E0 = _mm_max_epi16(c0, D0); // abs(v), 16b - const __m128i E1 = _mm_max_epi16(c1, D1); - const __m128i F = _mm_packs_epi16(E0, E1); - const __m128i G = _mm_min_epu8(F, kCst2); // context = 0,1,2 - const __m128i H = _mm_min_epu8(F, kCst67); // clamp_level in [0..67] - - _mm_storeu_si128((__m128i*)&ctxs[0], G); - _mm_storeu_si128((__m128i*)&levels[0], H); - - _mm_storeu_si128((__m128i*)&abs_levels[0], E0); - _mm_storeu_si128((__m128i*)&abs_levels[8], E1); - } - for (; n < res->last; ++n) { - const int ctx = ctxs[n]; - const int level = levels[n]; - const int flevel = abs_levels[n]; // full level - cost += VP8LevelFixedCosts[flevel] + t[level]; // simplified VP8LevelCost() - t = costs[n + 1][ctx]; - } - // Last coefficient is always non-zero - { - const int level = levels[n]; - const int flevel = abs_levels[n]; - assert(flevel != 0); - cost += VP8LevelFixedCosts[flevel] + t[level]; - if (n < 15) { - const int b = VP8EncBands[n + 1]; - const int ctx = ctxs[n]; - const int last_p0 = res->prob[b][ctx][0]; - cost += VP8BitCost(0, last_p0); - } - } - return cost; -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8EncDspCostInitSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitSSE2(void) { - VP8SetResidualCoeffs = SetResidualCoeffsSSE2; - VP8GetResidualCost = GetResidualCostSSE2; -} - -#else // !WEBP_USE_SSE2 - -WEBP_DSP_INIT_STUB(VP8EncDspCostInitSSE2) - -#endif // WEBP_USE_SSE2 diff --git a/Example/Pods/libwebp/src/dsp/cpu.c b/Example/Pods/libwebp/src/dsp/cpu.c deleted file mode 100644 index 8844cb40..00000000 --- a/Example/Pods/libwebp/src/dsp/cpu.c +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// CPU detection -// -// Author: Christian Duvivier (cduvivier@google.com) - -#include "./dsp.h" - -#if defined(WEBP_ANDROID_NEON) -#include -#endif - -//------------------------------------------------------------------------------ -// SSE2 detection. -// - -// apple/darwin gcc-4.0.1 defines __PIC__, but not __pic__ with -fPIC. -#if (defined(__pic__) || defined(__PIC__)) && defined(__i386__) -static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { - __asm__ volatile ( - "mov %%ebx, %%edi\n" - "cpuid\n" - "xchg %%edi, %%ebx\n" - : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) - : "a"(info_type), "c"(0)); -} -#elif defined(__x86_64__) && \ - (defined(__code_model_medium__) || defined(__code_model_large__)) && \ - defined(__PIC__) -static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { - __asm__ volatile ( - "xchg{q}\t{%%rbx}, %q1\n" - "cpuid\n" - "xchg{q}\t{%%rbx}, %q1\n" - : "=a"(cpu_info[0]), "=&r"(cpu_info[1]), "=c"(cpu_info[2]), - "=d"(cpu_info[3]) - : "a"(info_type), "c"(0)); -} -#elif defined(__i386__) || defined(__x86_64__) -static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { - __asm__ volatile ( - "cpuid\n" - : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) - : "a"(info_type), "c"(0)); -} -#elif (defined(_M_X64) || defined(_M_IX86)) && \ - defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 150030729 // >= VS2008 SP1 -#include -#define GetCPUInfo(info, type) __cpuidex(info, type, 0) // set ecx=0 -#elif defined(WEBP_MSC_SSE2) -#define GetCPUInfo __cpuid -#endif - -// NaCl has no support for xgetbv or the raw opcode. -#if !defined(__native_client__) && (defined(__i386__) || defined(__x86_64__)) -static WEBP_INLINE uint64_t xgetbv(void) { - const uint32_t ecx = 0; - uint32_t eax, edx; - // Use the raw opcode for xgetbv for compatibility with older toolchains. - __asm__ volatile ( - ".byte 0x0f, 0x01, 0xd0\n" - : "=a"(eax), "=d"(edx) : "c" (ecx)); - return ((uint64_t)edx << 32) | eax; -} -#elif (defined(_M_X64) || defined(_M_IX86)) && \ - defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219 // >= VS2010 SP1 -#include -#define xgetbv() _xgetbv(0) -#elif defined(_MSC_VER) && defined(_M_IX86) -static WEBP_INLINE uint64_t xgetbv(void) { - uint32_t eax_, edx_; - __asm { - xor ecx, ecx // ecx = 0 - // Use the raw opcode for xgetbv for compatibility with older toolchains. - __asm _emit 0x0f __asm _emit 0x01 __asm _emit 0xd0 - mov eax_, eax - mov edx_, edx - } - return ((uint64_t)edx_ << 32) | eax_; -} -#else -#define xgetbv() 0U // no AVX for older x64 or unrecognized toolchains. -#endif - -#if defined(__i386__) || defined(__x86_64__) || defined(WEBP_MSC_SSE2) -static int x86CPUInfo(CPUFeature feature) { - int max_cpuid_value; - int cpu_info[4]; - - // get the highest feature value cpuid supports - GetCPUInfo(cpu_info, 0); - max_cpuid_value = cpu_info[0]; - if (max_cpuid_value < 1) { - return 0; - } - - GetCPUInfo(cpu_info, 1); - if (feature == kSSE2) { - return 0 != (cpu_info[3] & 0x04000000); - } - if (feature == kSSE3) { - return 0 != (cpu_info[2] & 0x00000001); - } - if (feature == kSSE4_1) { - return 0 != (cpu_info[2] & 0x00080000); - } - if (feature == kAVX) { - // bits 27 (OSXSAVE) & 28 (256-bit AVX) - if ((cpu_info[2] & 0x18000000) == 0x18000000) { - // XMM state and YMM state enabled by the OS. - return (xgetbv() & 0x6) == 0x6; - } - } - if (feature == kAVX2) { - if (x86CPUInfo(kAVX) && max_cpuid_value >= 7) { - GetCPUInfo(cpu_info, 7); - return ((cpu_info[1] & 0x00000020) == 0x00000020); - } - } - return 0; -} -VP8CPUInfo VP8GetCPUInfo = x86CPUInfo; -#elif defined(WEBP_ANDROID_NEON) // NB: needs to be before generic NEON test. -static int AndroidCPUInfo(CPUFeature feature) { - const AndroidCpuFamily cpu_family = android_getCpuFamily(); - const uint64_t cpu_features = android_getCpuFeatures(); - if (feature == kNEON) { - return (cpu_family == ANDROID_CPU_FAMILY_ARM && - 0 != (cpu_features & ANDROID_CPU_ARM_FEATURE_NEON)); - } - return 0; -} -VP8CPUInfo VP8GetCPUInfo = AndroidCPUInfo; -#elif defined(WEBP_USE_NEON) -// define a dummy function to enable turning off NEON at runtime by setting -// VP8DecGetCPUInfo = NULL -static int armCPUInfo(CPUFeature feature) { - (void)feature; - return 1; -} -VP8CPUInfo VP8GetCPUInfo = armCPUInfo; -#elif defined(WEBP_USE_MIPS32) || defined(WEBP_USE_MIPS_DSP_R2) -static int mipsCPUInfo(CPUFeature feature) { - if ((feature == kMIPS32) || (feature == kMIPSdspR2)) { - return 1; - } else { - return 0; - } - -} -VP8CPUInfo VP8GetCPUInfo = mipsCPUInfo; -#else -VP8CPUInfo VP8GetCPUInfo = NULL; -#endif - diff --git a/Example/Pods/libwebp/src/dsp/dec.c b/Example/Pods/libwebp/src/dsp/dec.c deleted file mode 100644 index a7872064..00000000 --- a/Example/Pods/libwebp/src/dsp/dec.c +++ /dev/null @@ -1,766 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Speed-critical decoding functions, default plain-C implementations. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" -#include "../dec/vp8i.h" - -//------------------------------------------------------------------------------ - -static WEBP_INLINE uint8_t clip_8b(int v) { - return (!(v & ~0xff)) ? v : (v < 0) ? 0 : 255; -} - -//------------------------------------------------------------------------------ -// Transforms (Paragraph 14.4) - -#define STORE(x, y, v) \ - dst[x + y * BPS] = clip_8b(dst[x + y * BPS] + ((v) >> 3)) - -#define STORE2(y, dc, d, c) do { \ - const int DC = (dc); \ - STORE(0, y, DC + (d)); \ - STORE(1, y, DC + (c)); \ - STORE(2, y, DC - (c)); \ - STORE(3, y, DC - (d)); \ -} while (0) - -#define MUL1(a) ((((a) * 20091) >> 16) + (a)) -#define MUL2(a) (((a) * 35468) >> 16) - -static void TransformOne(const int16_t* in, uint8_t* dst) { - int C[4 * 4], *tmp; - int i; - tmp = C; - for (i = 0; i < 4; ++i) { // vertical pass - const int a = in[0] + in[8]; // [-4096, 4094] - const int b = in[0] - in[8]; // [-4095, 4095] - const int c = MUL2(in[4]) - MUL1(in[12]); // [-3783, 3783] - const int d = MUL1(in[4]) + MUL2(in[12]); // [-3785, 3781] - tmp[0] = a + d; // [-7881, 7875] - tmp[1] = b + c; // [-7878, 7878] - tmp[2] = b - c; // [-7878, 7878] - tmp[3] = a - d; // [-7877, 7879] - tmp += 4; - in++; - } - // Each pass is expanding the dynamic range by ~3.85 (upper bound). - // The exact value is (2. + (20091 + 35468) / 65536). - // After the second pass, maximum interval is [-3794, 3794], assuming - // an input in [-2048, 2047] interval. We then need to add a dst value - // in the [0, 255] range. - // In the worst case scenario, the input to clip_8b() can be as large as - // [-60713, 60968]. - tmp = C; - for (i = 0; i < 4; ++i) { // horizontal pass - const int dc = tmp[0] + 4; - const int a = dc + tmp[8]; - const int b = dc - tmp[8]; - const int c = MUL2(tmp[4]) - MUL1(tmp[12]); - const int d = MUL1(tmp[4]) + MUL2(tmp[12]); - STORE(0, 0, a + d); - STORE(1, 0, b + c); - STORE(2, 0, b - c); - STORE(3, 0, a - d); - tmp++; - dst += BPS; - } -} - -// Simplified transform when only in[0], in[1] and in[4] are non-zero -static void TransformAC3(const int16_t* in, uint8_t* dst) { - const int a = in[0] + 4; - const int c4 = MUL2(in[4]); - const int d4 = MUL1(in[4]); - const int c1 = MUL2(in[1]); - const int d1 = MUL1(in[1]); - STORE2(0, a + d4, d1, c1); - STORE2(1, a + c4, d1, c1); - STORE2(2, a - c4, d1, c1); - STORE2(3, a - d4, d1, c1); -} -#undef MUL1 -#undef MUL2 -#undef STORE2 - -static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) { - TransformOne(in, dst); - if (do_two) { - TransformOne(in + 16, dst + 4); - } -} - -static void TransformUV(const int16_t* in, uint8_t* dst) { - VP8Transform(in + 0 * 16, dst, 1); - VP8Transform(in + 2 * 16, dst + 4 * BPS, 1); -} - -static void TransformDC(const int16_t* in, uint8_t* dst) { - const int DC = in[0] + 4; - int i, j; - for (j = 0; j < 4; ++j) { - for (i = 0; i < 4; ++i) { - STORE(i, j, DC); - } - } -} - -static void TransformDCUV(const int16_t* in, uint8_t* dst) { - if (in[0 * 16]) VP8TransformDC(in + 0 * 16, dst); - if (in[1 * 16]) VP8TransformDC(in + 1 * 16, dst + 4); - if (in[2 * 16]) VP8TransformDC(in + 2 * 16, dst + 4 * BPS); - if (in[3 * 16]) VP8TransformDC(in + 3 * 16, dst + 4 * BPS + 4); -} - -#undef STORE - -//------------------------------------------------------------------------------ -// Paragraph 14.3 - -static void TransformWHT(const int16_t* in, int16_t* out) { - int tmp[16]; - int i; - for (i = 0; i < 4; ++i) { - const int a0 = in[0 + i] + in[12 + i]; - const int a1 = in[4 + i] + in[ 8 + i]; - const int a2 = in[4 + i] - in[ 8 + i]; - const int a3 = in[0 + i] - in[12 + i]; - tmp[0 + i] = a0 + a1; - tmp[8 + i] = a0 - a1; - tmp[4 + i] = a3 + a2; - tmp[12 + i] = a3 - a2; - } - for (i = 0; i < 4; ++i) { - const int dc = tmp[0 + i * 4] + 3; // w/ rounder - const int a0 = dc + tmp[3 + i * 4]; - const int a1 = tmp[1 + i * 4] + tmp[2 + i * 4]; - const int a2 = tmp[1 + i * 4] - tmp[2 + i * 4]; - const int a3 = dc - tmp[3 + i * 4]; - out[ 0] = (a0 + a1) >> 3; - out[16] = (a3 + a2) >> 3; - out[32] = (a0 - a1) >> 3; - out[48] = (a3 - a2) >> 3; - out += 64; - } -} - -void (*VP8TransformWHT)(const int16_t* in, int16_t* out); - -//------------------------------------------------------------------------------ -// Intra predictions - -#define DST(x, y) dst[(x) + (y) * BPS] - -static WEBP_INLINE void TrueMotion(uint8_t* dst, int size) { - const uint8_t* top = dst - BPS; - const uint8_t* const clip0 = VP8kclip1 - top[-1]; - int y; - for (y = 0; y < size; ++y) { - const uint8_t* const clip = clip0 + dst[-1]; - int x; - for (x = 0; x < size; ++x) { - dst[x] = clip[top[x]]; - } - dst += BPS; - } -} -static void TM4(uint8_t* dst) { TrueMotion(dst, 4); } -static void TM8uv(uint8_t* dst) { TrueMotion(dst, 8); } -static void TM16(uint8_t* dst) { TrueMotion(dst, 16); } - -//------------------------------------------------------------------------------ -// 16x16 - -static void VE16(uint8_t* dst) { // vertical - int j; - for (j = 0; j < 16; ++j) { - memcpy(dst + j * BPS, dst - BPS, 16); - } -} - -static void HE16(uint8_t* dst) { // horizontal - int j; - for (j = 16; j > 0; --j) { - memset(dst, dst[-1], 16); - dst += BPS; - } -} - -static WEBP_INLINE void Put16(int v, uint8_t* dst) { - int j; - for (j = 0; j < 16; ++j) { - memset(dst + j * BPS, v, 16); - } -} - -static void DC16(uint8_t* dst) { // DC - int DC = 16; - int j; - for (j = 0; j < 16; ++j) { - DC += dst[-1 + j * BPS] + dst[j - BPS]; - } - Put16(DC >> 5, dst); -} - -static void DC16NoTop(uint8_t* dst) { // DC with top samples not available - int DC = 8; - int j; - for (j = 0; j < 16; ++j) { - DC += dst[-1 + j * BPS]; - } - Put16(DC >> 4, dst); -} - -static void DC16NoLeft(uint8_t* dst) { // DC with left samples not available - int DC = 8; - int i; - for (i = 0; i < 16; ++i) { - DC += dst[i - BPS]; - } - Put16(DC >> 4, dst); -} - -static void DC16NoTopLeft(uint8_t* dst) { // DC with no top and left samples - Put16(0x80, dst); -} - -VP8PredFunc VP8PredLuma16[NUM_B_DC_MODES]; - -//------------------------------------------------------------------------------ -// 4x4 - -#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2) -#define AVG2(a, b) (((a) + (b) + 1) >> 1) - -static void VE4(uint8_t* dst) { // vertical - const uint8_t* top = dst - BPS; - const uint8_t vals[4] = { - AVG3(top[-1], top[0], top[1]), - AVG3(top[ 0], top[1], top[2]), - AVG3(top[ 1], top[2], top[3]), - AVG3(top[ 2], top[3], top[4]) - }; - int i; - for (i = 0; i < 4; ++i) { - memcpy(dst + i * BPS, vals, sizeof(vals)); - } -} - -static void HE4(uint8_t* dst) { // horizontal - const int A = dst[-1 - BPS]; - const int B = dst[-1]; - const int C = dst[-1 + BPS]; - const int D = dst[-1 + 2 * BPS]; - const int E = dst[-1 + 3 * BPS]; - WebPUint32ToMem(dst + 0 * BPS, 0x01010101U * AVG3(A, B, C)); - WebPUint32ToMem(dst + 1 * BPS, 0x01010101U * AVG3(B, C, D)); - WebPUint32ToMem(dst + 2 * BPS, 0x01010101U * AVG3(C, D, E)); - WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(D, E, E)); -} - -static void DC4(uint8_t* dst) { // DC - uint32_t dc = 4; - int i; - for (i = 0; i < 4; ++i) dc += dst[i - BPS] + dst[-1 + i * BPS]; - dc >>= 3; - for (i = 0; i < 4; ++i) memset(dst + i * BPS, dc, 4); -} - -static void RD4(uint8_t* dst) { // Down-right - const int I = dst[-1 + 0 * BPS]; - const int J = dst[-1 + 1 * BPS]; - const int K = dst[-1 + 2 * BPS]; - const int L = dst[-1 + 3 * BPS]; - const int X = dst[-1 - BPS]; - const int A = dst[0 - BPS]; - const int B = dst[1 - BPS]; - const int C = dst[2 - BPS]; - const int D = dst[3 - BPS]; - DST(0, 3) = AVG3(J, K, L); - DST(1, 3) = DST(0, 2) = AVG3(I, J, K); - DST(2, 3) = DST(1, 2) = DST(0, 1) = AVG3(X, I, J); - DST(3, 3) = DST(2, 2) = DST(1, 1) = DST(0, 0) = AVG3(A, X, I); - DST(3, 2) = DST(2, 1) = DST(1, 0) = AVG3(B, A, X); - DST(3, 1) = DST(2, 0) = AVG3(C, B, A); - DST(3, 0) = AVG3(D, C, B); -} - -static void LD4(uint8_t* dst) { // Down-Left - const int A = dst[0 - BPS]; - const int B = dst[1 - BPS]; - const int C = dst[2 - BPS]; - const int D = dst[3 - BPS]; - const int E = dst[4 - BPS]; - const int F = dst[5 - BPS]; - const int G = dst[6 - BPS]; - const int H = dst[7 - BPS]; - DST(0, 0) = AVG3(A, B, C); - DST(1, 0) = DST(0, 1) = AVG3(B, C, D); - DST(2, 0) = DST(1, 1) = DST(0, 2) = AVG3(C, D, E); - DST(3, 0) = DST(2, 1) = DST(1, 2) = DST(0, 3) = AVG3(D, E, F); - DST(3, 1) = DST(2, 2) = DST(1, 3) = AVG3(E, F, G); - DST(3, 2) = DST(2, 3) = AVG3(F, G, H); - DST(3, 3) = AVG3(G, H, H); -} - -static void VR4(uint8_t* dst) { // Vertical-Right - const int I = dst[-1 + 0 * BPS]; - const int J = dst[-1 + 1 * BPS]; - const int K = dst[-1 + 2 * BPS]; - const int X = dst[-1 - BPS]; - const int A = dst[0 - BPS]; - const int B = dst[1 - BPS]; - const int C = dst[2 - BPS]; - const int D = dst[3 - BPS]; - DST(0, 0) = DST(1, 2) = AVG2(X, A); - DST(1, 0) = DST(2, 2) = AVG2(A, B); - DST(2, 0) = DST(3, 2) = AVG2(B, C); - DST(3, 0) = AVG2(C, D); - - DST(0, 3) = AVG3(K, J, I); - DST(0, 2) = AVG3(J, I, X); - DST(0, 1) = DST(1, 3) = AVG3(I, X, A); - DST(1, 1) = DST(2, 3) = AVG3(X, A, B); - DST(2, 1) = DST(3, 3) = AVG3(A, B, C); - DST(3, 1) = AVG3(B, C, D); -} - -static void VL4(uint8_t* dst) { // Vertical-Left - const int A = dst[0 - BPS]; - const int B = dst[1 - BPS]; - const int C = dst[2 - BPS]; - const int D = dst[3 - BPS]; - const int E = dst[4 - BPS]; - const int F = dst[5 - BPS]; - const int G = dst[6 - BPS]; - const int H = dst[7 - BPS]; - DST(0, 0) = AVG2(A, B); - DST(1, 0) = DST(0, 2) = AVG2(B, C); - DST(2, 0) = DST(1, 2) = AVG2(C, D); - DST(3, 0) = DST(2, 2) = AVG2(D, E); - - DST(0, 1) = AVG3(A, B, C); - DST(1, 1) = DST(0, 3) = AVG3(B, C, D); - DST(2, 1) = DST(1, 3) = AVG3(C, D, E); - DST(3, 1) = DST(2, 3) = AVG3(D, E, F); - DST(3, 2) = AVG3(E, F, G); - DST(3, 3) = AVG3(F, G, H); -} - -static void HU4(uint8_t* dst) { // Horizontal-Up - const int I = dst[-1 + 0 * BPS]; - const int J = dst[-1 + 1 * BPS]; - const int K = dst[-1 + 2 * BPS]; - const int L = dst[-1 + 3 * BPS]; - DST(0, 0) = AVG2(I, J); - DST(2, 0) = DST(0, 1) = AVG2(J, K); - DST(2, 1) = DST(0, 2) = AVG2(K, L); - DST(1, 0) = AVG3(I, J, K); - DST(3, 0) = DST(1, 1) = AVG3(J, K, L); - DST(3, 1) = DST(1, 2) = AVG3(K, L, L); - DST(3, 2) = DST(2, 2) = - DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L; -} - -static void HD4(uint8_t* dst) { // Horizontal-Down - const int I = dst[-1 + 0 * BPS]; - const int J = dst[-1 + 1 * BPS]; - const int K = dst[-1 + 2 * BPS]; - const int L = dst[-1 + 3 * BPS]; - const int X = dst[-1 - BPS]; - const int A = dst[0 - BPS]; - const int B = dst[1 - BPS]; - const int C = dst[2 - BPS]; - - DST(0, 0) = DST(2, 1) = AVG2(I, X); - DST(0, 1) = DST(2, 2) = AVG2(J, I); - DST(0, 2) = DST(2, 3) = AVG2(K, J); - DST(0, 3) = AVG2(L, K); - - DST(3, 0) = AVG3(A, B, C); - DST(2, 0) = AVG3(X, A, B); - DST(1, 0) = DST(3, 1) = AVG3(I, X, A); - DST(1, 1) = DST(3, 2) = AVG3(J, I, X); - DST(1, 2) = DST(3, 3) = AVG3(K, J, I); - DST(1, 3) = AVG3(L, K, J); -} - -#undef DST -#undef AVG3 -#undef AVG2 - -VP8PredFunc VP8PredLuma4[NUM_BMODES]; - -//------------------------------------------------------------------------------ -// Chroma - -static void VE8uv(uint8_t* dst) { // vertical - int j; - for (j = 0; j < 8; ++j) { - memcpy(dst + j * BPS, dst - BPS, 8); - } -} - -static void HE8uv(uint8_t* dst) { // horizontal - int j; - for (j = 0; j < 8; ++j) { - memset(dst, dst[-1], 8); - dst += BPS; - } -} - -// helper for chroma-DC predictions -static WEBP_INLINE void Put8x8uv(uint8_t value, uint8_t* dst) { - int j; - for (j = 0; j < 8; ++j) { - memset(dst + j * BPS, value, 8); - } -} - -static void DC8uv(uint8_t* dst) { // DC - int dc0 = 8; - int i; - for (i = 0; i < 8; ++i) { - dc0 += dst[i - BPS] + dst[-1 + i * BPS]; - } - Put8x8uv(dc0 >> 4, dst); -} - -static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples - int dc0 = 4; - int i; - for (i = 0; i < 8; ++i) { - dc0 += dst[i - BPS]; - } - Put8x8uv(dc0 >> 3, dst); -} - -static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples - int dc0 = 4; - int i; - for (i = 0; i < 8; ++i) { - dc0 += dst[-1 + i * BPS]; - } - Put8x8uv(dc0 >> 3, dst); -} - -static void DC8uvNoTopLeft(uint8_t* dst) { // DC with nothing - Put8x8uv(0x80, dst); -} - -VP8PredFunc VP8PredChroma8[NUM_B_DC_MODES]; - -//------------------------------------------------------------------------------ -// Edge filtering functions - -// 4 pixels in, 2 pixels out -static WEBP_INLINE void do_filter2(uint8_t* p, int step) { - const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step]; - const int a = 3 * (q0 - p0) + VP8ksclip1[p1 - q1]; // in [-893,892] - const int a1 = VP8ksclip2[(a + 4) >> 3]; // in [-16,15] - const int a2 = VP8ksclip2[(a + 3) >> 3]; - p[-step] = VP8kclip1[p0 + a2]; - p[ 0] = VP8kclip1[q0 - a1]; -} - -// 4 pixels in, 4 pixels out -static WEBP_INLINE void do_filter4(uint8_t* p, int step) { - const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step]; - const int a = 3 * (q0 - p0); - const int a1 = VP8ksclip2[(a + 4) >> 3]; - const int a2 = VP8ksclip2[(a + 3) >> 3]; - const int a3 = (a1 + 1) >> 1; - p[-2*step] = VP8kclip1[p1 + a3]; - p[- step] = VP8kclip1[p0 + a2]; - p[ 0] = VP8kclip1[q0 - a1]; - p[ step] = VP8kclip1[q1 - a3]; -} - -// 6 pixels in, 6 pixels out -static WEBP_INLINE void do_filter6(uint8_t* p, int step) { - const int p2 = p[-3*step], p1 = p[-2*step], p0 = p[-step]; - const int q0 = p[0], q1 = p[step], q2 = p[2*step]; - const int a = VP8ksclip1[3 * (q0 - p0) + VP8ksclip1[p1 - q1]]; - // a is in [-128,127], a1 in [-27,27], a2 in [-18,18] and a3 in [-9,9] - const int a1 = (27 * a + 63) >> 7; // eq. to ((3 * a + 7) * 9) >> 7 - const int a2 = (18 * a + 63) >> 7; // eq. to ((2 * a + 7) * 9) >> 7 - const int a3 = (9 * a + 63) >> 7; // eq. to ((1 * a + 7) * 9) >> 7 - p[-3*step] = VP8kclip1[p2 + a3]; - p[-2*step] = VP8kclip1[p1 + a2]; - p[- step] = VP8kclip1[p0 + a1]; - p[ 0] = VP8kclip1[q0 - a1]; - p[ step] = VP8kclip1[q1 - a2]; - p[ 2*step] = VP8kclip1[q2 - a3]; -} - -static WEBP_INLINE int hev(const uint8_t* p, int step, int thresh) { - const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step]; - return (VP8kabs0[p1 - p0] > thresh) || (VP8kabs0[q1 - q0] > thresh); -} - -static WEBP_INLINE int needs_filter(const uint8_t* p, int step, int t) { - const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step]; - return ((4 * VP8kabs0[p0 - q0] + VP8kabs0[p1 - q1]) <= t); -} - -static WEBP_INLINE int needs_filter2(const uint8_t* p, - int step, int t, int it) { - const int p3 = p[-4 * step], p2 = p[-3 * step], p1 = p[-2 * step]; - const int p0 = p[-step], q0 = p[0]; - const int q1 = p[step], q2 = p[2 * step], q3 = p[3 * step]; - if ((4 * VP8kabs0[p0 - q0] + VP8kabs0[p1 - q1]) > t) return 0; - return VP8kabs0[p3 - p2] <= it && VP8kabs0[p2 - p1] <= it && - VP8kabs0[p1 - p0] <= it && VP8kabs0[q3 - q2] <= it && - VP8kabs0[q2 - q1] <= it && VP8kabs0[q1 - q0] <= it; -} - -//------------------------------------------------------------------------------ -// Simple In-loop filtering (Paragraph 15.2) - -static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { - int i; - const int thresh2 = 2 * thresh + 1; - for (i = 0; i < 16; ++i) { - if (needs_filter(p + i, stride, thresh2)) { - do_filter2(p + i, stride); - } - } -} - -static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { - int i; - const int thresh2 = 2 * thresh + 1; - for (i = 0; i < 16; ++i) { - if (needs_filter(p + i * stride, 1, thresh2)) { - do_filter2(p + i * stride, 1); - } - } -} - -static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4 * stride; - SimpleVFilter16(p, stride, thresh); - } -} - -static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4; - SimpleHFilter16(p, stride, thresh); - } -} - -//------------------------------------------------------------------------------ -// Complex In-loop filtering (Paragraph 15.3) - -static WEBP_INLINE void FilterLoop26(uint8_t* p, - int hstride, int vstride, int size, - int thresh, int ithresh, int hev_thresh) { - const int thresh2 = 2 * thresh + 1; - while (size-- > 0) { - if (needs_filter2(p, hstride, thresh2, ithresh)) { - if (hev(p, hstride, hev_thresh)) { - do_filter2(p, hstride); - } else { - do_filter6(p, hstride); - } - } - p += vstride; - } -} - -static WEBP_INLINE void FilterLoop24(uint8_t* p, - int hstride, int vstride, int size, - int thresh, int ithresh, int hev_thresh) { - const int thresh2 = 2 * thresh + 1; - while (size-- > 0) { - if (needs_filter2(p, hstride, thresh2, ithresh)) { - if (hev(p, hstride, hev_thresh)) { - do_filter2(p, hstride); - } else { - do_filter4(p, hstride); - } - } - p += vstride; - } -} - -// on macroblock edges -static void VFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh); -} - -static void HFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh); -} - -// on three inner edges -static void VFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4 * stride; - FilterLoop24(p, stride, 1, 16, thresh, ithresh, hev_thresh); - } -} - -static void HFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4; - FilterLoop24(p, 1, stride, 16, thresh, ithresh, hev_thresh); - } -} - -// 8-pixels wide variant, for chroma filtering -static void VFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(u, stride, 1, 8, thresh, ithresh, hev_thresh); - FilterLoop26(v, stride, 1, 8, thresh, ithresh, hev_thresh); -} - -static void HFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(u, 1, stride, 8, thresh, ithresh, hev_thresh); - FilterLoop26(v, 1, stride, 8, thresh, ithresh, hev_thresh); -} - -static void VFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop24(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); - FilterLoop24(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); -} - -static void HFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop24(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh); - FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh); -} - -//------------------------------------------------------------------------------ - -VP8DecIdct2 VP8Transform; -VP8DecIdct VP8TransformAC3; -VP8DecIdct VP8TransformUV; -VP8DecIdct VP8TransformDC; -VP8DecIdct VP8TransformDCUV; - -VP8LumaFilterFunc VP8VFilter16; -VP8LumaFilterFunc VP8HFilter16; -VP8ChromaFilterFunc VP8VFilter8; -VP8ChromaFilterFunc VP8HFilter8; -VP8LumaFilterFunc VP8VFilter16i; -VP8LumaFilterFunc VP8HFilter16i; -VP8ChromaFilterFunc VP8VFilter8i; -VP8ChromaFilterFunc VP8HFilter8i; -VP8SimpleFilterFunc VP8SimpleVFilter16; -VP8SimpleFilterFunc VP8SimpleHFilter16; -VP8SimpleFilterFunc VP8SimpleVFilter16i; -VP8SimpleFilterFunc VP8SimpleHFilter16i; - -extern void VP8DspInitSSE2(void); -extern void VP8DspInitSSE41(void); -extern void VP8DspInitNEON(void); -extern void VP8DspInitMIPS32(void); -extern void VP8DspInitMIPSdspR2(void); - -static volatile VP8CPUInfo dec_last_cpuinfo_used = - (VP8CPUInfo)&dec_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void VP8DspInit(void) { - if (dec_last_cpuinfo_used == VP8GetCPUInfo) return; - - VP8InitClipTables(); - - VP8TransformWHT = TransformWHT; - VP8Transform = TransformTwo; - VP8TransformUV = TransformUV; - VP8TransformDC = TransformDC; - VP8TransformDCUV = TransformDCUV; - VP8TransformAC3 = TransformAC3; - - VP8VFilter16 = VFilter16; - VP8HFilter16 = HFilter16; - VP8VFilter8 = VFilter8; - VP8HFilter8 = HFilter8; - VP8VFilter16i = VFilter16i; - VP8HFilter16i = HFilter16i; - VP8VFilter8i = VFilter8i; - VP8HFilter8i = HFilter8i; - VP8SimpleVFilter16 = SimpleVFilter16; - VP8SimpleHFilter16 = SimpleHFilter16; - VP8SimpleVFilter16i = SimpleVFilter16i; - VP8SimpleHFilter16i = SimpleHFilter16i; - - VP8PredLuma4[0] = DC4; - VP8PredLuma4[1] = TM4; - VP8PredLuma4[2] = VE4; - VP8PredLuma4[3] = HE4; - VP8PredLuma4[4] = RD4; - VP8PredLuma4[5] = VR4; - VP8PredLuma4[6] = LD4; - VP8PredLuma4[7] = VL4; - VP8PredLuma4[8] = HD4; - VP8PredLuma4[9] = HU4; - - VP8PredLuma16[0] = DC16; - VP8PredLuma16[1] = TM16; - VP8PredLuma16[2] = VE16; - VP8PredLuma16[3] = HE16; - VP8PredLuma16[4] = DC16NoTop; - VP8PredLuma16[5] = DC16NoLeft; - VP8PredLuma16[6] = DC16NoTopLeft; - - VP8PredChroma8[0] = DC8uv; - VP8PredChroma8[1] = TM8uv; - VP8PredChroma8[2] = VE8uv; - VP8PredChroma8[3] = HE8uv; - VP8PredChroma8[4] = DC8uvNoTop; - VP8PredChroma8[5] = DC8uvNoLeft; - VP8PredChroma8[6] = DC8uvNoTopLeft; - - // If defined, use CPUInfo() to overwrite some pointers with faster versions. - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - VP8DspInitSSE2(); -#if defined(WEBP_USE_SSE41) - if (VP8GetCPUInfo(kSSE4_1)) { - VP8DspInitSSE41(); - } -#endif - } -#endif -#if defined(WEBP_USE_NEON) - if (VP8GetCPUInfo(kNEON)) { - VP8DspInitNEON(); - } -#endif -#if defined(WEBP_USE_MIPS32) - if (VP8GetCPUInfo(kMIPS32)) { - VP8DspInitMIPS32(); - } -#endif -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - VP8DspInitMIPSdspR2(); - } -#endif - } - dec_last_cpuinfo_used = VP8GetCPUInfo; -} diff --git a/Example/Pods/libwebp/src/dsp/dec_clip_tables.c b/Example/Pods/libwebp/src/dsp/dec_clip_tables.c deleted file mode 100644 index 3b6dde86..00000000 --- a/Example/Pods/libwebp/src/dsp/dec_clip_tables.c +++ /dev/null @@ -1,366 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Clipping tables for filtering -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#define USE_STATIC_TABLES // undefine to have run-time table initialization - -#ifdef USE_STATIC_TABLES - -static const uint8_t abs0[255 + 255 + 1] = { - 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, - 0xf3, 0xf2, 0xf1, 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8, - 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde, 0xdd, 0xdc, - 0xdb, 0xda, 0xd9, 0xd8, 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0, - 0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5, 0xc4, - 0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, - 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf, 0xae, 0xad, 0xac, - 0xab, 0xaa, 0xa9, 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0, - 0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, - 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, - 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7e, 0x7d, 0x7c, - 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, - 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, - 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, - 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, 0x4c, - 0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, - 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, - 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, - 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, - 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, - 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, - 0x03, 0x02, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, - 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, - 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, - 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, - 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, - 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, - 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, - 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, - 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, - 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, - 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, - 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, - 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, - 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, - 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, - 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff -}; - -static const int8_t sclip1[1020 + 1020 + 1] = { - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, - 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, - 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, - 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, - 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, - 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, - 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, - 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, - 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, - 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, - 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f -}; - -static const int8_t sclip2[112 + 112 + 1] = { - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, - 0xfc, 0xfd, 0xfe, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f -}; - -static const uint8_t clip1[255 + 511 + 1] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, - 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, - 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, - 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, - 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, - 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, - 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, - 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, - 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, - 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, - 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, - 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, - 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, - 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, - 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, - 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff -}; - -#else - -// uninitialized tables -static uint8_t abs0[255 + 255 + 1]; -static int8_t sclip1[1020 + 1020 + 1]; -static int8_t sclip2[112 + 112 + 1]; -static uint8_t clip1[255 + 511 + 1]; - -// We declare this variable 'volatile' to prevent instruction reordering -// and make sure it's set to true _last_ (so as to be thread-safe) -static volatile int tables_ok = 0; - -#endif - -const int8_t* const VP8ksclip1 = &sclip1[1020]; -const int8_t* const VP8ksclip2 = &sclip2[112]; -const uint8_t* const VP8kclip1 = &clip1[255]; -const uint8_t* const VP8kabs0 = &abs0[255]; - -WEBP_TSAN_IGNORE_FUNCTION void VP8InitClipTables(void) { -#if !defined(USE_STATIC_TABLES) - int i; - if (!tables_ok) { - for (i = -255; i <= 255; ++i) { - abs0[255 + i] = (i < 0) ? -i : i; - } - for (i = -1020; i <= 1020; ++i) { - sclip1[1020 + i] = (i < -128) ? -128 : (i > 127) ? 127 : i; - } - for (i = -112; i <= 112; ++i) { - sclip2[112 + i] = (i < -16) ? -16 : (i > 15) ? 15 : i; - } - for (i = -255; i <= 255 + 255; ++i) { - clip1[255 + i] = (i < 0) ? 0 : (i > 255) ? 255 : i; - } - tables_ok = 1; - } -#endif // USE_STATIC_TABLES -} diff --git a/Example/Pods/libwebp/src/dsp/dec_mips32.c b/Example/Pods/libwebp/src/dsp/dec_mips32.c deleted file mode 100644 index 4e9ef426..00000000 --- a/Example/Pods/libwebp/src/dsp/dec_mips32.c +++ /dev/null @@ -1,587 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// MIPS version of dsp functions -// -// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) -// Jovan Zelincevic (jovan.zelincevic@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS32) - -#include "./mips_macro.h" - -static const int kC1 = 20091 + (1 << 16); -static const int kC2 = 35468; - -static WEBP_INLINE int abs_mips32(int x) { - const int sign = x >> 31; - return (x ^ sign) - sign; -} - -// 4 pixels in, 2 pixels out -static WEBP_INLINE void do_filter2(uint8_t* p, int step) { - const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step]; - const int a = 3 * (q0 - p0) + VP8ksclip1[p1 - q1]; - const int a1 = VP8ksclip2[(a + 4) >> 3]; - const int a2 = VP8ksclip2[(a + 3) >> 3]; - p[-step] = VP8kclip1[p0 + a2]; - p[ 0] = VP8kclip1[q0 - a1]; -} - -// 4 pixels in, 4 pixels out -static WEBP_INLINE void do_filter4(uint8_t* p, int step) { - const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step]; - const int a = 3 * (q0 - p0); - const int a1 = VP8ksclip2[(a + 4) >> 3]; - const int a2 = VP8ksclip2[(a + 3) >> 3]; - const int a3 = (a1 + 1) >> 1; - p[-2 * step] = VP8kclip1[p1 + a3]; - p[- step] = VP8kclip1[p0 + a2]; - p[ 0] = VP8kclip1[q0 - a1]; - p[ step] = VP8kclip1[q1 - a3]; -} - -// 6 pixels in, 6 pixels out -static WEBP_INLINE void do_filter6(uint8_t* p, int step) { - const int p2 = p[-3 * step], p1 = p[-2 * step], p0 = p[-step]; - const int q0 = p[0], q1 = p[step], q2 = p[2 * step]; - const int a = VP8ksclip1[3 * (q0 - p0) + VP8ksclip1[p1 - q1]]; - // a is in [-128,127], a1 in [-27,27], a2 in [-18,18] and a3 in [-9,9] - const int a1 = (27 * a + 63) >> 7; // eq. to ((3 * a + 7) * 9) >> 7 - const int a2 = (18 * a + 63) >> 7; // eq. to ((2 * a + 7) * 9) >> 7 - const int a3 = (9 * a + 63) >> 7; // eq. to ((1 * a + 7) * 9) >> 7 - p[-3 * step] = VP8kclip1[p2 + a3]; - p[-2 * step] = VP8kclip1[p1 + a2]; - p[- step] = VP8kclip1[p0 + a1]; - p[ 0] = VP8kclip1[q0 - a1]; - p[ step] = VP8kclip1[q1 - a2]; - p[ 2 * step] = VP8kclip1[q2 - a3]; -} - -static WEBP_INLINE int hev(const uint8_t* p, int step, int thresh) { - const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step]; - return (abs_mips32(p1 - p0) > thresh) || (abs_mips32(q1 - q0) > thresh); -} - -static WEBP_INLINE int needs_filter(const uint8_t* p, int step, int t) { - const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step]; - return ((4 * abs_mips32(p0 - q0) + abs_mips32(p1 - q1)) <= t); -} - -static WEBP_INLINE int needs_filter2(const uint8_t* p, - int step, int t, int it) { - const int p3 = p[-4 * step], p2 = p[-3 * step]; - const int p1 = p[-2 * step], p0 = p[-step]; - const int q0 = p[0], q1 = p[step], q2 = p[2 * step], q3 = p[3 * step]; - if ((4 * abs_mips32(p0 - q0) + abs_mips32(p1 - q1)) > t) { - return 0; - } - return abs_mips32(p3 - p2) <= it && abs_mips32(p2 - p1) <= it && - abs_mips32(p1 - p0) <= it && abs_mips32(q3 - q2) <= it && - abs_mips32(q2 - q1) <= it && abs_mips32(q1 - q0) <= it; -} - -static WEBP_INLINE void FilterLoop26(uint8_t* p, - int hstride, int vstride, int size, - int thresh, int ithresh, int hev_thresh) { - const int thresh2 = 2 * thresh + 1; - while (size-- > 0) { - if (needs_filter2(p, hstride, thresh2, ithresh)) { - if (hev(p, hstride, hev_thresh)) { - do_filter2(p, hstride); - } else { - do_filter6(p, hstride); - } - } - p += vstride; - } -} - -static WEBP_INLINE void FilterLoop24(uint8_t* p, - int hstride, int vstride, int size, - int thresh, int ithresh, int hev_thresh) { - const int thresh2 = 2 * thresh + 1; - while (size-- > 0) { - if (needs_filter2(p, hstride, thresh2, ithresh)) { - if (hev(p, hstride, hev_thresh)) { - do_filter2(p, hstride); - } else { - do_filter4(p, hstride); - } - } - p += vstride; - } -} - -// on macroblock edges -static void VFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh); -} - -static void HFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh); -} - -// 8-pixels wide variant, for chroma filtering -static void VFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(u, stride, 1, 8, thresh, ithresh, hev_thresh); - FilterLoop26(v, stride, 1, 8, thresh, ithresh, hev_thresh); -} - -static void HFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(u, 1, stride, 8, thresh, ithresh, hev_thresh); - FilterLoop26(v, 1, stride, 8, thresh, ithresh, hev_thresh); -} - -static void VFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop24(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); - FilterLoop24(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); -} - -static void HFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop24(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh); - FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh); -} - -// on three inner edges -static void VFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4 * stride; - FilterLoop24(p, stride, 1, 16, thresh, ithresh, hev_thresh); - } -} - -static void HFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4; - FilterLoop24(p, 1, stride, 16, thresh, ithresh, hev_thresh); - } -} - -//------------------------------------------------------------------------------ -// Simple In-loop filtering (Paragraph 15.2) - -static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { - int i; - const int thresh2 = 2 * thresh + 1; - for (i = 0; i < 16; ++i) { - if (needs_filter(p + i, stride, thresh2)) { - do_filter2(p + i, stride); - } - } -} - -static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { - int i; - const int thresh2 = 2 * thresh + 1; - for (i = 0; i < 16; ++i) { - if (needs_filter(p + i * stride, 1, thresh2)) { - do_filter2(p + i * stride, 1); - } - } -} - -static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4 * stride; - SimpleVFilter16(p, stride, thresh); - } -} - -static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4; - SimpleHFilter16(p, stride, thresh); - } -} - -static void TransformOne(const int16_t* in, uint8_t* dst) { - int temp0, temp1, temp2, temp3, temp4; - int temp5, temp6, temp7, temp8, temp9; - int temp10, temp11, temp12, temp13, temp14; - int temp15, temp16, temp17, temp18; - int16_t* p_in = (int16_t*)in; - - // loops unrolled and merged to avoid usage of tmp buffer - // and to reduce number of stalls. MUL macro is written - // in assembler and inlined - __asm__ volatile( - "lh %[temp0], 0(%[in]) \n\t" - "lh %[temp8], 16(%[in]) \n\t" - "lh %[temp4], 8(%[in]) \n\t" - "lh %[temp12], 24(%[in]) \n\t" - "addu %[temp16], %[temp0], %[temp8] \n\t" - "subu %[temp0], %[temp0], %[temp8] \n\t" - "mul %[temp8], %[temp4], %[kC2] \n\t" - "mul %[temp17], %[temp12], %[kC1] \n\t" - "mul %[temp4], %[temp4], %[kC1] \n\t" - "mul %[temp12], %[temp12], %[kC2] \n\t" - "lh %[temp1], 2(%[in]) \n\t" - "lh %[temp5], 10(%[in]) \n\t" - "lh %[temp9], 18(%[in]) \n\t" - "lh %[temp13], 26(%[in]) \n\t" - "sra %[temp8], %[temp8], 16 \n\t" - "sra %[temp17], %[temp17], 16 \n\t" - "sra %[temp4], %[temp4], 16 \n\t" - "sra %[temp12], %[temp12], 16 \n\t" - "lh %[temp2], 4(%[in]) \n\t" - "lh %[temp6], 12(%[in]) \n\t" - "lh %[temp10], 20(%[in]) \n\t" - "lh %[temp14], 28(%[in]) \n\t" - "subu %[temp17], %[temp8], %[temp17] \n\t" - "addu %[temp4], %[temp4], %[temp12] \n\t" - "addu %[temp8], %[temp16], %[temp4] \n\t" - "subu %[temp4], %[temp16], %[temp4] \n\t" - "addu %[temp16], %[temp1], %[temp9] \n\t" - "subu %[temp1], %[temp1], %[temp9] \n\t" - "lh %[temp3], 6(%[in]) \n\t" - "lh %[temp7], 14(%[in]) \n\t" - "lh %[temp11], 22(%[in]) \n\t" - "lh %[temp15], 30(%[in]) \n\t" - "addu %[temp12], %[temp0], %[temp17] \n\t" - "subu %[temp0], %[temp0], %[temp17] \n\t" - "mul %[temp9], %[temp5], %[kC2] \n\t" - "mul %[temp17], %[temp13], %[kC1] \n\t" - "mul %[temp5], %[temp5], %[kC1] \n\t" - "mul %[temp13], %[temp13], %[kC2] \n\t" - "sra %[temp9], %[temp9], 16 \n\t" - "sra %[temp17], %[temp17], 16 \n\t" - "subu %[temp17], %[temp9], %[temp17] \n\t" - "sra %[temp5], %[temp5], 16 \n\t" - "sra %[temp13], %[temp13], 16 \n\t" - "addu %[temp5], %[temp5], %[temp13] \n\t" - "addu %[temp13], %[temp1], %[temp17] \n\t" - "subu %[temp1], %[temp1], %[temp17] \n\t" - "mul %[temp17], %[temp14], %[kC1] \n\t" - "mul %[temp14], %[temp14], %[kC2] \n\t" - "addu %[temp9], %[temp16], %[temp5] \n\t" - "subu %[temp5], %[temp16], %[temp5] \n\t" - "addu %[temp16], %[temp2], %[temp10] \n\t" - "subu %[temp2], %[temp2], %[temp10] \n\t" - "mul %[temp10], %[temp6], %[kC2] \n\t" - "mul %[temp6], %[temp6], %[kC1] \n\t" - "sra %[temp17], %[temp17], 16 \n\t" - "sra %[temp14], %[temp14], 16 \n\t" - "sra %[temp10], %[temp10], 16 \n\t" - "sra %[temp6], %[temp6], 16 \n\t" - "subu %[temp17], %[temp10], %[temp17] \n\t" - "addu %[temp6], %[temp6], %[temp14] \n\t" - "addu %[temp10], %[temp16], %[temp6] \n\t" - "subu %[temp6], %[temp16], %[temp6] \n\t" - "addu %[temp14], %[temp2], %[temp17] \n\t" - "subu %[temp2], %[temp2], %[temp17] \n\t" - "mul %[temp17], %[temp15], %[kC1] \n\t" - "mul %[temp15], %[temp15], %[kC2] \n\t" - "addu %[temp16], %[temp3], %[temp11] \n\t" - "subu %[temp3], %[temp3], %[temp11] \n\t" - "mul %[temp11], %[temp7], %[kC2] \n\t" - "mul %[temp7], %[temp7], %[kC1] \n\t" - "addiu %[temp8], %[temp8], 4 \n\t" - "addiu %[temp12], %[temp12], 4 \n\t" - "addiu %[temp0], %[temp0], 4 \n\t" - "addiu %[temp4], %[temp4], 4 \n\t" - "sra %[temp17], %[temp17], 16 \n\t" - "sra %[temp15], %[temp15], 16 \n\t" - "sra %[temp11], %[temp11], 16 \n\t" - "sra %[temp7], %[temp7], 16 \n\t" - "subu %[temp17], %[temp11], %[temp17] \n\t" - "addu %[temp7], %[temp7], %[temp15] \n\t" - "addu %[temp15], %[temp3], %[temp17] \n\t" - "subu %[temp3], %[temp3], %[temp17] \n\t" - "addu %[temp11], %[temp16], %[temp7] \n\t" - "subu %[temp7], %[temp16], %[temp7] \n\t" - "addu %[temp16], %[temp8], %[temp10] \n\t" - "subu %[temp8], %[temp8], %[temp10] \n\t" - "mul %[temp10], %[temp9], %[kC2] \n\t" - "mul %[temp17], %[temp11], %[kC1] \n\t" - "mul %[temp9], %[temp9], %[kC1] \n\t" - "mul %[temp11], %[temp11], %[kC2] \n\t" - "sra %[temp10], %[temp10], 16 \n\t" - "sra %[temp17], %[temp17], 16 \n\t" - "sra %[temp9], %[temp9], 16 \n\t" - "sra %[temp11], %[temp11], 16 \n\t" - "subu %[temp17], %[temp10], %[temp17] \n\t" - "addu %[temp11], %[temp9], %[temp11] \n\t" - "addu %[temp10], %[temp12], %[temp14] \n\t" - "subu %[temp12], %[temp12], %[temp14] \n\t" - "mul %[temp14], %[temp13], %[kC2] \n\t" - "mul %[temp9], %[temp15], %[kC1] \n\t" - "mul %[temp13], %[temp13], %[kC1] \n\t" - "mul %[temp15], %[temp15], %[kC2] \n\t" - "sra %[temp14], %[temp14], 16 \n\t" - "sra %[temp9], %[temp9], 16 \n\t" - "sra %[temp13], %[temp13], 16 \n\t" - "sra %[temp15], %[temp15], 16 \n\t" - "subu %[temp9], %[temp14], %[temp9] \n\t" - "addu %[temp15], %[temp13], %[temp15] \n\t" - "addu %[temp14], %[temp0], %[temp2] \n\t" - "subu %[temp0], %[temp0], %[temp2] \n\t" - "mul %[temp2], %[temp1], %[kC2] \n\t" - "mul %[temp13], %[temp3], %[kC1] \n\t" - "mul %[temp1], %[temp1], %[kC1] \n\t" - "mul %[temp3], %[temp3], %[kC2] \n\t" - "sra %[temp2], %[temp2], 16 \n\t" - "sra %[temp13], %[temp13], 16 \n\t" - "sra %[temp1], %[temp1], 16 \n\t" - "sra %[temp3], %[temp3], 16 \n\t" - "subu %[temp13], %[temp2], %[temp13] \n\t" - "addu %[temp3], %[temp1], %[temp3] \n\t" - "addu %[temp2], %[temp4], %[temp6] \n\t" - "subu %[temp4], %[temp4], %[temp6] \n\t" - "mul %[temp6], %[temp5], %[kC2] \n\t" - "mul %[temp1], %[temp7], %[kC1] \n\t" - "mul %[temp5], %[temp5], %[kC1] \n\t" - "mul %[temp7], %[temp7], %[kC2] \n\t" - "sra %[temp6], %[temp6], 16 \n\t" - "sra %[temp1], %[temp1], 16 \n\t" - "sra %[temp5], %[temp5], 16 \n\t" - "sra %[temp7], %[temp7], 16 \n\t" - "subu %[temp1], %[temp6], %[temp1] \n\t" - "addu %[temp7], %[temp5], %[temp7] \n\t" - "addu %[temp5], %[temp16], %[temp11] \n\t" - "subu %[temp16], %[temp16], %[temp11] \n\t" - "addu %[temp11], %[temp8], %[temp17] \n\t" - "subu %[temp8], %[temp8], %[temp17] \n\t" - "sra %[temp5], %[temp5], 3 \n\t" - "sra %[temp16], %[temp16], 3 \n\t" - "sra %[temp11], %[temp11], 3 \n\t" - "sra %[temp8], %[temp8], 3 \n\t" - "addu %[temp17], %[temp10], %[temp15] \n\t" - "subu %[temp10], %[temp10], %[temp15] \n\t" - "addu %[temp15], %[temp12], %[temp9] \n\t" - "subu %[temp12], %[temp12], %[temp9] \n\t" - "sra %[temp17], %[temp17], 3 \n\t" - "sra %[temp10], %[temp10], 3 \n\t" - "sra %[temp15], %[temp15], 3 \n\t" - "sra %[temp12], %[temp12], 3 \n\t" - "addu %[temp9], %[temp14], %[temp3] \n\t" - "subu %[temp14], %[temp14], %[temp3] \n\t" - "addu %[temp3], %[temp0], %[temp13] \n\t" - "subu %[temp0], %[temp0], %[temp13] \n\t" - "sra %[temp9], %[temp9], 3 \n\t" - "sra %[temp14], %[temp14], 3 \n\t" - "sra %[temp3], %[temp3], 3 \n\t" - "sra %[temp0], %[temp0], 3 \n\t" - "addu %[temp13], %[temp2], %[temp7] \n\t" - "subu %[temp2], %[temp2], %[temp7] \n\t" - "addu %[temp7], %[temp4], %[temp1] \n\t" - "subu %[temp4], %[temp4], %[temp1] \n\t" - "sra %[temp13], %[temp13], 3 \n\t" - "sra %[temp2], %[temp2], 3 \n\t" - "sra %[temp7], %[temp7], 3 \n\t" - "sra %[temp4], %[temp4], 3 \n\t" - "addiu %[temp6], $zero, 255 \n\t" - "lbu %[temp1], 0+0*" XSTR(BPS) "(%[dst]) \n\t" - "addu %[temp1], %[temp1], %[temp5] \n\t" - "sra %[temp5], %[temp1], 8 \n\t" - "sra %[temp18], %[temp1], 31 \n\t" - "beqz %[temp5], 1f \n\t" - "xor %[temp1], %[temp1], %[temp1] \n\t" - "movz %[temp1], %[temp6], %[temp18] \n\t" - "1: \n\t" - "lbu %[temp18], 1+0*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp1], 0+0*" XSTR(BPS) "(%[dst]) \n\t" - "addu %[temp18], %[temp18], %[temp11] \n\t" - "sra %[temp11], %[temp18], 8 \n\t" - "sra %[temp1], %[temp18], 31 \n\t" - "beqz %[temp11], 2f \n\t" - "xor %[temp18], %[temp18], %[temp18] \n\t" - "movz %[temp18], %[temp6], %[temp1] \n\t" - "2: \n\t" - "lbu %[temp1], 2+0*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp18], 1+0*" XSTR(BPS) "(%[dst]) \n\t" - "addu %[temp1], %[temp1], %[temp8] \n\t" - "sra %[temp8], %[temp1], 8 \n\t" - "sra %[temp18], %[temp1], 31 \n\t" - "beqz %[temp8], 3f \n\t" - "xor %[temp1], %[temp1], %[temp1] \n\t" - "movz %[temp1], %[temp6], %[temp18] \n\t" - "3: \n\t" - "lbu %[temp18], 3+0*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp1], 2+0*" XSTR(BPS) "(%[dst]) \n\t" - "addu %[temp18], %[temp18], %[temp16] \n\t" - "sra %[temp16], %[temp18], 8 \n\t" - "sra %[temp1], %[temp18], 31 \n\t" - "beqz %[temp16], 4f \n\t" - "xor %[temp18], %[temp18], %[temp18] \n\t" - "movz %[temp18], %[temp6], %[temp1] \n\t" - "4: \n\t" - "sb %[temp18], 3+0*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp5], 0+1*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp8], 1+1*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp11], 2+1*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp16], 3+1*" XSTR(BPS) "(%[dst]) \n\t" - "addu %[temp5], %[temp5], %[temp17] \n\t" - "addu %[temp8], %[temp8], %[temp15] \n\t" - "addu %[temp11], %[temp11], %[temp12] \n\t" - "addu %[temp16], %[temp16], %[temp10] \n\t" - "sra %[temp18], %[temp5], 8 \n\t" - "sra %[temp1], %[temp5], 31 \n\t" - "beqz %[temp18], 5f \n\t" - "xor %[temp5], %[temp5], %[temp5] \n\t" - "movz %[temp5], %[temp6], %[temp1] \n\t" - "5: \n\t" - "sra %[temp18], %[temp8], 8 \n\t" - "sra %[temp1], %[temp8], 31 \n\t" - "beqz %[temp18], 6f \n\t" - "xor %[temp8], %[temp8], %[temp8] \n\t" - "movz %[temp8], %[temp6], %[temp1] \n\t" - "6: \n\t" - "sra %[temp18], %[temp11], 8 \n\t" - "sra %[temp1], %[temp11], 31 \n\t" - "sra %[temp17], %[temp16], 8 \n\t" - "sra %[temp15], %[temp16], 31 \n\t" - "beqz %[temp18], 7f \n\t" - "xor %[temp11], %[temp11], %[temp11] \n\t" - "movz %[temp11], %[temp6], %[temp1] \n\t" - "7: \n\t" - "beqz %[temp17], 8f \n\t" - "xor %[temp16], %[temp16], %[temp16] \n\t" - "movz %[temp16], %[temp6], %[temp15] \n\t" - "8: \n\t" - "sb %[temp5], 0+1*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp8], 1+1*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp11], 2+1*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp16], 3+1*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp5], 0+2*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp8], 1+2*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp11], 2+2*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp16], 3+2*" XSTR(BPS) "(%[dst]) \n\t" - "addu %[temp5], %[temp5], %[temp9] \n\t" - "addu %[temp8], %[temp8], %[temp3] \n\t" - "addu %[temp11], %[temp11], %[temp0] \n\t" - "addu %[temp16], %[temp16], %[temp14] \n\t" - "sra %[temp18], %[temp5], 8 \n\t" - "sra %[temp1], %[temp5], 31 \n\t" - "sra %[temp17], %[temp8], 8 \n\t" - "sra %[temp15], %[temp8], 31 \n\t" - "sra %[temp12], %[temp11], 8 \n\t" - "sra %[temp10], %[temp11], 31 \n\t" - "sra %[temp9], %[temp16], 8 \n\t" - "sra %[temp3], %[temp16], 31 \n\t" - "beqz %[temp18], 9f \n\t" - "xor %[temp5], %[temp5], %[temp5] \n\t" - "movz %[temp5], %[temp6], %[temp1] \n\t" - "9: \n\t" - "beqz %[temp17], 10f \n\t" - "xor %[temp8], %[temp8], %[temp8] \n\t" - "movz %[temp8], %[temp6], %[temp15] \n\t" - "10: \n\t" - "beqz %[temp12], 11f \n\t" - "xor %[temp11], %[temp11], %[temp11] \n\t" - "movz %[temp11], %[temp6], %[temp10] \n\t" - "11: \n\t" - "beqz %[temp9], 12f \n\t" - "xor %[temp16], %[temp16], %[temp16] \n\t" - "movz %[temp16], %[temp6], %[temp3] \n\t" - "12: \n\t" - "sb %[temp5], 0+2*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp8], 1+2*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp11], 2+2*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp16], 3+2*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp5], 0+3*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp8], 1+3*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp11], 2+3*" XSTR(BPS) "(%[dst]) \n\t" - "lbu %[temp16], 3+3*" XSTR(BPS) "(%[dst]) \n\t" - "addu %[temp5], %[temp5], %[temp13] \n\t" - "addu %[temp8], %[temp8], %[temp7] \n\t" - "addu %[temp11], %[temp11], %[temp4] \n\t" - "addu %[temp16], %[temp16], %[temp2] \n\t" - "sra %[temp18], %[temp5], 8 \n\t" - "sra %[temp1], %[temp5], 31 \n\t" - "sra %[temp17], %[temp8], 8 \n\t" - "sra %[temp15], %[temp8], 31 \n\t" - "sra %[temp12], %[temp11], 8 \n\t" - "sra %[temp10], %[temp11], 31 \n\t" - "sra %[temp9], %[temp16], 8 \n\t" - "sra %[temp3], %[temp16], 31 \n\t" - "beqz %[temp18], 13f \n\t" - "xor %[temp5], %[temp5], %[temp5] \n\t" - "movz %[temp5], %[temp6], %[temp1] \n\t" - "13: \n\t" - "beqz %[temp17], 14f \n\t" - "xor %[temp8], %[temp8], %[temp8] \n\t" - "movz %[temp8], %[temp6], %[temp15] \n\t" - "14: \n\t" - "beqz %[temp12], 15f \n\t" - "xor %[temp11], %[temp11], %[temp11] \n\t" - "movz %[temp11], %[temp6], %[temp10] \n\t" - "15: \n\t" - "beqz %[temp9], 16f \n\t" - "xor %[temp16], %[temp16], %[temp16] \n\t" - "movz %[temp16], %[temp6], %[temp3] \n\t" - "16: \n\t" - "sb %[temp5], 0+3*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp8], 1+3*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp11], 2+3*" XSTR(BPS) "(%[dst]) \n\t" - "sb %[temp16], 3+3*" XSTR(BPS) "(%[dst]) \n\t" - - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11), - [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14), - [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17), - [temp18]"=&r"(temp18) - : [in]"r"(p_in), [kC1]"r"(kC1), [kC2]"r"(kC2), [dst]"r"(dst) - : "memory", "hi", "lo" - ); -} - -static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) { - TransformOne(in, dst); - if (do_two) { - TransformOne(in + 16, dst + 4); - } -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8DspInitMIPS32(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitMIPS32(void) { - VP8InitClipTables(); - - VP8Transform = TransformTwo; - - VP8VFilter16 = VFilter16; - VP8HFilter16 = HFilter16; - VP8VFilter8 = VFilter8; - VP8HFilter8 = HFilter8; - VP8VFilter16i = VFilter16i; - VP8HFilter16i = HFilter16i; - VP8VFilter8i = VFilter8i; - VP8HFilter8i = HFilter8i; - - VP8SimpleVFilter16 = SimpleVFilter16; - VP8SimpleHFilter16 = SimpleHFilter16; - VP8SimpleVFilter16i = SimpleVFilter16i; - VP8SimpleHFilter16i = SimpleHFilter16i; -} - -#else // !WEBP_USE_MIPS32 - -WEBP_DSP_INIT_STUB(VP8DspInitMIPS32) - -#endif // WEBP_USE_MIPS32 diff --git a/Example/Pods/libwebp/src/dsp/dec_mips_dsp_r2.c b/Example/Pods/libwebp/src/dsp/dec_mips_dsp_r2.c deleted file mode 100644 index db5c6572..00000000 --- a/Example/Pods/libwebp/src/dsp/dec_mips_dsp_r2.c +++ /dev/null @@ -1,994 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// MIPS version of dsp functions -// -// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) -// Jovan Zelincevic (jovan.zelincevic@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS_DSP_R2) - -#include "./mips_macro.h" - -static const int kC1 = 20091 + (1 << 16); -static const int kC2 = 35468; - -#define MUL(a, b) (((a) * (b)) >> 16) - -static void TransformDC(const int16_t* in, uint8_t* dst) { - int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9, temp10; - - __asm__ volatile ( - LOAD_WITH_OFFSET_X4(temp1, temp2, temp3, temp4, dst, - 0, 0, 0, 0, - 0, 1, 2, 3, - BPS) - "lh %[temp5], 0(%[in]) \n\t" - "addiu %[temp5], %[temp5], 4 \n\t" - "ins %[temp5], %[temp5], 16, 16 \n\t" - "shra.ph %[temp5], %[temp5], 3 \n\t" - CONVERT_2_BYTES_TO_HALF(temp6, temp7, temp8, temp9, temp10, temp1, temp2, - temp3, temp1, temp2, temp3, temp4) - STORE_SAT_SUM_X2(temp6, temp7, temp8, temp9, temp10, temp1, temp2, temp3, - temp5, temp5, temp5, temp5, temp5, temp5, temp5, temp5, - dst, 0, 1, 2, 3, BPS) - - OUTPUT_EARLY_CLOBBER_REGS_10() - : [in]"r"(in), [dst]"r"(dst) - : "memory" - ); -} - -static void TransformAC3(const int16_t* in, uint8_t* dst) { - const int a = in[0] + 4; - int c4 = MUL(in[4], kC2); - const int d4 = MUL(in[4], kC1); - const int c1 = MUL(in[1], kC2); - const int d1 = MUL(in[1], kC1); - int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; - int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18; - - __asm__ volatile ( - "ins %[c4], %[d4], 16, 16 \n\t" - "replv.ph %[temp1], %[a] \n\t" - "replv.ph %[temp4], %[d1] \n\t" - ADD_SUB_HALVES(temp2, temp3, temp1, c4) - "replv.ph %[temp5], %[c1] \n\t" - SHIFT_R_SUM_X2(temp1, temp6, temp7, temp8, temp2, temp9, temp10, temp4, - temp2, temp2, temp3, temp3, temp4, temp5, temp4, temp5) - LOAD_WITH_OFFSET_X4(temp3, temp5, temp11, temp12, dst, - 0, 0, 0, 0, - 0, 1, 2, 3, - BPS) - CONVERT_2_BYTES_TO_HALF(temp13, temp14, temp3, temp15, temp5, temp16, - temp11, temp17, temp3, temp5, temp11, temp12) - PACK_2_HALVES_TO_WORD(temp12, temp18, temp7, temp6, temp1, temp8, temp2, - temp4, temp7, temp6, temp10, temp9) - STORE_SAT_SUM_X2(temp13, temp14, temp3, temp15, temp5, temp16, temp11, - temp17, temp12, temp18, temp1, temp8, temp2, temp4, - temp7, temp6, dst, 0, 1, 2, 3, BPS) - - OUTPUT_EARLY_CLOBBER_REGS_18(), - [c4]"+&r"(c4) - : [dst]"r"(dst), [a]"r"(a), [d1]"r"(d1), [d4]"r"(d4), [c1]"r"(c1) - : "memory" - ); -} - -static void TransformOne(const int16_t* in, uint8_t* dst) { - int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; - int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18; - - __asm__ volatile ( - "ulw %[temp1], 0(%[in]) \n\t" - "ulw %[temp2], 16(%[in]) \n\t" - LOAD_IN_X2(temp5, temp6, 24, 26) - ADD_SUB_HALVES(temp3, temp4, temp1, temp2) - LOAD_IN_X2(temp1, temp2, 8, 10) - MUL_SHIFT_SUM(temp7, temp8, temp9, temp10, temp11, temp12, temp13, temp14, - temp10, temp8, temp9, temp7, temp1, temp2, temp5, temp6, - temp13, temp11, temp14, temp12) - INSERT_HALF_X2(temp8, temp7, temp10, temp9) - "ulw %[temp17], 4(%[in]) \n\t" - "ulw %[temp18], 20(%[in]) \n\t" - ADD_SUB_HALVES(temp1, temp2, temp3, temp8) - ADD_SUB_HALVES(temp5, temp6, temp4, temp7) - ADD_SUB_HALVES(temp7, temp8, temp17, temp18) - LOAD_IN_X2(temp17, temp18, 12, 14) - LOAD_IN_X2(temp9, temp10, 28, 30) - MUL_SHIFT_SUM(temp11, temp12, temp13, temp14, temp15, temp16, temp4, temp17, - temp12, temp14, temp11, temp13, temp17, temp18, temp9, temp10, - temp15, temp4, temp16, temp17) - INSERT_HALF_X2(temp11, temp12, temp13, temp14) - ADD_SUB_HALVES(temp17, temp8, temp8, temp11) - ADD_SUB_HALVES(temp3, temp4, temp7, temp12) - - // horizontal - SRA_16(temp9, temp10, temp11, temp12, temp1, temp2, temp5, temp6) - INSERT_HALF_X2(temp1, temp6, temp5, temp2) - SRA_16(temp13, temp14, temp15, temp16, temp3, temp4, temp17, temp8) - "repl.ph %[temp2], 0x4 \n\t" - INSERT_HALF_X2(temp3, temp8, temp17, temp4) - "addq.ph %[temp1], %[temp1], %[temp2] \n\t" - "addq.ph %[temp6], %[temp6], %[temp2] \n\t" - ADD_SUB_HALVES(temp2, temp4, temp1, temp3) - ADD_SUB_HALVES(temp5, temp7, temp6, temp8) - MUL_SHIFT_SUM(temp1, temp3, temp6, temp8, temp9, temp13, temp17, temp18, - temp3, temp13, temp1, temp9, temp9, temp13, temp11, temp15, - temp6, temp17, temp8, temp18) - MUL_SHIFT_SUM(temp6, temp8, temp18, temp17, temp11, temp15, temp12, temp16, - temp8, temp15, temp6, temp11, temp12, temp16, temp10, temp14, - temp18, temp12, temp17, temp16) - INSERT_HALF_X2(temp1, temp3, temp9, temp13) - INSERT_HALF_X2(temp6, temp8, temp11, temp15) - SHIFT_R_SUM_X2(temp9, temp10, temp11, temp12, temp13, temp14, temp15, - temp16, temp2, temp4, temp5, temp7, temp3, temp1, temp8, - temp6) - PACK_2_HALVES_TO_WORD(temp1, temp2, temp3, temp4, temp9, temp12, temp13, - temp16, temp11, temp10, temp15, temp14) - LOAD_WITH_OFFSET_X4(temp10, temp11, temp14, temp15, dst, - 0, 0, 0, 0, - 0, 1, 2, 3, - BPS) - CONVERT_2_BYTES_TO_HALF(temp5, temp6, temp7, temp8, temp17, temp18, temp10, - temp11, temp10, temp11, temp14, temp15) - STORE_SAT_SUM_X2(temp5, temp6, temp7, temp8, temp17, temp18, temp10, temp11, - temp9, temp12, temp1, temp2, temp13, temp16, temp3, temp4, - dst, 0, 1, 2, 3, BPS) - - OUTPUT_EARLY_CLOBBER_REGS_18() - : [dst]"r"(dst), [in]"r"(in), [kC1]"r"(kC1), [kC2]"r"(kC2) - : "memory", "hi", "lo" - ); -} - -static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) { - TransformOne(in, dst); - if (do_two) { - TransformOne(in + 16, dst + 4); - } -} - -static WEBP_INLINE void FilterLoop26(uint8_t* p, - int hstride, int vstride, int size, - int thresh, int ithresh, int hev_thresh) { - const int thresh2 = 2 * thresh + 1; - int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; - int temp10, temp11, temp12, temp13, temp14, temp15; - - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "1: \n\t" - "negu %[temp1], %[hstride] \n\t" - "addiu %[size], %[size], -1 \n\t" - "sll %[temp2], %[hstride], 1 \n\t" - "sll %[temp3], %[temp1], 1 \n\t" - "addu %[temp4], %[temp2], %[hstride] \n\t" - "addu %[temp5], %[temp3], %[temp1] \n\t" - "lbu %[temp7], 0(%[p]) \n\t" - "sll %[temp6], %[temp3], 1 \n\t" - "lbux %[temp8], %[temp5](%[p]) \n\t" - "lbux %[temp9], %[temp3](%[p]) \n\t" - "lbux %[temp10], %[temp1](%[p]) \n\t" - "lbux %[temp11], %[temp6](%[p]) \n\t" - "lbux %[temp12], %[hstride](%[p]) \n\t" - "lbux %[temp13], %[temp2](%[p]) \n\t" - "lbux %[temp14], %[temp4](%[p]) \n\t" - "subu %[temp1], %[temp10], %[temp7] \n\t" - "subu %[temp2], %[temp9], %[temp12] \n\t" - "absq_s.w %[temp3], %[temp1] \n\t" - "absq_s.w %[temp4], %[temp2] \n\t" - "negu %[temp1], %[temp1] \n\t" - "sll %[temp3], %[temp3], 2 \n\t" - "addu %[temp15], %[temp3], %[temp4] \n\t" - "subu %[temp3], %[temp15], %[thresh2] \n\t" - "sll %[temp6], %[temp1], 1 \n\t" - "bgtz %[temp3], 3f \n\t" - " subu %[temp4], %[temp11], %[temp8] \n\t" - "absq_s.w %[temp4], %[temp4] \n\t" - "shll_s.w %[temp2], %[temp2], 24 \n\t" - "subu %[temp4], %[temp4], %[ithresh] \n\t" - "bgtz %[temp4], 3f \n\t" - " subu %[temp3], %[temp8], %[temp9] \n\t" - "absq_s.w %[temp3], %[temp3] \n\t" - "subu %[temp3], %[temp3], %[ithresh] \n\t" - "bgtz %[temp3], 3f \n\t" - " subu %[temp5], %[temp9], %[temp10] \n\t" - "absq_s.w %[temp3], %[temp5] \n\t" - "absq_s.w %[temp5], %[temp5] \n\t" - "subu %[temp3], %[temp3], %[ithresh] \n\t" - "bgtz %[temp3], 3f \n\t" - " subu %[temp3], %[temp14], %[temp13] \n\t" - "absq_s.w %[temp3], %[temp3] \n\t" - "slt %[temp5], %[hev_thresh], %[temp5] \n\t" - "subu %[temp3], %[temp3], %[ithresh] \n\t" - "bgtz %[temp3], 3f \n\t" - " subu %[temp3], %[temp13], %[temp12] \n\t" - "absq_s.w %[temp3], %[temp3] \n\t" - "sra %[temp4], %[temp2], 24 \n\t" - "subu %[temp3], %[temp3], %[ithresh] \n\t" - "bgtz %[temp3], 3f \n\t" - " subu %[temp15], %[temp12], %[temp7] \n\t" - "absq_s.w %[temp3], %[temp15] \n\t" - "absq_s.w %[temp15], %[temp15] \n\t" - "subu %[temp3], %[temp3], %[ithresh] \n\t" - "bgtz %[temp3], 3f \n\t" - " slt %[temp15], %[hev_thresh], %[temp15] \n\t" - "addu %[temp3], %[temp6], %[temp1] \n\t" - "or %[temp2], %[temp5], %[temp15] \n\t" - "addu %[temp5], %[temp4], %[temp3] \n\t" - "beqz %[temp2], 4f \n\t" - " shra_r.w %[temp1], %[temp5], 3 \n\t" - "addiu %[temp2], %[temp5], 3 \n\t" - "sra %[temp2], %[temp2], 3 \n\t" - "shll_s.w %[temp1], %[temp1], 27 \n\t" - "shll_s.w %[temp2], %[temp2], 27 \n\t" - "subu %[temp3], %[p], %[hstride] \n\t" - "sra %[temp1], %[temp1], 27 \n\t" - "sra %[temp2], %[temp2], 27 \n\t" - "subu %[temp1], %[temp7], %[temp1] \n\t" - "addu %[temp2], %[temp10], %[temp2] \n\t" - "lbux %[temp2], %[temp2](%[VP8kclip1]) \n\t" - "lbux %[temp1], %[temp1](%[VP8kclip1]) \n\t" - "sb %[temp2], 0(%[temp3]) \n\t" - "j 3f \n\t" - " sb %[temp1], 0(%[p]) \n\t" - "4: \n\t" - "shll_s.w %[temp5], %[temp5], 24 \n\t" - "subu %[temp14], %[p], %[hstride] \n\t" - "subu %[temp11], %[temp14], %[hstride] \n\t" - "sra %[temp6], %[temp5], 24 \n\t" - "sll %[temp1], %[temp6], 3 \n\t" - "subu %[temp15], %[temp11], %[hstride] \n\t" - "addu %[temp2], %[temp6], %[temp1] \n\t" - "sll %[temp3], %[temp2], 1 \n\t" - "addu %[temp4], %[temp3], %[temp2] \n\t" - "addiu %[temp2], %[temp2], 63 \n\t" - "addiu %[temp3], %[temp3], 63 \n\t" - "addiu %[temp4], %[temp4], 63 \n\t" - "sra %[temp2], %[temp2], 7 \n\t" - "sra %[temp3], %[temp3], 7 \n\t" - "sra %[temp4], %[temp4], 7 \n\t" - "addu %[temp1], %[temp8], %[temp2] \n\t" - "addu %[temp5], %[temp9], %[temp3] \n\t" - "addu %[temp6], %[temp10], %[temp4] \n\t" - "subu %[temp8], %[temp7], %[temp4] \n\t" - "subu %[temp7], %[temp12], %[temp3] \n\t" - "addu %[temp10], %[p], %[hstride] \n\t" - "subu %[temp9], %[temp13], %[temp2] \n\t" - "addu %[temp12], %[temp10], %[hstride] \n\t" - "lbux %[temp2], %[temp1](%[VP8kclip1]) \n\t" - "lbux %[temp3], %[temp5](%[VP8kclip1]) \n\t" - "lbux %[temp4], %[temp6](%[VP8kclip1]) \n\t" - "lbux %[temp5], %[temp8](%[VP8kclip1]) \n\t" - "lbux %[temp6], %[temp7](%[VP8kclip1]) \n\t" - "lbux %[temp8], %[temp9](%[VP8kclip1]) \n\t" - "sb %[temp2], 0(%[temp15]) \n\t" - "sb %[temp3], 0(%[temp11]) \n\t" - "sb %[temp4], 0(%[temp14]) \n\t" - "sb %[temp5], 0(%[p]) \n\t" - "sb %[temp6], 0(%[temp10]) \n\t" - "sb %[temp8], 0(%[temp12]) \n\t" - "3: \n\t" - "bgtz %[size], 1b \n\t" - " addu %[p], %[p], %[vstride] \n\t" - ".set pop \n\t" - : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),[temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6), - [temp7]"=&r"(temp7),[temp8]"=&r"(temp8),[temp9]"=&r"(temp9), - [temp10]"=&r"(temp10),[temp11]"=&r"(temp11),[temp12]"=&r"(temp12), - [temp13]"=&r"(temp13),[temp14]"=&r"(temp14),[temp15]"=&r"(temp15), - [size]"+&r"(size), [p]"+&r"(p) - : [hstride]"r"(hstride), [thresh2]"r"(thresh2), - [ithresh]"r"(ithresh),[vstride]"r"(vstride), [hev_thresh]"r"(hev_thresh), - [VP8kclip1]"r"(VP8kclip1) - : "memory" - ); -} - -static WEBP_INLINE void FilterLoop24(uint8_t* p, - int hstride, int vstride, int size, - int thresh, int ithresh, int hev_thresh) { - int p0, q0, p1, q1, p2, q2, p3, q3; - int step1, step2, temp1, temp2, temp3, temp4; - uint8_t* pTemp0; - uint8_t* pTemp1; - const int thresh2 = 2 * thresh + 1; - - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "bltz %[size], 3f \n\t" - " nop \n\t" - "2: \n\t" - "negu %[step1], %[hstride] \n\t" - "lbu %[q0], 0(%[p]) \n\t" - "lbux %[p0], %[step1](%[p]) \n\t" - "subu %[step1], %[step1], %[hstride] \n\t" - "lbux %[q1], %[hstride](%[p]) \n\t" - "subu %[temp1], %[p0], %[q0] \n\t" - "lbux %[p1], %[step1](%[p]) \n\t" - "addu %[step2], %[hstride], %[hstride] \n\t" - "absq_s.w %[temp2], %[temp1] \n\t" - "subu %[temp3], %[p1], %[q1] \n\t" - "absq_s.w %[temp4], %[temp3] \n\t" - "sll %[temp2], %[temp2], 2 \n\t" - "addu %[temp2], %[temp2], %[temp4] \n\t" - "subu %[temp4], %[temp2], %[thresh2] \n\t" - "subu %[step1], %[step1], %[hstride] \n\t" - "bgtz %[temp4], 0f \n\t" - " lbux %[p2], %[step1](%[p]) \n\t" - "subu %[step1], %[step1], %[hstride] \n\t" - "lbux %[q2], %[step2](%[p]) \n\t" - "lbux %[p3], %[step1](%[p]) \n\t" - "subu %[temp4], %[p2], %[p1] \n\t" - "addu %[step2], %[step2], %[hstride] \n\t" - "subu %[temp2], %[p3], %[p2] \n\t" - "absq_s.w %[temp4], %[temp4] \n\t" - "absq_s.w %[temp2], %[temp2] \n\t" - "lbux %[q3], %[step2](%[p]) \n\t" - "subu %[temp4], %[temp4], %[ithresh] \n\t" - "negu %[temp1], %[temp1] \n\t" - "bgtz %[temp4], 0f \n\t" - " subu %[temp2], %[temp2], %[ithresh] \n\t" - "subu %[p3], %[p1], %[p0] \n\t" - "bgtz %[temp2], 0f \n\t" - " absq_s.w %[p3], %[p3] \n\t" - "subu %[temp4], %[q3], %[q2] \n\t" - "subu %[pTemp0], %[p], %[hstride] \n\t" - "absq_s.w %[temp4], %[temp4] \n\t" - "subu %[temp2], %[p3], %[ithresh] \n\t" - "sll %[step1], %[temp1], 1 \n\t" - "bgtz %[temp2], 0f \n\t" - " subu %[temp4], %[temp4], %[ithresh] \n\t" - "subu %[temp2], %[q2], %[q1] \n\t" - "bgtz %[temp4], 0f \n\t" - " absq_s.w %[temp2], %[temp2] \n\t" - "subu %[q3], %[q1], %[q0] \n\t" - "absq_s.w %[q3], %[q3] \n\t" - "subu %[temp2], %[temp2], %[ithresh] \n\t" - "addu %[temp1], %[temp1], %[step1] \n\t" - "bgtz %[temp2], 0f \n\t" - " subu %[temp4], %[q3], %[ithresh] \n\t" - "slt %[p3], %[hev_thresh], %[p3] \n\t" - "bgtz %[temp4], 0f \n\t" - " slt %[q3], %[hev_thresh], %[q3] \n\t" - "or %[q3], %[q3], %[p3] \n\t" - "bgtz %[q3], 1f \n\t" - " shra_r.w %[temp2], %[temp1], 3 \n\t" - "addiu %[temp1], %[temp1], 3 \n\t" - "sra %[temp1], %[temp1], 3 \n\t" - "shll_s.w %[temp2], %[temp2], 27 \n\t" - "shll_s.w %[temp1], %[temp1], 27 \n\t" - "addu %[pTemp1], %[p], %[hstride] \n\t" - "sra %[temp2], %[temp2], 27 \n\t" - "sra %[temp1], %[temp1], 27 \n\t" - "addiu %[step1], %[temp2], 1 \n\t" - "sra %[step1], %[step1], 1 \n\t" - "addu %[p0], %[p0], %[temp1] \n\t" - "addu %[p1], %[p1], %[step1] \n\t" - "subu %[q0], %[q0], %[temp2] \n\t" - "subu %[q1], %[q1], %[step1] \n\t" - "lbux %[temp2], %[p0](%[VP8kclip1]) \n\t" - "lbux %[temp3], %[q0](%[VP8kclip1]) \n\t" - "lbux %[temp4], %[q1](%[VP8kclip1]) \n\t" - "sb %[temp2], 0(%[pTemp0]) \n\t" - "lbux %[temp1], %[p1](%[VP8kclip1]) \n\t" - "subu %[pTemp0], %[pTemp0], %[hstride] \n\t" - "sb %[temp3], 0(%[p]) \n\t" - "sb %[temp4], 0(%[pTemp1]) \n\t" - "j 0f \n\t" - " sb %[temp1], 0(%[pTemp0]) \n\t" - "1: \n\t" - "shll_s.w %[temp3], %[temp3], 24 \n\t" - "sra %[temp3], %[temp3], 24 \n\t" - "addu %[temp1], %[temp1], %[temp3] \n\t" - "shra_r.w %[temp2], %[temp1], 3 \n\t" - "addiu %[temp1], %[temp1], 3 \n\t" - "shll_s.w %[temp2], %[temp2], 27 \n\t" - "sra %[temp1], %[temp1], 3 \n\t" - "shll_s.w %[temp1], %[temp1], 27 \n\t" - "sra %[temp2], %[temp2], 27 \n\t" - "sra %[temp1], %[temp1], 27 \n\t" - "addu %[p0], %[p0], %[temp1] \n\t" - "subu %[q0], %[q0], %[temp2] \n\t" - "lbux %[temp1], %[p0](%[VP8kclip1]) \n\t" - "lbux %[temp2], %[q0](%[VP8kclip1]) \n\t" - "sb %[temp2], 0(%[p]) \n\t" - "sb %[temp1], 0(%[pTemp0]) \n\t" - "0: \n\t" - "subu %[size], %[size], 1 \n\t" - "bgtz %[size], 2b \n\t" - " addu %[p], %[p], %[vstride] \n\t" - "3: \n\t" - ".set pop \n\t" - : [p0]"=&r"(p0), [q0]"=&r"(q0), [p1]"=&r"(p1), [q1]"=&r"(q1), - [p2]"=&r"(p2), [q2]"=&r"(q2), [p3]"=&r"(p3), [q3]"=&r"(q3), - [step2]"=&r"(step2), [step1]"=&r"(step1), [temp1]"=&r"(temp1), - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), - [pTemp0]"=&r"(pTemp0), [pTemp1]"=&r"(pTemp1), [p]"+&r"(p), - [size]"+&r"(size) - : [vstride]"r"(vstride), [ithresh]"r"(ithresh), - [hev_thresh]"r"(hev_thresh), [hstride]"r"(hstride), - [VP8kclip1]"r"(VP8kclip1), [thresh2]"r"(thresh2) - : "memory" - ); -} - -// on macroblock edges -static void VFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh); -} - -static void HFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh); -} - -// 8-pixels wide variant, for chroma filtering -static void VFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(u, stride, 1, 8, thresh, ithresh, hev_thresh); - FilterLoop26(v, stride, 1, 8, thresh, ithresh, hev_thresh); -} - -static void HFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(u, 1, stride, 8, thresh, ithresh, hev_thresh); - FilterLoop26(v, 1, stride, 8, thresh, ithresh, hev_thresh); -} - -// on three inner edges -static void VFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4 * stride; - FilterLoop24(p, stride, 1, 16, thresh, ithresh, hev_thresh); - } -} - -static void HFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4; - FilterLoop24(p, 1, stride, 16, thresh, ithresh, hev_thresh); - } -} - -static void VFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop24(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); - FilterLoop24(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); -} - -static void HFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop24(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh); - FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh); -} - -#undef MUL - -//------------------------------------------------------------------------------ -// Simple In-loop filtering (Paragraph 15.2) - -static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { - int i; - const int thresh2 = 2 * thresh + 1; - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; - uint8_t* p1 = p - stride; - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "li %[i], 16 \n\t" - "0: \n\t" - "negu %[temp4], %[stride] \n\t" - "sll %[temp5], %[temp4], 1 \n\t" - "lbu %[temp2], 0(%[p]) \n\t" - "lbux %[temp3], %[stride](%[p]) \n\t" - "lbux %[temp1], %[temp4](%[p]) \n\t" - "lbux %[temp0], %[temp5](%[p]) \n\t" - "subu %[temp7], %[temp1], %[temp2] \n\t" - "subu %[temp6], %[temp0], %[temp3] \n\t" - "absq_s.w %[temp4], %[temp7] \n\t" - "absq_s.w %[temp5], %[temp6] \n\t" - "sll %[temp4], %[temp4], 2 \n\t" - "subu %[temp5], %[temp5], %[thresh2] \n\t" - "addu %[temp5], %[temp4], %[temp5] \n\t" - "negu %[temp8], %[temp7] \n\t" - "bgtz %[temp5], 1f \n\t" - " addiu %[i], %[i], -1 \n\t" - "sll %[temp4], %[temp8], 1 \n\t" - "shll_s.w %[temp5], %[temp6], 24 \n\t" - "addu %[temp3], %[temp4], %[temp8] \n\t" - "sra %[temp5], %[temp5], 24 \n\t" - "addu %[temp3], %[temp3], %[temp5] \n\t" - "addiu %[temp7], %[temp3], 3 \n\t" - "sra %[temp7], %[temp7], 3 \n\t" - "shra_r.w %[temp8], %[temp3], 3 \n\t" - "shll_s.w %[temp0], %[temp7], 27 \n\t" - "shll_s.w %[temp4], %[temp8], 27 \n\t" - "sra %[temp0], %[temp0], 27 \n\t" - "sra %[temp4], %[temp4], 27 \n\t" - "addu %[temp7], %[temp1], %[temp0] \n\t" - "subu %[temp2], %[temp2], %[temp4] \n\t" - "lbux %[temp3], %[temp7](%[VP8kclip1]) \n\t" - "lbux %[temp4], %[temp2](%[VP8kclip1]) \n\t" - "sb %[temp3], 0(%[p1]) \n\t" - "sb %[temp4], 0(%[p]) \n\t" - "1: \n\t" - "addiu %[p1], %[p1], 1 \n\t" - "bgtz %[i], 0b \n\t" - " addiu %[p], %[p], 1 \n\t" - " .set pop \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [p]"+&r"(p), [i]"=&r"(i), [p1]"+&r"(p1) - : [stride]"r"(stride), [VP8kclip1]"r"(VP8kclip1), [thresh2]"r"(thresh2) - : "memory" - ); -} - -// TEMP0 = SRC[A + A1 * BPS] -// TEMP1 = SRC[B + B1 * BPS] -// TEMP2 = SRC[C + C1 * BPS] -// TEMP3 = SRC[D + D1 * BPS] -#define LOAD_4_BYTES(TEMP0, TEMP1, TEMP2, TEMP3, \ - A, A1, B, B1, C, C1, D, D1, SRC) \ - "lbu %[" #TEMP0 "], " #A "+" #A1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \ - "lbu %[" #TEMP1 "], " #B "+" #B1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \ - "lbu %[" #TEMP2 "], " #C "+" #C1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \ - "lbu %[" #TEMP3 "], " #D "+" #D1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \ - -static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { - int i; - const int thresh2 = 2 * thresh + 1; - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "li %[i], 16 \n\t" - "0: \n\t" - LOAD_4_BYTES(temp0, temp1, temp2, temp3, -2, 0, -1, 0, 0, 0, 1, 0, p) - "subu %[temp7], %[temp1], %[temp2] \n\t" - "subu %[temp6], %[temp0], %[temp3] \n\t" - "absq_s.w %[temp4], %[temp7] \n\t" - "absq_s.w %[temp5], %[temp6] \n\t" - "sll %[temp4], %[temp4], 2 \n\t" - "addu %[temp5], %[temp4], %[temp5] \n\t" - "subu %[temp5], %[temp5], %[thresh2] \n\t" - "negu %[temp8], %[temp7] \n\t" - "bgtz %[temp5], 1f \n\t" - " addiu %[i], %[i], -1 \n\t" - "sll %[temp4], %[temp8], 1 \n\t" - "shll_s.w %[temp5], %[temp6], 24 \n\t" - "addu %[temp3], %[temp4], %[temp8] \n\t" - "sra %[temp5], %[temp5], 24 \n\t" - "addu %[temp3], %[temp3], %[temp5] \n\t" - "addiu %[temp7], %[temp3], 3 \n\t" - "sra %[temp7], %[temp7], 3 \n\t" - "shra_r.w %[temp8], %[temp3], 3 \n\t" - "shll_s.w %[temp0], %[temp7], 27 \n\t" - "shll_s.w %[temp4], %[temp8], 27 \n\t" - "sra %[temp0], %[temp0], 27 \n\t" - "sra %[temp4], %[temp4], 27 \n\t" - "addu %[temp7], %[temp1], %[temp0] \n\t" - "subu %[temp2], %[temp2], %[temp4] \n\t" - "lbux %[temp3], %[temp7](%[VP8kclip1]) \n\t" - "lbux %[temp4], %[temp2](%[VP8kclip1]) \n\t" - "sb %[temp3], -1(%[p]) \n\t" - "sb %[temp4], 0(%[p]) \n\t" - "1: \n\t" - "bgtz %[i], 0b \n\t" - " addu %[p], %[p], %[stride] \n\t" - ".set pop \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [p]"+&r"(p), [i]"=&r"(i) - : [stride]"r"(stride), [VP8kclip1]"r"(VP8kclip1), [thresh2]"r"(thresh2) - : "memory" - ); -} - -static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4 * stride; - SimpleVFilter16(p, stride, thresh); - } -} - -static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4; - SimpleHFilter16(p, stride, thresh); - } -} - -// DST[A * BPS] = TEMP0 -// DST[B + C * BPS] = TEMP1 -#define STORE_8_BYTES(TEMP0, TEMP1, A, B, C, DST) \ - "usw %[" #TEMP0 "], " #A "*" XSTR(BPS) "(%[" #DST "]) \n\t" \ - "usw %[" #TEMP1 "], " #B "+" #C "*" XSTR(BPS) "(%[" #DST "]) \n\t" - -static void VE4(uint8_t* dst) { // vertical - const uint8_t* top = dst - BPS; - int temp0, temp1, temp2, temp3, temp4, temp5, temp6; - __asm__ volatile ( - "ulw %[temp0], -1(%[top]) \n\t" - "ulh %[temp1], 3(%[top]) \n\t" - "preceu.ph.qbr %[temp2], %[temp0] \n\t" - "preceu.ph.qbl %[temp3], %[temp0] \n\t" - "preceu.ph.qbr %[temp4], %[temp1] \n\t" - "packrl.ph %[temp5], %[temp3], %[temp2] \n\t" - "packrl.ph %[temp6], %[temp4], %[temp3] \n\t" - "shll.ph %[temp5], %[temp5], 1 \n\t" - "shll.ph %[temp6], %[temp6], 1 \n\t" - "addq.ph %[temp2], %[temp5], %[temp2] \n\t" - "addq.ph %[temp6], %[temp6], %[temp4] \n\t" - "addq.ph %[temp2], %[temp2], %[temp3] \n\t" - "addq.ph %[temp6], %[temp6], %[temp3] \n\t" - "shra_r.ph %[temp2], %[temp2], 2 \n\t" - "shra_r.ph %[temp6], %[temp6], 2 \n\t" - "precr.qb.ph %[temp4], %[temp6], %[temp2] \n\t" - STORE_8_BYTES(temp4, temp4, 0, 0, 1, dst) - STORE_8_BYTES(temp4, temp4, 2, 0, 3, dst) - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6) - : [top]"r"(top), [dst]"r"(dst) - : "memory" - ); -} - -static void DC4(uint8_t* dst) { // DC - int temp0, temp1, temp2, temp3, temp4; - __asm__ volatile ( - "ulw %[temp0], -1*" XSTR(BPS) "(%[dst]) \n\t" - LOAD_4_BYTES(temp1, temp2, temp3, temp4, -1, 0, -1, 1, -1, 2, -1, 3, dst) - "ins %[temp1], %[temp2], 8, 8 \n\t" - "ins %[temp1], %[temp3], 16, 8 \n\t" - "ins %[temp1], %[temp4], 24, 8 \n\t" - "raddu.w.qb %[temp0], %[temp0] \n\t" - "raddu.w.qb %[temp1], %[temp1] \n\t" - "addu %[temp0], %[temp0], %[temp1] \n\t" - "shra_r.w %[temp0], %[temp0], 3 \n\t" - "replv.qb %[temp0], %[temp0] \n\t" - STORE_8_BYTES(temp0, temp0, 0, 0, 1, dst) - STORE_8_BYTES(temp0, temp0, 2, 0, 3, dst) - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4) - : [dst]"r"(dst) - : "memory" - ); -} - -static void RD4(uint8_t* dst) { // Down-right - int temp0, temp1, temp2, temp3, temp4; - int temp5, temp6, temp7, temp8; - __asm__ volatile ( - LOAD_4_BYTES(temp0, temp1, temp2, temp3, -1, 0, -1, 1, -1, 2, -1, 3, dst) - "ulw %[temp7], -1-" XSTR(BPS) "(%[dst]) \n\t" - "ins %[temp1], %[temp0], 16, 16 \n\t" - "preceu.ph.qbr %[temp5], %[temp7] \n\t" - "ins %[temp2], %[temp1], 16, 16 \n\t" - "preceu.ph.qbl %[temp4], %[temp7] \n\t" - "ins %[temp3], %[temp2], 16, 16 \n\t" - "shll.ph %[temp2], %[temp2], 1 \n\t" - "addq.ph %[temp3], %[temp3], %[temp1] \n\t" - "packrl.ph %[temp6], %[temp5], %[temp1] \n\t" - "addq.ph %[temp3], %[temp3], %[temp2] \n\t" - "addq.ph %[temp1], %[temp1], %[temp5] \n\t" - "shll.ph %[temp6], %[temp6], 1 \n\t" - "addq.ph %[temp1], %[temp1], %[temp6] \n\t" - "packrl.ph %[temp0], %[temp4], %[temp5] \n\t" - "addq.ph %[temp8], %[temp5], %[temp4] \n\t" - "shra_r.ph %[temp3], %[temp3], 2 \n\t" - "shll.ph %[temp0], %[temp0], 1 \n\t" - "shra_r.ph %[temp1], %[temp1], 2 \n\t" - "addq.ph %[temp8], %[temp0], %[temp8] \n\t" - "lbu %[temp5], 3-" XSTR(BPS) "(%[dst]) \n\t" - "precrq.ph.w %[temp7], %[temp7], %[temp7] \n\t" - "shra_r.ph %[temp8], %[temp8], 2 \n\t" - "ins %[temp7], %[temp5], 0, 8 \n\t" - "precr.qb.ph %[temp2], %[temp1], %[temp3] \n\t" - "raddu.w.qb %[temp4], %[temp7] \n\t" - "precr.qb.ph %[temp6], %[temp8], %[temp1] \n\t" - "shra_r.w %[temp4], %[temp4], 2 \n\t" - STORE_8_BYTES(temp2, temp6, 3, 0, 1, dst) - "prepend %[temp2], %[temp8], 8 \n\t" - "prepend %[temp6], %[temp4], 8 \n\t" - STORE_8_BYTES(temp2, temp6, 2, 0, 0, dst) - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8) - : [dst]"r"(dst) - : "memory" - ); -} - -// TEMP0 = SRC[A * BPS] -// TEMP1 = SRC[B + C * BPS] -#define LOAD_8_BYTES(TEMP0, TEMP1, A, B, C, SRC) \ - "ulw %[" #TEMP0 "], " #A "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \ - "ulw %[" #TEMP1 "], " #B "+" #C "*" XSTR(BPS) "(%[" #SRC "]) \n\t" - -static void LD4(uint8_t* dst) { // Down-Left - int temp0, temp1, temp2, temp3, temp4; - int temp5, temp6, temp7, temp8, temp9; - __asm__ volatile ( - LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst) - "preceu.ph.qbl %[temp2], %[temp0] \n\t" - "preceu.ph.qbr %[temp3], %[temp0] \n\t" - "preceu.ph.qbr %[temp4], %[temp1] \n\t" - "preceu.ph.qbl %[temp5], %[temp1] \n\t" - "packrl.ph %[temp6], %[temp2], %[temp3] \n\t" - "packrl.ph %[temp7], %[temp4], %[temp2] \n\t" - "packrl.ph %[temp8], %[temp5], %[temp4] \n\t" - "shll.ph %[temp6], %[temp6], 1 \n\t" - "addq.ph %[temp9], %[temp2], %[temp6] \n\t" - "shll.ph %[temp7], %[temp7], 1 \n\t" - "addq.ph %[temp9], %[temp9], %[temp3] \n\t" - "shll.ph %[temp8], %[temp8], 1 \n\t" - "shra_r.ph %[temp9], %[temp9], 2 \n\t" - "addq.ph %[temp3], %[temp4], %[temp7] \n\t" - "addq.ph %[temp0], %[temp5], %[temp8] \n\t" - "addq.ph %[temp3], %[temp3], %[temp2] \n\t" - "addq.ph %[temp0], %[temp0], %[temp4] \n\t" - "shra_r.ph %[temp3], %[temp3], 2 \n\t" - "shra_r.ph %[temp0], %[temp0], 2 \n\t" - "srl %[temp1], %[temp1], 24 \n\t" - "sll %[temp1], %[temp1], 1 \n\t" - "raddu.w.qb %[temp5], %[temp5] \n\t" - "precr.qb.ph %[temp9], %[temp3], %[temp9] \n\t" - "precr.qb.ph %[temp3], %[temp0], %[temp3] \n\t" - "addu %[temp1], %[temp1], %[temp5] \n\t" - "shra_r.w %[temp1], %[temp1], 2 \n\t" - STORE_8_BYTES(temp9, temp3, 0, 0, 2, dst) - "prepend %[temp9], %[temp0], 8 \n\t" - "prepend %[temp3], %[temp1], 8 \n\t" - STORE_8_BYTES(temp9, temp3, 1, 0, 3, dst) - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [temp9]"=&r"(temp9) - : [dst]"r"(dst) - : "memory" - ); -} - -//------------------------------------------------------------------------------ -// Chroma - -static void DC8uv(uint8_t* dst) { // DC - int temp0, temp1, temp2, temp3, temp4; - int temp5, temp6, temp7, temp8, temp9; - __asm__ volatile ( - LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst) - LOAD_4_BYTES(temp2, temp3, temp4, temp5, -1, 0, -1, 1, -1, 2, -1, 3, dst) - LOAD_4_BYTES(temp6, temp7, temp8, temp9, -1, 4, -1, 5, -1, 6, -1, 7, dst) - "raddu.w.qb %[temp0], %[temp0] \n\t" - "raddu.w.qb %[temp1], %[temp1] \n\t" - "addu %[temp2], %[temp2], %[temp3] \n\t" - "addu %[temp4], %[temp4], %[temp5] \n\t" - "addu %[temp6], %[temp6], %[temp7] \n\t" - "addu %[temp8], %[temp8], %[temp9] \n\t" - "addu %[temp0], %[temp0], %[temp1] \n\t" - "addu %[temp2], %[temp2], %[temp4] \n\t" - "addu %[temp6], %[temp6], %[temp8] \n\t" - "addu %[temp0], %[temp0], %[temp2] \n\t" - "addu %[temp0], %[temp0], %[temp6] \n\t" - "shra_r.w %[temp0], %[temp0], 4 \n\t" - "replv.qb %[temp0], %[temp0] \n\t" - STORE_8_BYTES(temp0, temp0, 0, 4, 0, dst) - STORE_8_BYTES(temp0, temp0, 1, 4, 1, dst) - STORE_8_BYTES(temp0, temp0, 2, 4, 2, dst) - STORE_8_BYTES(temp0, temp0, 3, 4, 3, dst) - STORE_8_BYTES(temp0, temp0, 4, 4, 4, dst) - STORE_8_BYTES(temp0, temp0, 5, 4, 5, dst) - STORE_8_BYTES(temp0, temp0, 6, 4, 6, dst) - STORE_8_BYTES(temp0, temp0, 7, 4, 7, dst) - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [temp9]"=&r"(temp9) - : [dst]"r"(dst) - : "memory" - ); -} - -static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples - int temp0, temp1; - __asm__ volatile ( - LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst) - "raddu.w.qb %[temp0], %[temp0] \n\t" - "raddu.w.qb %[temp1], %[temp1] \n\t" - "addu %[temp0], %[temp0], %[temp1] \n\t" - "shra_r.w %[temp0], %[temp0], 3 \n\t" - "replv.qb %[temp0], %[temp0] \n\t" - STORE_8_BYTES(temp0, temp0, 0, 4, 0, dst) - STORE_8_BYTES(temp0, temp0, 1, 4, 1, dst) - STORE_8_BYTES(temp0, temp0, 2, 4, 2, dst) - STORE_8_BYTES(temp0, temp0, 3, 4, 3, dst) - STORE_8_BYTES(temp0, temp0, 4, 4, 4, dst) - STORE_8_BYTES(temp0, temp0, 5, 4, 5, dst) - STORE_8_BYTES(temp0, temp0, 6, 4, 6, dst) - STORE_8_BYTES(temp0, temp0, 7, 4, 7, dst) - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1) - : [dst]"r"(dst) - : "memory" - ); -} - -static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples - int temp0, temp1, temp2, temp3, temp4; - int temp5, temp6, temp7, temp8; - __asm__ volatile ( - LOAD_4_BYTES(temp2, temp3, temp4, temp5, -1, 0, -1, 1, -1, 2, -1, 3, dst) - LOAD_4_BYTES(temp6, temp7, temp8, temp1, -1, 4, -1, 5, -1, 6, -1, 7, dst) - "addu %[temp2], %[temp2], %[temp3] \n\t" - "addu %[temp4], %[temp4], %[temp5] \n\t" - "addu %[temp6], %[temp6], %[temp7] \n\t" - "addu %[temp8], %[temp8], %[temp1] \n\t" - "addu %[temp2], %[temp2], %[temp4] \n\t" - "addu %[temp6], %[temp6], %[temp8] \n\t" - "addu %[temp0], %[temp6], %[temp2] \n\t" - "shra_r.w %[temp0], %[temp0], 3 \n\t" - "replv.qb %[temp0], %[temp0] \n\t" - STORE_8_BYTES(temp0, temp0, 0, 4, 0, dst) - STORE_8_BYTES(temp0, temp0, 1, 4, 1, dst) - STORE_8_BYTES(temp0, temp0, 2, 4, 2, dst) - STORE_8_BYTES(temp0, temp0, 3, 4, 3, dst) - STORE_8_BYTES(temp0, temp0, 4, 4, 4, dst) - STORE_8_BYTES(temp0, temp0, 5, 4, 5, dst) - STORE_8_BYTES(temp0, temp0, 6, 4, 6, dst) - STORE_8_BYTES(temp0, temp0, 7, 4, 7, dst) - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8) - : [dst]"r"(dst) - : "memory" - ); -} - -#undef LOAD_8_BYTES -#undef STORE_8_BYTES -#undef LOAD_4_BYTES - -#define CLIPPING(SIZE) \ - "preceu.ph.qbl %[temp2], %[temp0] \n\t" \ - "preceu.ph.qbr %[temp0], %[temp0] \n\t" \ -".if " #SIZE " == 8 \n\t" \ - "preceu.ph.qbl %[temp3], %[temp1] \n\t" \ - "preceu.ph.qbr %[temp1], %[temp1] \n\t" \ -".endif \n\t" \ - "addu.ph %[temp2], %[temp2], %[dst_1] \n\t" \ - "addu.ph %[temp0], %[temp0], %[dst_1] \n\t" \ -".if " #SIZE " == 8 \n\t" \ - "addu.ph %[temp3], %[temp3], %[dst_1] \n\t" \ - "addu.ph %[temp1], %[temp1], %[dst_1] \n\t" \ -".endif \n\t" \ - "shll_s.ph %[temp2], %[temp2], 7 \n\t" \ - "shll_s.ph %[temp0], %[temp0], 7 \n\t" \ -".if " #SIZE " == 8 \n\t" \ - "shll_s.ph %[temp3], %[temp3], 7 \n\t" \ - "shll_s.ph %[temp1], %[temp1], 7 \n\t" \ -".endif \n\t" \ - "precrqu_s.qb.ph %[temp0], %[temp2], %[temp0] \n\t" \ -".if " #SIZE " == 8 \n\t" \ - "precrqu_s.qb.ph %[temp1], %[temp3], %[temp1] \n\t" \ -".endif \n\t" - - -#define CLIP_8B_TO_DST(DST, TOP, SIZE) do { \ - int dst_1 = ((int)(DST)[-1] << 16) + (DST)[-1]; \ - int temp0, temp1, temp2, temp3; \ - __asm__ volatile ( \ - ".if " #SIZE " < 8 \n\t" \ - "ulw %[temp0], 0(%[top]) \n\t" \ - "subu.ph %[dst_1], %[dst_1], %[top_1] \n\t" \ - CLIPPING(4) \ - "usw %[temp0], 0(%[dst]) \n\t" \ - ".else \n\t" \ - "ulw %[temp0], 0(%[top]) \n\t" \ - "ulw %[temp1], 4(%[top]) \n\t" \ - "subu.ph %[dst_1], %[dst_1], %[top_1] \n\t" \ - CLIPPING(8) \ - "usw %[temp0], 0(%[dst]) \n\t" \ - "usw %[temp1], 4(%[dst]) \n\t" \ - ".if " #SIZE " == 16 \n\t" \ - "ulw %[temp0], 8(%[top]) \n\t" \ - "ulw %[temp1], 12(%[top]) \n\t" \ - CLIPPING(8) \ - "usw %[temp0], 8(%[dst]) \n\t" \ - "usw %[temp1], 12(%[dst]) \n\t" \ - ".endif \n\t" \ - ".endif \n\t" \ - : [dst_1]"+&r"(dst_1), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), \ - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3) \ - : [top_1]"r"(top_1), [top]"r"((TOP)), [dst]"r"((DST)) \ - : "memory" \ - ); \ -} while (0) - -#define CLIP_TO_DST(DST, SIZE) do { \ - int y; \ - const uint8_t* top = (DST) - BPS; \ - const int top_1 = ((int)top[-1] << 16) + top[-1]; \ - for (y = 0; y < (SIZE); ++y) { \ - CLIP_8B_TO_DST((DST), top, (SIZE)); \ - (DST) += BPS; \ - } \ -} while (0) - -#define TRUE_MOTION(DST, SIZE) \ -static void TrueMotion##SIZE(uint8_t* (DST)) { \ - CLIP_TO_DST((DST), (SIZE)); \ -} - -TRUE_MOTION(dst, 4) -TRUE_MOTION(dst, 8) -TRUE_MOTION(dst, 16) - -#undef TRUE_MOTION -#undef CLIP_TO_DST -#undef CLIP_8B_TO_DST -#undef CLIPPING - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8DspInitMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitMIPSdspR2(void) { - VP8TransformDC = TransformDC; - VP8TransformAC3 = TransformAC3; - VP8Transform = TransformTwo; - - VP8VFilter16 = VFilter16; - VP8HFilter16 = HFilter16; - VP8VFilter8 = VFilter8; - VP8HFilter8 = HFilter8; - VP8VFilter16i = VFilter16i; - VP8HFilter16i = HFilter16i; - VP8VFilter8i = VFilter8i; - VP8HFilter8i = HFilter8i; - VP8SimpleVFilter16 = SimpleVFilter16; - VP8SimpleHFilter16 = SimpleHFilter16; - VP8SimpleVFilter16i = SimpleVFilter16i; - VP8SimpleHFilter16i = SimpleHFilter16i; - - VP8PredLuma4[0] = DC4; - VP8PredLuma4[1] = TrueMotion4; - VP8PredLuma4[2] = VE4; - VP8PredLuma4[4] = RD4; - VP8PredLuma4[6] = LD4; - - VP8PredChroma8[0] = DC8uv; - VP8PredChroma8[1] = TrueMotion8; - VP8PredChroma8[4] = DC8uvNoTop; - VP8PredChroma8[5] = DC8uvNoLeft; - - VP8PredLuma16[1] = TrueMotion16; -} - -#else // !WEBP_USE_MIPS_DSP_R2 - -WEBP_DSP_INIT_STUB(VP8DspInitMIPSdspR2) - -#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/Example/Pods/libwebp/src/dsp/dec_neon.c b/Example/Pods/libwebp/src/dsp/dec_neon.c deleted file mode 100644 index a63f43fe..00000000 --- a/Example/Pods/libwebp/src/dsp/dec_neon.c +++ /dev/null @@ -1,1639 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// ARM NEON version of dsp functions and loop filtering. -// -// Authors: Somnath Banerjee (somnath@google.com) -// Johann Koenig (johannkoenig@google.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_NEON) - -#include "./neon.h" -#include "../dec/vp8i.h" - -//------------------------------------------------------------------------------ -// NxM Loading functions - -// Load/Store vertical edge -#define LOAD8x4(c1, c2, c3, c4, b1, b2, stride) \ - "vld4.8 {" #c1 "[0]," #c2 "[0]," #c3 "[0]," #c4 "[0]}," #b1 "," #stride "\n" \ - "vld4.8 {" #c1 "[1]," #c2 "[1]," #c3 "[1]," #c4 "[1]}," #b2 "," #stride "\n" \ - "vld4.8 {" #c1 "[2]," #c2 "[2]," #c3 "[2]," #c4 "[2]}," #b1 "," #stride "\n" \ - "vld4.8 {" #c1 "[3]," #c2 "[3]," #c3 "[3]," #c4 "[3]}," #b2 "," #stride "\n" \ - "vld4.8 {" #c1 "[4]," #c2 "[4]," #c3 "[4]," #c4 "[4]}," #b1 "," #stride "\n" \ - "vld4.8 {" #c1 "[5]," #c2 "[5]," #c3 "[5]," #c4 "[5]}," #b2 "," #stride "\n" \ - "vld4.8 {" #c1 "[6]," #c2 "[6]," #c3 "[6]," #c4 "[6]}," #b1 "," #stride "\n" \ - "vld4.8 {" #c1 "[7]," #c2 "[7]," #c3 "[7]," #c4 "[7]}," #b2 "," #stride "\n" - -#define STORE8x2(c1, c2, p, stride) \ - "vst2.8 {" #c1 "[0], " #c2 "[0]}," #p "," #stride " \n" \ - "vst2.8 {" #c1 "[1], " #c2 "[1]}," #p "," #stride " \n" \ - "vst2.8 {" #c1 "[2], " #c2 "[2]}," #p "," #stride " \n" \ - "vst2.8 {" #c1 "[3], " #c2 "[3]}," #p "," #stride " \n" \ - "vst2.8 {" #c1 "[4], " #c2 "[4]}," #p "," #stride " \n" \ - "vst2.8 {" #c1 "[5], " #c2 "[5]}," #p "," #stride " \n" \ - "vst2.8 {" #c1 "[6], " #c2 "[6]}," #p "," #stride " \n" \ - "vst2.8 {" #c1 "[7], " #c2 "[7]}," #p "," #stride " \n" - -#if !defined(WORK_AROUND_GCC) - -// This intrinsics version makes gcc-4.6.3 crash during Load4x??() compilation -// (register alloc, probably). The variants somewhat mitigate the problem, but -// not quite. HFilter16i() remains problematic. -static WEBP_INLINE uint8x8x4_t Load4x8(const uint8_t* const src, int stride) { - const uint8x8_t zero = vdup_n_u8(0); - uint8x8x4_t out; - INIT_VECTOR4(out, zero, zero, zero, zero); - out = vld4_lane_u8(src + 0 * stride, out, 0); - out = vld4_lane_u8(src + 1 * stride, out, 1); - out = vld4_lane_u8(src + 2 * stride, out, 2); - out = vld4_lane_u8(src + 3 * stride, out, 3); - out = vld4_lane_u8(src + 4 * stride, out, 4); - out = vld4_lane_u8(src + 5 * stride, out, 5); - out = vld4_lane_u8(src + 6 * stride, out, 6); - out = vld4_lane_u8(src + 7 * stride, out, 7); - return out; -} - -static WEBP_INLINE void Load4x16(const uint8_t* const src, int stride, - uint8x16_t* const p1, uint8x16_t* const p0, - uint8x16_t* const q0, uint8x16_t* const q1) { - // row0 = p1[0..7]|p0[0..7]|q0[0..7]|q1[0..7] - // row8 = p1[8..15]|p0[8..15]|q0[8..15]|q1[8..15] - const uint8x8x4_t row0 = Load4x8(src - 2 + 0 * stride, stride); - const uint8x8x4_t row8 = Load4x8(src - 2 + 8 * stride, stride); - *p1 = vcombine_u8(row0.val[0], row8.val[0]); - *p0 = vcombine_u8(row0.val[1], row8.val[1]); - *q0 = vcombine_u8(row0.val[2], row8.val[2]); - *q1 = vcombine_u8(row0.val[3], row8.val[3]); -} - -#else // WORK_AROUND_GCC - -#define LOADQ_LANE_32b(VALUE, LANE) do { \ - (VALUE) = vld1q_lane_u32((const uint32_t*)src, (VALUE), (LANE)); \ - src += stride; \ -} while (0) - -static WEBP_INLINE void Load4x16(const uint8_t* src, int stride, - uint8x16_t* const p1, uint8x16_t* const p0, - uint8x16_t* const q0, uint8x16_t* const q1) { - const uint32x4_t zero = vdupq_n_u32(0); - uint32x4x4_t in; - INIT_VECTOR4(in, zero, zero, zero, zero); - src -= 2; - LOADQ_LANE_32b(in.val[0], 0); - LOADQ_LANE_32b(in.val[1], 0); - LOADQ_LANE_32b(in.val[2], 0); - LOADQ_LANE_32b(in.val[3], 0); - LOADQ_LANE_32b(in.val[0], 1); - LOADQ_LANE_32b(in.val[1], 1); - LOADQ_LANE_32b(in.val[2], 1); - LOADQ_LANE_32b(in.val[3], 1); - LOADQ_LANE_32b(in.val[0], 2); - LOADQ_LANE_32b(in.val[1], 2); - LOADQ_LANE_32b(in.val[2], 2); - LOADQ_LANE_32b(in.val[3], 2); - LOADQ_LANE_32b(in.val[0], 3); - LOADQ_LANE_32b(in.val[1], 3); - LOADQ_LANE_32b(in.val[2], 3); - LOADQ_LANE_32b(in.val[3], 3); - // Transpose four 4x4 parts: - { - const uint8x16x2_t row01 = vtrnq_u8(vreinterpretq_u8_u32(in.val[0]), - vreinterpretq_u8_u32(in.val[1])); - const uint8x16x2_t row23 = vtrnq_u8(vreinterpretq_u8_u32(in.val[2]), - vreinterpretq_u8_u32(in.val[3])); - const uint16x8x2_t row02 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[0]), - vreinterpretq_u16_u8(row23.val[0])); - const uint16x8x2_t row13 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[1]), - vreinterpretq_u16_u8(row23.val[1])); - *p1 = vreinterpretq_u8_u16(row02.val[0]); - *p0 = vreinterpretq_u8_u16(row13.val[0]); - *q0 = vreinterpretq_u8_u16(row02.val[1]); - *q1 = vreinterpretq_u8_u16(row13.val[1]); - } -} -#undef LOADQ_LANE_32b - -#endif // !WORK_AROUND_GCC - -static WEBP_INLINE void Load8x16(const uint8_t* const src, int stride, - uint8x16_t* const p3, uint8x16_t* const p2, - uint8x16_t* const p1, uint8x16_t* const p0, - uint8x16_t* const q0, uint8x16_t* const q1, - uint8x16_t* const q2, uint8x16_t* const q3) { - Load4x16(src - 2, stride, p3, p2, p1, p0); - Load4x16(src + 2, stride, q0, q1, q2, q3); -} - -static WEBP_INLINE void Load16x4(const uint8_t* const src, int stride, - uint8x16_t* const p1, uint8x16_t* const p0, - uint8x16_t* const q0, uint8x16_t* const q1) { - *p1 = vld1q_u8(src - 2 * stride); - *p0 = vld1q_u8(src - 1 * stride); - *q0 = vld1q_u8(src + 0 * stride); - *q1 = vld1q_u8(src + 1 * stride); -} - -static WEBP_INLINE void Load16x8(const uint8_t* const src, int stride, - uint8x16_t* const p3, uint8x16_t* const p2, - uint8x16_t* const p1, uint8x16_t* const p0, - uint8x16_t* const q0, uint8x16_t* const q1, - uint8x16_t* const q2, uint8x16_t* const q3) { - Load16x4(src - 2 * stride, stride, p3, p2, p1, p0); - Load16x4(src + 2 * stride, stride, q0, q1, q2, q3); -} - -static WEBP_INLINE void Load8x8x2(const uint8_t* const u, - const uint8_t* const v, - int stride, - uint8x16_t* const p3, uint8x16_t* const p2, - uint8x16_t* const p1, uint8x16_t* const p0, - uint8x16_t* const q0, uint8x16_t* const q1, - uint8x16_t* const q2, uint8x16_t* const q3) { - // We pack the 8x8 u-samples in the lower half of the uint8x16_t destination - // and the v-samples on the higher half. - *p3 = vcombine_u8(vld1_u8(u - 4 * stride), vld1_u8(v - 4 * stride)); - *p2 = vcombine_u8(vld1_u8(u - 3 * stride), vld1_u8(v - 3 * stride)); - *p1 = vcombine_u8(vld1_u8(u - 2 * stride), vld1_u8(v - 2 * stride)); - *p0 = vcombine_u8(vld1_u8(u - 1 * stride), vld1_u8(v - 1 * stride)); - *q0 = vcombine_u8(vld1_u8(u + 0 * stride), vld1_u8(v + 0 * stride)); - *q1 = vcombine_u8(vld1_u8(u + 1 * stride), vld1_u8(v + 1 * stride)); - *q2 = vcombine_u8(vld1_u8(u + 2 * stride), vld1_u8(v + 2 * stride)); - *q3 = vcombine_u8(vld1_u8(u + 3 * stride), vld1_u8(v + 3 * stride)); -} - -#if !defined(WORK_AROUND_GCC) - -#define LOAD_UV_8(ROW) \ - vcombine_u8(vld1_u8(u - 4 + (ROW) * stride), vld1_u8(v - 4 + (ROW) * stride)) - -static WEBP_INLINE void Load8x8x2T(const uint8_t* const u, - const uint8_t* const v, - int stride, - uint8x16_t* const p3, uint8x16_t* const p2, - uint8x16_t* const p1, uint8x16_t* const p0, - uint8x16_t* const q0, uint8x16_t* const q1, - uint8x16_t* const q2, uint8x16_t* const q3) { - // We pack the 8x8 u-samples in the lower half of the uint8x16_t destination - // and the v-samples on the higher half. - const uint8x16_t row0 = LOAD_UV_8(0); - const uint8x16_t row1 = LOAD_UV_8(1); - const uint8x16_t row2 = LOAD_UV_8(2); - const uint8x16_t row3 = LOAD_UV_8(3); - const uint8x16_t row4 = LOAD_UV_8(4); - const uint8x16_t row5 = LOAD_UV_8(5); - const uint8x16_t row6 = LOAD_UV_8(6); - const uint8x16_t row7 = LOAD_UV_8(7); - // Perform two side-by-side 8x8 transposes - // u00 u01 u02 u03 u04 u05 u06 u07 | v00 v01 v02 v03 v04 v05 v06 v07 - // u10 u11 u12 u13 u14 u15 u16 u17 | v10 v11 v12 ... - // u20 u21 u22 u23 u24 u25 u26 u27 | v20 v21 ... - // u30 u31 u32 u33 u34 u35 u36 u37 | ... - // u40 u41 u42 u43 u44 u45 u46 u47 | ... - // u50 u51 u52 u53 u54 u55 u56 u57 | ... - // u60 u61 u62 u63 u64 u65 u66 u67 | v60 ... - // u70 u71 u72 u73 u74 u75 u76 u77 | v70 v71 v72 ... - const uint8x16x2_t row01 = vtrnq_u8(row0, row1); // u00 u10 u02 u12 ... - // u01 u11 u03 u13 ... - const uint8x16x2_t row23 = vtrnq_u8(row2, row3); // u20 u30 u22 u32 ... - // u21 u31 u23 u33 ... - const uint8x16x2_t row45 = vtrnq_u8(row4, row5); // ... - const uint8x16x2_t row67 = vtrnq_u8(row6, row7); // ... - const uint16x8x2_t row02 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[0]), - vreinterpretq_u16_u8(row23.val[0])); - const uint16x8x2_t row13 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[1]), - vreinterpretq_u16_u8(row23.val[1])); - const uint16x8x2_t row46 = vtrnq_u16(vreinterpretq_u16_u8(row45.val[0]), - vreinterpretq_u16_u8(row67.val[0])); - const uint16x8x2_t row57 = vtrnq_u16(vreinterpretq_u16_u8(row45.val[1]), - vreinterpretq_u16_u8(row67.val[1])); - const uint32x4x2_t row04 = vtrnq_u32(vreinterpretq_u32_u16(row02.val[0]), - vreinterpretq_u32_u16(row46.val[0])); - const uint32x4x2_t row26 = vtrnq_u32(vreinterpretq_u32_u16(row02.val[1]), - vreinterpretq_u32_u16(row46.val[1])); - const uint32x4x2_t row15 = vtrnq_u32(vreinterpretq_u32_u16(row13.val[0]), - vreinterpretq_u32_u16(row57.val[0])); - const uint32x4x2_t row37 = vtrnq_u32(vreinterpretq_u32_u16(row13.val[1]), - vreinterpretq_u32_u16(row57.val[1])); - *p3 = vreinterpretq_u8_u32(row04.val[0]); - *p2 = vreinterpretq_u8_u32(row15.val[0]); - *p1 = vreinterpretq_u8_u32(row26.val[0]); - *p0 = vreinterpretq_u8_u32(row37.val[0]); - *q0 = vreinterpretq_u8_u32(row04.val[1]); - *q1 = vreinterpretq_u8_u32(row15.val[1]); - *q2 = vreinterpretq_u8_u32(row26.val[1]); - *q3 = vreinterpretq_u8_u32(row37.val[1]); -} -#undef LOAD_UV_8 - -#endif // !WORK_AROUND_GCC - -static WEBP_INLINE void Store2x8(const uint8x8x2_t v, - uint8_t* const dst, int stride) { - vst2_lane_u8(dst + 0 * stride, v, 0); - vst2_lane_u8(dst + 1 * stride, v, 1); - vst2_lane_u8(dst + 2 * stride, v, 2); - vst2_lane_u8(dst + 3 * stride, v, 3); - vst2_lane_u8(dst + 4 * stride, v, 4); - vst2_lane_u8(dst + 5 * stride, v, 5); - vst2_lane_u8(dst + 6 * stride, v, 6); - vst2_lane_u8(dst + 7 * stride, v, 7); -} - -static WEBP_INLINE void Store2x16(const uint8x16_t p0, const uint8x16_t q0, - uint8_t* const dst, int stride) { - uint8x8x2_t lo, hi; - lo.val[0] = vget_low_u8(p0); - lo.val[1] = vget_low_u8(q0); - hi.val[0] = vget_high_u8(p0); - hi.val[1] = vget_high_u8(q0); - Store2x8(lo, dst - 1 + 0 * stride, stride); - Store2x8(hi, dst - 1 + 8 * stride, stride); -} - -#if !defined(WORK_AROUND_GCC) -static WEBP_INLINE void Store4x8(const uint8x8x4_t v, - uint8_t* const dst, int stride) { - vst4_lane_u8(dst + 0 * stride, v, 0); - vst4_lane_u8(dst + 1 * stride, v, 1); - vst4_lane_u8(dst + 2 * stride, v, 2); - vst4_lane_u8(dst + 3 * stride, v, 3); - vst4_lane_u8(dst + 4 * stride, v, 4); - vst4_lane_u8(dst + 5 * stride, v, 5); - vst4_lane_u8(dst + 6 * stride, v, 6); - vst4_lane_u8(dst + 7 * stride, v, 7); -} - -static WEBP_INLINE void Store4x16(const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - uint8_t* const dst, int stride) { - uint8x8x4_t lo, hi; - INIT_VECTOR4(lo, - vget_low_u8(p1), vget_low_u8(p0), - vget_low_u8(q0), vget_low_u8(q1)); - INIT_VECTOR4(hi, - vget_high_u8(p1), vget_high_u8(p0), - vget_high_u8(q0), vget_high_u8(q1)); - Store4x8(lo, dst - 2 + 0 * stride, stride); - Store4x8(hi, dst - 2 + 8 * stride, stride); -} -#endif // !WORK_AROUND_GCC - -static WEBP_INLINE void Store16x2(const uint8x16_t p0, const uint8x16_t q0, - uint8_t* const dst, int stride) { - vst1q_u8(dst - stride, p0); - vst1q_u8(dst, q0); -} - -static WEBP_INLINE void Store16x4(const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - uint8_t* const dst, int stride) { - Store16x2(p1, p0, dst - stride, stride); - Store16x2(q0, q1, dst + stride, stride); -} - -static WEBP_INLINE void Store8x2x2(const uint8x16_t p0, const uint8x16_t q0, - uint8_t* const u, uint8_t* const v, - int stride) { - // p0 and q0 contain the u+v samples packed in low/high halves. - vst1_u8(u - stride, vget_low_u8(p0)); - vst1_u8(u, vget_low_u8(q0)); - vst1_u8(v - stride, vget_high_u8(p0)); - vst1_u8(v, vget_high_u8(q0)); -} - -static WEBP_INLINE void Store8x4x2(const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - uint8_t* const u, uint8_t* const v, - int stride) { - // The p1...q1 registers contain the u+v samples packed in low/high halves. - Store8x2x2(p1, p0, u - stride, v - stride, stride); - Store8x2x2(q0, q1, u + stride, v + stride, stride); -} - -#if !defined(WORK_AROUND_GCC) - -#define STORE6_LANE(DST, VAL0, VAL1, LANE) do { \ - vst3_lane_u8((DST) - 3, (VAL0), (LANE)); \ - vst3_lane_u8((DST) + 0, (VAL1), (LANE)); \ - (DST) += stride; \ -} while (0) - -static WEBP_INLINE void Store6x8x2(const uint8x16_t p2, const uint8x16_t p1, - const uint8x16_t p0, const uint8x16_t q0, - const uint8x16_t q1, const uint8x16_t q2, - uint8_t* u, uint8_t* v, - int stride) { - uint8x8x3_t u0, u1, v0, v1; - INIT_VECTOR3(u0, vget_low_u8(p2), vget_low_u8(p1), vget_low_u8(p0)); - INIT_VECTOR3(u1, vget_low_u8(q0), vget_low_u8(q1), vget_low_u8(q2)); - INIT_VECTOR3(v0, vget_high_u8(p2), vget_high_u8(p1), vget_high_u8(p0)); - INIT_VECTOR3(v1, vget_high_u8(q0), vget_high_u8(q1), vget_high_u8(q2)); - STORE6_LANE(u, u0, u1, 0); - STORE6_LANE(u, u0, u1, 1); - STORE6_LANE(u, u0, u1, 2); - STORE6_LANE(u, u0, u1, 3); - STORE6_LANE(u, u0, u1, 4); - STORE6_LANE(u, u0, u1, 5); - STORE6_LANE(u, u0, u1, 6); - STORE6_LANE(u, u0, u1, 7); - STORE6_LANE(v, v0, v1, 0); - STORE6_LANE(v, v0, v1, 1); - STORE6_LANE(v, v0, v1, 2); - STORE6_LANE(v, v0, v1, 3); - STORE6_LANE(v, v0, v1, 4); - STORE6_LANE(v, v0, v1, 5); - STORE6_LANE(v, v0, v1, 6); - STORE6_LANE(v, v0, v1, 7); -} -#undef STORE6_LANE - -static WEBP_INLINE void Store4x8x2(const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - uint8_t* const u, uint8_t* const v, - int stride) { - uint8x8x4_t u0, v0; - INIT_VECTOR4(u0, - vget_low_u8(p1), vget_low_u8(p0), - vget_low_u8(q0), vget_low_u8(q1)); - INIT_VECTOR4(v0, - vget_high_u8(p1), vget_high_u8(p0), - vget_high_u8(q0), vget_high_u8(q1)); - vst4_lane_u8(u - 2 + 0 * stride, u0, 0); - vst4_lane_u8(u - 2 + 1 * stride, u0, 1); - vst4_lane_u8(u - 2 + 2 * stride, u0, 2); - vst4_lane_u8(u - 2 + 3 * stride, u0, 3); - vst4_lane_u8(u - 2 + 4 * stride, u0, 4); - vst4_lane_u8(u - 2 + 5 * stride, u0, 5); - vst4_lane_u8(u - 2 + 6 * stride, u0, 6); - vst4_lane_u8(u - 2 + 7 * stride, u0, 7); - vst4_lane_u8(v - 2 + 0 * stride, v0, 0); - vst4_lane_u8(v - 2 + 1 * stride, v0, 1); - vst4_lane_u8(v - 2 + 2 * stride, v0, 2); - vst4_lane_u8(v - 2 + 3 * stride, v0, 3); - vst4_lane_u8(v - 2 + 4 * stride, v0, 4); - vst4_lane_u8(v - 2 + 5 * stride, v0, 5); - vst4_lane_u8(v - 2 + 6 * stride, v0, 6); - vst4_lane_u8(v - 2 + 7 * stride, v0, 7); -} - -#endif // !WORK_AROUND_GCC - -// Zero extend 'v' to an int16x8_t. -static WEBP_INLINE int16x8_t ConvertU8ToS16(uint8x8_t v) { - return vreinterpretq_s16_u16(vmovl_u8(v)); -} - -// Performs unsigned 8b saturation on 'dst01' and 'dst23' storing the result -// to the corresponding rows of 'dst'. -static WEBP_INLINE void SaturateAndStore4x4(uint8_t* const dst, - const int16x8_t dst01, - const int16x8_t dst23) { - // Unsigned saturate to 8b. - const uint8x8_t dst01_u8 = vqmovun_s16(dst01); - const uint8x8_t dst23_u8 = vqmovun_s16(dst23); - - // Store the results. - vst1_lane_u32((uint32_t*)(dst + 0 * BPS), vreinterpret_u32_u8(dst01_u8), 0); - vst1_lane_u32((uint32_t*)(dst + 1 * BPS), vreinterpret_u32_u8(dst01_u8), 1); - vst1_lane_u32((uint32_t*)(dst + 2 * BPS), vreinterpret_u32_u8(dst23_u8), 0); - vst1_lane_u32((uint32_t*)(dst + 3 * BPS), vreinterpret_u32_u8(dst23_u8), 1); -} - -static WEBP_INLINE void Add4x4(const int16x8_t row01, const int16x8_t row23, - uint8_t* const dst) { - uint32x2_t dst01 = vdup_n_u32(0); - uint32x2_t dst23 = vdup_n_u32(0); - - // Load the source pixels. - dst01 = vld1_lane_u32((uint32_t*)(dst + 0 * BPS), dst01, 0); - dst23 = vld1_lane_u32((uint32_t*)(dst + 2 * BPS), dst23, 0); - dst01 = vld1_lane_u32((uint32_t*)(dst + 1 * BPS), dst01, 1); - dst23 = vld1_lane_u32((uint32_t*)(dst + 3 * BPS), dst23, 1); - - { - // Convert to 16b. - const int16x8_t dst01_s16 = ConvertU8ToS16(vreinterpret_u8_u32(dst01)); - const int16x8_t dst23_s16 = ConvertU8ToS16(vreinterpret_u8_u32(dst23)); - - // Descale with rounding. - const int16x8_t out01 = vrsraq_n_s16(dst01_s16, row01, 3); - const int16x8_t out23 = vrsraq_n_s16(dst23_s16, row23, 3); - // Add the inverse transform. - SaturateAndStore4x4(dst, out01, out23); - } -} - -//----------------------------------------------------------------------------- -// Simple In-loop filtering (Paragraph 15.2) - -static uint8x16_t NeedsFilter(const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - int thresh) { - const uint8x16_t thresh_v = vdupq_n_u8((uint8_t)thresh); - const uint8x16_t a_p0_q0 = vabdq_u8(p0, q0); // abs(p0-q0) - const uint8x16_t a_p1_q1 = vabdq_u8(p1, q1); // abs(p1-q1) - const uint8x16_t a_p0_q0_2 = vqaddq_u8(a_p0_q0, a_p0_q0); // 2 * abs(p0-q0) - const uint8x16_t a_p1_q1_2 = vshrq_n_u8(a_p1_q1, 1); // abs(p1-q1) / 2 - const uint8x16_t sum = vqaddq_u8(a_p0_q0_2, a_p1_q1_2); - const uint8x16_t mask = vcgeq_u8(thresh_v, sum); - return mask; -} - -static int8x16_t FlipSign(const uint8x16_t v) { - const uint8x16_t sign_bit = vdupq_n_u8(0x80); - return vreinterpretq_s8_u8(veorq_u8(v, sign_bit)); -} - -static uint8x16_t FlipSignBack(const int8x16_t v) { - const int8x16_t sign_bit = vdupq_n_s8(0x80); - return vreinterpretq_u8_s8(veorq_s8(v, sign_bit)); -} - -static int8x16_t GetBaseDelta(const int8x16_t p1, const int8x16_t p0, - const int8x16_t q0, const int8x16_t q1) { - const int8x16_t q0_p0 = vqsubq_s8(q0, p0); // (q0-p0) - const int8x16_t p1_q1 = vqsubq_s8(p1, q1); // (p1-q1) - const int8x16_t s1 = vqaddq_s8(p1_q1, q0_p0); // (p1-q1) + 1 * (q0 - p0) - const int8x16_t s2 = vqaddq_s8(q0_p0, s1); // (p1-q1) + 2 * (q0 - p0) - const int8x16_t s3 = vqaddq_s8(q0_p0, s2); // (p1-q1) + 3 * (q0 - p0) - return s3; -} - -static int8x16_t GetBaseDelta0(const int8x16_t p0, const int8x16_t q0) { - const int8x16_t q0_p0 = vqsubq_s8(q0, p0); // (q0-p0) - const int8x16_t s1 = vqaddq_s8(q0_p0, q0_p0); // 2 * (q0 - p0) - const int8x16_t s2 = vqaddq_s8(q0_p0, s1); // 3 * (q0 - p0) - return s2; -} - -//------------------------------------------------------------------------------ - -static void ApplyFilter2NoFlip(const int8x16_t p0s, const int8x16_t q0s, - const int8x16_t delta, - int8x16_t* const op0, int8x16_t* const oq0) { - const int8x16_t kCst3 = vdupq_n_s8(0x03); - const int8x16_t kCst4 = vdupq_n_s8(0x04); - const int8x16_t delta_p3 = vqaddq_s8(delta, kCst3); - const int8x16_t delta_p4 = vqaddq_s8(delta, kCst4); - const int8x16_t delta3 = vshrq_n_s8(delta_p3, 3); - const int8x16_t delta4 = vshrq_n_s8(delta_p4, 3); - *op0 = vqaddq_s8(p0s, delta3); - *oq0 = vqsubq_s8(q0s, delta4); -} - -#if defined(WEBP_USE_INTRINSICS) - -static void ApplyFilter2(const int8x16_t p0s, const int8x16_t q0s, - const int8x16_t delta, - uint8x16_t* const op0, uint8x16_t* const oq0) { - const int8x16_t kCst3 = vdupq_n_s8(0x03); - const int8x16_t kCst4 = vdupq_n_s8(0x04); - const int8x16_t delta_p3 = vqaddq_s8(delta, kCst3); - const int8x16_t delta_p4 = vqaddq_s8(delta, kCst4); - const int8x16_t delta3 = vshrq_n_s8(delta_p3, 3); - const int8x16_t delta4 = vshrq_n_s8(delta_p4, 3); - const int8x16_t sp0 = vqaddq_s8(p0s, delta3); - const int8x16_t sq0 = vqsubq_s8(q0s, delta4); - *op0 = FlipSignBack(sp0); - *oq0 = FlipSignBack(sq0); -} - -static void DoFilter2(const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - const uint8x16_t mask, - uint8x16_t* const op0, uint8x16_t* const oq0) { - const int8x16_t p1s = FlipSign(p1); - const int8x16_t p0s = FlipSign(p0); - const int8x16_t q0s = FlipSign(q0); - const int8x16_t q1s = FlipSign(q1); - const int8x16_t delta0 = GetBaseDelta(p1s, p0s, q0s, q1s); - const int8x16_t delta1 = vandq_s8(delta0, vreinterpretq_s8_u8(mask)); - ApplyFilter2(p0s, q0s, delta1, op0, oq0); -} - -static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { - uint8x16_t p1, p0, q0, q1, op0, oq0; - Load16x4(p, stride, &p1, &p0, &q0, &q1); - { - const uint8x16_t mask = NeedsFilter(p1, p0, q0, q1, thresh); - DoFilter2(p1, p0, q0, q1, mask, &op0, &oq0); - } - Store16x2(op0, oq0, p, stride); -} - -static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { - uint8x16_t p1, p0, q0, q1, oq0, op0; - Load4x16(p, stride, &p1, &p0, &q0, &q1); - { - const uint8x16_t mask = NeedsFilter(p1, p0, q0, q1, thresh); - DoFilter2(p1, p0, q0, q1, mask, &op0, &oq0); - } - Store2x16(op0, oq0, p, stride); -} - -#else - -#define QRegs "q0", "q1", "q2", "q3", \ - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" - -#define FLIP_SIGN_BIT2(a, b, s) \ - "veor " #a "," #a "," #s " \n" \ - "veor " #b "," #b "," #s " \n" \ - -#define FLIP_SIGN_BIT4(a, b, c, d, s) \ - FLIP_SIGN_BIT2(a, b, s) \ - FLIP_SIGN_BIT2(c, d, s) \ - -#define NEEDS_FILTER(p1, p0, q0, q1, thresh, mask) \ - "vabd.u8 q15," #p0 "," #q0 " \n" /* abs(p0 - q0) */ \ - "vabd.u8 q14," #p1 "," #q1 " \n" /* abs(p1 - q1) */ \ - "vqadd.u8 q15, q15, q15 \n" /* abs(p0 - q0) * 2 */ \ - "vshr.u8 q14, q14, #1 \n" /* abs(p1 - q1) / 2 */ \ - "vqadd.u8 q15, q15, q14 \n" /* abs(p0 - q0) * 2 + abs(p1 - q1) / 2 */ \ - "vdup.8 q14, " #thresh " \n" \ - "vcge.u8 " #mask ", q14, q15 \n" /* mask <= thresh */ - -#define GET_BASE_DELTA(p1, p0, q0, q1, o) \ - "vqsub.s8 q15," #q0 "," #p0 " \n" /* (q0 - p0) */ \ - "vqsub.s8 " #o "," #p1 "," #q1 " \n" /* (p1 - q1) */ \ - "vqadd.s8 " #o "," #o ", q15 \n" /* (p1 - q1) + 1 * (p0 - q0) */ \ - "vqadd.s8 " #o "," #o ", q15 \n" /* (p1 - q1) + 2 * (p0 - q0) */ \ - "vqadd.s8 " #o "," #o ", q15 \n" /* (p1 - q1) + 3 * (p0 - q0) */ - -#define DO_SIMPLE_FILTER(p0, q0, fl) \ - "vmov.i8 q15, #0x03 \n" \ - "vqadd.s8 q15, q15, " #fl " \n" /* filter1 = filter + 3 */ \ - "vshr.s8 q15, q15, #3 \n" /* filter1 >> 3 */ \ - "vqadd.s8 " #p0 "," #p0 ", q15 \n" /* p0 += filter1 */ \ - \ - "vmov.i8 q15, #0x04 \n" \ - "vqadd.s8 q15, q15, " #fl " \n" /* filter1 = filter + 4 */ \ - "vshr.s8 q15, q15, #3 \n" /* filter2 >> 3 */ \ - "vqsub.s8 " #q0 "," #q0 ", q15 \n" /* q0 -= filter2 */ - -// Applies filter on 2 pixels (p0 and q0) -#define DO_FILTER2(p1, p0, q0, q1, thresh) \ - NEEDS_FILTER(p1, p0, q0, q1, thresh, q9) /* filter mask in q9 */ \ - "vmov.i8 q10, #0x80 \n" /* sign bit */ \ - FLIP_SIGN_BIT4(p1, p0, q0, q1, q10) /* convert to signed value */ \ - GET_BASE_DELTA(p1, p0, q0, q1, q11) /* get filter level */ \ - "vand q9, q9, q11 \n" /* apply filter mask */ \ - DO_SIMPLE_FILTER(p0, q0, q9) /* apply filter */ \ - FLIP_SIGN_BIT2(p0, q0, q10) - -static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { - __asm__ volatile ( - "sub %[p], %[p], %[stride], lsl #1 \n" // p -= 2 * stride - - "vld1.u8 {q1}, [%[p]], %[stride] \n" // p1 - "vld1.u8 {q2}, [%[p]], %[stride] \n" // p0 - "vld1.u8 {q3}, [%[p]], %[stride] \n" // q0 - "vld1.u8 {q12}, [%[p]] \n" // q1 - - DO_FILTER2(q1, q2, q3, q12, %[thresh]) - - "sub %[p], %[p], %[stride], lsl #1 \n" // p -= 2 * stride - - "vst1.u8 {q2}, [%[p]], %[stride] \n" // store op0 - "vst1.u8 {q3}, [%[p]] \n" // store oq0 - : [p] "+r"(p) - : [stride] "r"(stride), [thresh] "r"(thresh) - : "memory", QRegs - ); -} - -static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { - __asm__ volatile ( - "sub r4, %[p], #2 \n" // base1 = p - 2 - "lsl r6, %[stride], #1 \n" // r6 = 2 * stride - "add r5, r4, %[stride] \n" // base2 = base1 + stride - - LOAD8x4(d2, d3, d4, d5, [r4], [r5], r6) - LOAD8x4(d24, d25, d26, d27, [r4], [r5], r6) - "vswp d3, d24 \n" // p1:q1 p0:q3 - "vswp d5, d26 \n" // q0:q2 q1:q4 - "vswp q2, q12 \n" // p1:q1 p0:q2 q0:q3 q1:q4 - - DO_FILTER2(q1, q2, q12, q13, %[thresh]) - - "sub %[p], %[p], #1 \n" // p - 1 - - "vswp d5, d24 \n" - STORE8x2(d4, d5, [%[p]], %[stride]) - STORE8x2(d24, d25, [%[p]], %[stride]) - - : [p] "+r"(p) - : [stride] "r"(stride), [thresh] "r"(thresh) - : "memory", "r4", "r5", "r6", QRegs - ); -} - -#endif // WEBP_USE_INTRINSICS - -static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) { - uint32_t k; - for (k = 3; k != 0; --k) { - p += 4 * stride; - SimpleVFilter16(p, stride, thresh); - } -} - -static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) { - uint32_t k; - for (k = 3; k != 0; --k) { - p += 4; - SimpleHFilter16(p, stride, thresh); - } -} - -//------------------------------------------------------------------------------ -// Complex In-loop filtering (Paragraph 15.3) - -static uint8x16_t NeedsHev(const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - int hev_thresh) { - const uint8x16_t hev_thresh_v = vdupq_n_u8((uint8_t)hev_thresh); - const uint8x16_t a_p1_p0 = vabdq_u8(p1, p0); // abs(p1 - p0) - const uint8x16_t a_q1_q0 = vabdq_u8(q1, q0); // abs(q1 - q0) - const uint8x16_t mask1 = vcgtq_u8(a_p1_p0, hev_thresh_v); - const uint8x16_t mask2 = vcgtq_u8(a_q1_q0, hev_thresh_v); - const uint8x16_t mask = vorrq_u8(mask1, mask2); - return mask; -} - -static uint8x16_t NeedsFilter2(const uint8x16_t p3, const uint8x16_t p2, - const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - const uint8x16_t q2, const uint8x16_t q3, - int ithresh, int thresh) { - const uint8x16_t ithresh_v = vdupq_n_u8((uint8_t)ithresh); - const uint8x16_t a_p3_p2 = vabdq_u8(p3, p2); // abs(p3 - p2) - const uint8x16_t a_p2_p1 = vabdq_u8(p2, p1); // abs(p2 - p1) - const uint8x16_t a_p1_p0 = vabdq_u8(p1, p0); // abs(p1 - p0) - const uint8x16_t a_q3_q2 = vabdq_u8(q3, q2); // abs(q3 - q2) - const uint8x16_t a_q2_q1 = vabdq_u8(q2, q1); // abs(q2 - q1) - const uint8x16_t a_q1_q0 = vabdq_u8(q1, q0); // abs(q1 - q0) - const uint8x16_t max1 = vmaxq_u8(a_p3_p2, a_p2_p1); - const uint8x16_t max2 = vmaxq_u8(a_p1_p0, a_q3_q2); - const uint8x16_t max3 = vmaxq_u8(a_q2_q1, a_q1_q0); - const uint8x16_t max12 = vmaxq_u8(max1, max2); - const uint8x16_t max123 = vmaxq_u8(max12, max3); - const uint8x16_t mask2 = vcgeq_u8(ithresh_v, max123); - const uint8x16_t mask1 = NeedsFilter(p1, p0, q0, q1, thresh); - const uint8x16_t mask = vandq_u8(mask1, mask2); - return mask; -} - -// 4-points filter - -static void ApplyFilter4( - const int8x16_t p1, const int8x16_t p0, - const int8x16_t q0, const int8x16_t q1, - const int8x16_t delta0, - uint8x16_t* const op1, uint8x16_t* const op0, - uint8x16_t* const oq0, uint8x16_t* const oq1) { - const int8x16_t kCst3 = vdupq_n_s8(0x03); - const int8x16_t kCst4 = vdupq_n_s8(0x04); - const int8x16_t delta1 = vqaddq_s8(delta0, kCst4); - const int8x16_t delta2 = vqaddq_s8(delta0, kCst3); - const int8x16_t a1 = vshrq_n_s8(delta1, 3); - const int8x16_t a2 = vshrq_n_s8(delta2, 3); - const int8x16_t a3 = vrshrq_n_s8(a1, 1); // a3 = (a1 + 1) >> 1 - *op0 = FlipSignBack(vqaddq_s8(p0, a2)); // clip(p0 + a2) - *oq0 = FlipSignBack(vqsubq_s8(q0, a1)); // clip(q0 - a1) - *op1 = FlipSignBack(vqaddq_s8(p1, a3)); // clip(p1 + a3) - *oq1 = FlipSignBack(vqsubq_s8(q1, a3)); // clip(q1 - a3) -} - -static void DoFilter4( - const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - const uint8x16_t mask, const uint8x16_t hev_mask, - uint8x16_t* const op1, uint8x16_t* const op0, - uint8x16_t* const oq0, uint8x16_t* const oq1) { - // This is a fused version of DoFilter2() calling ApplyFilter2 directly - const int8x16_t p1s = FlipSign(p1); - int8x16_t p0s = FlipSign(p0); - int8x16_t q0s = FlipSign(q0); - const int8x16_t q1s = FlipSign(q1); - const uint8x16_t simple_lf_mask = vandq_u8(mask, hev_mask); - - // do_filter2 part (simple loopfilter on pixels with hev) - { - const int8x16_t delta = GetBaseDelta(p1s, p0s, q0s, q1s); - const int8x16_t simple_lf_delta = - vandq_s8(delta, vreinterpretq_s8_u8(simple_lf_mask)); - ApplyFilter2NoFlip(p0s, q0s, simple_lf_delta, &p0s, &q0s); - } - - // do_filter4 part (complex loopfilter on pixels without hev) - { - const int8x16_t delta0 = GetBaseDelta0(p0s, q0s); - // we use: (mask & hev_mask) ^ mask = mask & !hev_mask - const uint8x16_t complex_lf_mask = veorq_u8(simple_lf_mask, mask); - const int8x16_t complex_lf_delta = - vandq_s8(delta0, vreinterpretq_s8_u8(complex_lf_mask)); - ApplyFilter4(p1s, p0s, q0s, q1s, complex_lf_delta, op1, op0, oq0, oq1); - } -} - -// 6-points filter - -static void ApplyFilter6( - const int8x16_t p2, const int8x16_t p1, const int8x16_t p0, - const int8x16_t q0, const int8x16_t q1, const int8x16_t q2, - const int8x16_t delta, - uint8x16_t* const op2, uint8x16_t* const op1, uint8x16_t* const op0, - uint8x16_t* const oq0, uint8x16_t* const oq1, uint8x16_t* const oq2) { - const int16x8_t kCst63 = vdupq_n_s16(63); - const int8x8_t kCst27 = vdup_n_s8(27); - const int8x8_t kCst18 = vdup_n_s8(18); - const int8x8_t kCst9 = vdup_n_s8(9); - const int8x8_t delta_lo = vget_low_s8(delta); - const int8x8_t delta_hi = vget_high_s8(delta); - const int16x8_t s1_lo = vmlal_s8(kCst63, kCst27, delta_lo); // 63 + 27 * a - const int16x8_t s1_hi = vmlal_s8(kCst63, kCst27, delta_hi); // 63 + 27 * a - const int16x8_t s2_lo = vmlal_s8(kCst63, kCst18, delta_lo); // 63 + 18 * a - const int16x8_t s2_hi = vmlal_s8(kCst63, kCst18, delta_hi); // 63 + 18 * a - const int16x8_t s3_lo = vmlal_s8(kCst63, kCst9, delta_lo); // 63 + 9 * a - const int16x8_t s3_hi = vmlal_s8(kCst63, kCst9, delta_hi); // 63 + 9 * a - const int8x8_t a1_lo = vqshrn_n_s16(s1_lo, 7); - const int8x8_t a1_hi = vqshrn_n_s16(s1_hi, 7); - const int8x8_t a2_lo = vqshrn_n_s16(s2_lo, 7); - const int8x8_t a2_hi = vqshrn_n_s16(s2_hi, 7); - const int8x8_t a3_lo = vqshrn_n_s16(s3_lo, 7); - const int8x8_t a3_hi = vqshrn_n_s16(s3_hi, 7); - const int8x16_t a1 = vcombine_s8(a1_lo, a1_hi); - const int8x16_t a2 = vcombine_s8(a2_lo, a2_hi); - const int8x16_t a3 = vcombine_s8(a3_lo, a3_hi); - - *op0 = FlipSignBack(vqaddq_s8(p0, a1)); // clip(p0 + a1) - *oq0 = FlipSignBack(vqsubq_s8(q0, a1)); // clip(q0 - q1) - *oq1 = FlipSignBack(vqsubq_s8(q1, a2)); // clip(q1 - a2) - *op1 = FlipSignBack(vqaddq_s8(p1, a2)); // clip(p1 + a2) - *oq2 = FlipSignBack(vqsubq_s8(q2, a3)); // clip(q2 - a3) - *op2 = FlipSignBack(vqaddq_s8(p2, a3)); // clip(p2 + a3) -} - -static void DoFilter6( - const uint8x16_t p2, const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, const uint8x16_t q2, - const uint8x16_t mask, const uint8x16_t hev_mask, - uint8x16_t* const op2, uint8x16_t* const op1, uint8x16_t* const op0, - uint8x16_t* const oq0, uint8x16_t* const oq1, uint8x16_t* const oq2) { - // This is a fused version of DoFilter2() calling ApplyFilter2 directly - const int8x16_t p2s = FlipSign(p2); - const int8x16_t p1s = FlipSign(p1); - int8x16_t p0s = FlipSign(p0); - int8x16_t q0s = FlipSign(q0); - const int8x16_t q1s = FlipSign(q1); - const int8x16_t q2s = FlipSign(q2); - const uint8x16_t simple_lf_mask = vandq_u8(mask, hev_mask); - const int8x16_t delta0 = GetBaseDelta(p1s, p0s, q0s, q1s); - - // do_filter2 part (simple loopfilter on pixels with hev) - { - const int8x16_t simple_lf_delta = - vandq_s8(delta0, vreinterpretq_s8_u8(simple_lf_mask)); - ApplyFilter2NoFlip(p0s, q0s, simple_lf_delta, &p0s, &q0s); - } - - // do_filter6 part (complex loopfilter on pixels without hev) - { - // we use: (mask & hev_mask) ^ mask = mask & !hev_mask - const uint8x16_t complex_lf_mask = veorq_u8(simple_lf_mask, mask); - const int8x16_t complex_lf_delta = - vandq_s8(delta0, vreinterpretq_s8_u8(complex_lf_mask)); - ApplyFilter6(p2s, p1s, p0s, q0s, q1s, q2s, complex_lf_delta, - op2, op1, op0, oq0, oq1, oq2); - } -} - -// on macroblock edges - -static void VFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; - Load16x8(p, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); - { - const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, - ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); - uint8x16_t op2, op1, op0, oq0, oq1, oq2; - DoFilter6(p2, p1, p0, q0, q1, q2, mask, hev_mask, - &op2, &op1, &op0, &oq0, &oq1, &oq2); - Store16x2(op2, op1, p - 2 * stride, stride); - Store16x2(op0, oq0, p + 0 * stride, stride); - Store16x2(oq1, oq2, p + 2 * stride, stride); - } -} - -static void HFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; - Load8x16(p, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); - { - const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, - ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); - uint8x16_t op2, op1, op0, oq0, oq1, oq2; - DoFilter6(p2, p1, p0, q0, q1, q2, mask, hev_mask, - &op2, &op1, &op0, &oq0, &oq1, &oq2); - Store2x16(op2, op1, p - 2, stride); - Store2x16(op0, oq0, p + 0, stride); - Store2x16(oq1, oq2, p + 2, stride); - } -} - -// on three inner edges -static void VFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - uint32_t k; - uint8x16_t p3, p2, p1, p0; - Load16x4(p + 2 * stride, stride, &p3, &p2, &p1, &p0); - for (k = 3; k != 0; --k) { - uint8x16_t q0, q1, q2, q3; - p += 4 * stride; - Load16x4(p + 2 * stride, stride, &q0, &q1, &q2, &q3); - { - const uint8x16_t mask = - NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); - // p3 and p2 are not just temporary variables here: they will be - // re-used for next span. And q2/q3 will become p1/p0 accordingly. - DoFilter4(p1, p0, q0, q1, mask, hev_mask, &p1, &p0, &p3, &p2); - Store16x4(p1, p0, p3, p2, p, stride); - p1 = q2; - p0 = q3; - } - } -} - -#if !defined(WORK_AROUND_GCC) -static void HFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - uint32_t k; - uint8x16_t p3, p2, p1, p0; - Load4x16(p + 2, stride, &p3, &p2, &p1, &p0); - for (k = 3; k != 0; --k) { - uint8x16_t q0, q1, q2, q3; - p += 4; - Load4x16(p + 2, stride, &q0, &q1, &q2, &q3); - { - const uint8x16_t mask = - NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); - DoFilter4(p1, p0, q0, q1, mask, hev_mask, &p1, &p0, &p3, &p2); - Store4x16(p1, p0, p3, p2, p, stride); - p1 = q2; - p0 = q3; - } - } -} -#endif // !WORK_AROUND_GCC - -// 8-pixels wide variant, for chroma filtering -static void VFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; - Load8x8x2(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); - { - const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, - ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); - uint8x16_t op2, op1, op0, oq0, oq1, oq2; - DoFilter6(p2, p1, p0, q0, q1, q2, mask, hev_mask, - &op2, &op1, &op0, &oq0, &oq1, &oq2); - Store8x2x2(op2, op1, u - 2 * stride, v - 2 * stride, stride); - Store8x2x2(op0, oq0, u + 0 * stride, v + 0 * stride, stride); - Store8x2x2(oq1, oq2, u + 2 * stride, v + 2 * stride, stride); - } -} -static void VFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; - u += 4 * stride; - v += 4 * stride; - Load8x8x2(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); - { - const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, - ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); - uint8x16_t op1, op0, oq0, oq1; - DoFilter4(p1, p0, q0, q1, mask, hev_mask, &op1, &op0, &oq0, &oq1); - Store8x4x2(op1, op0, oq0, oq1, u, v, stride); - } -} - -#if !defined(WORK_AROUND_GCC) -static void HFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; - Load8x8x2T(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); - { - const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, - ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); - uint8x16_t op2, op1, op0, oq0, oq1, oq2; - DoFilter6(p2, p1, p0, q0, q1, q2, mask, hev_mask, - &op2, &op1, &op0, &oq0, &oq1, &oq2); - Store6x8x2(op2, op1, op0, oq0, oq1, oq2, u, v, stride); - } -} - -static void HFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; - u += 4; - v += 4; - Load8x8x2T(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); - { - const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, - ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); - uint8x16_t op1, op0, oq0, oq1; - DoFilter4(p1, p0, q0, q1, mask, hev_mask, &op1, &op0, &oq0, &oq1); - Store4x8x2(op1, op0, oq0, oq1, u, v, stride); - } -} -#endif // !WORK_AROUND_GCC - -//----------------------------------------------------------------------------- -// Inverse transforms (Paragraph 14.4) - -// Technically these are unsigned but vqdmulh is only available in signed. -// vqdmulh returns high half (effectively >> 16) but also doubles the value, -// changing the >> 16 to >> 15 and requiring an additional >> 1. -// We use this to our advantage with kC2. The canonical value is 35468. -// However, the high bit is set so treating it as signed will give incorrect -// results. We avoid this by down shifting by 1 here to clear the highest bit. -// Combined with the doubling effect of vqdmulh we get >> 16. -// This can not be applied to kC1 because the lowest bit is set. Down shifting -// the constant would reduce precision. - -// libwebp uses a trick to avoid some extra addition that libvpx does. -// Instead of: -// temp2 = ip[12] + ((ip[12] * cospi8sqrt2minus1) >> 16); -// libwebp adds 1 << 16 to cospi8sqrt2minus1 (kC1). However, this causes the -// same issue with kC1 and vqdmulh that we work around by down shifting kC2 - -static const int16_t kC1 = 20091; -static const int16_t kC2 = 17734; // half of kC2, actually. See comment above. - -#if defined(WEBP_USE_INTRINSICS) -static WEBP_INLINE void Transpose8x2(const int16x8_t in0, const int16x8_t in1, - int16x8x2_t* const out) { - // a0 a1 a2 a3 | b0 b1 b2 b3 => a0 b0 c0 d0 | a1 b1 c1 d1 - // c0 c1 c2 c3 | d0 d1 d2 d3 a2 b2 c2 d2 | a3 b3 c3 d3 - const int16x8x2_t tmp0 = vzipq_s16(in0, in1); // a0 c0 a1 c1 a2 c2 ... - // b0 d0 b1 d1 b2 d2 ... - *out = vzipq_s16(tmp0.val[0], tmp0.val[1]); -} - -static WEBP_INLINE void TransformPass(int16x8x2_t* const rows) { - // {rows} = in0 | in4 - // in8 | in12 - // B1 = in4 | in12 - const int16x8_t B1 = - vcombine_s16(vget_high_s16(rows->val[0]), vget_high_s16(rows->val[1])); - // C0 = kC1 * in4 | kC1 * in12 - // C1 = kC2 * in4 | kC2 * in12 - const int16x8_t C0 = vsraq_n_s16(B1, vqdmulhq_n_s16(B1, kC1), 1); - const int16x8_t C1 = vqdmulhq_n_s16(B1, kC2); - const int16x4_t a = vqadd_s16(vget_low_s16(rows->val[0]), - vget_low_s16(rows->val[1])); // in0 + in8 - const int16x4_t b = vqsub_s16(vget_low_s16(rows->val[0]), - vget_low_s16(rows->val[1])); // in0 - in8 - // c = kC2 * in4 - kC1 * in12 - // d = kC1 * in4 + kC2 * in12 - const int16x4_t c = vqsub_s16(vget_low_s16(C1), vget_high_s16(C0)); - const int16x4_t d = vqadd_s16(vget_low_s16(C0), vget_high_s16(C1)); - const int16x8_t D0 = vcombine_s16(a, b); // D0 = a | b - const int16x8_t D1 = vcombine_s16(d, c); // D1 = d | c - const int16x8_t E0 = vqaddq_s16(D0, D1); // a+d | b+c - const int16x8_t E_tmp = vqsubq_s16(D0, D1); // a-d | b-c - const int16x8_t E1 = vcombine_s16(vget_high_s16(E_tmp), vget_low_s16(E_tmp)); - Transpose8x2(E0, E1, rows); -} - -static void TransformOne(const int16_t* in, uint8_t* dst) { - int16x8x2_t rows; - INIT_VECTOR2(rows, vld1q_s16(in + 0), vld1q_s16(in + 8)); - TransformPass(&rows); - TransformPass(&rows); - Add4x4(rows.val[0], rows.val[1], dst); -} - -#else - -static void TransformOne(const int16_t* in, uint8_t* dst) { - const int kBPS = BPS; - // kC1, kC2. Padded because vld1.16 loads 8 bytes - const int16_t constants[4] = { kC1, kC2, 0, 0 }; - /* Adapted from libvpx: vp8/common/arm/neon/shortidct4x4llm_neon.asm */ - __asm__ volatile ( - "vld1.16 {q1, q2}, [%[in]] \n" - "vld1.16 {d0}, [%[constants]] \n" - - /* d2: in[0] - * d3: in[8] - * d4: in[4] - * d5: in[12] - */ - "vswp d3, d4 \n" - - /* q8 = {in[4], in[12]} * kC1 * 2 >> 16 - * q9 = {in[4], in[12]} * kC2 >> 16 - */ - "vqdmulh.s16 q8, q2, d0[0] \n" - "vqdmulh.s16 q9, q2, d0[1] \n" - - /* d22 = a = in[0] + in[8] - * d23 = b = in[0] - in[8] - */ - "vqadd.s16 d22, d2, d3 \n" - "vqsub.s16 d23, d2, d3 \n" - - /* The multiplication should be x * kC1 >> 16 - * However, with vqdmulh we get x * kC1 * 2 >> 16 - * (multiply, double, return high half) - * We avoided this in kC2 by pre-shifting the constant. - * q8 = in[4]/[12] * kC1 >> 16 - */ - "vshr.s16 q8, q8, #1 \n" - - /* Add {in[4], in[12]} back after the multiplication. This is handled by - * adding 1 << 16 to kC1 in the libwebp C code. - */ - "vqadd.s16 q8, q2, q8 \n" - - /* d20 = c = in[4]*kC2 - in[12]*kC1 - * d21 = d = in[4]*kC1 + in[12]*kC2 - */ - "vqsub.s16 d20, d18, d17 \n" - "vqadd.s16 d21, d19, d16 \n" - - /* d2 = tmp[0] = a + d - * d3 = tmp[1] = b + c - * d4 = tmp[2] = b - c - * d5 = tmp[3] = a - d - */ - "vqadd.s16 d2, d22, d21 \n" - "vqadd.s16 d3, d23, d20 \n" - "vqsub.s16 d4, d23, d20 \n" - "vqsub.s16 d5, d22, d21 \n" - - "vzip.16 q1, q2 \n" - "vzip.16 q1, q2 \n" - - "vswp d3, d4 \n" - - /* q8 = {tmp[4], tmp[12]} * kC1 * 2 >> 16 - * q9 = {tmp[4], tmp[12]} * kC2 >> 16 - */ - "vqdmulh.s16 q8, q2, d0[0] \n" - "vqdmulh.s16 q9, q2, d0[1] \n" - - /* d22 = a = tmp[0] + tmp[8] - * d23 = b = tmp[0] - tmp[8] - */ - "vqadd.s16 d22, d2, d3 \n" - "vqsub.s16 d23, d2, d3 \n" - - /* See long winded explanations prior */ - "vshr.s16 q8, q8, #1 \n" - "vqadd.s16 q8, q2, q8 \n" - - /* d20 = c = in[4]*kC2 - in[12]*kC1 - * d21 = d = in[4]*kC1 + in[12]*kC2 - */ - "vqsub.s16 d20, d18, d17 \n" - "vqadd.s16 d21, d19, d16 \n" - - /* d2 = tmp[0] = a + d - * d3 = tmp[1] = b + c - * d4 = tmp[2] = b - c - * d5 = tmp[3] = a - d - */ - "vqadd.s16 d2, d22, d21 \n" - "vqadd.s16 d3, d23, d20 \n" - "vqsub.s16 d4, d23, d20 \n" - "vqsub.s16 d5, d22, d21 \n" - - "vld1.32 d6[0], [%[dst]], %[kBPS] \n" - "vld1.32 d6[1], [%[dst]], %[kBPS] \n" - "vld1.32 d7[0], [%[dst]], %[kBPS] \n" - "vld1.32 d7[1], [%[dst]], %[kBPS] \n" - - "sub %[dst], %[dst], %[kBPS], lsl #2 \n" - - /* (val) + 4 >> 3 */ - "vrshr.s16 d2, d2, #3 \n" - "vrshr.s16 d3, d3, #3 \n" - "vrshr.s16 d4, d4, #3 \n" - "vrshr.s16 d5, d5, #3 \n" - - "vzip.16 q1, q2 \n" - "vzip.16 q1, q2 \n" - - /* Must accumulate before saturating */ - "vmovl.u8 q8, d6 \n" - "vmovl.u8 q9, d7 \n" - - "vqadd.s16 q1, q1, q8 \n" - "vqadd.s16 q2, q2, q9 \n" - - "vqmovun.s16 d0, q1 \n" - "vqmovun.s16 d1, q2 \n" - - "vst1.32 d0[0], [%[dst]], %[kBPS] \n" - "vst1.32 d0[1], [%[dst]], %[kBPS] \n" - "vst1.32 d1[0], [%[dst]], %[kBPS] \n" - "vst1.32 d1[1], [%[dst]] \n" - - : [in] "+r"(in), [dst] "+r"(dst) /* modified registers */ - : [kBPS] "r"(kBPS), [constants] "r"(constants) /* constants */ - : "memory", "q0", "q1", "q2", "q8", "q9", "q10", "q11" /* clobbered */ - ); -} - -#endif // WEBP_USE_INTRINSICS - -static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) { - TransformOne(in, dst); - if (do_two) { - TransformOne(in + 16, dst + 4); - } -} - -static void TransformDC(const int16_t* in, uint8_t* dst) { - const int16x8_t DC = vdupq_n_s16(in[0]); - Add4x4(DC, DC, dst); -} - -//------------------------------------------------------------------------------ - -#define STORE_WHT(dst, col, rows) do { \ - *dst = vgetq_lane_s32(rows.val[0], col); (dst) += 16; \ - *dst = vgetq_lane_s32(rows.val[1], col); (dst) += 16; \ - *dst = vgetq_lane_s32(rows.val[2], col); (dst) += 16; \ - *dst = vgetq_lane_s32(rows.val[3], col); (dst) += 16; \ -} while (0) - -static void TransformWHT(const int16_t* in, int16_t* out) { - int32x4x4_t tmp; - - { - // Load the source. - const int16x4_t in00_03 = vld1_s16(in + 0); - const int16x4_t in04_07 = vld1_s16(in + 4); - const int16x4_t in08_11 = vld1_s16(in + 8); - const int16x4_t in12_15 = vld1_s16(in + 12); - const int32x4_t a0 = vaddl_s16(in00_03, in12_15); // in[0..3] + in[12..15] - const int32x4_t a1 = vaddl_s16(in04_07, in08_11); // in[4..7] + in[8..11] - const int32x4_t a2 = vsubl_s16(in04_07, in08_11); // in[4..7] - in[8..11] - const int32x4_t a3 = vsubl_s16(in00_03, in12_15); // in[0..3] - in[12..15] - tmp.val[0] = vaddq_s32(a0, a1); - tmp.val[1] = vaddq_s32(a3, a2); - tmp.val[2] = vsubq_s32(a0, a1); - tmp.val[3] = vsubq_s32(a3, a2); - // Arrange the temporary results column-wise. - tmp = Transpose4x4(tmp); - } - - { - const int32x4_t kCst3 = vdupq_n_s32(3); - const int32x4_t dc = vaddq_s32(tmp.val[0], kCst3); // add rounder - const int32x4_t a0 = vaddq_s32(dc, tmp.val[3]); - const int32x4_t a1 = vaddq_s32(tmp.val[1], tmp.val[2]); - const int32x4_t a2 = vsubq_s32(tmp.val[1], tmp.val[2]); - const int32x4_t a3 = vsubq_s32(dc, tmp.val[3]); - - tmp.val[0] = vaddq_s32(a0, a1); - tmp.val[1] = vaddq_s32(a3, a2); - tmp.val[2] = vsubq_s32(a0, a1); - tmp.val[3] = vsubq_s32(a3, a2); - - // right shift the results by 3. - tmp.val[0] = vshrq_n_s32(tmp.val[0], 3); - tmp.val[1] = vshrq_n_s32(tmp.val[1], 3); - tmp.val[2] = vshrq_n_s32(tmp.val[2], 3); - tmp.val[3] = vshrq_n_s32(tmp.val[3], 3); - - STORE_WHT(out, 0, tmp); - STORE_WHT(out, 1, tmp); - STORE_WHT(out, 2, tmp); - STORE_WHT(out, 3, tmp); - } -} - -#undef STORE_WHT - -//------------------------------------------------------------------------------ - -#define MUL(a, b) (((a) * (b)) >> 16) -static void TransformAC3(const int16_t* in, uint8_t* dst) { - static const int kC1_full = 20091 + (1 << 16); - static const int kC2_full = 35468; - const int16x4_t A = vld1_dup_s16(in); - const int16x4_t c4 = vdup_n_s16(MUL(in[4], kC2_full)); - const int16x4_t d4 = vdup_n_s16(MUL(in[4], kC1_full)); - const int c1 = MUL(in[1], kC2_full); - const int d1 = MUL(in[1], kC1_full); - const uint64_t cd = (uint64_t)( d1 & 0xffff) << 0 | - (uint64_t)( c1 & 0xffff) << 16 | - (uint64_t)(-c1 & 0xffff) << 32 | - (uint64_t)(-d1 & 0xffff) << 48; - const int16x4_t CD = vcreate_s16(cd); - const int16x4_t B = vqadd_s16(A, CD); - const int16x8_t m0_m1 = vcombine_s16(vqadd_s16(B, d4), vqadd_s16(B, c4)); - const int16x8_t m2_m3 = vcombine_s16(vqsub_s16(B, c4), vqsub_s16(B, d4)); - Add4x4(m0_m1, m2_m3, dst); -} -#undef MUL - -//------------------------------------------------------------------------------ -// 4x4 - -static void DC4(uint8_t* dst) { // DC - const uint8x8_t A = vld1_u8(dst - BPS); // top row - const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top - const uint16x4_t p1 = vpadd_u16(p0, p0); - const uint16x8_t L0 = vmovl_u8(vld1_u8(dst + 0 * BPS - 1)); - const uint16x8_t L1 = vmovl_u8(vld1_u8(dst + 1 * BPS - 1)); - const uint16x8_t L2 = vmovl_u8(vld1_u8(dst + 2 * BPS - 1)); - const uint16x8_t L3 = vmovl_u8(vld1_u8(dst + 3 * BPS - 1)); - const uint16x8_t s0 = vaddq_u16(L0, L1); - const uint16x8_t s1 = vaddq_u16(L2, L3); - const uint16x8_t s01 = vaddq_u16(s0, s1); - const uint16x8_t sum = vaddq_u16(s01, vcombine_u16(p1, p1)); - const uint8x8_t dc0 = vrshrn_n_u16(sum, 3); // (sum + 4) >> 3 - const uint8x8_t dc = vdup_lane_u8(dc0, 0); - int i; - for (i = 0; i < 4; ++i) { - vst1_lane_u32((uint32_t*)(dst + i * BPS), vreinterpret_u32_u8(dc), 0); - } -} - -// TrueMotion (4x4 + 8x8) -static WEBP_INLINE void TrueMotion(uint8_t* dst, int size) { - const uint8x8_t TL = vld1_dup_u8(dst - BPS - 1); // top-left pixel 'A[-1]' - const uint8x8_t T = vld1_u8(dst - BPS); // top row 'A[0..3]' - const int16x8_t d = vreinterpretq_s16_u16(vsubl_u8(T, TL)); // A[c] - A[-1] - int y; - for (y = 0; y < size; y += 4) { - // left edge - const int16x8_t L0 = ConvertU8ToS16(vld1_dup_u8(dst + 0 * BPS - 1)); - const int16x8_t L1 = ConvertU8ToS16(vld1_dup_u8(dst + 1 * BPS - 1)); - const int16x8_t L2 = ConvertU8ToS16(vld1_dup_u8(dst + 2 * BPS - 1)); - const int16x8_t L3 = ConvertU8ToS16(vld1_dup_u8(dst + 3 * BPS - 1)); - const int16x8_t r0 = vaddq_s16(L0, d); // L[r] + A[c] - A[-1] - const int16x8_t r1 = vaddq_s16(L1, d); - const int16x8_t r2 = vaddq_s16(L2, d); - const int16x8_t r3 = vaddq_s16(L3, d); - // Saturate and store the result. - const uint32x2_t r0_u32 = vreinterpret_u32_u8(vqmovun_s16(r0)); - const uint32x2_t r1_u32 = vreinterpret_u32_u8(vqmovun_s16(r1)); - const uint32x2_t r2_u32 = vreinterpret_u32_u8(vqmovun_s16(r2)); - const uint32x2_t r3_u32 = vreinterpret_u32_u8(vqmovun_s16(r3)); - if (size == 4) { - vst1_lane_u32((uint32_t*)(dst + 0 * BPS), r0_u32, 0); - vst1_lane_u32((uint32_t*)(dst + 1 * BPS), r1_u32, 0); - vst1_lane_u32((uint32_t*)(dst + 2 * BPS), r2_u32, 0); - vst1_lane_u32((uint32_t*)(dst + 3 * BPS), r3_u32, 0); - } else { - vst1_u32((uint32_t*)(dst + 0 * BPS), r0_u32); - vst1_u32((uint32_t*)(dst + 1 * BPS), r1_u32); - vst1_u32((uint32_t*)(dst + 2 * BPS), r2_u32); - vst1_u32((uint32_t*)(dst + 3 * BPS), r3_u32); - } - dst += 4 * BPS; - } -} - -static void TM4(uint8_t* dst) { TrueMotion(dst, 4); } - -static void VE4(uint8_t* dst) { // vertical - // NB: avoid vld1_u64 here as an alignment hint may be added -> SIGBUS. - const uint64x1_t A0 = vreinterpret_u64_u8(vld1_u8(dst - BPS - 1)); // top row - const uint64x1_t A1 = vshr_n_u64(A0, 8); - const uint64x1_t A2 = vshr_n_u64(A0, 16); - const uint8x8_t ABCDEFGH = vreinterpret_u8_u64(A0); - const uint8x8_t BCDEFGH0 = vreinterpret_u8_u64(A1); - const uint8x8_t CDEFGH00 = vreinterpret_u8_u64(A2); - const uint8x8_t b = vhadd_u8(ABCDEFGH, CDEFGH00); - const uint8x8_t avg = vrhadd_u8(b, BCDEFGH0); - int i; - for (i = 0; i < 4; ++i) { - vst1_lane_u32((uint32_t*)(dst + i * BPS), vreinterpret_u32_u8(avg), 0); - } -} - -static void RD4(uint8_t* dst) { // Down-right - const uint8x8_t XABCD_u8 = vld1_u8(dst - BPS - 1); - const uint64x1_t XABCD = vreinterpret_u64_u8(XABCD_u8); - const uint64x1_t ____XABC = vshl_n_u64(XABCD, 32); - const uint32_t I = dst[-1 + 0 * BPS]; - const uint32_t J = dst[-1 + 1 * BPS]; - const uint32_t K = dst[-1 + 2 * BPS]; - const uint32_t L = dst[-1 + 3 * BPS]; - const uint64x1_t LKJI____ = vcreate_u64(L | (K << 8) | (J << 16) | (I << 24)); - const uint64x1_t LKJIXABC = vorr_u64(LKJI____, ____XABC); - const uint8x8_t KJIXABC_ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 8)); - const uint8x8_t JIXABC__ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 16)); - const uint8_t D = vget_lane_u8(XABCD_u8, 4); - const uint8x8_t JIXABCD_ = vset_lane_u8(D, JIXABC__, 6); - const uint8x8_t LKJIXABC_u8 = vreinterpret_u8_u64(LKJIXABC); - const uint8x8_t avg1 = vhadd_u8(JIXABCD_, LKJIXABC_u8); - const uint8x8_t avg2 = vrhadd_u8(avg1, KJIXABC_); - const uint64x1_t avg2_u64 = vreinterpret_u64_u8(avg2); - const uint32x2_t r3 = vreinterpret_u32_u8(avg2); - const uint32x2_t r2 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 8)); - const uint32x2_t r1 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 16)); - const uint32x2_t r0 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 24)); - vst1_lane_u32((uint32_t*)(dst + 0 * BPS), r0, 0); - vst1_lane_u32((uint32_t*)(dst + 1 * BPS), r1, 0); - vst1_lane_u32((uint32_t*)(dst + 2 * BPS), r2, 0); - vst1_lane_u32((uint32_t*)(dst + 3 * BPS), r3, 0); -} - -static void LD4(uint8_t* dst) { // Down-left - // Note using the same shift trick as VE4() is slower here. - const uint8x8_t ABCDEFGH = vld1_u8(dst - BPS + 0); - const uint8x8_t BCDEFGH0 = vld1_u8(dst - BPS + 1); - const uint8x8_t CDEFGH00 = vld1_u8(dst - BPS + 2); - const uint8x8_t CDEFGHH0 = vset_lane_u8(dst[-BPS + 7], CDEFGH00, 6); - const uint8x8_t avg1 = vhadd_u8(ABCDEFGH, CDEFGHH0); - const uint8x8_t avg2 = vrhadd_u8(avg1, BCDEFGH0); - const uint64x1_t avg2_u64 = vreinterpret_u64_u8(avg2); - const uint32x2_t r0 = vreinterpret_u32_u8(avg2); - const uint32x2_t r1 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 8)); - const uint32x2_t r2 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 16)); - const uint32x2_t r3 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 24)); - vst1_lane_u32((uint32_t*)(dst + 0 * BPS), r0, 0); - vst1_lane_u32((uint32_t*)(dst + 1 * BPS), r1, 0); - vst1_lane_u32((uint32_t*)(dst + 2 * BPS), r2, 0); - vst1_lane_u32((uint32_t*)(dst + 3 * BPS), r3, 0); -} - -//------------------------------------------------------------------------------ -// Chroma - -static void VE8uv(uint8_t* dst) { // vertical - const uint8x8_t top = vld1_u8(dst - BPS); - int j; - for (j = 0; j < 8; ++j) { - vst1_u8(dst + j * BPS, top); - } -} - -static void HE8uv(uint8_t* dst) { // horizontal - int j; - for (j = 0; j < 8; ++j) { - const uint8x8_t left = vld1_dup_u8(dst - 1); - vst1_u8(dst, left); - dst += BPS; - } -} - -static WEBP_INLINE void DC8(uint8_t* dst, int do_top, int do_left) { - uint16x8_t sum_top; - uint16x8_t sum_left; - uint8x8_t dc0; - - if (do_top) { - const uint8x8_t A = vld1_u8(dst - BPS); // top row - const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top - const uint16x4_t p1 = vpadd_u16(p0, p0); - const uint16x4_t p2 = vpadd_u16(p1, p1); - sum_top = vcombine_u16(p2, p2); - } - - if (do_left) { - const uint16x8_t L0 = vmovl_u8(vld1_u8(dst + 0 * BPS - 1)); - const uint16x8_t L1 = vmovl_u8(vld1_u8(dst + 1 * BPS - 1)); - const uint16x8_t L2 = vmovl_u8(vld1_u8(dst + 2 * BPS - 1)); - const uint16x8_t L3 = vmovl_u8(vld1_u8(dst + 3 * BPS - 1)); - const uint16x8_t L4 = vmovl_u8(vld1_u8(dst + 4 * BPS - 1)); - const uint16x8_t L5 = vmovl_u8(vld1_u8(dst + 5 * BPS - 1)); - const uint16x8_t L6 = vmovl_u8(vld1_u8(dst + 6 * BPS - 1)); - const uint16x8_t L7 = vmovl_u8(vld1_u8(dst + 7 * BPS - 1)); - const uint16x8_t s0 = vaddq_u16(L0, L1); - const uint16x8_t s1 = vaddq_u16(L2, L3); - const uint16x8_t s2 = vaddq_u16(L4, L5); - const uint16x8_t s3 = vaddq_u16(L6, L7); - const uint16x8_t s01 = vaddq_u16(s0, s1); - const uint16x8_t s23 = vaddq_u16(s2, s3); - sum_left = vaddq_u16(s01, s23); - } - - if (do_top && do_left) { - const uint16x8_t sum = vaddq_u16(sum_left, sum_top); - dc0 = vrshrn_n_u16(sum, 4); - } else if (do_top) { - dc0 = vrshrn_n_u16(sum_top, 3); - } else if (do_left) { - dc0 = vrshrn_n_u16(sum_left, 3); - } else { - dc0 = vdup_n_u8(0x80); - } - - { - const uint8x8_t dc = vdup_lane_u8(dc0, 0); - int i; - for (i = 0; i < 8; ++i) { - vst1_u32((uint32_t*)(dst + i * BPS), vreinterpret_u32_u8(dc)); - } - } -} - -static void DC8uv(uint8_t* dst) { DC8(dst, 1, 1); } -static void DC8uvNoTop(uint8_t* dst) { DC8(dst, 0, 1); } -static void DC8uvNoLeft(uint8_t* dst) { DC8(dst, 1, 0); } -static void DC8uvNoTopLeft(uint8_t* dst) { DC8(dst, 0, 0); } - -static void TM8uv(uint8_t* dst) { TrueMotion(dst, 8); } - -//------------------------------------------------------------------------------ -// 16x16 - -static void VE16(uint8_t* dst) { // vertical - const uint8x16_t top = vld1q_u8(dst - BPS); - int j; - for (j = 0; j < 16; ++j) { - vst1q_u8(dst + j * BPS, top); - } -} - -static void HE16(uint8_t* dst) { // horizontal - int j; - for (j = 0; j < 16; ++j) { - const uint8x16_t left = vld1q_dup_u8(dst - 1); - vst1q_u8(dst, left); - dst += BPS; - } -} - -static WEBP_INLINE void DC16(uint8_t* dst, int do_top, int do_left) { - uint16x8_t sum_top; - uint16x8_t sum_left; - uint8x8_t dc0; - - if (do_top) { - const uint8x16_t A = vld1q_u8(dst - BPS); // top row - const uint16x8_t p0 = vpaddlq_u8(A); // cascading summation of the top - const uint16x4_t p1 = vadd_u16(vget_low_u16(p0), vget_high_u16(p0)); - const uint16x4_t p2 = vpadd_u16(p1, p1); - const uint16x4_t p3 = vpadd_u16(p2, p2); - sum_top = vcombine_u16(p3, p3); - } - - if (do_left) { - int i; - sum_left = vdupq_n_u16(0); - for (i = 0; i < 16; i += 8) { - const uint16x8_t L0 = vmovl_u8(vld1_u8(dst + (i + 0) * BPS - 1)); - const uint16x8_t L1 = vmovl_u8(vld1_u8(dst + (i + 1) * BPS - 1)); - const uint16x8_t L2 = vmovl_u8(vld1_u8(dst + (i + 2) * BPS - 1)); - const uint16x8_t L3 = vmovl_u8(vld1_u8(dst + (i + 3) * BPS - 1)); - const uint16x8_t L4 = vmovl_u8(vld1_u8(dst + (i + 4) * BPS - 1)); - const uint16x8_t L5 = vmovl_u8(vld1_u8(dst + (i + 5) * BPS - 1)); - const uint16x8_t L6 = vmovl_u8(vld1_u8(dst + (i + 6) * BPS - 1)); - const uint16x8_t L7 = vmovl_u8(vld1_u8(dst + (i + 7) * BPS - 1)); - const uint16x8_t s0 = vaddq_u16(L0, L1); - const uint16x8_t s1 = vaddq_u16(L2, L3); - const uint16x8_t s2 = vaddq_u16(L4, L5); - const uint16x8_t s3 = vaddq_u16(L6, L7); - const uint16x8_t s01 = vaddq_u16(s0, s1); - const uint16x8_t s23 = vaddq_u16(s2, s3); - const uint16x8_t sum = vaddq_u16(s01, s23); - sum_left = vaddq_u16(sum_left, sum); - } - } - - if (do_top && do_left) { - const uint16x8_t sum = vaddq_u16(sum_left, sum_top); - dc0 = vrshrn_n_u16(sum, 5); - } else if (do_top) { - dc0 = vrshrn_n_u16(sum_top, 4); - } else if (do_left) { - dc0 = vrshrn_n_u16(sum_left, 4); - } else { - dc0 = vdup_n_u8(0x80); - } - - { - const uint8x16_t dc = vdupq_lane_u8(dc0, 0); - int i; - for (i = 0; i < 16; ++i) { - vst1q_u8(dst + i * BPS, dc); - } - } -} - -static void DC16TopLeft(uint8_t* dst) { DC16(dst, 1, 1); } -static void DC16NoTop(uint8_t* dst) { DC16(dst, 0, 1); } -static void DC16NoLeft(uint8_t* dst) { DC16(dst, 1, 0); } -static void DC16NoTopLeft(uint8_t* dst) { DC16(dst, 0, 0); } - -static void TM16(uint8_t* dst) { - const uint8x8_t TL = vld1_dup_u8(dst - BPS - 1); // top-left pixel 'A[-1]' - const uint8x16_t T = vld1q_u8(dst - BPS); // top row 'A[0..15]' - // A[c] - A[-1] - const int16x8_t d_lo = vreinterpretq_s16_u16(vsubl_u8(vget_low_u8(T), TL)); - const int16x8_t d_hi = vreinterpretq_s16_u16(vsubl_u8(vget_high_u8(T), TL)); - int y; - for (y = 0; y < 16; y += 4) { - // left edge - const int16x8_t L0 = ConvertU8ToS16(vld1_dup_u8(dst + 0 * BPS - 1)); - const int16x8_t L1 = ConvertU8ToS16(vld1_dup_u8(dst + 1 * BPS - 1)); - const int16x8_t L2 = ConvertU8ToS16(vld1_dup_u8(dst + 2 * BPS - 1)); - const int16x8_t L3 = ConvertU8ToS16(vld1_dup_u8(dst + 3 * BPS - 1)); - const int16x8_t r0_lo = vaddq_s16(L0, d_lo); // L[r] + A[c] - A[-1] - const int16x8_t r1_lo = vaddq_s16(L1, d_lo); - const int16x8_t r2_lo = vaddq_s16(L2, d_lo); - const int16x8_t r3_lo = vaddq_s16(L3, d_lo); - const int16x8_t r0_hi = vaddq_s16(L0, d_hi); - const int16x8_t r1_hi = vaddq_s16(L1, d_hi); - const int16x8_t r2_hi = vaddq_s16(L2, d_hi); - const int16x8_t r3_hi = vaddq_s16(L3, d_hi); - // Saturate and store the result. - const uint8x16_t row0 = vcombine_u8(vqmovun_s16(r0_lo), vqmovun_s16(r0_hi)); - const uint8x16_t row1 = vcombine_u8(vqmovun_s16(r1_lo), vqmovun_s16(r1_hi)); - const uint8x16_t row2 = vcombine_u8(vqmovun_s16(r2_lo), vqmovun_s16(r2_hi)); - const uint8x16_t row3 = vcombine_u8(vqmovun_s16(r3_lo), vqmovun_s16(r3_hi)); - vst1q_u8(dst + 0 * BPS, row0); - vst1q_u8(dst + 1 * BPS, row1); - vst1q_u8(dst + 2 * BPS, row2); - vst1q_u8(dst + 3 * BPS, row3); - dst += 4 * BPS; - } -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8DspInitNEON(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitNEON(void) { - VP8Transform = TransformTwo; - VP8TransformAC3 = TransformAC3; - VP8TransformDC = TransformDC; - VP8TransformWHT = TransformWHT; - - VP8VFilter16 = VFilter16; - VP8VFilter16i = VFilter16i; - VP8HFilter16 = HFilter16; -#if !defined(WORK_AROUND_GCC) - VP8HFilter16i = HFilter16i; -#endif - VP8VFilter8 = VFilter8; - VP8VFilter8i = VFilter8i; -#if !defined(WORK_AROUND_GCC) - VP8HFilter8 = HFilter8; - VP8HFilter8i = HFilter8i; -#endif - VP8SimpleVFilter16 = SimpleVFilter16; - VP8SimpleHFilter16 = SimpleHFilter16; - VP8SimpleVFilter16i = SimpleVFilter16i; - VP8SimpleHFilter16i = SimpleHFilter16i; - - VP8PredLuma4[0] = DC4; - VP8PredLuma4[1] = TM4; - VP8PredLuma4[2] = VE4; - VP8PredLuma4[4] = RD4; - VP8PredLuma4[6] = LD4; - - VP8PredLuma16[0] = DC16TopLeft; - VP8PredLuma16[1] = TM16; - VP8PredLuma16[2] = VE16; - VP8PredLuma16[3] = HE16; - VP8PredLuma16[4] = DC16NoTop; - VP8PredLuma16[5] = DC16NoLeft; - VP8PredLuma16[6] = DC16NoTopLeft; - - VP8PredChroma8[0] = DC8uv; - VP8PredChroma8[1] = TM8uv; - VP8PredChroma8[2] = VE8uv; - VP8PredChroma8[3] = HE8uv; - VP8PredChroma8[4] = DC8uvNoTop; - VP8PredChroma8[5] = DC8uvNoLeft; - VP8PredChroma8[6] = DC8uvNoTopLeft; -} - -#else // !WEBP_USE_NEON - -WEBP_DSP_INIT_STUB(VP8DspInitNEON) - -#endif // WEBP_USE_NEON diff --git a/Example/Pods/libwebp/src/dsp/dec_sse2.c b/Example/Pods/libwebp/src/dsp/dec_sse2.c deleted file mode 100644 index 935bf02e..00000000 --- a/Example/Pods/libwebp/src/dsp/dec_sse2.c +++ /dev/null @@ -1,1282 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// SSE2 version of some decoding functions (idct, loop filtering). -// -// Author: somnath@google.com (Somnath Banerjee) -// cduvivier@google.com (Christian Duvivier) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE2) - -// The 3-coeff sparse transform in SSE2 is not really faster than the plain-C -// one it seems => disable it by default. Uncomment the following to enable: -// #define USE_TRANSFORM_AC3 - -#include -#include "../dec/vp8i.h" - -//------------------------------------------------------------------------------ -// Transforms (Paragraph 14.4) - -static void Transform(const int16_t* in, uint8_t* dst, int do_two) { - // This implementation makes use of 16-bit fixed point versions of two - // multiply constants: - // K1 = sqrt(2) * cos (pi/8) ~= 85627 / 2^16 - // K2 = sqrt(2) * sin (pi/8) ~= 35468 / 2^16 - // - // To be able to use signed 16-bit integers, we use the following trick to - // have constants within range: - // - Associated constants are obtained by subtracting the 16-bit fixed point - // version of one: - // k = K - (1 << 16) => K = k + (1 << 16) - // K1 = 85267 => k1 = 20091 - // K2 = 35468 => k2 = -30068 - // - The multiplication of a variable by a constant become the sum of the - // variable and the multiplication of that variable by the associated - // constant: - // (x * K) >> 16 = (x * (k + (1 << 16))) >> 16 = ((x * k ) >> 16) + x - const __m128i k1 = _mm_set1_epi16(20091); - const __m128i k2 = _mm_set1_epi16(-30068); - __m128i T0, T1, T2, T3; - - // Load and concatenate the transform coefficients (we'll do two transforms - // in parallel). In the case of only one transform, the second half of the - // vectors will just contain random value we'll never use nor store. - __m128i in0, in1, in2, in3; - { - in0 = _mm_loadl_epi64((const __m128i*)&in[0]); - in1 = _mm_loadl_epi64((const __m128i*)&in[4]); - in2 = _mm_loadl_epi64((const __m128i*)&in[8]); - in3 = _mm_loadl_epi64((const __m128i*)&in[12]); - // a00 a10 a20 a30 x x x x - // a01 a11 a21 a31 x x x x - // a02 a12 a22 a32 x x x x - // a03 a13 a23 a33 x x x x - if (do_two) { - const __m128i inB0 = _mm_loadl_epi64((const __m128i*)&in[16]); - const __m128i inB1 = _mm_loadl_epi64((const __m128i*)&in[20]); - const __m128i inB2 = _mm_loadl_epi64((const __m128i*)&in[24]); - const __m128i inB3 = _mm_loadl_epi64((const __m128i*)&in[28]); - in0 = _mm_unpacklo_epi64(in0, inB0); - in1 = _mm_unpacklo_epi64(in1, inB1); - in2 = _mm_unpacklo_epi64(in2, inB2); - in3 = _mm_unpacklo_epi64(in3, inB3); - // a00 a10 a20 a30 b00 b10 b20 b30 - // a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 - // a03 a13 a23 a33 b03 b13 b23 b33 - } - } - - // Vertical pass and subsequent transpose. - { - // First pass, c and d calculations are longer because of the "trick" - // multiplications. - const __m128i a = _mm_add_epi16(in0, in2); - const __m128i b = _mm_sub_epi16(in0, in2); - // c = MUL(in1, K2) - MUL(in3, K1) = MUL(in1, k2) - MUL(in3, k1) + in1 - in3 - const __m128i c1 = _mm_mulhi_epi16(in1, k2); - const __m128i c2 = _mm_mulhi_epi16(in3, k1); - const __m128i c3 = _mm_sub_epi16(in1, in3); - const __m128i c4 = _mm_sub_epi16(c1, c2); - const __m128i c = _mm_add_epi16(c3, c4); - // d = MUL(in1, K1) + MUL(in3, K2) = MUL(in1, k1) + MUL(in3, k2) + in1 + in3 - const __m128i d1 = _mm_mulhi_epi16(in1, k1); - const __m128i d2 = _mm_mulhi_epi16(in3, k2); - const __m128i d3 = _mm_add_epi16(in1, in3); - const __m128i d4 = _mm_add_epi16(d1, d2); - const __m128i d = _mm_add_epi16(d3, d4); - - // Second pass. - const __m128i tmp0 = _mm_add_epi16(a, d); - const __m128i tmp1 = _mm_add_epi16(b, c); - const __m128i tmp2 = _mm_sub_epi16(b, c); - const __m128i tmp3 = _mm_sub_epi16(a, d); - - // Transpose the two 4x4. - // a00 a01 a02 a03 b00 b01 b02 b03 - // a10 a11 a12 a13 b10 b11 b12 b13 - // a20 a21 a22 a23 b20 b21 b22 b23 - // a30 a31 a32 a33 b30 b31 b32 b33 - const __m128i transpose0_0 = _mm_unpacklo_epi16(tmp0, tmp1); - const __m128i transpose0_1 = _mm_unpacklo_epi16(tmp2, tmp3); - const __m128i transpose0_2 = _mm_unpackhi_epi16(tmp0, tmp1); - const __m128i transpose0_3 = _mm_unpackhi_epi16(tmp2, tmp3); - // a00 a10 a01 a11 a02 a12 a03 a13 - // a20 a30 a21 a31 a22 a32 a23 a33 - // b00 b10 b01 b11 b02 b12 b03 b13 - // b20 b30 b21 b31 b22 b32 b23 b33 - const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3); - const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3); - // a00 a10 a20 a30 a01 a11 a21 a31 - // b00 b10 b20 b30 b01 b11 b21 b31 - // a02 a12 a22 a32 a03 a13 a23 a33 - // b02 b12 a22 b32 b03 b13 b23 b33 - T0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1); - T1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1); - T2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3); - T3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3); - // a00 a10 a20 a30 b00 b10 b20 b30 - // a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 - // a03 a13 a23 a33 b03 b13 b23 b33 - } - - // Horizontal pass and subsequent transpose. - { - // First pass, c and d calculations are longer because of the "trick" - // multiplications. - const __m128i four = _mm_set1_epi16(4); - const __m128i dc = _mm_add_epi16(T0, four); - const __m128i a = _mm_add_epi16(dc, T2); - const __m128i b = _mm_sub_epi16(dc, T2); - // c = MUL(T1, K2) - MUL(T3, K1) = MUL(T1, k2) - MUL(T3, k1) + T1 - T3 - const __m128i c1 = _mm_mulhi_epi16(T1, k2); - const __m128i c2 = _mm_mulhi_epi16(T3, k1); - const __m128i c3 = _mm_sub_epi16(T1, T3); - const __m128i c4 = _mm_sub_epi16(c1, c2); - const __m128i c = _mm_add_epi16(c3, c4); - // d = MUL(T1, K1) + MUL(T3, K2) = MUL(T1, k1) + MUL(T3, k2) + T1 + T3 - const __m128i d1 = _mm_mulhi_epi16(T1, k1); - const __m128i d2 = _mm_mulhi_epi16(T3, k2); - const __m128i d3 = _mm_add_epi16(T1, T3); - const __m128i d4 = _mm_add_epi16(d1, d2); - const __m128i d = _mm_add_epi16(d3, d4); - - // Second pass. - const __m128i tmp0 = _mm_add_epi16(a, d); - const __m128i tmp1 = _mm_add_epi16(b, c); - const __m128i tmp2 = _mm_sub_epi16(b, c); - const __m128i tmp3 = _mm_sub_epi16(a, d); - const __m128i shifted0 = _mm_srai_epi16(tmp0, 3); - const __m128i shifted1 = _mm_srai_epi16(tmp1, 3); - const __m128i shifted2 = _mm_srai_epi16(tmp2, 3); - const __m128i shifted3 = _mm_srai_epi16(tmp3, 3); - - // Transpose the two 4x4. - // a00 a01 a02 a03 b00 b01 b02 b03 - // a10 a11 a12 a13 b10 b11 b12 b13 - // a20 a21 a22 a23 b20 b21 b22 b23 - // a30 a31 a32 a33 b30 b31 b32 b33 - const __m128i transpose0_0 = _mm_unpacklo_epi16(shifted0, shifted1); - const __m128i transpose0_1 = _mm_unpacklo_epi16(shifted2, shifted3); - const __m128i transpose0_2 = _mm_unpackhi_epi16(shifted0, shifted1); - const __m128i transpose0_3 = _mm_unpackhi_epi16(shifted2, shifted3); - // a00 a10 a01 a11 a02 a12 a03 a13 - // a20 a30 a21 a31 a22 a32 a23 a33 - // b00 b10 b01 b11 b02 b12 b03 b13 - // b20 b30 b21 b31 b22 b32 b23 b33 - const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3); - const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3); - // a00 a10 a20 a30 a01 a11 a21 a31 - // b00 b10 b20 b30 b01 b11 b21 b31 - // a02 a12 a22 a32 a03 a13 a23 a33 - // b02 b12 a22 b32 b03 b13 b23 b33 - T0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1); - T1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1); - T2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3); - T3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3); - // a00 a10 a20 a30 b00 b10 b20 b30 - // a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 - // a03 a13 a23 a33 b03 b13 b23 b33 - } - - // Add inverse transform to 'dst' and store. - { - const __m128i zero = _mm_setzero_si128(); - // Load the reference(s). - __m128i dst0, dst1, dst2, dst3; - if (do_two) { - // Load eight bytes/pixels per line. - dst0 = _mm_loadl_epi64((__m128i*)(dst + 0 * BPS)); - dst1 = _mm_loadl_epi64((__m128i*)(dst + 1 * BPS)); - dst2 = _mm_loadl_epi64((__m128i*)(dst + 2 * BPS)); - dst3 = _mm_loadl_epi64((__m128i*)(dst + 3 * BPS)); - } else { - // Load four bytes/pixels per line. - dst0 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 0 * BPS)); - dst1 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 1 * BPS)); - dst2 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 2 * BPS)); - dst3 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 3 * BPS)); - } - // Convert to 16b. - dst0 = _mm_unpacklo_epi8(dst0, zero); - dst1 = _mm_unpacklo_epi8(dst1, zero); - dst2 = _mm_unpacklo_epi8(dst2, zero); - dst3 = _mm_unpacklo_epi8(dst3, zero); - // Add the inverse transform(s). - dst0 = _mm_add_epi16(dst0, T0); - dst1 = _mm_add_epi16(dst1, T1); - dst2 = _mm_add_epi16(dst2, T2); - dst3 = _mm_add_epi16(dst3, T3); - // Unsigned saturate to 8b. - dst0 = _mm_packus_epi16(dst0, dst0); - dst1 = _mm_packus_epi16(dst1, dst1); - dst2 = _mm_packus_epi16(dst2, dst2); - dst3 = _mm_packus_epi16(dst3, dst3); - // Store the results. - if (do_two) { - // Store eight bytes/pixels per line. - _mm_storel_epi64((__m128i*)(dst + 0 * BPS), dst0); - _mm_storel_epi64((__m128i*)(dst + 1 * BPS), dst1); - _mm_storel_epi64((__m128i*)(dst + 2 * BPS), dst2); - _mm_storel_epi64((__m128i*)(dst + 3 * BPS), dst3); - } else { - // Store four bytes/pixels per line. - WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(dst0)); - WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(dst1)); - WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(dst2)); - WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(dst3)); - } - } -} - -#if defined(USE_TRANSFORM_AC3) -#define MUL(a, b) (((a) * (b)) >> 16) -static void TransformAC3(const int16_t* in, uint8_t* dst) { - static const int kC1 = 20091 + (1 << 16); - static const int kC2 = 35468; - const __m128i A = _mm_set1_epi16(in[0] + 4); - const __m128i c4 = _mm_set1_epi16(MUL(in[4], kC2)); - const __m128i d4 = _mm_set1_epi16(MUL(in[4], kC1)); - const int c1 = MUL(in[1], kC2); - const int d1 = MUL(in[1], kC1); - const __m128i CD = _mm_set_epi16(0, 0, 0, 0, -d1, -c1, c1, d1); - const __m128i B = _mm_adds_epi16(A, CD); - const __m128i m0 = _mm_adds_epi16(B, d4); - const __m128i m1 = _mm_adds_epi16(B, c4); - const __m128i m2 = _mm_subs_epi16(B, c4); - const __m128i m3 = _mm_subs_epi16(B, d4); - const __m128i zero = _mm_setzero_si128(); - // Load the source pixels. - __m128i dst0 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 0 * BPS)); - __m128i dst1 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 1 * BPS)); - __m128i dst2 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 2 * BPS)); - __m128i dst3 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 3 * BPS)); - // Convert to 16b. - dst0 = _mm_unpacklo_epi8(dst0, zero); - dst1 = _mm_unpacklo_epi8(dst1, zero); - dst2 = _mm_unpacklo_epi8(dst2, zero); - dst3 = _mm_unpacklo_epi8(dst3, zero); - // Add the inverse transform. - dst0 = _mm_adds_epi16(dst0, _mm_srai_epi16(m0, 3)); - dst1 = _mm_adds_epi16(dst1, _mm_srai_epi16(m1, 3)); - dst2 = _mm_adds_epi16(dst2, _mm_srai_epi16(m2, 3)); - dst3 = _mm_adds_epi16(dst3, _mm_srai_epi16(m3, 3)); - // Unsigned saturate to 8b. - dst0 = _mm_packus_epi16(dst0, dst0); - dst1 = _mm_packus_epi16(dst1, dst1); - dst2 = _mm_packus_epi16(dst2, dst2); - dst3 = _mm_packus_epi16(dst3, dst3); - // Store the results. - WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(dst0)); - WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(dst1)); - WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(dst2)); - WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(dst3)); -} -#undef MUL -#endif // USE_TRANSFORM_AC3 - -//------------------------------------------------------------------------------ -// Loop Filter (Paragraph 15) - -// Compute abs(p - q) = subs(p - q) OR subs(q - p) -#define MM_ABS(p, q) _mm_or_si128( \ - _mm_subs_epu8((q), (p)), \ - _mm_subs_epu8((p), (q))) - -// Shift each byte of "x" by 3 bits while preserving by the sign bit. -static WEBP_INLINE void SignedShift8b(__m128i* const x) { - const __m128i zero = _mm_setzero_si128(); - const __m128i lo_0 = _mm_unpacklo_epi8(zero, *x); - const __m128i hi_0 = _mm_unpackhi_epi8(zero, *x); - const __m128i lo_1 = _mm_srai_epi16(lo_0, 3 + 8); - const __m128i hi_1 = _mm_srai_epi16(hi_0, 3 + 8); - *x = _mm_packs_epi16(lo_1, hi_1); -} - -#define FLIP_SIGN_BIT2(a, b) { \ - a = _mm_xor_si128(a, sign_bit); \ - b = _mm_xor_si128(b, sign_bit); \ -} - -#define FLIP_SIGN_BIT4(a, b, c, d) { \ - FLIP_SIGN_BIT2(a, b); \ - FLIP_SIGN_BIT2(c, d); \ -} - -// input/output is uint8_t -static WEBP_INLINE void GetNotHEV(const __m128i* const p1, - const __m128i* const p0, - const __m128i* const q0, - const __m128i* const q1, - int hev_thresh, __m128i* const not_hev) { - const __m128i zero = _mm_setzero_si128(); - const __m128i t_1 = MM_ABS(*p1, *p0); - const __m128i t_2 = MM_ABS(*q1, *q0); - - const __m128i h = _mm_set1_epi8(hev_thresh); - const __m128i t_max = _mm_max_epu8(t_1, t_2); - - const __m128i t_max_h = _mm_subs_epu8(t_max, h); - *not_hev = _mm_cmpeq_epi8(t_max_h, zero); // not_hev <= t1 && not_hev <= t2 -} - -// input pixels are int8_t -static WEBP_INLINE void GetBaseDelta(const __m128i* const p1, - const __m128i* const p0, - const __m128i* const q0, - const __m128i* const q1, - __m128i* const delta) { - // beware of addition order, for saturation! - const __m128i p1_q1 = _mm_subs_epi8(*p1, *q1); // p1 - q1 - const __m128i q0_p0 = _mm_subs_epi8(*q0, *p0); // q0 - p0 - const __m128i s1 = _mm_adds_epi8(p1_q1, q0_p0); // p1 - q1 + 1 * (q0 - p0) - const __m128i s2 = _mm_adds_epi8(q0_p0, s1); // p1 - q1 + 2 * (q0 - p0) - const __m128i s3 = _mm_adds_epi8(q0_p0, s2); // p1 - q1 + 3 * (q0 - p0) - *delta = s3; -} - -// input and output are int8_t -static WEBP_INLINE void DoSimpleFilter(__m128i* const p0, __m128i* const q0, - const __m128i* const fl) { - const __m128i k3 = _mm_set1_epi8(3); - const __m128i k4 = _mm_set1_epi8(4); - __m128i v3 = _mm_adds_epi8(*fl, k3); - __m128i v4 = _mm_adds_epi8(*fl, k4); - - SignedShift8b(&v4); // v4 >> 3 - SignedShift8b(&v3); // v3 >> 3 - *q0 = _mm_subs_epi8(*q0, v4); // q0 -= v4 - *p0 = _mm_adds_epi8(*p0, v3); // p0 += v3 -} - -// Updates values of 2 pixels at MB edge during complex filtering. -// Update operations: -// q = q - delta and p = p + delta; where delta = [(a_hi >> 7), (a_lo >> 7)] -// Pixels 'pi' and 'qi' are int8_t on input, uint8_t on output (sign flip). -static WEBP_INLINE void Update2Pixels(__m128i* const pi, __m128i* const qi, - const __m128i* const a0_lo, - const __m128i* const a0_hi) { - const __m128i a1_lo = _mm_srai_epi16(*a0_lo, 7); - const __m128i a1_hi = _mm_srai_epi16(*a0_hi, 7); - const __m128i delta = _mm_packs_epi16(a1_lo, a1_hi); - const __m128i sign_bit = _mm_set1_epi8(0x80); - *pi = _mm_adds_epi8(*pi, delta); - *qi = _mm_subs_epi8(*qi, delta); - FLIP_SIGN_BIT2(*pi, *qi); -} - -// input pixels are uint8_t -static WEBP_INLINE void NeedsFilter(const __m128i* const p1, - const __m128i* const p0, - const __m128i* const q0, - const __m128i* const q1, - int thresh, __m128i* const mask) { - const __m128i m_thresh = _mm_set1_epi8(thresh); - const __m128i t1 = MM_ABS(*p1, *q1); // abs(p1 - q1) - const __m128i kFE = _mm_set1_epi8(0xFE); - const __m128i t2 = _mm_and_si128(t1, kFE); // set lsb of each byte to zero - const __m128i t3 = _mm_srli_epi16(t2, 1); // abs(p1 - q1) / 2 - - const __m128i t4 = MM_ABS(*p0, *q0); // abs(p0 - q0) - const __m128i t5 = _mm_adds_epu8(t4, t4); // abs(p0 - q0) * 2 - const __m128i t6 = _mm_adds_epu8(t5, t3); // abs(p0-q0)*2 + abs(p1-q1)/2 - - const __m128i t7 = _mm_subs_epu8(t6, m_thresh); // mask <= m_thresh - *mask = _mm_cmpeq_epi8(t7, _mm_setzero_si128()); -} - -//------------------------------------------------------------------------------ -// Edge filtering functions - -// Applies filter on 2 pixels (p0 and q0) -static WEBP_INLINE void DoFilter2(__m128i* const p1, __m128i* const p0, - __m128i* const q0, __m128i* const q1, - int thresh) { - __m128i a, mask; - const __m128i sign_bit = _mm_set1_epi8(0x80); - // convert p1/q1 to int8_t (for GetBaseDelta) - const __m128i p1s = _mm_xor_si128(*p1, sign_bit); - const __m128i q1s = _mm_xor_si128(*q1, sign_bit); - - NeedsFilter(p1, p0, q0, q1, thresh, &mask); - - FLIP_SIGN_BIT2(*p0, *q0); - GetBaseDelta(&p1s, p0, q0, &q1s, &a); - a = _mm_and_si128(a, mask); // mask filter values we don't care about - DoSimpleFilter(p0, q0, &a); - FLIP_SIGN_BIT2(*p0, *q0); -} - -// Applies filter on 4 pixels (p1, p0, q0 and q1) -static WEBP_INLINE void DoFilter4(__m128i* const p1, __m128i* const p0, - __m128i* const q0, __m128i* const q1, - const __m128i* const mask, int hev_thresh) { - const __m128i zero = _mm_setzero_si128(); - const __m128i sign_bit = _mm_set1_epi8(0x80); - const __m128i k64 = _mm_set1_epi8(64); - const __m128i k3 = _mm_set1_epi8(3); - const __m128i k4 = _mm_set1_epi8(4); - __m128i not_hev; - __m128i t1, t2, t3; - - // compute hev mask - GetNotHEV(p1, p0, q0, q1, hev_thresh, ¬_hev); - - // convert to signed values - FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1); - - t1 = _mm_subs_epi8(*p1, *q1); // p1 - q1 - t1 = _mm_andnot_si128(not_hev, t1); // hev(p1 - q1) - t2 = _mm_subs_epi8(*q0, *p0); // q0 - p0 - t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 1 * (q0 - p0) - t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 2 * (q0 - p0) - t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 3 * (q0 - p0) - t1 = _mm_and_si128(t1, *mask); // mask filter values we don't care about - - t2 = _mm_adds_epi8(t1, k3); // 3 * (q0 - p0) + hev(p1 - q1) + 3 - t3 = _mm_adds_epi8(t1, k4); // 3 * (q0 - p0) + hev(p1 - q1) + 4 - SignedShift8b(&t2); // (3 * (q0 - p0) + hev(p1 - q1) + 3) >> 3 - SignedShift8b(&t3); // (3 * (q0 - p0) + hev(p1 - q1) + 4) >> 3 - *p0 = _mm_adds_epi8(*p0, t2); // p0 += t2 - *q0 = _mm_subs_epi8(*q0, t3); // q0 -= t3 - FLIP_SIGN_BIT2(*p0, *q0); - - // this is equivalent to signed (a + 1) >> 1 calculation - t2 = _mm_add_epi8(t3, sign_bit); - t3 = _mm_avg_epu8(t2, zero); - t3 = _mm_sub_epi8(t3, k64); - - t3 = _mm_and_si128(not_hev, t3); // if !hev - *q1 = _mm_subs_epi8(*q1, t3); // q1 -= t3 - *p1 = _mm_adds_epi8(*p1, t3); // p1 += t3 - FLIP_SIGN_BIT2(*p1, *q1); -} - -// Applies filter on 6 pixels (p2, p1, p0, q0, q1 and q2) -static WEBP_INLINE void DoFilter6(__m128i* const p2, __m128i* const p1, - __m128i* const p0, __m128i* const q0, - __m128i* const q1, __m128i* const q2, - const __m128i* const mask, int hev_thresh) { - const __m128i zero = _mm_setzero_si128(); - const __m128i sign_bit = _mm_set1_epi8(0x80); - __m128i a, not_hev; - - // compute hev mask - GetNotHEV(p1, p0, q0, q1, hev_thresh, ¬_hev); - - FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1); - FLIP_SIGN_BIT2(*p2, *q2); - GetBaseDelta(p1, p0, q0, q1, &a); - - { // do simple filter on pixels with hev - const __m128i m = _mm_andnot_si128(not_hev, *mask); - const __m128i f = _mm_and_si128(a, m); - DoSimpleFilter(p0, q0, &f); - } - - { // do strong filter on pixels with not hev - const __m128i k9 = _mm_set1_epi16(0x0900); - const __m128i k63 = _mm_set1_epi16(63); - - const __m128i m = _mm_and_si128(not_hev, *mask); - const __m128i f = _mm_and_si128(a, m); - - const __m128i f_lo = _mm_unpacklo_epi8(zero, f); - const __m128i f_hi = _mm_unpackhi_epi8(zero, f); - - const __m128i f9_lo = _mm_mulhi_epi16(f_lo, k9); // Filter (lo) * 9 - const __m128i f9_hi = _mm_mulhi_epi16(f_hi, k9); // Filter (hi) * 9 - - const __m128i a2_lo = _mm_add_epi16(f9_lo, k63); // Filter * 9 + 63 - const __m128i a2_hi = _mm_add_epi16(f9_hi, k63); // Filter * 9 + 63 - - const __m128i a1_lo = _mm_add_epi16(a2_lo, f9_lo); // Filter * 18 + 63 - const __m128i a1_hi = _mm_add_epi16(a2_hi, f9_hi); // Filter * 18 + 63 - - const __m128i a0_lo = _mm_add_epi16(a1_lo, f9_lo); // Filter * 27 + 63 - const __m128i a0_hi = _mm_add_epi16(a1_hi, f9_hi); // Filter * 27 + 63 - - Update2Pixels(p2, q2, &a2_lo, &a2_hi); - Update2Pixels(p1, q1, &a1_lo, &a1_hi); - Update2Pixels(p0, q0, &a0_lo, &a0_hi); - } -} - -// reads 8 rows across a vertical edge. -static WEBP_INLINE void Load8x4(const uint8_t* const b, int stride, - __m128i* const p, __m128i* const q) { - // A0 = 63 62 61 60 23 22 21 20 43 42 41 40 03 02 01 00 - // A1 = 73 72 71 70 33 32 31 30 53 52 51 50 13 12 11 10 - const __m128i A0 = _mm_set_epi32( - WebPMemToUint32(&b[6 * stride]), WebPMemToUint32(&b[2 * stride]), - WebPMemToUint32(&b[4 * stride]), WebPMemToUint32(&b[0 * stride])); - const __m128i A1 = _mm_set_epi32( - WebPMemToUint32(&b[7 * stride]), WebPMemToUint32(&b[3 * stride]), - WebPMemToUint32(&b[5 * stride]), WebPMemToUint32(&b[1 * stride])); - - // B0 = 53 43 52 42 51 41 50 40 13 03 12 02 11 01 10 00 - // B1 = 73 63 72 62 71 61 70 60 33 23 32 22 31 21 30 20 - const __m128i B0 = _mm_unpacklo_epi8(A0, A1); - const __m128i B1 = _mm_unpackhi_epi8(A0, A1); - - // C0 = 33 23 13 03 32 22 12 02 31 21 11 01 30 20 10 00 - // C1 = 73 63 53 43 72 62 52 42 71 61 51 41 70 60 50 40 - const __m128i C0 = _mm_unpacklo_epi16(B0, B1); - const __m128i C1 = _mm_unpackhi_epi16(B0, B1); - - // *p = 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00 - // *q = 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02 - *p = _mm_unpacklo_epi32(C0, C1); - *q = _mm_unpackhi_epi32(C0, C1); -} - -static WEBP_INLINE void Load16x4(const uint8_t* const r0, - const uint8_t* const r8, - int stride, - __m128i* const p1, __m128i* const p0, - __m128i* const q0, __m128i* const q1) { - // Assume the pixels around the edge (|) are numbered as follows - // 00 01 | 02 03 - // 10 11 | 12 13 - // ... | ... - // e0 e1 | e2 e3 - // f0 f1 | f2 f3 - // - // r0 is pointing to the 0th row (00) - // r8 is pointing to the 8th row (80) - - // Load - // p1 = 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00 - // q0 = 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02 - // p0 = f1 e1 d1 c1 b1 a1 91 81 f0 e0 d0 c0 b0 a0 90 80 - // q1 = f3 e3 d3 c3 b3 a3 93 83 f2 e2 d2 c2 b2 a2 92 82 - Load8x4(r0, stride, p1, q0); - Load8x4(r8, stride, p0, q1); - - { - // p1 = f0 e0 d0 c0 b0 a0 90 80 70 60 50 40 30 20 10 00 - // p0 = f1 e1 d1 c1 b1 a1 91 81 71 61 51 41 31 21 11 01 - // q0 = f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02 - // q1 = f3 e3 d3 c3 b3 a3 93 83 73 63 53 43 33 23 13 03 - const __m128i t1 = *p1; - const __m128i t2 = *q0; - *p1 = _mm_unpacklo_epi64(t1, *p0); - *p0 = _mm_unpackhi_epi64(t1, *p0); - *q0 = _mm_unpacklo_epi64(t2, *q1); - *q1 = _mm_unpackhi_epi64(t2, *q1); - } -} - -static WEBP_INLINE void Store4x4(__m128i* const x, uint8_t* dst, int stride) { - int i; - for (i = 0; i < 4; ++i, dst += stride) { - WebPUint32ToMem(dst, _mm_cvtsi128_si32(*x)); - *x = _mm_srli_si128(*x, 4); - } -} - -// Transpose back and store -static WEBP_INLINE void Store16x4(const __m128i* const p1, - const __m128i* const p0, - const __m128i* const q0, - const __m128i* const q1, - uint8_t* r0, uint8_t* r8, - int stride) { - __m128i t1, p1_s, p0_s, q0_s, q1_s; - - // p0 = 71 70 61 60 51 50 41 40 31 30 21 20 11 10 01 00 - // p1 = f1 f0 e1 e0 d1 d0 c1 c0 b1 b0 a1 a0 91 90 81 80 - t1 = *p0; - p0_s = _mm_unpacklo_epi8(*p1, t1); - p1_s = _mm_unpackhi_epi8(*p1, t1); - - // q0 = 73 72 63 62 53 52 43 42 33 32 23 22 13 12 03 02 - // q1 = f3 f2 e3 e2 d3 d2 c3 c2 b3 b2 a3 a2 93 92 83 82 - t1 = *q0; - q0_s = _mm_unpacklo_epi8(t1, *q1); - q1_s = _mm_unpackhi_epi8(t1, *q1); - - // p0 = 33 32 31 30 23 22 21 20 13 12 11 10 03 02 01 00 - // q0 = 73 72 71 70 63 62 61 60 53 52 51 50 43 42 41 40 - t1 = p0_s; - p0_s = _mm_unpacklo_epi16(t1, q0_s); - q0_s = _mm_unpackhi_epi16(t1, q0_s); - - // p1 = b3 b2 b1 b0 a3 a2 a1 a0 93 92 91 90 83 82 81 80 - // q1 = f3 f2 f1 f0 e3 e2 e1 e0 d3 d2 d1 d0 c3 c2 c1 c0 - t1 = p1_s; - p1_s = _mm_unpacklo_epi16(t1, q1_s); - q1_s = _mm_unpackhi_epi16(t1, q1_s); - - Store4x4(&p0_s, r0, stride); - r0 += 4 * stride; - Store4x4(&q0_s, r0, stride); - - Store4x4(&p1_s, r8, stride); - r8 += 4 * stride; - Store4x4(&q1_s, r8, stride); -} - -//------------------------------------------------------------------------------ -// Simple In-loop filtering (Paragraph 15.2) - -static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { - // Load - __m128i p1 = _mm_loadu_si128((__m128i*)&p[-2 * stride]); - __m128i p0 = _mm_loadu_si128((__m128i*)&p[-stride]); - __m128i q0 = _mm_loadu_si128((__m128i*)&p[0]); - __m128i q1 = _mm_loadu_si128((__m128i*)&p[stride]); - - DoFilter2(&p1, &p0, &q0, &q1, thresh); - - // Store - _mm_storeu_si128((__m128i*)&p[-stride], p0); - _mm_storeu_si128((__m128i*)&p[0], q0); -} - -static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { - __m128i p1, p0, q0, q1; - - p -= 2; // beginning of p1 - - Load16x4(p, p + 8 * stride, stride, &p1, &p0, &q0, &q1); - DoFilter2(&p1, &p0, &q0, &q1, thresh); - Store16x4(&p1, &p0, &q0, &q1, p, p + 8 * stride, stride); -} - -static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4 * stride; - SimpleVFilter16(p, stride, thresh); - } -} - -static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) { - int k; - for (k = 3; k > 0; --k) { - p += 4; - SimpleHFilter16(p, stride, thresh); - } -} - -//------------------------------------------------------------------------------ -// Complex In-loop filtering (Paragraph 15.3) - -#define MAX_DIFF1(p3, p2, p1, p0, m) do { \ - m = MM_ABS(p1, p0); \ - m = _mm_max_epu8(m, MM_ABS(p3, p2)); \ - m = _mm_max_epu8(m, MM_ABS(p2, p1)); \ -} while (0) - -#define MAX_DIFF2(p3, p2, p1, p0, m) do { \ - m = _mm_max_epu8(m, MM_ABS(p1, p0)); \ - m = _mm_max_epu8(m, MM_ABS(p3, p2)); \ - m = _mm_max_epu8(m, MM_ABS(p2, p1)); \ -} while (0) - -#define LOAD_H_EDGES4(p, stride, e1, e2, e3, e4) { \ - e1 = _mm_loadu_si128((__m128i*)&(p)[0 * stride]); \ - e2 = _mm_loadu_si128((__m128i*)&(p)[1 * stride]); \ - e3 = _mm_loadu_si128((__m128i*)&(p)[2 * stride]); \ - e4 = _mm_loadu_si128((__m128i*)&(p)[3 * stride]); \ -} - -#define LOADUV_H_EDGE(p, u, v, stride) do { \ - const __m128i U = _mm_loadl_epi64((__m128i*)&(u)[(stride)]); \ - const __m128i V = _mm_loadl_epi64((__m128i*)&(v)[(stride)]); \ - p = _mm_unpacklo_epi64(U, V); \ -} while (0) - -#define LOADUV_H_EDGES4(u, v, stride, e1, e2, e3, e4) { \ - LOADUV_H_EDGE(e1, u, v, 0 * stride); \ - LOADUV_H_EDGE(e2, u, v, 1 * stride); \ - LOADUV_H_EDGE(e3, u, v, 2 * stride); \ - LOADUV_H_EDGE(e4, u, v, 3 * stride); \ -} - -#define STOREUV(p, u, v, stride) { \ - _mm_storel_epi64((__m128i*)&u[(stride)], p); \ - p = _mm_srli_si128(p, 8); \ - _mm_storel_epi64((__m128i*)&v[(stride)], p); \ -} - -static WEBP_INLINE void ComplexMask(const __m128i* const p1, - const __m128i* const p0, - const __m128i* const q0, - const __m128i* const q1, - int thresh, int ithresh, - __m128i* const mask) { - const __m128i it = _mm_set1_epi8(ithresh); - const __m128i diff = _mm_subs_epu8(*mask, it); - const __m128i thresh_mask = _mm_cmpeq_epi8(diff, _mm_setzero_si128()); - __m128i filter_mask; - NeedsFilter(p1, p0, q0, q1, thresh, &filter_mask); - *mask = _mm_and_si128(thresh_mask, filter_mask); -} - -// on macroblock edges -static void VFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - __m128i t1; - __m128i mask; - __m128i p2, p1, p0, q0, q1, q2; - - // Load p3, p2, p1, p0 - LOAD_H_EDGES4(p - 4 * stride, stride, t1, p2, p1, p0); - MAX_DIFF1(t1, p2, p1, p0, mask); - - // Load q0, q1, q2, q3 - LOAD_H_EDGES4(p, stride, q0, q1, q2, t1); - MAX_DIFF2(t1, q2, q1, q0, mask); - - ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); - DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); - - // Store - _mm_storeu_si128((__m128i*)&p[-3 * stride], p2); - _mm_storeu_si128((__m128i*)&p[-2 * stride], p1); - _mm_storeu_si128((__m128i*)&p[-1 * stride], p0); - _mm_storeu_si128((__m128i*)&p[+0 * stride], q0); - _mm_storeu_si128((__m128i*)&p[+1 * stride], q1); - _mm_storeu_si128((__m128i*)&p[+2 * stride], q2); -} - -static void HFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - __m128i mask; - __m128i p3, p2, p1, p0, q0, q1, q2, q3; - - uint8_t* const b = p - 4; - Load16x4(b, b + 8 * stride, stride, &p3, &p2, &p1, &p0); // p3, p2, p1, p0 - MAX_DIFF1(p3, p2, p1, p0, mask); - - Load16x4(p, p + 8 * stride, stride, &q0, &q1, &q2, &q3); // q0, q1, q2, q3 - MAX_DIFF2(q3, q2, q1, q0, mask); - - ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); - DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); - - Store16x4(&p3, &p2, &p1, &p0, b, b + 8 * stride, stride); - Store16x4(&q0, &q1, &q2, &q3, p, p + 8 * stride, stride); -} - -// on three inner edges -static void VFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - int k; - __m128i p3, p2, p1, p0; // loop invariants - - LOAD_H_EDGES4(p, stride, p3, p2, p1, p0); // prologue - - for (k = 3; k > 0; --k) { - __m128i mask, tmp1, tmp2; - uint8_t* const b = p + 2 * stride; // beginning of p1 - p += 4 * stride; - - MAX_DIFF1(p3, p2, p1, p0, mask); // compute partial mask - LOAD_H_EDGES4(p, stride, p3, p2, tmp1, tmp2); - MAX_DIFF2(p3, p2, tmp1, tmp2, mask); - - // p3 and p2 are not just temporary variables here: they will be - // re-used for next span. And q2/q3 will become p1/p0 accordingly. - ComplexMask(&p1, &p0, &p3, &p2, thresh, ithresh, &mask); - DoFilter4(&p1, &p0, &p3, &p2, &mask, hev_thresh); - - // Store - _mm_storeu_si128((__m128i*)&b[0 * stride], p1); - _mm_storeu_si128((__m128i*)&b[1 * stride], p0); - _mm_storeu_si128((__m128i*)&b[2 * stride], p3); - _mm_storeu_si128((__m128i*)&b[3 * stride], p2); - - // rotate samples - p1 = tmp1; - p0 = tmp2; - } -} - -static void HFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - int k; - __m128i p3, p2, p1, p0; // loop invariants - - Load16x4(p, p + 8 * stride, stride, &p3, &p2, &p1, &p0); // prologue - - for (k = 3; k > 0; --k) { - __m128i mask, tmp1, tmp2; - uint8_t* const b = p + 2; // beginning of p1 - - p += 4; // beginning of q0 (and next span) - - MAX_DIFF1(p3, p2, p1, p0, mask); // compute partial mask - Load16x4(p, p + 8 * stride, stride, &p3, &p2, &tmp1, &tmp2); - MAX_DIFF2(p3, p2, tmp1, tmp2, mask); - - ComplexMask(&p1, &p0, &p3, &p2, thresh, ithresh, &mask); - DoFilter4(&p1, &p0, &p3, &p2, &mask, hev_thresh); - - Store16x4(&p1, &p0, &p3, &p2, b, b + 8 * stride, stride); - - // rotate samples - p1 = tmp1; - p0 = tmp2; - } -} - -// 8-pixels wide variant, for chroma filtering -static void VFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - __m128i mask; - __m128i t1, p2, p1, p0, q0, q1, q2; - - // Load p3, p2, p1, p0 - LOADUV_H_EDGES4(u - 4 * stride, v - 4 * stride, stride, t1, p2, p1, p0); - MAX_DIFF1(t1, p2, p1, p0, mask); - - // Load q0, q1, q2, q3 - LOADUV_H_EDGES4(u, v, stride, q0, q1, q2, t1); - MAX_DIFF2(t1, q2, q1, q0, mask); - - ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); - DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); - - // Store - STOREUV(p2, u, v, -3 * stride); - STOREUV(p1, u, v, -2 * stride); - STOREUV(p0, u, v, -1 * stride); - STOREUV(q0, u, v, 0 * stride); - STOREUV(q1, u, v, 1 * stride); - STOREUV(q2, u, v, 2 * stride); -} - -static void HFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - __m128i mask; - __m128i p3, p2, p1, p0, q0, q1, q2, q3; - - uint8_t* const tu = u - 4; - uint8_t* const tv = v - 4; - Load16x4(tu, tv, stride, &p3, &p2, &p1, &p0); // p3, p2, p1, p0 - MAX_DIFF1(p3, p2, p1, p0, mask); - - Load16x4(u, v, stride, &q0, &q1, &q2, &q3); // q0, q1, q2, q3 - MAX_DIFF2(q3, q2, q1, q0, mask); - - ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); - DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); - - Store16x4(&p3, &p2, &p1, &p0, tu, tv, stride); - Store16x4(&q0, &q1, &q2, &q3, u, v, stride); -} - -static void VFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - __m128i mask; - __m128i t1, t2, p1, p0, q0, q1; - - // Load p3, p2, p1, p0 - LOADUV_H_EDGES4(u, v, stride, t2, t1, p1, p0); - MAX_DIFF1(t2, t1, p1, p0, mask); - - u += 4 * stride; - v += 4 * stride; - - // Load q0, q1, q2, q3 - LOADUV_H_EDGES4(u, v, stride, q0, q1, t1, t2); - MAX_DIFF2(t2, t1, q1, q0, mask); - - ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); - DoFilter4(&p1, &p0, &q0, &q1, &mask, hev_thresh); - - // Store - STOREUV(p1, u, v, -2 * stride); - STOREUV(p0, u, v, -1 * stride); - STOREUV(q0, u, v, 0 * stride); - STOREUV(q1, u, v, 1 * stride); -} - -static void HFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - __m128i mask; - __m128i t1, t2, p1, p0, q0, q1; - Load16x4(u, v, stride, &t2, &t1, &p1, &p0); // p3, p2, p1, p0 - MAX_DIFF1(t2, t1, p1, p0, mask); - - u += 4; // beginning of q0 - v += 4; - Load16x4(u, v, stride, &q0, &q1, &t1, &t2); // q0, q1, q2, q3 - MAX_DIFF2(t2, t1, q1, q0, mask); - - ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); - DoFilter4(&p1, &p0, &q0, &q1, &mask, hev_thresh); - - u -= 2; // beginning of p1 - v -= 2; - Store16x4(&p1, &p0, &q0, &q1, u, v, stride); -} - -//------------------------------------------------------------------------------ -// 4x4 predictions - -#define DST(x, y) dst[(x) + (y) * BPS] -#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2) - -// We use the following 8b-arithmetic tricks: -// (a + 2 * b + c + 2) >> 2 = (AC + b + 1) >> 1 -// where: AC = (a + c) >> 1 = [(a + c + 1) >> 1] - [(a^c) & 1] -// and: -// (a + 2 * b + c + 2) >> 2 = (AB + BC + 1) >> 1 - (ab|bc)&lsb -// where: AC = (a + b + 1) >> 1, BC = (b + c + 1) >> 1 -// and ab = a ^ b, bc = b ^ c, lsb = (AC^BC)&1 - -static void VE4(uint8_t* dst) { // vertical - const __m128i one = _mm_set1_epi8(1); - const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS - 1)); - const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1); - const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2); - const __m128i a = _mm_avg_epu8(ABCDEFGH, CDEFGH00); - const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGH00), one); - const __m128i b = _mm_subs_epu8(a, lsb); - const __m128i avg = _mm_avg_epu8(b, BCDEFGH0); - const uint32_t vals = _mm_cvtsi128_si32(avg); - int i; - for (i = 0; i < 4; ++i) { - WebPUint32ToMem(dst + i * BPS, vals); - } -} - -static void LD4(uint8_t* dst) { // Down-Left - const __m128i one = _mm_set1_epi8(1); - const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS)); - const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1); - const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2); - const __m128i CDEFGHH0 = _mm_insert_epi16(CDEFGH00, dst[-BPS + 7], 3); - const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, CDEFGHH0); - const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one); - const __m128i avg2 = _mm_subs_epu8(avg1, lsb); - const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0); - WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcdefg )); - WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); - WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); - WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); -} - -static void VR4(uint8_t* dst) { // Vertical-Right - const __m128i one = _mm_set1_epi8(1); - const int I = dst[-1 + 0 * BPS]; - const int J = dst[-1 + 1 * BPS]; - const int K = dst[-1 + 2 * BPS]; - const int X = dst[-1 - BPS]; - const __m128i XABCD = _mm_loadl_epi64((__m128i*)(dst - BPS - 1)); - const __m128i ABCD0 = _mm_srli_si128(XABCD, 1); - const __m128i abcd = _mm_avg_epu8(XABCD, ABCD0); - const __m128i _XABCD = _mm_slli_si128(XABCD, 1); - const __m128i IXABCD = _mm_insert_epi16(_XABCD, I | (X << 8), 0); - const __m128i avg1 = _mm_avg_epu8(IXABCD, ABCD0); - const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one); - const __m128i avg2 = _mm_subs_epu8(avg1, lsb); - const __m128i efgh = _mm_avg_epu8(avg2, XABCD); - WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcd )); - WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( efgh )); - WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1))); - WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1))); - - // these two are hard to implement in SSE2, so we keep the C-version: - DST(0, 2) = AVG3(J, I, X); - DST(0, 3) = AVG3(K, J, I); -} - -static void VL4(uint8_t* dst) { // Vertical-Left - const __m128i one = _mm_set1_epi8(1); - const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS)); - const __m128i BCDEFGH_ = _mm_srli_si128(ABCDEFGH, 1); - const __m128i CDEFGH__ = _mm_srli_si128(ABCDEFGH, 2); - const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, BCDEFGH_); - const __m128i avg2 = _mm_avg_epu8(CDEFGH__, BCDEFGH_); - const __m128i avg3 = _mm_avg_epu8(avg1, avg2); - const __m128i lsb1 = _mm_and_si128(_mm_xor_si128(avg1, avg2), one); - const __m128i ab = _mm_xor_si128(ABCDEFGH, BCDEFGH_); - const __m128i bc = _mm_xor_si128(CDEFGH__, BCDEFGH_); - const __m128i abbc = _mm_or_si128(ab, bc); - const __m128i lsb2 = _mm_and_si128(abbc, lsb1); - const __m128i avg4 = _mm_subs_epu8(avg3, lsb2); - const uint32_t extra_out = _mm_cvtsi128_si32(_mm_srli_si128(avg4, 4)); - WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( avg1 )); - WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( avg4 )); - WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1))); - WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1))); - - // these two are hard to get and irregular - DST(3, 2) = (extra_out >> 0) & 0xff; - DST(3, 3) = (extra_out >> 8) & 0xff; -} - -static void RD4(uint8_t* dst) { // Down-right - const __m128i one = _mm_set1_epi8(1); - const __m128i XABCD = _mm_loadl_epi64((__m128i*)(dst - BPS - 1)); - const __m128i ____XABCD = _mm_slli_si128(XABCD, 4); - const uint32_t I = dst[-1 + 0 * BPS]; - const uint32_t J = dst[-1 + 1 * BPS]; - const uint32_t K = dst[-1 + 2 * BPS]; - const uint32_t L = dst[-1 + 3 * BPS]; - const __m128i LKJI_____ = - _mm_cvtsi32_si128(L | (K << 8) | (J << 16) | (I << 24)); - const __m128i LKJIXABCD = _mm_or_si128(LKJI_____, ____XABCD); - const __m128i KJIXABCD_ = _mm_srli_si128(LKJIXABCD, 1); - const __m128i JIXABCD__ = _mm_srli_si128(LKJIXABCD, 2); - const __m128i avg1 = _mm_avg_epu8(JIXABCD__, LKJIXABCD); - const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one); - const __m128i avg2 = _mm_subs_epu8(avg1, lsb); - const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_); - WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32( abcdefg )); - WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); - WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); - WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); -} - -#undef DST -#undef AVG3 - -//------------------------------------------------------------------------------ -// Luma 16x16 - -static WEBP_INLINE void TrueMotion(uint8_t* dst, int size) { - const uint8_t* top = dst - BPS; - const __m128i zero = _mm_setzero_si128(); - int y; - if (size == 4) { - const __m128i top_values = _mm_cvtsi32_si128(WebPMemToUint32(top)); - const __m128i top_base = _mm_unpacklo_epi8(top_values, zero); - for (y = 0; y < 4; ++y, dst += BPS) { - const int val = dst[-1] - top[-1]; - const __m128i base = _mm_set1_epi16(val); - const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero); - WebPUint32ToMem(dst, _mm_cvtsi128_si32(out)); - } - } else if (size == 8) { - const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); - const __m128i top_base = _mm_unpacklo_epi8(top_values, zero); - for (y = 0; y < 8; ++y, dst += BPS) { - const int val = dst[-1] - top[-1]; - const __m128i base = _mm_set1_epi16(val); - const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero); - _mm_storel_epi64((__m128i*)dst, out); - } - } else { - const __m128i top_values = _mm_loadu_si128((const __m128i*)top); - const __m128i top_base_0 = _mm_unpacklo_epi8(top_values, zero); - const __m128i top_base_1 = _mm_unpackhi_epi8(top_values, zero); - for (y = 0; y < 16; ++y, dst += BPS) { - const int val = dst[-1] - top[-1]; - const __m128i base = _mm_set1_epi16(val); - const __m128i out_0 = _mm_add_epi16(base, top_base_0); - const __m128i out_1 = _mm_add_epi16(base, top_base_1); - const __m128i out = _mm_packus_epi16(out_0, out_1); - _mm_storeu_si128((__m128i*)dst, out); - } - } -} - -static void TM4(uint8_t* dst) { TrueMotion(dst, 4); } -static void TM8uv(uint8_t* dst) { TrueMotion(dst, 8); } -static void TM16(uint8_t* dst) { TrueMotion(dst, 16); } - -static void VE16(uint8_t* dst) { - const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS)); - int j; - for (j = 0; j < 16; ++j) { - _mm_storeu_si128((__m128i*)(dst + j * BPS), top); - } -} - -static void HE16(uint8_t* dst) { // horizontal - int j; - for (j = 16; j > 0; --j) { - const __m128i values = _mm_set1_epi8(dst[-1]); - _mm_storeu_si128((__m128i*)dst, values); - dst += BPS; - } -} - -static WEBP_INLINE void Put16(uint8_t v, uint8_t* dst) { - int j; - const __m128i values = _mm_set1_epi8(v); - for (j = 0; j < 16; ++j) { - _mm_storeu_si128((__m128i*)(dst + j * BPS), values); - } -} - -static void DC16(uint8_t* dst) { // DC - const __m128i zero = _mm_setzero_si128(); - const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS)); - const __m128i sad8x2 = _mm_sad_epu8(top, zero); - // sum the two sads: sad8x2[0:1] + sad8x2[8:9] - const __m128i sum = _mm_add_epi16(sad8x2, _mm_shuffle_epi32(sad8x2, 2)); - int left = 0; - int j; - for (j = 0; j < 16; ++j) { - left += dst[-1 + j * BPS]; - } - { - const int DC = _mm_cvtsi128_si32(sum) + left + 16; - Put16(DC >> 5, dst); - } -} - -static void DC16NoTop(uint8_t* dst) { // DC with top samples not available - int DC = 8; - int j; - for (j = 0; j < 16; ++j) { - DC += dst[-1 + j * BPS]; - } - Put16(DC >> 4, dst); -} - -static void DC16NoLeft(uint8_t* dst) { // DC with left samples not available - const __m128i zero = _mm_setzero_si128(); - const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS)); - const __m128i sad8x2 = _mm_sad_epu8(top, zero); - // sum the two sads: sad8x2[0:1] + sad8x2[8:9] - const __m128i sum = _mm_add_epi16(sad8x2, _mm_shuffle_epi32(sad8x2, 2)); - const int DC = _mm_cvtsi128_si32(sum) + 8; - Put16(DC >> 4, dst); -} - -static void DC16NoTopLeft(uint8_t* dst) { // DC with no top and left samples - Put16(0x80, dst); -} - -//------------------------------------------------------------------------------ -// Chroma - -static void VE8uv(uint8_t* dst) { // vertical - int j; - const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS)); - for (j = 0; j < 8; ++j) { - _mm_storel_epi64((__m128i*)(dst + j * BPS), top); - } -} - -static void HE8uv(uint8_t* dst) { // horizontal - int j; - for (j = 0; j < 8; ++j) { - const __m128i values = _mm_set1_epi8(dst[-1]); - _mm_storel_epi64((__m128i*)dst, values); - dst += BPS; - } -} - -// helper for chroma-DC predictions -static WEBP_INLINE void Put8x8uv(uint8_t v, uint8_t* dst) { - int j; - const __m128i values = _mm_set1_epi8(v); - for (j = 0; j < 8; ++j) { - _mm_storel_epi64((__m128i*)(dst + j * BPS), values); - } -} - -static void DC8uv(uint8_t* dst) { // DC - const __m128i zero = _mm_setzero_si128(); - const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS)); - const __m128i sum = _mm_sad_epu8(top, zero); - int left = 0; - int j; - for (j = 0; j < 8; ++j) { - left += dst[-1 + j * BPS]; - } - { - const int DC = _mm_cvtsi128_si32(sum) + left + 8; - Put8x8uv(DC >> 4, dst); - } -} - -static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples - const __m128i zero = _mm_setzero_si128(); - const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS)); - const __m128i sum = _mm_sad_epu8(top, zero); - const int DC = _mm_cvtsi128_si32(sum) + 4; - Put8x8uv(DC >> 3, dst); -} - -static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples - int dc0 = 4; - int i; - for (i = 0; i < 8; ++i) { - dc0 += dst[-1 + i * BPS]; - } - Put8x8uv(dc0 >> 3, dst); -} - -static void DC8uvNoTopLeft(uint8_t* dst) { // DC with nothing - Put8x8uv(0x80, dst); -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8DspInitSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitSSE2(void) { - VP8Transform = Transform; -#if defined(USE_TRANSFORM_AC3) - VP8TransformAC3 = TransformAC3; -#endif - - VP8VFilter16 = VFilter16; - VP8HFilter16 = HFilter16; - VP8VFilter8 = VFilter8; - VP8HFilter8 = HFilter8; - VP8VFilter16i = VFilter16i; - VP8HFilter16i = HFilter16i; - VP8VFilter8i = VFilter8i; - VP8HFilter8i = HFilter8i; - - VP8SimpleVFilter16 = SimpleVFilter16; - VP8SimpleHFilter16 = SimpleHFilter16; - VP8SimpleVFilter16i = SimpleVFilter16i; - VP8SimpleHFilter16i = SimpleHFilter16i; - - VP8PredLuma4[1] = TM4; - VP8PredLuma4[2] = VE4; - VP8PredLuma4[4] = RD4; - VP8PredLuma4[5] = VR4; - VP8PredLuma4[6] = LD4; - VP8PredLuma4[7] = VL4; - - VP8PredLuma16[0] = DC16; - VP8PredLuma16[1] = TM16; - VP8PredLuma16[2] = VE16; - VP8PredLuma16[3] = HE16; - VP8PredLuma16[4] = DC16NoTop; - VP8PredLuma16[5] = DC16NoLeft; - VP8PredLuma16[6] = DC16NoTopLeft; - - VP8PredChroma8[0] = DC8uv; - VP8PredChroma8[1] = TM8uv; - VP8PredChroma8[2] = VE8uv; - VP8PredChroma8[3] = HE8uv; - VP8PredChroma8[4] = DC8uvNoTop; - VP8PredChroma8[5] = DC8uvNoLeft; - VP8PredChroma8[6] = DC8uvNoTopLeft; -} - -#else // !WEBP_USE_SSE2 - -WEBP_DSP_INIT_STUB(VP8DspInitSSE2) - -#endif // WEBP_USE_SSE2 diff --git a/Example/Pods/libwebp/src/dsp/dec_sse41.c b/Example/Pods/libwebp/src/dsp/dec_sse41.c deleted file mode 100644 index 224c6f89..00000000 --- a/Example/Pods/libwebp/src/dsp/dec_sse41.c +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// SSE4 version of some decoding functions. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE41) - -#include -#include "../dec/vp8i.h" - -static void HE16(uint8_t* dst) { // horizontal - int j; - const __m128i kShuffle3 = _mm_set1_epi8(3); - for (j = 16; j > 0; --j) { - const __m128i in = _mm_cvtsi32_si128(WebPMemToUint32(dst - 4)); - const __m128i values = _mm_shuffle_epi8(in, kShuffle3); - _mm_storeu_si128((__m128i*)dst, values); - dst += BPS; - } -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8DspInitSSE41(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitSSE41(void) { - VP8PredLuma16[3] = HE16; -} - -#else // !WEBP_USE_SSE41 - -WEBP_DSP_INIT_STUB(VP8DspInitSSE41) - -#endif // WEBP_USE_SSE41 diff --git a/Example/Pods/libwebp/src/dsp/dsp.h b/Example/Pods/libwebp/src/dsp/dsp.h deleted file mode 100644 index 95f1ce0f..00000000 --- a/Example/Pods/libwebp/src/dsp/dsp.h +++ /dev/null @@ -1,497 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Speed-critical functions. -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_DSP_DSP_H_ -#define WEBP_DSP_DSP_H_ - -#include "../webp/types.h" -#include "../utils/utils.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define BPS 32 // this is the common stride for enc/dec - -//------------------------------------------------------------------------------ -// CPU detection - -#if defined(__GNUC__) -# define LOCAL_GCC_VERSION ((__GNUC__ << 8) | __GNUC_MINOR__) -# define LOCAL_GCC_PREREQ(maj, min) \ - (LOCAL_GCC_VERSION >= (((maj) << 8) | (min))) -#else -# define LOCAL_GCC_VERSION 0 -# define LOCAL_GCC_PREREQ(maj, min) 0 -#endif - -#ifndef __has_builtin -# define __has_builtin(x) 0 -#endif - -#if defined(_MSC_VER) && _MSC_VER > 1310 && \ - (defined(_M_X64) || defined(_M_IX86)) -#define WEBP_MSC_SSE2 // Visual C++ SSE2 targets -#endif - -#if defined(_MSC_VER) && _MSC_VER >= 1500 && \ - (defined(_M_X64) || defined(_M_IX86)) -#define WEBP_MSC_SSE41 // Visual C++ SSE4.1 targets -#endif - -// WEBP_HAVE_* are used to indicate the presence of the instruction set in dsp -// files without intrinsics, allowing the corresponding Init() to be called. -// Files containing intrinsics will need to be built targeting the instruction -// set so should succeed on one of the earlier tests. -#if defined(__SSE2__) || defined(WEBP_MSC_SSE2) || defined(WEBP_HAVE_SSE2) -#define WEBP_USE_SSE2 -#endif - -#if defined(__SSE4_1__) || defined(WEBP_MSC_SSE41) || defined(WEBP_HAVE_SSE41) -#define WEBP_USE_SSE41 -#endif - -#if defined(__AVX2__) || defined(WEBP_HAVE_AVX2) -#define WEBP_USE_AVX2 -#endif - -#if defined(__ANDROID__) && defined(__ARM_ARCH_7A__) -#define WEBP_ANDROID_NEON // Android targets that might support NEON -#endif - -// The intrinsics currently cause compiler errors with arm-nacl-gcc and the -// inline assembly would need to be modified for use with Native Client. -#if (defined(__ARM_NEON__) || defined(WEBP_ANDROID_NEON) || \ - defined(__aarch64__)) && !defined(__native_client__) -#define WEBP_USE_NEON -#endif - -#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM) -#define WEBP_USE_NEON -#define WEBP_USE_INTRINSICS -#endif - -#if defined(__mips__) && !defined(__mips64) && \ - defined(__mips_isa_rev) && (__mips_isa_rev >= 1) && (__mips_isa_rev < 6) -#define WEBP_USE_MIPS32 -#if (__mips_isa_rev >= 2) -#define WEBP_USE_MIPS32_R2 -#if defined(__mips_dspr2) || (__mips_dsp_rev >= 2) -#define WEBP_USE_MIPS_DSP_R2 -#endif -#endif -#endif - -// This macro prevents thread_sanitizer from reporting known concurrent writes. -#define WEBP_TSAN_IGNORE_FUNCTION -#if defined(__has_feature) -#if __has_feature(thread_sanitizer) -#undef WEBP_TSAN_IGNORE_FUNCTION -#define WEBP_TSAN_IGNORE_FUNCTION __attribute__((no_sanitize_thread)) -#endif -#endif - -typedef enum { - kSSE2, - kSSE3, - kSSE4_1, - kAVX, - kAVX2, - kNEON, - kMIPS32, - kMIPSdspR2 -} CPUFeature; -// returns true if the CPU supports the feature. -typedef int (*VP8CPUInfo)(CPUFeature feature); -WEBP_EXTERN(VP8CPUInfo) VP8GetCPUInfo; - -//------------------------------------------------------------------------------ -// Init stub generator - -// Defines an init function stub to ensure each module exposes a symbol, -// avoiding a compiler warning. -#define WEBP_DSP_INIT_STUB(func) \ - extern void func(void); \ - WEBP_TSAN_IGNORE_FUNCTION void func(void) {} - -//------------------------------------------------------------------------------ -// Encoding - -// Transforms -// VP8Idct: Does one of two inverse transforms. If do_two is set, the transforms -// will be done for (ref, in, dst) and (ref + 4, in + 16, dst + 4). -typedef void (*VP8Idct)(const uint8_t* ref, const int16_t* in, uint8_t* dst, - int do_two); -typedef void (*VP8Fdct)(const uint8_t* src, const uint8_t* ref, int16_t* out); -typedef void (*VP8WHT)(const int16_t* in, int16_t* out); -extern VP8Idct VP8ITransform; -extern VP8Fdct VP8FTransform; -extern VP8Fdct VP8FTransform2; // performs two transforms at a time -extern VP8WHT VP8FTransformWHT; -// Predictions -// *dst is the destination block. *top and *left can be NULL. -typedef void (*VP8IntraPreds)(uint8_t *dst, const uint8_t* left, - const uint8_t* top); -typedef void (*VP8Intra4Preds)(uint8_t *dst, const uint8_t* top); -extern VP8Intra4Preds VP8EncPredLuma4; -extern VP8IntraPreds VP8EncPredLuma16; -extern VP8IntraPreds VP8EncPredChroma8; - -typedef int (*VP8Metric)(const uint8_t* pix, const uint8_t* ref); -extern VP8Metric VP8SSE16x16, VP8SSE16x8, VP8SSE8x8, VP8SSE4x4; -typedef int (*VP8WMetric)(const uint8_t* pix, const uint8_t* ref, - const uint16_t* const weights); -extern VP8WMetric VP8TDisto4x4, VP8TDisto16x16; - -typedef void (*VP8BlockCopy)(const uint8_t* src, uint8_t* dst); -extern VP8BlockCopy VP8Copy4x4; -extern VP8BlockCopy VP8Copy16x8; -// Quantization -struct VP8Matrix; // forward declaration -typedef int (*VP8QuantizeBlock)(int16_t in[16], int16_t out[16], - const struct VP8Matrix* const mtx); -// Same as VP8QuantizeBlock, but quantizes two consecutive blocks. -typedef int (*VP8Quantize2Blocks)(int16_t in[32], int16_t out[32], - const struct VP8Matrix* const mtx); - -extern VP8QuantizeBlock VP8EncQuantizeBlock; -extern VP8Quantize2Blocks VP8EncQuantize2Blocks; - -// specific to 2nd transform: -typedef int (*VP8QuantizeBlockWHT)(int16_t in[16], int16_t out[16], - const struct VP8Matrix* const mtx); -extern VP8QuantizeBlockWHT VP8EncQuantizeBlockWHT; - -extern const int VP8DspScan[16 + 4 + 4]; - -// Collect histogram for susceptibility calculation. -#define MAX_COEFF_THRESH 31 // size of histogram used by CollectHistogram. -typedef struct { - // We only need to store max_value and last_non_zero, not the distribution. - int max_value; - int last_non_zero; -} VP8Histogram; -typedef void (*VP8CHisto)(const uint8_t* ref, const uint8_t* pred, - int start_block, int end_block, - VP8Histogram* const histo); -extern VP8CHisto VP8CollectHistogram; -// General-purpose util function to help VP8CollectHistogram(). -void VP8SetHistogramData(const int distribution[MAX_COEFF_THRESH + 1], - VP8Histogram* const histo); - -// must be called before using any of the above -void VP8EncDspInit(void); - -//------------------------------------------------------------------------------ -// cost functions (encoding) - -extern const uint16_t VP8EntropyCost[256]; // 8bit fixed-point log(p) -// approximate cost per level: -extern const uint16_t VP8LevelFixedCosts[2047 /*MAX_LEVEL*/ + 1]; -extern const uint8_t VP8EncBands[16 + 1]; - -struct VP8Residual; -typedef void (*VP8SetResidualCoeffsFunc)(const int16_t* const coeffs, - struct VP8Residual* const res); -extern VP8SetResidualCoeffsFunc VP8SetResidualCoeffs; - -// Cost calculation function. -typedef int (*VP8GetResidualCostFunc)(int ctx0, - const struct VP8Residual* const res); -extern VP8GetResidualCostFunc VP8GetResidualCost; - -// must be called before anything using the above -void VP8EncDspCostInit(void); - -//------------------------------------------------------------------------------ -// Decoding - -typedef void (*VP8DecIdct)(const int16_t* coeffs, uint8_t* dst); -// when doing two transforms, coeffs is actually int16_t[2][16]. -typedef void (*VP8DecIdct2)(const int16_t* coeffs, uint8_t* dst, int do_two); -extern VP8DecIdct2 VP8Transform; -extern VP8DecIdct VP8TransformAC3; -extern VP8DecIdct VP8TransformUV; -extern VP8DecIdct VP8TransformDC; -extern VP8DecIdct VP8TransformDCUV; -extern VP8WHT VP8TransformWHT; - -// *dst is the destination block, with stride BPS. Boundary samples are -// assumed accessible when needed. -typedef void (*VP8PredFunc)(uint8_t* dst); -extern VP8PredFunc VP8PredLuma16[/* NUM_B_DC_MODES */]; -extern VP8PredFunc VP8PredChroma8[/* NUM_B_DC_MODES */]; -extern VP8PredFunc VP8PredLuma4[/* NUM_BMODES */]; - -// clipping tables (for filtering) -extern const int8_t* const VP8ksclip1; // clips [-1020, 1020] to [-128, 127] -extern const int8_t* const VP8ksclip2; // clips [-112, 112] to [-16, 15] -extern const uint8_t* const VP8kclip1; // clips [-255,511] to [0,255] -extern const uint8_t* const VP8kabs0; // abs(x) for x in [-255,255] -// must be called first -void VP8InitClipTables(void); - -// simple filter (only for luma) -typedef void (*VP8SimpleFilterFunc)(uint8_t* p, int stride, int thresh); -extern VP8SimpleFilterFunc VP8SimpleVFilter16; -extern VP8SimpleFilterFunc VP8SimpleHFilter16; -extern VP8SimpleFilterFunc VP8SimpleVFilter16i; // filter 3 inner edges -extern VP8SimpleFilterFunc VP8SimpleHFilter16i; - -// regular filter (on both macroblock edges and inner edges) -typedef void (*VP8LumaFilterFunc)(uint8_t* luma, int stride, - int thresh, int ithresh, int hev_t); -typedef void (*VP8ChromaFilterFunc)(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_t); -// on outer edge -extern VP8LumaFilterFunc VP8VFilter16; -extern VP8LumaFilterFunc VP8HFilter16; -extern VP8ChromaFilterFunc VP8VFilter8; -extern VP8ChromaFilterFunc VP8HFilter8; - -// on inner edge -extern VP8LumaFilterFunc VP8VFilter16i; // filtering 3 inner edges altogether -extern VP8LumaFilterFunc VP8HFilter16i; -extern VP8ChromaFilterFunc VP8VFilter8i; // filtering u and v altogether -extern VP8ChromaFilterFunc VP8HFilter8i; - -// must be called before anything using the above -void VP8DspInit(void); - -//------------------------------------------------------------------------------ -// WebP I/O - -#define FANCY_UPSAMPLING // undefined to remove fancy upsampling support - -// Convert a pair of y/u/v lines together to the output rgb/a colorspace. -// bottom_y can be NULL if only one line of output is needed (at top/bottom). -typedef void (*WebPUpsampleLinePairFunc)( - const uint8_t* top_y, const uint8_t* bottom_y, - const uint8_t* top_u, const uint8_t* top_v, - const uint8_t* cur_u, const uint8_t* cur_v, - uint8_t* top_dst, uint8_t* bottom_dst, int len); - -#ifdef FANCY_UPSAMPLING - -// Fancy upsampling functions to convert YUV to RGB(A) modes -extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; - -#endif // FANCY_UPSAMPLING - -// Per-row point-sampling methods. -typedef void (*WebPSamplerRowFunc)(const uint8_t* y, - const uint8_t* u, const uint8_t* v, - uint8_t* dst, int len); -// Generic function to apply 'WebPSamplerRowFunc' to the whole plane: -void WebPSamplerProcessPlane(const uint8_t* y, int y_stride, - const uint8_t* u, const uint8_t* v, int uv_stride, - uint8_t* dst, int dst_stride, - int width, int height, WebPSamplerRowFunc func); - -// Sampling functions to convert rows of YUV to RGB(A) -extern WebPSamplerRowFunc WebPSamplers[/* MODE_LAST */]; - -// General function for converting two lines of ARGB or RGBA. -// 'alpha_is_last' should be true if 0xff000000 is stored in memory as -// as 0x00, 0x00, 0x00, 0xff (little endian). -WebPUpsampleLinePairFunc WebPGetLinePairConverter(int alpha_is_last); - -// YUV444->RGB converters -typedef void (*WebPYUV444Converter)(const uint8_t* y, - const uint8_t* u, const uint8_t* v, - uint8_t* dst, int len); - -extern WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */]; - -// Must be called before using the WebPUpsamplers[] (and for premultiplied -// colorspaces like rgbA, rgbA4444, etc) -void WebPInitUpsamplers(void); -// Must be called before using WebPSamplers[] -void WebPInitSamplers(void); -// Must be called before using WebPYUV444Converters[] -void WebPInitYUV444Converters(void); - -//------------------------------------------------------------------------------ -// ARGB -> YUV converters - -// Convert ARGB samples to luma Y. -extern void (*WebPConvertARGBToY)(const uint32_t* argb, uint8_t* y, int width); -// Convert ARGB samples to U/V with downsampling. do_store should be '1' for -// even lines and '0' for odd ones. 'src_width' is the original width, not -// the U/V one. -extern void (*WebPConvertARGBToUV)(const uint32_t* argb, uint8_t* u, uint8_t* v, - int src_width, int do_store); - -// Convert a row of accumulated (four-values) of rgba32 toward U/V -extern void (*WebPConvertRGBA32ToUV)(const uint16_t* rgb, - uint8_t* u, uint8_t* v, int width); - -// Convert RGB or BGR to Y -extern void (*WebPConvertRGB24ToY)(const uint8_t* rgb, uint8_t* y, int width); -extern void (*WebPConvertBGR24ToY)(const uint8_t* bgr, uint8_t* y, int width); - -// used for plain-C fallback. -extern void WebPConvertARGBToUV_C(const uint32_t* argb, uint8_t* u, uint8_t* v, - int src_width, int do_store); -extern void WebPConvertRGBA32ToUV_C(const uint16_t* rgb, - uint8_t* u, uint8_t* v, int width); - -// Must be called before using the above. -void WebPInitConvertARGBToYUV(void); - -//------------------------------------------------------------------------------ -// Rescaler - -struct WebPRescaler; - -// Import a row of data and save its contribution in the rescaler. -// 'channel' denotes the channel number to be imported. 'Expand' corresponds to -// the wrk->x_expand case. Otherwise, 'Shrink' is to be used. -typedef void (*WebPRescalerImportRowFunc)(struct WebPRescaler* const wrk, - const uint8_t* src); - -extern WebPRescalerImportRowFunc WebPRescalerImportRowExpand; -extern WebPRescalerImportRowFunc WebPRescalerImportRowShrink; - -// Export one row (starting at x_out position) from rescaler. -// 'Expand' corresponds to the wrk->y_expand case. -// Otherwise 'Shrink' is to be used -typedef void (*WebPRescalerExportRowFunc)(struct WebPRescaler* const wrk); -extern WebPRescalerExportRowFunc WebPRescalerExportRowExpand; -extern WebPRescalerExportRowFunc WebPRescalerExportRowShrink; - -// Plain-C implementation, as fall-back. -extern void WebPRescalerImportRowExpandC(struct WebPRescaler* const wrk, - const uint8_t* src); -extern void WebPRescalerImportRowShrinkC(struct WebPRescaler* const wrk, - const uint8_t* src); -extern void WebPRescalerExportRowExpandC(struct WebPRescaler* const wrk); -extern void WebPRescalerExportRowShrinkC(struct WebPRescaler* const wrk); - -// Main entry calls: -extern void WebPRescalerImportRow(struct WebPRescaler* const wrk, - const uint8_t* src); -// Export one row (starting at x_out position) from rescaler. -extern void WebPRescalerExportRow(struct WebPRescaler* const wrk); - -// Must be called first before using the above. -void WebPRescalerDspInit(void); - -//------------------------------------------------------------------------------ -// Utilities for processing transparent channel. - -// Apply alpha pre-multiply on an rgba, bgra or argb plane of size w * h. -// alpha_first should be 0 for argb, 1 for rgba or bgra (where alpha is last). -extern void (*WebPApplyAlphaMultiply)( - uint8_t* rgba, int alpha_first, int w, int h, int stride); - -// Same, buf specifically for RGBA4444 format -extern void (*WebPApplyAlphaMultiply4444)( - uint8_t* rgba4444, int w, int h, int stride); - -// Dispatch the values from alpha[] plane to the ARGB destination 'dst'. -// Returns true if alpha[] plane has non-trivial values different from 0xff. -extern int (*WebPDispatchAlpha)(const uint8_t* alpha, int alpha_stride, - int width, int height, - uint8_t* dst, int dst_stride); - -// Transfer packed 8b alpha[] values to green channel in dst[], zero'ing the -// A/R/B values. 'dst_stride' is the stride for dst[] in uint32_t units. -extern void (*WebPDispatchAlphaToGreen)(const uint8_t* alpha, int alpha_stride, - int width, int height, - uint32_t* dst, int dst_stride); - -// Extract the alpha values from 32b values in argb[] and pack them into alpha[] -// (this is the opposite of WebPDispatchAlpha). -// Returns true if there's only trivial 0xff alpha values. -extern int (*WebPExtractAlpha)(const uint8_t* argb, int argb_stride, - int width, int height, - uint8_t* alpha, int alpha_stride); - -// Pre-Multiply operation transforms x into x * A / 255 (where x=Y,R,G or B). -// Un-Multiply operation transforms x into x * 255 / A. - -// Pre-Multiply or Un-Multiply (if 'inverse' is true) argb values in a row. -extern void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse); - -// Same a WebPMultARGBRow(), but for several rows. -void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows, - int inverse); - -// Same for a row of single values, with side alpha values. -extern void (*WebPMultRow)(uint8_t* const ptr, const uint8_t* const alpha, - int width, int inverse); - -// Same a WebPMultRow(), but for several 'num_rows' rows. -void WebPMultRows(uint8_t* ptr, int stride, - const uint8_t* alpha, int alpha_stride, - int width, int num_rows, int inverse); - -// Plain-C versions, used as fallback by some implementations. -void WebPMultRowC(uint8_t* const ptr, const uint8_t* const alpha, - int width, int inverse); -void WebPMultARGBRowC(uint32_t* const ptr, int width, int inverse); - -// To be called first before using the above. -void WebPInitAlphaProcessing(void); - -// ARGB packing function: a/r/g/b input is rgba or bgra order. -extern void (*VP8PackARGB)(const uint8_t* a, const uint8_t* r, - const uint8_t* g, const uint8_t* b, int len, - uint32_t* out); - -// RGB packing function. 'step' can be 3 or 4. r/g/b input is rgb or bgr order. -extern void (*VP8PackRGB)(const uint8_t* r, const uint8_t* g, const uint8_t* b, - int len, int step, uint32_t* out); - -// To be called first before using the above. -void VP8EncDspARGBInit(void); - -//------------------------------------------------------------------------------ -// Filter functions - -typedef enum { // Filter types. - WEBP_FILTER_NONE = 0, - WEBP_FILTER_HORIZONTAL, - WEBP_FILTER_VERTICAL, - WEBP_FILTER_GRADIENT, - WEBP_FILTER_LAST = WEBP_FILTER_GRADIENT + 1, // end marker - WEBP_FILTER_BEST, // meta-types - WEBP_FILTER_FAST -} WEBP_FILTER_TYPE; - -typedef void (*WebPFilterFunc)(const uint8_t* in, int width, int height, - int stride, uint8_t* out); -typedef void (*WebPUnfilterFunc)(int width, int height, int stride, - int row, int num_rows, uint8_t* data); - -// Filter the given data using the given predictor. -// 'in' corresponds to a 2-dimensional pixel array of size (stride * height) -// in raster order. -// 'stride' is number of bytes per scan line (with possible padding). -// 'out' should be pre-allocated. -extern WebPFilterFunc WebPFilters[WEBP_FILTER_LAST]; - -// In-place reconstruct the original data from the given filtered data. -// The reconstruction will be done for 'num_rows' rows starting from 'row' -// (assuming rows upto 'row - 1' are already reconstructed). -extern WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST]; - -// To be called first before using the above. -void VP8FiltersInit(void); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_DSP_DSP_H_ */ diff --git a/Example/Pods/libwebp/src/dsp/enc.c b/Example/Pods/libwebp/src/dsp/enc.c deleted file mode 100644 index 8899d500..00000000 --- a/Example/Pods/libwebp/src/dsp/enc.c +++ /dev/null @@ -1,800 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Speed-critical encoding functions. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include // for abs() - -#include "./dsp.h" -#include "../enc/vp8enci.h" - -static WEBP_INLINE uint8_t clip_8b(int v) { - return (!(v & ~0xff)) ? v : (v < 0) ? 0 : 255; -} - -static WEBP_INLINE int clip_max(int v, int max) { - return (v > max) ? max : v; -} - -//------------------------------------------------------------------------------ -// Compute susceptibility based on DCT-coeff histograms: -// the higher, the "easier" the macroblock is to compress. - -const int VP8DspScan[16 + 4 + 4] = { - // Luma - 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS, - 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS, - 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS, - 0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS, - - 0 + 0 * BPS, 4 + 0 * BPS, 0 + 4 * BPS, 4 + 4 * BPS, // U - 8 + 0 * BPS, 12 + 0 * BPS, 8 + 4 * BPS, 12 + 4 * BPS // V -}; - -// general-purpose util function -void VP8SetHistogramData(const int distribution[MAX_COEFF_THRESH + 1], - VP8Histogram* const histo) { - int max_value = 0, last_non_zero = 1; - int k; - for (k = 0; k <= MAX_COEFF_THRESH; ++k) { - const int value = distribution[k]; - if (value > 0) { - if (value > max_value) max_value = value; - last_non_zero = k; - } - } - histo->max_value = max_value; - histo->last_non_zero = last_non_zero; -} - -static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, - int start_block, int end_block, - VP8Histogram* const histo) { - int j; - int distribution[MAX_COEFF_THRESH + 1] = { 0 }; - for (j = start_block; j < end_block; ++j) { - int k; - int16_t out[16]; - - VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); - - // Convert coefficients to bin. - for (k = 0; k < 16; ++k) { - const int v = abs(out[k]) >> 3; // TODO(skal): add rounding? - const int clipped_value = clip_max(v, MAX_COEFF_THRESH); - ++distribution[clipped_value]; - } - } - VP8SetHistogramData(distribution, histo); -} - -//------------------------------------------------------------------------------ -// run-time tables (~4k) - -static uint8_t clip1[255 + 510 + 1]; // clips [-255,510] to [0,255] - -// We declare this variable 'volatile' to prevent instruction reordering -// and make sure it's set to true _last_ (so as to be thread-safe) -static volatile int tables_ok = 0; - -static WEBP_TSAN_IGNORE_FUNCTION void InitTables(void) { - if (!tables_ok) { - int i; - for (i = -255; i <= 255 + 255; ++i) { - clip1[255 + i] = clip_8b(i); - } - tables_ok = 1; - } -} - - -//------------------------------------------------------------------------------ -// Transforms (Paragraph 14.4) - -#define STORE(x, y, v) \ - dst[(x) + (y) * BPS] = clip_8b(ref[(x) + (y) * BPS] + ((v) >> 3)) - -static const int kC1 = 20091 + (1 << 16); -static const int kC2 = 35468; -#define MUL(a, b) (((a) * (b)) >> 16) - -static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, - uint8_t* dst) { - int C[4 * 4], *tmp; - int i; - tmp = C; - for (i = 0; i < 4; ++i) { // vertical pass - const int a = in[0] + in[8]; - const int b = in[0] - in[8]; - const int c = MUL(in[4], kC2) - MUL(in[12], kC1); - const int d = MUL(in[4], kC1) + MUL(in[12], kC2); - tmp[0] = a + d; - tmp[1] = b + c; - tmp[2] = b - c; - tmp[3] = a - d; - tmp += 4; - in++; - } - - tmp = C; - for (i = 0; i < 4; ++i) { // horizontal pass - const int dc = tmp[0] + 4; - const int a = dc + tmp[8]; - const int b = dc - tmp[8]; - const int c = MUL(tmp[4], kC2) - MUL(tmp[12], kC1); - const int d = MUL(tmp[4], kC1) + MUL(tmp[12], kC2); - STORE(0, i, a + d); - STORE(1, i, b + c); - STORE(2, i, b - c); - STORE(3, i, a - d); - tmp++; - } -} - -static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst, - int do_two) { - ITransformOne(ref, in, dst); - if (do_two) { - ITransformOne(ref + 4, in + 16, dst + 4); - } -} - -static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) { - int i; - int tmp[16]; - for (i = 0; i < 4; ++i, src += BPS, ref += BPS) { - const int d0 = src[0] - ref[0]; // 9bit dynamic range ([-255,255]) - const int d1 = src[1] - ref[1]; - const int d2 = src[2] - ref[2]; - const int d3 = src[3] - ref[3]; - const int a0 = (d0 + d3); // 10b [-510,510] - const int a1 = (d1 + d2); - const int a2 = (d1 - d2); - const int a3 = (d0 - d3); - tmp[0 + i * 4] = (a0 + a1) * 8; // 14b [-8160,8160] - tmp[1 + i * 4] = (a2 * 2217 + a3 * 5352 + 1812) >> 9; // [-7536,7542] - tmp[2 + i * 4] = (a0 - a1) * 8; - tmp[3 + i * 4] = (a3 * 2217 - a2 * 5352 + 937) >> 9; - } - for (i = 0; i < 4; ++i) { - const int a0 = (tmp[0 + i] + tmp[12 + i]); // 15b - const int a1 = (tmp[4 + i] + tmp[ 8 + i]); - const int a2 = (tmp[4 + i] - tmp[ 8 + i]); - const int a3 = (tmp[0 + i] - tmp[12 + i]); - out[0 + i] = (a0 + a1 + 7) >> 4; // 12b - out[4 + i] = ((a2 * 2217 + a3 * 5352 + 12000) >> 16) + (a3 != 0); - out[8 + i] = (a0 - a1 + 7) >> 4; - out[12+ i] = ((a3 * 2217 - a2 * 5352 + 51000) >> 16); - } -} - -static void FTransform2(const uint8_t* src, const uint8_t* ref, int16_t* out) { - VP8FTransform(src, ref, out); - VP8FTransform(src + 4, ref + 4, out + 16); -} - -static void FTransformWHT(const int16_t* in, int16_t* out) { - // input is 12b signed - int32_t tmp[16]; - int i; - for (i = 0; i < 4; ++i, in += 64) { - const int a0 = (in[0 * 16] + in[2 * 16]); // 13b - const int a1 = (in[1 * 16] + in[3 * 16]); - const int a2 = (in[1 * 16] - in[3 * 16]); - const int a3 = (in[0 * 16] - in[2 * 16]); - tmp[0 + i * 4] = a0 + a1; // 14b - tmp[1 + i * 4] = a3 + a2; - tmp[2 + i * 4] = a3 - a2; - tmp[3 + i * 4] = a0 - a1; - } - for (i = 0; i < 4; ++i) { - const int a0 = (tmp[0 + i] + tmp[8 + i]); // 15b - const int a1 = (tmp[4 + i] + tmp[12+ i]); - const int a2 = (tmp[4 + i] - tmp[12+ i]); - const int a3 = (tmp[0 + i] - tmp[8 + i]); - const int b0 = a0 + a1; // 16b - const int b1 = a3 + a2; - const int b2 = a3 - a2; - const int b3 = a0 - a1; - out[ 0 + i] = b0 >> 1; // 15b - out[ 4 + i] = b1 >> 1; - out[ 8 + i] = b2 >> 1; - out[12 + i] = b3 >> 1; - } -} - -#undef MUL -#undef STORE - -//------------------------------------------------------------------------------ -// Intra predictions - -static WEBP_INLINE void Fill(uint8_t* dst, int value, int size) { - int j; - for (j = 0; j < size; ++j) { - memset(dst + j * BPS, value, size); - } -} - -static WEBP_INLINE void VerticalPred(uint8_t* dst, - const uint8_t* top, int size) { - int j; - if (top != NULL) { - for (j = 0; j < size; ++j) memcpy(dst + j * BPS, top, size); - } else { - Fill(dst, 127, size); - } -} - -static WEBP_INLINE void HorizontalPred(uint8_t* dst, - const uint8_t* left, int size) { - if (left != NULL) { - int j; - for (j = 0; j < size; ++j) { - memset(dst + j * BPS, left[j], size); - } - } else { - Fill(dst, 129, size); - } -} - -static WEBP_INLINE void TrueMotion(uint8_t* dst, const uint8_t* left, - const uint8_t* top, int size) { - int y; - if (left != NULL) { - if (top != NULL) { - const uint8_t* const clip = clip1 + 255 - left[-1]; - for (y = 0; y < size; ++y) { - const uint8_t* const clip_table = clip + left[y]; - int x; - for (x = 0; x < size; ++x) { - dst[x] = clip_table[top[x]]; - } - dst += BPS; - } - } else { - HorizontalPred(dst, left, size); - } - } else { - // true motion without left samples (hence: with default 129 value) - // is equivalent to VE prediction where you just copy the top samples. - // Note that if top samples are not available, the default value is - // then 129, and not 127 as in the VerticalPred case. - if (top != NULL) { - VerticalPred(dst, top, size); - } else { - Fill(dst, 129, size); - } - } -} - -static WEBP_INLINE void DCMode(uint8_t* dst, const uint8_t* left, - const uint8_t* top, - int size, int round, int shift) { - int DC = 0; - int j; - if (top != NULL) { - for (j = 0; j < size; ++j) DC += top[j]; - if (left != NULL) { // top and left present - for (j = 0; j < size; ++j) DC += left[j]; - } else { // top, but no left - DC += DC; - } - DC = (DC + round) >> shift; - } else if (left != NULL) { // left but no top - for (j = 0; j < size; ++j) DC += left[j]; - DC += DC; - DC = (DC + round) >> shift; - } else { // no top, no left, nothing. - DC = 0x80; - } - Fill(dst, DC, size); -} - -//------------------------------------------------------------------------------ -// Chroma 8x8 prediction (paragraph 12.2) - -static void IntraChromaPreds(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { - // U block - DCMode(C8DC8 + dst, left, top, 8, 8, 4); - VerticalPred(C8VE8 + dst, top, 8); - HorizontalPred(C8HE8 + dst, left, 8); - TrueMotion(C8TM8 + dst, left, top, 8); - // V block - dst += 8; - if (top != NULL) top += 8; - if (left != NULL) left += 16; - DCMode(C8DC8 + dst, left, top, 8, 8, 4); - VerticalPred(C8VE8 + dst, top, 8); - HorizontalPred(C8HE8 + dst, left, 8); - TrueMotion(C8TM8 + dst, left, top, 8); -} - -//------------------------------------------------------------------------------ -// luma 16x16 prediction (paragraph 12.3) - -static void Intra16Preds(uint8_t* dst, - const uint8_t* left, const uint8_t* top) { - DCMode(I16DC16 + dst, left, top, 16, 16, 5); - VerticalPred(I16VE16 + dst, top, 16); - HorizontalPred(I16HE16 + dst, left, 16); - TrueMotion(I16TM16 + dst, left, top, 16); -} - -//------------------------------------------------------------------------------ -// luma 4x4 prediction - -#define DST(x, y) dst[(x) + (y) * BPS] -#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2) -#define AVG2(a, b) (((a) + (b) + 1) >> 1) - -static void VE4(uint8_t* dst, const uint8_t* top) { // vertical - const uint8_t vals[4] = { - AVG3(top[-1], top[0], top[1]), - AVG3(top[ 0], top[1], top[2]), - AVG3(top[ 1], top[2], top[3]), - AVG3(top[ 2], top[3], top[4]) - }; - int i; - for (i = 0; i < 4; ++i) { - memcpy(dst + i * BPS, vals, 4); - } -} - -static void HE4(uint8_t* dst, const uint8_t* top) { // horizontal - const int X = top[-1]; - const int I = top[-2]; - const int J = top[-3]; - const int K = top[-4]; - const int L = top[-5]; - WebPUint32ToMem(dst + 0 * BPS, 0x01010101U * AVG3(X, I, J)); - WebPUint32ToMem(dst + 1 * BPS, 0x01010101U * AVG3(I, J, K)); - WebPUint32ToMem(dst + 2 * BPS, 0x01010101U * AVG3(J, K, L)); - WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(K, L, L)); -} - -static void DC4(uint8_t* dst, const uint8_t* top) { - uint32_t dc = 4; - int i; - for (i = 0; i < 4; ++i) dc += top[i] + top[-5 + i]; - Fill(dst, dc >> 3, 4); -} - -static void RD4(uint8_t* dst, const uint8_t* top) { - const int X = top[-1]; - const int I = top[-2]; - const int J = top[-3]; - const int K = top[-4]; - const int L = top[-5]; - const int A = top[0]; - const int B = top[1]; - const int C = top[2]; - const int D = top[3]; - DST(0, 3) = AVG3(J, K, L); - DST(0, 2) = DST(1, 3) = AVG3(I, J, K); - DST(0, 1) = DST(1, 2) = DST(2, 3) = AVG3(X, I, J); - DST(0, 0) = DST(1, 1) = DST(2, 2) = DST(3, 3) = AVG3(A, X, I); - DST(1, 0) = DST(2, 1) = DST(3, 2) = AVG3(B, A, X); - DST(2, 0) = DST(3, 1) = AVG3(C, B, A); - DST(3, 0) = AVG3(D, C, B); -} - -static void LD4(uint8_t* dst, const uint8_t* top) { - const int A = top[0]; - const int B = top[1]; - const int C = top[2]; - const int D = top[3]; - const int E = top[4]; - const int F = top[5]; - const int G = top[6]; - const int H = top[7]; - DST(0, 0) = AVG3(A, B, C); - DST(1, 0) = DST(0, 1) = AVG3(B, C, D); - DST(2, 0) = DST(1, 1) = DST(0, 2) = AVG3(C, D, E); - DST(3, 0) = DST(2, 1) = DST(1, 2) = DST(0, 3) = AVG3(D, E, F); - DST(3, 1) = DST(2, 2) = DST(1, 3) = AVG3(E, F, G); - DST(3, 2) = DST(2, 3) = AVG3(F, G, H); - DST(3, 3) = AVG3(G, H, H); -} - -static void VR4(uint8_t* dst, const uint8_t* top) { - const int X = top[-1]; - const int I = top[-2]; - const int J = top[-3]; - const int K = top[-4]; - const int A = top[0]; - const int B = top[1]; - const int C = top[2]; - const int D = top[3]; - DST(0, 0) = DST(1, 2) = AVG2(X, A); - DST(1, 0) = DST(2, 2) = AVG2(A, B); - DST(2, 0) = DST(3, 2) = AVG2(B, C); - DST(3, 0) = AVG2(C, D); - - DST(0, 3) = AVG3(K, J, I); - DST(0, 2) = AVG3(J, I, X); - DST(0, 1) = DST(1, 3) = AVG3(I, X, A); - DST(1, 1) = DST(2, 3) = AVG3(X, A, B); - DST(2, 1) = DST(3, 3) = AVG3(A, B, C); - DST(3, 1) = AVG3(B, C, D); -} - -static void VL4(uint8_t* dst, const uint8_t* top) { - const int A = top[0]; - const int B = top[1]; - const int C = top[2]; - const int D = top[3]; - const int E = top[4]; - const int F = top[5]; - const int G = top[6]; - const int H = top[7]; - DST(0, 0) = AVG2(A, B); - DST(1, 0) = DST(0, 2) = AVG2(B, C); - DST(2, 0) = DST(1, 2) = AVG2(C, D); - DST(3, 0) = DST(2, 2) = AVG2(D, E); - - DST(0, 1) = AVG3(A, B, C); - DST(1, 1) = DST(0, 3) = AVG3(B, C, D); - DST(2, 1) = DST(1, 3) = AVG3(C, D, E); - DST(3, 1) = DST(2, 3) = AVG3(D, E, F); - DST(3, 2) = AVG3(E, F, G); - DST(3, 3) = AVG3(F, G, H); -} - -static void HU4(uint8_t* dst, const uint8_t* top) { - const int I = top[-2]; - const int J = top[-3]; - const int K = top[-4]; - const int L = top[-5]; - DST(0, 0) = AVG2(I, J); - DST(2, 0) = DST(0, 1) = AVG2(J, K); - DST(2, 1) = DST(0, 2) = AVG2(K, L); - DST(1, 0) = AVG3(I, J, K); - DST(3, 0) = DST(1, 1) = AVG3(J, K, L); - DST(3, 1) = DST(1, 2) = AVG3(K, L, L); - DST(3, 2) = DST(2, 2) = - DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L; -} - -static void HD4(uint8_t* dst, const uint8_t* top) { - const int X = top[-1]; - const int I = top[-2]; - const int J = top[-3]; - const int K = top[-4]; - const int L = top[-5]; - const int A = top[0]; - const int B = top[1]; - const int C = top[2]; - - DST(0, 0) = DST(2, 1) = AVG2(I, X); - DST(0, 1) = DST(2, 2) = AVG2(J, I); - DST(0, 2) = DST(2, 3) = AVG2(K, J); - DST(0, 3) = AVG2(L, K); - - DST(3, 0) = AVG3(A, B, C); - DST(2, 0) = AVG3(X, A, B); - DST(1, 0) = DST(3, 1) = AVG3(I, X, A); - DST(1, 1) = DST(3, 2) = AVG3(J, I, X); - DST(1, 2) = DST(3, 3) = AVG3(K, J, I); - DST(1, 3) = AVG3(L, K, J); -} - -static void TM4(uint8_t* dst, const uint8_t* top) { - int x, y; - const uint8_t* const clip = clip1 + 255 - top[-1]; - for (y = 0; y < 4; ++y) { - const uint8_t* const clip_table = clip + top[-2 - y]; - for (x = 0; x < 4; ++x) { - dst[x] = clip_table[top[x]]; - } - dst += BPS; - } -} - -#undef DST -#undef AVG3 -#undef AVG2 - -// Left samples are top[-5 .. -2], top_left is top[-1], top are -// located at top[0..3], and top right is top[4..7] -static void Intra4Preds(uint8_t* dst, const uint8_t* top) { - DC4(I4DC4 + dst, top); - TM4(I4TM4 + dst, top); - VE4(I4VE4 + dst, top); - HE4(I4HE4 + dst, top); - RD4(I4RD4 + dst, top); - VR4(I4VR4 + dst, top); - LD4(I4LD4 + dst, top); - VL4(I4VL4 + dst, top); - HD4(I4HD4 + dst, top); - HU4(I4HU4 + dst, top); -} - -//------------------------------------------------------------------------------ -// Metric - -static WEBP_INLINE int GetSSE(const uint8_t* a, const uint8_t* b, - int w, int h) { - int count = 0; - int y, x; - for (y = 0; y < h; ++y) { - for (x = 0; x < w; ++x) { - const int diff = (int)a[x] - b[x]; - count += diff * diff; - } - a += BPS; - b += BPS; - } - return count; -} - -static int SSE16x16(const uint8_t* a, const uint8_t* b) { - return GetSSE(a, b, 16, 16); -} -static int SSE16x8(const uint8_t* a, const uint8_t* b) { - return GetSSE(a, b, 16, 8); -} -static int SSE8x8(const uint8_t* a, const uint8_t* b) { - return GetSSE(a, b, 8, 8); -} -static int SSE4x4(const uint8_t* a, const uint8_t* b) { - return GetSSE(a, b, 4, 4); -} - -//------------------------------------------------------------------------------ -// Texture distortion -// -// We try to match the spectral content (weighted) between source and -// reconstructed samples. - -// Hadamard transform -// Returns the weighted sum of the absolute value of transformed coefficients. -static int TTransform(const uint8_t* in, const uint16_t* w) { - int sum = 0; - int tmp[16]; - int i; - // horizontal pass - for (i = 0; i < 4; ++i, in += BPS) { - const int a0 = in[0] + in[2]; - const int a1 = in[1] + in[3]; - const int a2 = in[1] - in[3]; - const int a3 = in[0] - in[2]; - tmp[0 + i * 4] = a0 + a1; - tmp[1 + i * 4] = a3 + a2; - tmp[2 + i * 4] = a3 - a2; - tmp[3 + i * 4] = a0 - a1; - } - // vertical pass - for (i = 0; i < 4; ++i, ++w) { - const int a0 = tmp[0 + i] + tmp[8 + i]; - const int a1 = tmp[4 + i] + tmp[12+ i]; - const int a2 = tmp[4 + i] - tmp[12+ i]; - const int a3 = tmp[0 + i] - tmp[8 + i]; - const int b0 = a0 + a1; - const int b1 = a3 + a2; - const int b2 = a3 - a2; - const int b3 = a0 - a1; - - sum += w[ 0] * abs(b0); - sum += w[ 4] * abs(b1); - sum += w[ 8] * abs(b2); - sum += w[12] * abs(b3); - } - return sum; -} - -static int Disto4x4(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - const int sum1 = TTransform(a, w); - const int sum2 = TTransform(b, w); - return abs(sum2 - sum1) >> 5; -} - -static int Disto16x16(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - int D = 0; - int x, y; - for (y = 0; y < 16 * BPS; y += 4 * BPS) { - for (x = 0; x < 16; x += 4) { - D += Disto4x4(a + x + y, b + x + y, w); - } - } - return D; -} - -//------------------------------------------------------------------------------ -// Quantization -// - -static const uint8_t kZigzag[16] = { - 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 -}; - -// Simple quantization -static int QuantizeBlock(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - int last = -1; - int n; - for (n = 0; n < 16; ++n) { - const int j = kZigzag[n]; - const int sign = (in[j] < 0); - const uint32_t coeff = (sign ? -in[j] : in[j]) + mtx->sharpen_[j]; - if (coeff > mtx->zthresh_[j]) { - const uint32_t Q = mtx->q_[j]; - const uint32_t iQ = mtx->iq_[j]; - const uint32_t B = mtx->bias_[j]; - int level = QUANTDIV(coeff, iQ, B); - if (level > MAX_LEVEL) level = MAX_LEVEL; - if (sign) level = -level; - in[j] = level * Q; - out[n] = level; - if (level) last = n; - } else { - out[n] = 0; - in[j] = 0; - } - } - return (last >= 0); -} - -static int Quantize2Blocks(int16_t in[32], int16_t out[32], - const VP8Matrix* const mtx) { - int nz; - nz = VP8EncQuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0; - nz |= VP8EncQuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1; - return nz; -} - -static int QuantizeBlockWHT(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - int n, last = -1; - for (n = 0; n < 16; ++n) { - const int j = kZigzag[n]; - const int sign = (in[j] < 0); - const uint32_t coeff = sign ? -in[j] : in[j]; - assert(mtx->sharpen_[j] == 0); - if (coeff > mtx->zthresh_[j]) { - const uint32_t Q = mtx->q_[j]; - const uint32_t iQ = mtx->iq_[j]; - const uint32_t B = mtx->bias_[j]; - int level = QUANTDIV(coeff, iQ, B); - if (level > MAX_LEVEL) level = MAX_LEVEL; - if (sign) level = -level; - in[j] = level * Q; - out[n] = level; - if (level) last = n; - } else { - out[n] = 0; - in[j] = 0; - } - } - return (last >= 0); -} - -//------------------------------------------------------------------------------ -// Block copy - -static WEBP_INLINE void Copy(const uint8_t* src, uint8_t* dst, int w, int h) { - int y; - for (y = 0; y < h; ++y) { - memcpy(dst, src, w); - src += BPS; - dst += BPS; - } -} - -static void Copy4x4(const uint8_t* src, uint8_t* dst) { - Copy(src, dst, 4, 4); -} - -static void Copy16x8(const uint8_t* src, uint8_t* dst) { - Copy(src, dst, 16, 8); -} - -//------------------------------------------------------------------------------ -// Initialization - -// Speed-critical function pointers. We have to initialize them to the default -// implementations within VP8EncDspInit(). -VP8CHisto VP8CollectHistogram; -VP8Idct VP8ITransform; -VP8Fdct VP8FTransform; -VP8Fdct VP8FTransform2; -VP8WHT VP8FTransformWHT; -VP8Intra4Preds VP8EncPredLuma4; -VP8IntraPreds VP8EncPredLuma16; -VP8IntraPreds VP8EncPredChroma8; -VP8Metric VP8SSE16x16; -VP8Metric VP8SSE8x8; -VP8Metric VP8SSE16x8; -VP8Metric VP8SSE4x4; -VP8WMetric VP8TDisto4x4; -VP8WMetric VP8TDisto16x16; -VP8QuantizeBlock VP8EncQuantizeBlock; -VP8Quantize2Blocks VP8EncQuantize2Blocks; -VP8QuantizeBlockWHT VP8EncQuantizeBlockWHT; -VP8BlockCopy VP8Copy4x4; -VP8BlockCopy VP8Copy16x8; - -extern void VP8EncDspInitSSE2(void); -extern void VP8EncDspInitSSE41(void); -extern void VP8EncDspInitAVX2(void); -extern void VP8EncDspInitNEON(void); -extern void VP8EncDspInitMIPS32(void); -extern void VP8EncDspInitMIPSdspR2(void); - -static volatile VP8CPUInfo enc_last_cpuinfo_used = - (VP8CPUInfo)&enc_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInit(void) { - if (enc_last_cpuinfo_used == VP8GetCPUInfo) return; - - VP8DspInit(); // common inverse transforms - InitTables(); - - // default C implementations - VP8CollectHistogram = CollectHistogram; - VP8ITransform = ITransform; - VP8FTransform = FTransform; - VP8FTransform2 = FTransform2; - VP8FTransformWHT = FTransformWHT; - VP8EncPredLuma4 = Intra4Preds; - VP8EncPredLuma16 = Intra16Preds; - VP8EncPredChroma8 = IntraChromaPreds; - VP8SSE16x16 = SSE16x16; - VP8SSE8x8 = SSE8x8; - VP8SSE16x8 = SSE16x8; - VP8SSE4x4 = SSE4x4; - VP8TDisto4x4 = Disto4x4; - VP8TDisto16x16 = Disto16x16; - VP8EncQuantizeBlock = QuantizeBlock; - VP8EncQuantize2Blocks = Quantize2Blocks; - VP8EncQuantizeBlockWHT = QuantizeBlockWHT; - VP8Copy4x4 = Copy4x4; - VP8Copy16x8 = Copy16x8; - - // If defined, use CPUInfo() to overwrite some pointers with faster versions. - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - VP8EncDspInitSSE2(); -#if defined(WEBP_USE_SSE41) - if (VP8GetCPUInfo(kSSE4_1)) { - VP8EncDspInitSSE41(); - } -#endif - } -#endif -#if defined(WEBP_USE_AVX2) - if (VP8GetCPUInfo(kAVX2)) { - VP8EncDspInitAVX2(); - } -#endif -#if defined(WEBP_USE_NEON) - if (VP8GetCPUInfo(kNEON)) { - VP8EncDspInitNEON(); - } -#endif -#if defined(WEBP_USE_MIPS32) - if (VP8GetCPUInfo(kMIPS32)) { - VP8EncDspInitMIPS32(); - } -#endif -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - VP8EncDspInitMIPSdspR2(); - } -#endif - } - enc_last_cpuinfo_used = VP8GetCPUInfo; -} diff --git a/Example/Pods/libwebp/src/dsp/enc_avx2.c b/Example/Pods/libwebp/src/dsp/enc_avx2.c deleted file mode 100644 index 93efb30b..00000000 --- a/Example/Pods/libwebp/src/dsp/enc_avx2.c +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// AVX2 version of speed-critical encoding functions. - -#include "./dsp.h" - -#if defined(WEBP_USE_AVX2) - -#endif // WEBP_USE_AVX2 - -//------------------------------------------------------------------------------ -// Entry point - -WEBP_DSP_INIT_STUB(VP8EncDspInitAVX2) diff --git a/Example/Pods/libwebp/src/dsp/enc_mips32.c b/Example/Pods/libwebp/src/dsp/enc_mips32.c deleted file mode 100644 index fd10143d..00000000 --- a/Example/Pods/libwebp/src/dsp/enc_mips32.c +++ /dev/null @@ -1,672 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// MIPS version of speed-critical encoding functions. -// -// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) -// Jovan Zelincevic (jovan.zelincevic@imgtec.com) -// Slobodan Prijic (slobodan.prijic@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS32) - -#include "./mips_macro.h" -#include "../enc/vp8enci.h" -#include "../enc/cost.h" - -static const int kC1 = 20091 + (1 << 16); -static const int kC2 = 35468; - -// macro for one vertical pass in ITransformOne -// MUL macro inlined -// temp0..temp15 holds tmp[0]..tmp[15] -// A..D - offsets in bytes to load from in buffer -// TEMP0..TEMP3 - registers for corresponding tmp elements -// TEMP4..TEMP5 - temporary registers -#define VERTICAL_PASS(A, B, C, D, TEMP4, TEMP0, TEMP1, TEMP2, TEMP3) \ - "lh %[temp16], " #A "(%[temp20]) \n\t" \ - "lh %[temp18], " #B "(%[temp20]) \n\t" \ - "lh %[temp17], " #C "(%[temp20]) \n\t" \ - "lh %[temp19], " #D "(%[temp20]) \n\t" \ - "addu %[" #TEMP4 "], %[temp16], %[temp18] \n\t" \ - "subu %[temp16], %[temp16], %[temp18] \n\t" \ - "mul %[" #TEMP0 "], %[temp17], %[kC2] \n\t" \ - "mul %[temp18], %[temp19], %[kC1] \n\t" \ - "mul %[temp17], %[temp17], %[kC1] \n\t" \ - "mul %[temp19], %[temp19], %[kC2] \n\t" \ - "sra %[" #TEMP0 "], %[" #TEMP0 "], 16 \n\n" \ - "sra %[temp18], %[temp18], 16 \n\n" \ - "sra %[temp17], %[temp17], 16 \n\n" \ - "sra %[temp19], %[temp19], 16 \n\n" \ - "subu %[" #TEMP2 "], %[" #TEMP0 "], %[temp18] \n\t" \ - "addu %[" #TEMP3 "], %[temp17], %[temp19] \n\t" \ - "addu %[" #TEMP0 "], %[" #TEMP4 "], %[" #TEMP3 "] \n\t" \ - "addu %[" #TEMP1 "], %[temp16], %[" #TEMP2 "] \n\t" \ - "subu %[" #TEMP2 "], %[temp16], %[" #TEMP2 "] \n\t" \ - "subu %[" #TEMP3 "], %[" #TEMP4 "], %[" #TEMP3 "] \n\t" - -// macro for one horizontal pass in ITransformOne -// MUL and STORE macros inlined -// a = clip_8b(a) is replaced with: a = max(a, 0); a = min(a, 255) -// temp0..temp15 holds tmp[0]..tmp[15] -// A - offset in bytes to load from ref and store to dst buffer -// TEMP0, TEMP4, TEMP8 and TEMP12 - registers for corresponding tmp elements -#define HORIZONTAL_PASS(A, TEMP0, TEMP4, TEMP8, TEMP12) \ - "addiu %[" #TEMP0 "], %[" #TEMP0 "], 4 \n\t" \ - "addu %[temp16], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \ - "subu %[temp17], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \ - "mul %[" #TEMP0 "], %[" #TEMP4 "], %[kC2] \n\t" \ - "mul %[" #TEMP8 "], %[" #TEMP12 "], %[kC1] \n\t" \ - "mul %[" #TEMP4 "], %[" #TEMP4 "], %[kC1] \n\t" \ - "mul %[" #TEMP12 "], %[" #TEMP12 "], %[kC2] \n\t" \ - "sra %[" #TEMP0 "], %[" #TEMP0 "], 16 \n\t" \ - "sra %[" #TEMP8 "], %[" #TEMP8 "], 16 \n\t" \ - "sra %[" #TEMP4 "], %[" #TEMP4 "], 16 \n\t" \ - "sra %[" #TEMP12 "], %[" #TEMP12 "], 16 \n\t" \ - "subu %[temp18], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \ - "addu %[temp19], %[" #TEMP4 "], %[" #TEMP12 "] \n\t" \ - "addu %[" #TEMP0 "], %[temp16], %[temp19] \n\t" \ - "addu %[" #TEMP4 "], %[temp17], %[temp18] \n\t" \ - "subu %[" #TEMP8 "], %[temp17], %[temp18] \n\t" \ - "subu %[" #TEMP12 "], %[temp16], %[temp19] \n\t" \ - "lw %[temp20], 0(%[args]) \n\t" \ - "sra %[" #TEMP0 "], %[" #TEMP0 "], 3 \n\t" \ - "sra %[" #TEMP4 "], %[" #TEMP4 "], 3 \n\t" \ - "sra %[" #TEMP8 "], %[" #TEMP8 "], 3 \n\t" \ - "sra %[" #TEMP12 "], %[" #TEMP12 "], 3 \n\t" \ - "lbu %[temp16], 0+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \ - "lbu %[temp17], 1+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \ - "lbu %[temp18], 2+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \ - "lbu %[temp19], 3+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \ - "addu %[" #TEMP0 "], %[temp16], %[" #TEMP0 "] \n\t" \ - "addu %[" #TEMP4 "], %[temp17], %[" #TEMP4 "] \n\t" \ - "addu %[" #TEMP8 "], %[temp18], %[" #TEMP8 "] \n\t" \ - "addu %[" #TEMP12 "], %[temp19], %[" #TEMP12 "] \n\t" \ - "slt %[temp16], %[" #TEMP0 "], $zero \n\t" \ - "slt %[temp17], %[" #TEMP4 "], $zero \n\t" \ - "slt %[temp18], %[" #TEMP8 "], $zero \n\t" \ - "slt %[temp19], %[" #TEMP12 "], $zero \n\t" \ - "movn %[" #TEMP0 "], $zero, %[temp16] \n\t" \ - "movn %[" #TEMP4 "], $zero, %[temp17] \n\t" \ - "movn %[" #TEMP8 "], $zero, %[temp18] \n\t" \ - "movn %[" #TEMP12 "], $zero, %[temp19] \n\t" \ - "addiu %[temp20], $zero, 255 \n\t" \ - "slt %[temp16], %[" #TEMP0 "], %[temp20] \n\t" \ - "slt %[temp17], %[" #TEMP4 "], %[temp20] \n\t" \ - "slt %[temp18], %[" #TEMP8 "], %[temp20] \n\t" \ - "slt %[temp19], %[" #TEMP12 "], %[temp20] \n\t" \ - "movz %[" #TEMP0 "], %[temp20], %[temp16] \n\t" \ - "movz %[" #TEMP4 "], %[temp20], %[temp17] \n\t" \ - "lw %[temp16], 8(%[args]) \n\t" \ - "movz %[" #TEMP8 "], %[temp20], %[temp18] \n\t" \ - "movz %[" #TEMP12 "], %[temp20], %[temp19] \n\t" \ - "sb %[" #TEMP0 "], 0+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" \ - "sb %[" #TEMP4 "], 1+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" \ - "sb %[" #TEMP8 "], 2+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" \ - "sb %[" #TEMP12 "], 3+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" - -// Does one or two inverse transforms. -static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, - uint8_t* dst) { - int temp0, temp1, temp2, temp3, temp4, temp5, temp6; - int temp7, temp8, temp9, temp10, temp11, temp12, temp13; - int temp14, temp15, temp16, temp17, temp18, temp19, temp20; - const int* args[3] = {(const int*)ref, (const int*)in, (const int*)dst}; - - __asm__ volatile( - "lw %[temp20], 4(%[args]) \n\t" - VERTICAL_PASS(0, 16, 8, 24, temp4, temp0, temp1, temp2, temp3) - VERTICAL_PASS(2, 18, 10, 26, temp8, temp4, temp5, temp6, temp7) - VERTICAL_PASS(4, 20, 12, 28, temp12, temp8, temp9, temp10, temp11) - VERTICAL_PASS(6, 22, 14, 30, temp20, temp12, temp13, temp14, temp15) - - HORIZONTAL_PASS(0, temp0, temp4, temp8, temp12) - HORIZONTAL_PASS(1, temp1, temp5, temp9, temp13) - HORIZONTAL_PASS(2, temp2, temp6, temp10, temp14) - HORIZONTAL_PASS(3, temp3, temp7, temp11, temp15) - - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11), - [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14), - [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17), - [temp18]"=&r"(temp18), [temp19]"=&r"(temp19), [temp20]"=&r"(temp20) - : [args]"r"(args), [kC1]"r"(kC1), [kC2]"r"(kC2) - : "memory", "hi", "lo" - ); -} - -static void ITransform(const uint8_t* ref, const int16_t* in, - uint8_t* dst, int do_two) { - ITransformOne(ref, in, dst); - if (do_two) { - ITransformOne(ref + 4, in + 16, dst + 4); - } -} - -#undef VERTICAL_PASS -#undef HORIZONTAL_PASS - -// macro for one pass through for loop in QuantizeBlock -// QUANTDIV macro inlined -// J - offset in bytes (kZigzag[n] * 2) -// K - offset in bytes (kZigzag[n] * 4) -// N - offset in bytes (n * 2) -#define QUANTIZE_ONE(J, K, N) \ - "lh %[temp0], " #J "(%[ppin]) \n\t" \ - "lhu %[temp1], " #J "(%[ppsharpen]) \n\t" \ - "lw %[temp2], " #K "(%[ppzthresh]) \n\t" \ - "sra %[sign], %[temp0], 15 \n\t" \ - "xor %[coeff], %[temp0], %[sign] \n\t" \ - "subu %[coeff], %[coeff], %[sign] \n\t" \ - "addu %[coeff], %[coeff], %[temp1] \n\t" \ - "slt %[temp4], %[temp2], %[coeff] \n\t" \ - "addiu %[temp5], $zero, 0 \n\t" \ - "addiu %[level], $zero, 0 \n\t" \ - "beqz %[temp4], 2f \n\t" \ - "lhu %[temp1], " #J "(%[ppiq]) \n\t" \ - "lw %[temp2], " #K "(%[ppbias]) \n\t" \ - "lhu %[temp3], " #J "(%[ppq]) \n\t" \ - "mul %[level], %[coeff], %[temp1] \n\t" \ - "addu %[level], %[level], %[temp2] \n\t" \ - "sra %[level], %[level], 17 \n\t" \ - "slt %[temp4], %[max_level], %[level] \n\t" \ - "movn %[level], %[max_level], %[temp4] \n\t" \ - "xor %[level], %[level], %[sign] \n\t" \ - "subu %[level], %[level], %[sign] \n\t" \ - "mul %[temp5], %[level], %[temp3] \n\t" \ -"2: \n\t" \ - "sh %[temp5], " #J "(%[ppin]) \n\t" \ - "sh %[level], " #N "(%[pout]) \n\t" - -static int QuantizeBlock(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - int temp0, temp1, temp2, temp3, temp4, temp5; - int sign, coeff, level, i; - int max_level = MAX_LEVEL; - - int16_t* ppin = &in[0]; - int16_t* pout = &out[0]; - const uint16_t* ppsharpen = &mtx->sharpen_[0]; - const uint32_t* ppzthresh = &mtx->zthresh_[0]; - const uint16_t* ppq = &mtx->q_[0]; - const uint16_t* ppiq = &mtx->iq_[0]; - const uint32_t* ppbias = &mtx->bias_[0]; - - __asm__ volatile( - QUANTIZE_ONE( 0, 0, 0) - QUANTIZE_ONE( 2, 4, 2) - QUANTIZE_ONE( 8, 16, 4) - QUANTIZE_ONE(16, 32, 6) - QUANTIZE_ONE(10, 20, 8) - QUANTIZE_ONE( 4, 8, 10) - QUANTIZE_ONE( 6, 12, 12) - QUANTIZE_ONE(12, 24, 14) - QUANTIZE_ONE(18, 36, 16) - QUANTIZE_ONE(24, 48, 18) - QUANTIZE_ONE(26, 52, 20) - QUANTIZE_ONE(20, 40, 22) - QUANTIZE_ONE(14, 28, 24) - QUANTIZE_ONE(22, 44, 26) - QUANTIZE_ONE(28, 56, 28) - QUANTIZE_ONE(30, 60, 30) - - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [sign]"=&r"(sign), [coeff]"=&r"(coeff), - [level]"=&r"(level) - : [pout]"r"(pout), [ppin]"r"(ppin), - [ppiq]"r"(ppiq), [max_level]"r"(max_level), - [ppbias]"r"(ppbias), [ppzthresh]"r"(ppzthresh), - [ppsharpen]"r"(ppsharpen), [ppq]"r"(ppq) - : "memory", "hi", "lo" - ); - - // moved out from macro to increase possibility for earlier breaking - for (i = 15; i >= 0; i--) { - if (out[i]) return 1; - } - return 0; -} - -static int Quantize2Blocks(int16_t in[32], int16_t out[32], - const VP8Matrix* const mtx) { - int nz; - nz = QuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0; - nz |= QuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1; - return nz; -} - -#undef QUANTIZE_ONE - -// macro for one horizontal pass in Disto4x4 (TTransform) -// two calls of function TTransform are merged into single one -// A - offset in bytes to load from a and b buffers -// E..H - offsets in bytes to store first results to tmp buffer -// E1..H1 - offsets in bytes to store second results to tmp buffer -#define HORIZONTAL_PASS(A, E, F, G, H, E1, F1, G1, H1) \ - "lbu %[temp0], 0+" XSTR(BPS) "*" #A "(%[a]) \n\t" \ - "lbu %[temp1], 1+" XSTR(BPS) "*" #A "(%[a]) \n\t" \ - "lbu %[temp2], 2+" XSTR(BPS) "*" #A "(%[a]) \n\t" \ - "lbu %[temp3], 3+" XSTR(BPS) "*" #A "(%[a]) \n\t" \ - "lbu %[temp4], 0+" XSTR(BPS) "*" #A "(%[b]) \n\t" \ - "lbu %[temp5], 1+" XSTR(BPS) "*" #A "(%[b]) \n\t" \ - "lbu %[temp6], 2+" XSTR(BPS) "*" #A "(%[b]) \n\t" \ - "lbu %[temp7], 3+" XSTR(BPS) "*" #A "(%[b]) \n\t" \ - "addu %[temp8], %[temp0], %[temp2] \n\t" \ - "subu %[temp0], %[temp0], %[temp2] \n\t" \ - "addu %[temp2], %[temp1], %[temp3] \n\t" \ - "subu %[temp1], %[temp1], %[temp3] \n\t" \ - "addu %[temp3], %[temp4], %[temp6] \n\t" \ - "subu %[temp4], %[temp4], %[temp6] \n\t" \ - "addu %[temp6], %[temp5], %[temp7] \n\t" \ - "subu %[temp5], %[temp5], %[temp7] \n\t" \ - "addu %[temp7], %[temp8], %[temp2] \n\t" \ - "subu %[temp2], %[temp8], %[temp2] \n\t" \ - "addu %[temp8], %[temp0], %[temp1] \n\t" \ - "subu %[temp0], %[temp0], %[temp1] \n\t" \ - "addu %[temp1], %[temp3], %[temp6] \n\t" \ - "subu %[temp3], %[temp3], %[temp6] \n\t" \ - "addu %[temp6], %[temp4], %[temp5] \n\t" \ - "subu %[temp4], %[temp4], %[temp5] \n\t" \ - "sw %[temp7], " #E "(%[tmp]) \n\t" \ - "sw %[temp2], " #H "(%[tmp]) \n\t" \ - "sw %[temp8], " #F "(%[tmp]) \n\t" \ - "sw %[temp0], " #G "(%[tmp]) \n\t" \ - "sw %[temp1], " #E1 "(%[tmp]) \n\t" \ - "sw %[temp3], " #H1 "(%[tmp]) \n\t" \ - "sw %[temp6], " #F1 "(%[tmp]) \n\t" \ - "sw %[temp4], " #G1 "(%[tmp]) \n\t" - -// macro for one vertical pass in Disto4x4 (TTransform) -// two calls of function TTransform are merged into single one -// since only one accu is available in mips32r1 instruction set -// first is done second call of function TTransform and after -// that first one. -// const int sum1 = TTransform(a, w); -// const int sum2 = TTransform(b, w); -// return abs(sum2 - sum1) >> 5; -// (sum2 - sum1) is calculated with madds (sub2) and msubs (sub1) -// A..D - offsets in bytes to load first results from tmp buffer -// A1..D1 - offsets in bytes to load second results from tmp buffer -// E..H - offsets in bytes to load from w buffer -#define VERTICAL_PASS(A, B, C, D, A1, B1, C1, D1, E, F, G, H) \ - "lw %[temp0], " #A1 "(%[tmp]) \n\t" \ - "lw %[temp1], " #C1 "(%[tmp]) \n\t" \ - "lw %[temp2], " #B1 "(%[tmp]) \n\t" \ - "lw %[temp3], " #D1 "(%[tmp]) \n\t" \ - "addu %[temp8], %[temp0], %[temp1] \n\t" \ - "subu %[temp0], %[temp0], %[temp1] \n\t" \ - "addu %[temp1], %[temp2], %[temp3] \n\t" \ - "subu %[temp2], %[temp2], %[temp3] \n\t" \ - "addu %[temp3], %[temp8], %[temp1] \n\t" \ - "subu %[temp8], %[temp8], %[temp1] \n\t" \ - "addu %[temp1], %[temp0], %[temp2] \n\t" \ - "subu %[temp0], %[temp0], %[temp2] \n\t" \ - "sra %[temp4], %[temp3], 31 \n\t" \ - "sra %[temp5], %[temp1], 31 \n\t" \ - "sra %[temp6], %[temp0], 31 \n\t" \ - "sra %[temp7], %[temp8], 31 \n\t" \ - "xor %[temp3], %[temp3], %[temp4] \n\t" \ - "xor %[temp1], %[temp1], %[temp5] \n\t" \ - "xor %[temp0], %[temp0], %[temp6] \n\t" \ - "xor %[temp8], %[temp8], %[temp7] \n\t" \ - "subu %[temp3], %[temp3], %[temp4] \n\t" \ - "subu %[temp1], %[temp1], %[temp5] \n\t" \ - "subu %[temp0], %[temp0], %[temp6] \n\t" \ - "subu %[temp8], %[temp8], %[temp7] \n\t" \ - "lhu %[temp4], " #E "(%[w]) \n\t" \ - "lhu %[temp5], " #F "(%[w]) \n\t" \ - "lhu %[temp6], " #G "(%[w]) \n\t" \ - "lhu %[temp7], " #H "(%[w]) \n\t" \ - "madd %[temp4], %[temp3] \n\t" \ - "madd %[temp5], %[temp1] \n\t" \ - "madd %[temp6], %[temp0] \n\t" \ - "madd %[temp7], %[temp8] \n\t" \ - "lw %[temp0], " #A "(%[tmp]) \n\t" \ - "lw %[temp1], " #C "(%[tmp]) \n\t" \ - "lw %[temp2], " #B "(%[tmp]) \n\t" \ - "lw %[temp3], " #D "(%[tmp]) \n\t" \ - "addu %[temp8], %[temp0], %[temp1] \n\t" \ - "subu %[temp0], %[temp0], %[temp1] \n\t" \ - "addu %[temp1], %[temp2], %[temp3] \n\t" \ - "subu %[temp2], %[temp2], %[temp3] \n\t" \ - "addu %[temp3], %[temp8], %[temp1] \n\t" \ - "subu %[temp1], %[temp8], %[temp1] \n\t" \ - "addu %[temp8], %[temp0], %[temp2] \n\t" \ - "subu %[temp0], %[temp0], %[temp2] \n\t" \ - "sra %[temp2], %[temp3], 31 \n\t" \ - "xor %[temp3], %[temp3], %[temp2] \n\t" \ - "subu %[temp3], %[temp3], %[temp2] \n\t" \ - "msub %[temp4], %[temp3] \n\t" \ - "sra %[temp2], %[temp8], 31 \n\t" \ - "sra %[temp3], %[temp0], 31 \n\t" \ - "sra %[temp4], %[temp1], 31 \n\t" \ - "xor %[temp8], %[temp8], %[temp2] \n\t" \ - "xor %[temp0], %[temp0], %[temp3] \n\t" \ - "xor %[temp1], %[temp1], %[temp4] \n\t" \ - "subu %[temp8], %[temp8], %[temp2] \n\t" \ - "subu %[temp0], %[temp0], %[temp3] \n\t" \ - "subu %[temp1], %[temp1], %[temp4] \n\t" \ - "msub %[temp5], %[temp8] \n\t" \ - "msub %[temp6], %[temp0] \n\t" \ - "msub %[temp7], %[temp1] \n\t" - -static int Disto4x4(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - int tmp[32]; - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; - - __asm__ volatile( - HORIZONTAL_PASS(0, 0, 4, 8, 12, 64, 68, 72, 76) - HORIZONTAL_PASS(1, 16, 20, 24, 28, 80, 84, 88, 92) - HORIZONTAL_PASS(2, 32, 36, 40, 44, 96, 100, 104, 108) - HORIZONTAL_PASS(3, 48, 52, 56, 60, 112, 116, 120, 124) - "mthi $zero \n\t" - "mtlo $zero \n\t" - VERTICAL_PASS( 0, 16, 32, 48, 64, 80, 96, 112, 0, 8, 16, 24) - VERTICAL_PASS( 4, 20, 36, 52, 68, 84, 100, 116, 2, 10, 18, 26) - VERTICAL_PASS( 8, 24, 40, 56, 72, 88, 104, 120, 4, 12, 20, 28) - VERTICAL_PASS(12, 28, 44, 60, 76, 92, 108, 124, 6, 14, 22, 30) - "mflo %[temp0] \n\t" - "sra %[temp1], %[temp0], 31 \n\t" - "xor %[temp0], %[temp0], %[temp1] \n\t" - "subu %[temp0], %[temp0], %[temp1] \n\t" - "sra %[temp0], %[temp0], 5 \n\t" - - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8) - : [a]"r"(a), [b]"r"(b), [w]"r"(w), [tmp]"r"(tmp) - : "memory", "hi", "lo" - ); - - return temp0; -} - -#undef VERTICAL_PASS -#undef HORIZONTAL_PASS - -static int Disto16x16(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - int D = 0; - int x, y; - for (y = 0; y < 16 * BPS; y += 4 * BPS) { - for (x = 0; x < 16; x += 4) { - D += Disto4x4(a + x + y, b + x + y, w); - } - } - return D; -} - -// macro for one horizontal pass in FTransform -// temp0..temp15 holds tmp[0]..tmp[15] -// A - offset in bytes to load from src and ref buffers -// TEMP0..TEMP3 - registers for corresponding tmp elements -#define HORIZONTAL_PASS(A, TEMP0, TEMP1, TEMP2, TEMP3) \ - "lw %[" #TEMP1 "], 0(%[args]) \n\t" \ - "lw %[" #TEMP2 "], 4(%[args]) \n\t" \ - "lbu %[temp16], 0+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \ - "lbu %[temp17], 0+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \ - "lbu %[temp18], 1+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \ - "lbu %[temp19], 1+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \ - "subu %[temp20], %[temp16], %[temp17] \n\t" \ - "lbu %[temp16], 2+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \ - "lbu %[temp17], 2+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \ - "subu %[" #TEMP0 "], %[temp18], %[temp19] \n\t" \ - "lbu %[temp18], 3+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \ - "lbu %[temp19], 3+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \ - "subu %[" #TEMP1 "], %[temp16], %[temp17] \n\t" \ - "subu %[" #TEMP2 "], %[temp18], %[temp19] \n\t" \ - "addu %[" #TEMP3 "], %[temp20], %[" #TEMP2 "] \n\t" \ - "subu %[" #TEMP2 "], %[temp20], %[" #TEMP2 "] \n\t" \ - "addu %[temp20], %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \ - "subu %[" #TEMP0 "], %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \ - "mul %[temp16], %[" #TEMP2 "], %[c5352] \n\t" \ - "mul %[temp17], %[" #TEMP2 "], %[c2217] \n\t" \ - "mul %[temp18], %[" #TEMP0 "], %[c5352] \n\t" \ - "mul %[temp19], %[" #TEMP0 "], %[c2217] \n\t" \ - "addu %[" #TEMP1 "], %[" #TEMP3 "], %[temp20] \n\t" \ - "subu %[temp20], %[" #TEMP3 "], %[temp20] \n\t" \ - "sll %[" #TEMP0 "], %[" #TEMP1 "], 3 \n\t" \ - "sll %[" #TEMP2 "], %[temp20], 3 \n\t" \ - "addiu %[temp16], %[temp16], 1812 \n\t" \ - "addiu %[temp17], %[temp17], 937 \n\t" \ - "addu %[temp16], %[temp16], %[temp19] \n\t" \ - "subu %[temp17], %[temp17], %[temp18] \n\t" \ - "sra %[" #TEMP1 "], %[temp16], 9 \n\t" \ - "sra %[" #TEMP3 "], %[temp17], 9 \n\t" - -// macro for one vertical pass in FTransform -// temp0..temp15 holds tmp[0]..tmp[15] -// A..D - offsets in bytes to store to out buffer -// TEMP0, TEMP4, TEMP8 and TEMP12 - registers for corresponding tmp elements -#define VERTICAL_PASS(A, B, C, D, TEMP0, TEMP4, TEMP8, TEMP12) \ - "addu %[temp16], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \ - "subu %[temp19], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \ - "addu %[temp17], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \ - "subu %[temp18], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \ - "mul %[" #TEMP8 "], %[temp19], %[c2217] \n\t" \ - "mul %[" #TEMP12 "], %[temp18], %[c2217] \n\t" \ - "mul %[" #TEMP4 "], %[temp19], %[c5352] \n\t" \ - "mul %[temp18], %[temp18], %[c5352] \n\t" \ - "addiu %[temp16], %[temp16], 7 \n\t" \ - "addu %[" #TEMP0 "], %[temp16], %[temp17] \n\t" \ - "sra %[" #TEMP0 "], %[" #TEMP0 "], 4 \n\t" \ - "addu %[" #TEMP12 "], %[" #TEMP12 "], %[" #TEMP4 "] \n\t" \ - "subu %[" #TEMP4 "], %[temp16], %[temp17] \n\t" \ - "sra %[" #TEMP4 "], %[" #TEMP4 "], 4 \n\t" \ - "addiu %[" #TEMP8 "], %[" #TEMP8 "], 30000 \n\t" \ - "addiu %[" #TEMP12 "], %[" #TEMP12 "], 12000 \n\t" \ - "addiu %[" #TEMP8 "], %[" #TEMP8 "], 21000 \n\t" \ - "subu %[" #TEMP8 "], %[" #TEMP8 "], %[temp18] \n\t" \ - "sra %[" #TEMP12 "], %[" #TEMP12 "], 16 \n\t" \ - "sra %[" #TEMP8 "], %[" #TEMP8 "], 16 \n\t" \ - "addiu %[temp16], %[" #TEMP12 "], 1 \n\t" \ - "movn %[" #TEMP12 "], %[temp16], %[temp19] \n\t" \ - "sh %[" #TEMP0 "], " #A "(%[temp20]) \n\t" \ - "sh %[" #TEMP4 "], " #C "(%[temp20]) \n\t" \ - "sh %[" #TEMP8 "], " #D "(%[temp20]) \n\t" \ - "sh %[" #TEMP12 "], " #B "(%[temp20]) \n\t" - -static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) { - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; - int temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16; - int temp17, temp18, temp19, temp20; - const int c2217 = 2217; - const int c5352 = 5352; - const int* const args[3] = - { (const int*)src, (const int*)ref, (const int*)out }; - - __asm__ volatile( - HORIZONTAL_PASS(0, temp0, temp1, temp2, temp3) - HORIZONTAL_PASS(1, temp4, temp5, temp6, temp7) - HORIZONTAL_PASS(2, temp8, temp9, temp10, temp11) - HORIZONTAL_PASS(3, temp12, temp13, temp14, temp15) - "lw %[temp20], 8(%[args]) \n\t" - VERTICAL_PASS(0, 8, 16, 24, temp0, temp4, temp8, temp12) - VERTICAL_PASS(2, 10, 18, 26, temp1, temp5, temp9, temp13) - VERTICAL_PASS(4, 12, 20, 28, temp2, temp6, temp10, temp14) - VERTICAL_PASS(6, 14, 22, 30, temp3, temp7, temp11, temp15) - - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11), - [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14), - [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17), - [temp18]"=&r"(temp18), [temp19]"=&r"(temp19), [temp20]"=&r"(temp20) - : [args]"r"(args), [c2217]"r"(c2217), [c5352]"r"(c5352) - : "memory", "hi", "lo" - ); -} - -#undef VERTICAL_PASS -#undef HORIZONTAL_PASS - -#if !defined(WORK_AROUND_GCC) - -#define GET_SSE_INNER(A, B, C, D) \ - "lbu %[temp0], " #A "(%[a]) \n\t" \ - "lbu %[temp1], " #A "(%[b]) \n\t" \ - "lbu %[temp2], " #B "(%[a]) \n\t" \ - "lbu %[temp3], " #B "(%[b]) \n\t" \ - "lbu %[temp4], " #C "(%[a]) \n\t" \ - "lbu %[temp5], " #C "(%[b]) \n\t" \ - "lbu %[temp6], " #D "(%[a]) \n\t" \ - "lbu %[temp7], " #D "(%[b]) \n\t" \ - "subu %[temp0], %[temp0], %[temp1] \n\t" \ - "subu %[temp2], %[temp2], %[temp3] \n\t" \ - "subu %[temp4], %[temp4], %[temp5] \n\t" \ - "subu %[temp6], %[temp6], %[temp7] \n\t" \ - "madd %[temp0], %[temp0] \n\t" \ - "madd %[temp2], %[temp2] \n\t" \ - "madd %[temp4], %[temp4] \n\t" \ - "madd %[temp6], %[temp6] \n\t" - -#define GET_SSE(A, B, C, D) \ - GET_SSE_INNER(A, A + 1, A + 2, A + 3) \ - GET_SSE_INNER(B, B + 1, B + 2, B + 3) \ - GET_SSE_INNER(C, C + 1, C + 2, C + 3) \ - GET_SSE_INNER(D, D + 1, D + 2, D + 3) - -static int SSE16x16(const uint8_t* a, const uint8_t* b) { - int count; - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; - - __asm__ volatile( - "mult $zero, $zero \n\t" - - GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS) - GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS) - GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS) - GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS) - GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS) - GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS) - GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS) - GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS) - GET_SSE( 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS) - GET_SSE( 9 * BPS, 4 + 9 * BPS, 8 + 9 * BPS, 12 + 9 * BPS) - GET_SSE(10 * BPS, 4 + 10 * BPS, 8 + 10 * BPS, 12 + 10 * BPS) - GET_SSE(11 * BPS, 4 + 11 * BPS, 8 + 11 * BPS, 12 + 11 * BPS) - GET_SSE(12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS) - GET_SSE(13 * BPS, 4 + 13 * BPS, 8 + 13 * BPS, 12 + 13 * BPS) - GET_SSE(14 * BPS, 4 + 14 * BPS, 8 + 14 * BPS, 12 + 14 * BPS) - GET_SSE(15 * BPS, 4 + 15 * BPS, 8 + 15 * BPS, 12 + 15 * BPS) - - "mflo %[count] \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count) - : [a]"r"(a), [b]"r"(b) - : "memory", "hi", "lo" - ); - return count; -} - -static int SSE16x8(const uint8_t* a, const uint8_t* b) { - int count; - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; - - __asm__ volatile( - "mult $zero, $zero \n\t" - - GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS) - GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS) - GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS) - GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS) - GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS) - GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS) - GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS) - GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS) - - "mflo %[count] \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count) - : [a]"r"(a), [b]"r"(b) - : "memory", "hi", "lo" - ); - return count; -} - -static int SSE8x8(const uint8_t* a, const uint8_t* b) { - int count; - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; - - __asm__ volatile( - "mult $zero, $zero \n\t" - - GET_SSE(0 * BPS, 4 + 0 * BPS, 1 * BPS, 4 + 1 * BPS) - GET_SSE(2 * BPS, 4 + 2 * BPS, 3 * BPS, 4 + 3 * BPS) - GET_SSE(4 * BPS, 4 + 4 * BPS, 5 * BPS, 4 + 5 * BPS) - GET_SSE(6 * BPS, 4 + 6 * BPS, 7 * BPS, 4 + 7 * BPS) - - "mflo %[count] \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count) - : [a]"r"(a), [b]"r"(b) - : "memory", "hi", "lo" - ); - return count; -} - -static int SSE4x4(const uint8_t* a, const uint8_t* b) { - int count; - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; - - __asm__ volatile( - "mult $zero, $zero \n\t" - - GET_SSE(0 * BPS, 1 * BPS, 2 * BPS, 3 * BPS) - - "mflo %[count] \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count) - : [a]"r"(a), [b]"r"(b) - : "memory", "hi", "lo" - ); - return count; -} - -#undef GET_SSE -#undef GET_SSE_INNER - -#endif // !WORK_AROUND_GCC - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8EncDspInitMIPS32(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitMIPS32(void) { - VP8ITransform = ITransform; - VP8FTransform = FTransform; - VP8EncQuantizeBlock = QuantizeBlock; - VP8EncQuantize2Blocks = Quantize2Blocks; - VP8TDisto4x4 = Disto4x4; - VP8TDisto16x16 = Disto16x16; -#if !defined(WORK_AROUND_GCC) - VP8SSE16x16 = SSE16x16; - VP8SSE8x8 = SSE8x8; - VP8SSE16x8 = SSE16x8; - VP8SSE4x4 = SSE4x4; -#endif -} - -#else // !WEBP_USE_MIPS32 - -WEBP_DSP_INIT_STUB(VP8EncDspInitMIPS32) - -#endif // WEBP_USE_MIPS32 diff --git a/Example/Pods/libwebp/src/dsp/enc_mips_dsp_r2.c b/Example/Pods/libwebp/src/dsp/enc_mips_dsp_r2.c deleted file mode 100644 index 7c814fa0..00000000 --- a/Example/Pods/libwebp/src/dsp/enc_mips_dsp_r2.c +++ /dev/null @@ -1,1512 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// MIPS version of speed-critical encoding functions. -// -// Author(s): Darko Laus (darko.laus@imgtec.com) -// Mirko Raus (mirko.raus@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS_DSP_R2) - -#include "./mips_macro.h" -#include "../enc/cost.h" -#include "../enc/vp8enci.h" - -static const int kC1 = 20091 + (1 << 16); -static const int kC2 = 35468; - -// O - output -// I - input (macro doesn't change it) -#define ADD_SUB_HALVES_X4(O0, O1, O2, O3, O4, O5, O6, O7, \ - I0, I1, I2, I3, I4, I5, I6, I7) \ - "addq.ph %[" #O0 "], %[" #I0 "], %[" #I1 "] \n\t" \ - "subq.ph %[" #O1 "], %[" #I0 "], %[" #I1 "] \n\t" \ - "addq.ph %[" #O2 "], %[" #I2 "], %[" #I3 "] \n\t" \ - "subq.ph %[" #O3 "], %[" #I2 "], %[" #I3 "] \n\t" \ - "addq.ph %[" #O4 "], %[" #I4 "], %[" #I5 "] \n\t" \ - "subq.ph %[" #O5 "], %[" #I4 "], %[" #I5 "] \n\t" \ - "addq.ph %[" #O6 "], %[" #I6 "], %[" #I7 "] \n\t" \ - "subq.ph %[" #O7 "], %[" #I6 "], %[" #I7 "] \n\t" - -// IO - input/output -#define ABS_X8(IO0, IO1, IO2, IO3, IO4, IO5, IO6, IO7) \ - "absq_s.ph %[" #IO0 "], %[" #IO0 "] \n\t" \ - "absq_s.ph %[" #IO1 "], %[" #IO1 "] \n\t" \ - "absq_s.ph %[" #IO2 "], %[" #IO2 "] \n\t" \ - "absq_s.ph %[" #IO3 "], %[" #IO3 "] \n\t" \ - "absq_s.ph %[" #IO4 "], %[" #IO4 "] \n\t" \ - "absq_s.ph %[" #IO5 "], %[" #IO5 "] \n\t" \ - "absq_s.ph %[" #IO6 "], %[" #IO6 "] \n\t" \ - "absq_s.ph %[" #IO7 "], %[" #IO7 "] \n\t" - -// dpa.w.ph $ac0 temp0 ,temp1 -// $ac += temp0[31..16] * temp1[31..16] + temp0[15..0] * temp1[15..0] -// dpax.w.ph $ac0 temp0 ,temp1 -// $ac += temp0[31..16] * temp1[15..0] + temp0[15..0] * temp1[31..16] -// O - output -// I - input (macro doesn't change it) -#define MUL_HALF(O0, I0, I1, I2, I3, I4, I5, I6, I7, \ - I8, I9, I10, I11, I12, I13, I14, I15) \ - "mult $ac0, $zero, $zero \n\t" \ - "dpa.w.ph $ac0, %[" #I2 "], %[" #I0 "] \n\t" \ - "dpax.w.ph $ac0, %[" #I5 "], %[" #I6 "] \n\t" \ - "dpa.w.ph $ac0, %[" #I8 "], %[" #I9 "] \n\t" \ - "dpax.w.ph $ac0, %[" #I11 "], %[" #I4 "] \n\t" \ - "dpa.w.ph $ac0, %[" #I12 "], %[" #I7 "] \n\t" \ - "dpax.w.ph $ac0, %[" #I13 "], %[" #I1 "] \n\t" \ - "dpa.w.ph $ac0, %[" #I14 "], %[" #I3 "] \n\t" \ - "dpax.w.ph $ac0, %[" #I15 "], %[" #I10 "] \n\t" \ - "mflo %[" #O0 "], $ac0 \n\t" - -#define OUTPUT_EARLY_CLOBBER_REGS_17() \ - OUTPUT_EARLY_CLOBBER_REGS_10(), \ - [temp11]"=&r"(temp11), [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), \ - [temp14]"=&r"(temp14), [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), \ - [temp17]"=&r"(temp17) - -// macro for one horizontal pass in FTransform -// temp0..temp15 holds tmp[0]..tmp[15] -// A - offset in bytes to load from src and ref buffers -// TEMP0..TEMP3 - registers for corresponding tmp elements -#define HORIZONTAL_PASS(A, TEMP0, TEMP1, TEMP2, TEMP3) \ - "lw %[" #TEMP0 "], 0(%[args]) \n\t" \ - "lw %[" #TEMP1 "], 4(%[args]) \n\t" \ - "lw %[" #TEMP2 "], " XSTR(BPS) "*" #A "(%[" #TEMP0 "]) \n\t" \ - "lw %[" #TEMP3 "], " XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \ - "preceu.ph.qbl %[" #TEMP0 "], %[" #TEMP2 "] \n\t" \ - "preceu.ph.qbl %[" #TEMP1 "], %[" #TEMP3 "] \n\t" \ - "preceu.ph.qbr %[" #TEMP2 "], %[" #TEMP2 "] \n\t" \ - "preceu.ph.qbr %[" #TEMP3 "], %[" #TEMP3 "] \n\t" \ - "subq.ph %[" #TEMP0 "], %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \ - "subq.ph %[" #TEMP2 "], %[" #TEMP2 "], %[" #TEMP3 "] \n\t" \ - "rotr %[" #TEMP0 "], %[" #TEMP0 "], 16 \n\t" \ - "addq.ph %[" #TEMP1 "], %[" #TEMP2 "], %[" #TEMP0 "] \n\t" \ - "subq.ph %[" #TEMP3 "], %[" #TEMP2 "], %[" #TEMP0 "] \n\t" \ - "seh %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \ - "sra %[temp16], %[" #TEMP1 "], 16 \n\t" \ - "seh %[temp19], %[" #TEMP3 "] \n\t" \ - "sra %[" #TEMP3 "], %[" #TEMP3 "], 16 \n\t" \ - "subu %[" #TEMP2 "], %[" #TEMP0 "], %[temp16] \n\t" \ - "addu %[" #TEMP0 "], %[" #TEMP0 "], %[temp16] \n\t" \ - "mul %[temp17], %[temp19], %[c2217] \n\t" \ - "mul %[temp18], %[" #TEMP3 "], %[c5352] \n\t" \ - "mul %[" #TEMP1 "], %[temp19], %[c5352] \n\t" \ - "mul %[temp16], %[" #TEMP3 "], %[c2217] \n\t" \ - "sll %[" #TEMP2 "], %[" #TEMP2 "], 3 \n\t" \ - "sll %[" #TEMP0 "], %[" #TEMP0 "], 3 \n\t" \ - "subu %[" #TEMP3 "], %[temp17], %[temp18] \n\t" \ - "addu %[" #TEMP1 "], %[temp16], %[" #TEMP1 "] \n\t" \ - "addiu %[" #TEMP3 "], %[" #TEMP3 "], 937 \n\t" \ - "addiu %[" #TEMP1 "], %[" #TEMP1 "], 1812 \n\t" \ - "sra %[" #TEMP3 "], %[" #TEMP3 "], 9 \n\t" \ - "sra %[" #TEMP1 "], %[" #TEMP1 "], 9 \n\t" - -// macro for one vertical pass in FTransform -// temp0..temp15 holds tmp[0]..tmp[15] -// A..D - offsets in bytes to store to out buffer -// TEMP0, TEMP4, TEMP8 and TEMP12 - registers for corresponding tmp elements -#define VERTICAL_PASS(A, B, C, D, TEMP0, TEMP4, TEMP8, TEMP12) \ - "addu %[temp16], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \ - "subu %[temp19], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \ - "addu %[temp17], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \ - "subu %[temp18], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \ - "mul %[" #TEMP8 "], %[temp19], %[c2217] \n\t" \ - "mul %[" #TEMP12 "], %[temp18], %[c2217] \n\t" \ - "mul %[" #TEMP4 "], %[temp19], %[c5352] \n\t" \ - "mul %[temp18], %[temp18], %[c5352] \n\t" \ - "addiu %[temp16], %[temp16], 7 \n\t" \ - "addu %[" #TEMP0 "], %[temp16], %[temp17] \n\t" \ - "sra %[" #TEMP0 "], %[" #TEMP0 "], 4 \n\t" \ - "addu %[" #TEMP12 "], %[" #TEMP12 "], %[" #TEMP4 "] \n\t" \ - "subu %[" #TEMP4 "], %[temp16], %[temp17] \n\t" \ - "sra %[" #TEMP4 "], %[" #TEMP4 "], 4 \n\t" \ - "addiu %[" #TEMP8 "], %[" #TEMP8 "], 30000 \n\t" \ - "addiu %[" #TEMP12 "], %[" #TEMP12 "], 12000 \n\t" \ - "addiu %[" #TEMP8 "], %[" #TEMP8 "], 21000 \n\t" \ - "subu %[" #TEMP8 "], %[" #TEMP8 "], %[temp18] \n\t" \ - "sra %[" #TEMP12 "], %[" #TEMP12 "], 16 \n\t" \ - "sra %[" #TEMP8 "], %[" #TEMP8 "], 16 \n\t" \ - "addiu %[temp16], %[" #TEMP12 "], 1 \n\t" \ - "movn %[" #TEMP12 "], %[temp16], %[temp19] \n\t" \ - "sh %[" #TEMP0 "], " #A "(%[temp20]) \n\t" \ - "sh %[" #TEMP4 "], " #C "(%[temp20]) \n\t" \ - "sh %[" #TEMP8 "], " #D "(%[temp20]) \n\t" \ - "sh %[" #TEMP12 "], " #B "(%[temp20]) \n\t" - -static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) { - const int c2217 = 2217; - const int c5352 = 5352; - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; - int temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16; - int temp17, temp18, temp19, temp20; - const int* const args[3] = - { (const int*)src, (const int*)ref, (const int*)out }; - - __asm__ volatile ( - HORIZONTAL_PASS(0, temp0, temp1, temp2, temp3) - HORIZONTAL_PASS(1, temp4, temp5, temp6, temp7) - HORIZONTAL_PASS(2, temp8, temp9, temp10, temp11) - HORIZONTAL_PASS(3, temp12, temp13, temp14, temp15) - "lw %[temp20], 8(%[args]) \n\t" - VERTICAL_PASS(0, 8, 16, 24, temp0, temp4, temp8, temp12) - VERTICAL_PASS(2, 10, 18, 26, temp1, temp5, temp9, temp13) - VERTICAL_PASS(4, 12, 20, 28, temp2, temp6, temp10, temp14) - VERTICAL_PASS(6, 14, 22, 30, temp3, temp7, temp11, temp15) - OUTPUT_EARLY_CLOBBER_REGS_18(), - [temp0]"=&r"(temp0), [temp19]"=&r"(temp19), [temp20]"=&r"(temp20) - : [args]"r"(args), [c2217]"r"(c2217), [c5352]"r"(c5352) - : "memory", "hi", "lo" - ); -} - -#undef VERTICAL_PASS -#undef HORIZONTAL_PASS - -static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, - uint8_t* dst) { - int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; - int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18; - - __asm__ volatile ( - "ulw %[temp1], 0(%[in]) \n\t" - "ulw %[temp2], 16(%[in]) \n\t" - LOAD_IN_X2(temp5, temp6, 24, 26) - ADD_SUB_HALVES(temp3, temp4, temp1, temp2) - LOAD_IN_X2(temp1, temp2, 8, 10) - MUL_SHIFT_SUM(temp7, temp8, temp9, temp10, temp11, temp12, temp13, temp14, - temp10, temp8, temp9, temp7, temp1, temp2, temp5, temp6, - temp13, temp11, temp14, temp12) - INSERT_HALF_X2(temp8, temp7, temp10, temp9) - "ulw %[temp17], 4(%[in]) \n\t" - "ulw %[temp18], 20(%[in]) \n\t" - ADD_SUB_HALVES(temp1, temp2, temp3, temp8) - ADD_SUB_HALVES(temp5, temp6, temp4, temp7) - ADD_SUB_HALVES(temp7, temp8, temp17, temp18) - LOAD_IN_X2(temp17, temp18, 12, 14) - LOAD_IN_X2(temp9, temp10, 28, 30) - MUL_SHIFT_SUM(temp11, temp12, temp13, temp14, temp15, temp16, temp4, temp17, - temp12, temp14, temp11, temp13, temp17, temp18, temp9, temp10, - temp15, temp4, temp16, temp17) - INSERT_HALF_X2(temp11, temp12, temp13, temp14) - ADD_SUB_HALVES(temp17, temp8, temp8, temp11) - ADD_SUB_HALVES(temp3, temp4, temp7, temp12) - - // horizontal - SRA_16(temp9, temp10, temp11, temp12, temp1, temp2, temp5, temp6) - INSERT_HALF_X2(temp1, temp6, temp5, temp2) - SRA_16(temp13, temp14, temp15, temp16, temp3, temp4, temp17, temp8) - "repl.ph %[temp2], 0x4 \n\t" - INSERT_HALF_X2(temp3, temp8, temp17, temp4) - "addq.ph %[temp1], %[temp1], %[temp2] \n\t" - "addq.ph %[temp6], %[temp6], %[temp2] \n\t" - ADD_SUB_HALVES(temp2, temp4, temp1, temp3) - ADD_SUB_HALVES(temp5, temp7, temp6, temp8) - MUL_SHIFT_SUM(temp1, temp3, temp6, temp8, temp9, temp13, temp17, temp18, - temp3, temp13, temp1, temp9, temp9, temp13, temp11, temp15, - temp6, temp17, temp8, temp18) - MUL_SHIFT_SUM(temp6, temp8, temp18, temp17, temp11, temp15, temp12, temp16, - temp8, temp15, temp6, temp11, temp12, temp16, temp10, temp14, - temp18, temp12, temp17, temp16) - INSERT_HALF_X2(temp1, temp3, temp9, temp13) - INSERT_HALF_X2(temp6, temp8, temp11, temp15) - SHIFT_R_SUM_X2(temp9, temp10, temp11, temp12, temp13, temp14, temp15, - temp16, temp2, temp4, temp5, temp7, temp3, temp1, temp8, - temp6) - PACK_2_HALVES_TO_WORD(temp1, temp2, temp3, temp4, temp9, temp12, temp13, - temp16, temp11, temp10, temp15, temp14) - LOAD_WITH_OFFSET_X4(temp10, temp11, temp14, temp15, ref, - 0, 0, 0, 0, - 0, 1, 2, 3, - BPS) - CONVERT_2_BYTES_TO_HALF(temp5, temp6, temp7, temp8, temp17, temp18, temp10, - temp11, temp10, temp11, temp14, temp15) - STORE_SAT_SUM_X2(temp5, temp6, temp7, temp8, temp17, temp18, temp10, temp11, - temp9, temp12, temp1, temp2, temp13, temp16, temp3, temp4, - dst, 0, 1, 2, 3, BPS) - - OUTPUT_EARLY_CLOBBER_REGS_18() - : [dst]"r"(dst), [in]"r"(in), [kC1]"r"(kC1), [kC2]"r"(kC2), [ref]"r"(ref) - : "memory", "hi", "lo" - ); -} - -static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst, - int do_two) { - ITransformOne(ref, in, dst); - if (do_two) { - ITransformOne(ref + 4, in + 16, dst + 4); - } -} - -static int Disto4x4(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; - int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17; - - __asm__ volatile ( - LOAD_WITH_OFFSET_X4(temp1, temp2, temp3, temp4, a, - 0, 0, 0, 0, - 0, 1, 2, 3, - BPS) - CONVERT_2_BYTES_TO_HALF(temp5, temp6, temp7, temp8, temp9,temp10, temp11, - temp12, temp1, temp2, temp3, temp4) - ADD_SUB_HALVES_X4(temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, - temp5, temp6, temp7, temp8, temp9, temp10, temp11, temp12) - PACK_2_HALVES_TO_WORD(temp9, temp10, temp11, temp12, temp1, temp3, temp5, - temp7, temp2, temp4, temp6, temp8) - ADD_SUB_HALVES_X4(temp2, temp4, temp6, temp8, temp9, temp1, temp3, temp10, - temp1, temp9, temp3, temp10, temp5, temp11, temp7, temp12) - ADD_SUB_HALVES_X4(temp5, temp11, temp7, temp2, temp9, temp3, temp6, temp12, - temp2, temp9, temp6, temp3, temp4, temp1, temp8, temp10) - ADD_SUB_HALVES_X4(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2, - temp5, temp7, temp11, temp2, temp9, temp6, temp3, temp12) - ABS_X8(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2) - LOAD_WITH_OFFSET_X4(temp3, temp6, temp9, temp12, w, - 0, 4, 8, 12, - 0, 0, 0, 0, - 0) - LOAD_WITH_OFFSET_X4(temp13, temp14, temp15, temp16, w, - 0, 4, 8, 12, - 1, 1, 1, 1, - 16) - MUL_HALF(temp17, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, - temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16) - LOAD_WITH_OFFSET_X4(temp1, temp2, temp3, temp4, b, - 0, 0, 0, 0, - 0, 1, 2, 3, - BPS) - CONVERT_2_BYTES_TO_HALF(temp5,temp6, temp7, temp8, temp9,temp10, temp11, - temp12, temp1, temp2, temp3, temp4) - ADD_SUB_HALVES_X4(temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, - temp5, temp6, temp7, temp8, temp9, temp10, temp11, temp12) - PACK_2_HALVES_TO_WORD(temp9, temp10, temp11, temp12, temp1, temp3, temp5, - temp7, temp2, temp4, temp6, temp8) - ADD_SUB_HALVES_X4(temp2, temp4, temp6, temp8, temp9, temp1, temp3, temp10, - temp1, temp9, temp3, temp10, temp5, temp11, temp7, temp12) - ADD_SUB_HALVES_X4(temp5, temp11, temp7, temp2, temp9, temp3, temp6, temp12, - temp2, temp9, temp6, temp3, temp4, temp1, temp8, temp10) - ADD_SUB_HALVES_X4(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2, - temp5, temp7, temp11, temp2, temp9, temp6, temp3, temp12) - ABS_X8(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2) - LOAD_WITH_OFFSET_X4(temp3, temp6, temp9, temp12, w, - 0, 4, 8, 12, - 0, 0, 0, 0, - 0) - LOAD_WITH_OFFSET_X4(temp13, temp14, temp15, temp16, w, - 0, 4, 8, 12, - 1, 1, 1, 1, - 16) - MUL_HALF(temp3, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, - temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16) - OUTPUT_EARLY_CLOBBER_REGS_17() - : [a]"r"(a), [b]"r"(b), [w]"r"(w) - : "memory", "hi", "lo" - ); - return abs(temp3 - temp17) >> 5; -} - -static int Disto16x16(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - int D = 0; - int x, y; - for (y = 0; y < 16 * BPS; y += 4 * BPS) { - for (x = 0; x < 16; x += 4) { - D += Disto4x4(a + x + y, b + x + y, w); - } - } - return D; -} - -//------------------------------------------------------------------------------ -// Intra predictions - -#define FILL_PART(J, SIZE) \ - "usw %[value], 0+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \ - "usw %[value], 4+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \ - ".if " #SIZE " == 16 \n\t" \ - "usw %[value], 8+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \ - "usw %[value], 12+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \ - ".endif \n\t" - -#define FILL_8_OR_16(DST, VALUE, SIZE) do { \ - int value = (VALUE); \ - __asm__ volatile ( \ - "replv.qb %[value], %[value] \n\t" \ - FILL_PART( 0, SIZE) \ - FILL_PART( 1, SIZE) \ - FILL_PART( 2, SIZE) \ - FILL_PART( 3, SIZE) \ - FILL_PART( 4, SIZE) \ - FILL_PART( 5, SIZE) \ - FILL_PART( 6, SIZE) \ - FILL_PART( 7, SIZE) \ - ".if " #SIZE " == 16 \n\t" \ - FILL_PART( 8, 16) \ - FILL_PART( 9, 16) \ - FILL_PART(10, 16) \ - FILL_PART(11, 16) \ - FILL_PART(12, 16) \ - FILL_PART(13, 16) \ - FILL_PART(14, 16) \ - FILL_PART(15, 16) \ - ".endif \n\t" \ - : [value]"+&r"(value) \ - : [dst]"r"((DST)) \ - : "memory" \ - ); \ -} while (0) - -#define VERTICAL_PRED(DST, TOP, SIZE) \ -static WEBP_INLINE void VerticalPred##SIZE(uint8_t* (DST), \ - const uint8_t* (TOP)) { \ - int j; \ - if ((TOP)) { \ - for (j = 0; j < (SIZE); ++j) memcpy((DST) + j * BPS, (TOP), (SIZE)); \ - } else { \ - FILL_8_OR_16((DST), 127, (SIZE)); \ - } \ -} - -VERTICAL_PRED(dst, top, 8) -VERTICAL_PRED(dst, top, 16) - -#undef VERTICAL_PRED - -#define HORIZONTAL_PRED(DST, LEFT, SIZE) \ -static WEBP_INLINE void HorizontalPred##SIZE(uint8_t* (DST), \ - const uint8_t* (LEFT)) { \ - if (LEFT) { \ - int j; \ - for (j = 0; j < (SIZE); ++j) { \ - memset((DST) + j * BPS, (LEFT)[j], (SIZE)); \ - } \ - } else { \ - FILL_8_OR_16((DST), 129, (SIZE)); \ - } \ -} - -HORIZONTAL_PRED(dst, left, 8) -HORIZONTAL_PRED(dst, left, 16) - -#undef HORIZONTAL_PRED - -#define CLIPPING() \ - "preceu.ph.qbl %[temp2], %[temp0] \n\t" \ - "preceu.ph.qbr %[temp0], %[temp0] \n\t" \ - "preceu.ph.qbl %[temp3], %[temp1] \n\t" \ - "preceu.ph.qbr %[temp1], %[temp1] \n\t" \ - "addu.ph %[temp2], %[temp2], %[leftY_1] \n\t" \ - "addu.ph %[temp0], %[temp0], %[leftY_1] \n\t" \ - "addu.ph %[temp3], %[temp3], %[leftY_1] \n\t" \ - "addu.ph %[temp1], %[temp1], %[leftY_1] \n\t" \ - "shll_s.ph %[temp2], %[temp2], 7 \n\t" \ - "shll_s.ph %[temp0], %[temp0], 7 \n\t" \ - "shll_s.ph %[temp3], %[temp3], 7 \n\t" \ - "shll_s.ph %[temp1], %[temp1], 7 \n\t" \ - "precrqu_s.qb.ph %[temp0], %[temp2], %[temp0] \n\t" \ - "precrqu_s.qb.ph %[temp1], %[temp3], %[temp1] \n\t" - -#define CLIP_8B_TO_DST(DST, LEFT, TOP, SIZE) do { \ - int leftY_1 = ((int)(LEFT)[y] << 16) + (LEFT)[y]; \ - int temp0, temp1, temp2, temp3; \ - __asm__ volatile ( \ - "replv.ph %[leftY_1], %[leftY_1] \n\t" \ - "ulw %[temp0], 0(%[top]) \n\t" \ - "ulw %[temp1], 4(%[top]) \n\t" \ - "subu.ph %[leftY_1], %[leftY_1], %[left_1] \n\t" \ - CLIPPING() \ - "usw %[temp0], 0(%[dst]) \n\t" \ - "usw %[temp1], 4(%[dst]) \n\t" \ - ".if " #SIZE " == 16 \n\t" \ - "ulw %[temp0], 8(%[top]) \n\t" \ - "ulw %[temp1], 12(%[top]) \n\t" \ - CLIPPING() \ - "usw %[temp0], 8(%[dst]) \n\t" \ - "usw %[temp1], 12(%[dst]) \n\t" \ - ".endif \n\t" \ - : [leftY_1]"+&r"(leftY_1), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), \ - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3) \ - : [left_1]"r"(left_1), [top]"r"((TOP)), [dst]"r"((DST)) \ - : "memory" \ - ); \ -} while (0) - -#define CLIP_TO_DST(DST, LEFT, TOP, SIZE) do { \ - int y; \ - const int left_1 = ((int)(LEFT)[-1] << 16) + (LEFT)[-1]; \ - for (y = 0; y < (SIZE); ++y) { \ - CLIP_8B_TO_DST((DST), (LEFT), (TOP), (SIZE)); \ - (DST) += BPS; \ - } \ -} while (0) - -#define TRUE_MOTION(DST, LEFT, TOP, SIZE) \ -static WEBP_INLINE void TrueMotion##SIZE(uint8_t* (DST), const uint8_t* (LEFT),\ - const uint8_t* (TOP)) { \ - if ((LEFT) != NULL) { \ - if ((TOP) != NULL) { \ - CLIP_TO_DST((DST), (LEFT), (TOP), (SIZE)); \ - } else { \ - HorizontalPred##SIZE((DST), (LEFT)); \ - } \ - } else { \ - /* true motion without left samples (hence: with default 129 value) */ \ - /* is equivalent to VE prediction where you just copy the top samples. */ \ - /* Note that if top samples are not available, the default value is */ \ - /* then 129, and not 127 as in the VerticalPred case. */ \ - if ((TOP) != NULL) { \ - VerticalPred##SIZE((DST), (TOP)); \ - } else { \ - FILL_8_OR_16((DST), 129, (SIZE)); \ - } \ - } \ -} - -TRUE_MOTION(dst, left, top, 8) -TRUE_MOTION(dst, left, top, 16) - -#undef TRUE_MOTION -#undef CLIP_TO_DST -#undef CLIP_8B_TO_DST -#undef CLIPPING - -static WEBP_INLINE void DCMode16(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { - int DC, DC1; - int temp0, temp1, temp2, temp3; - - __asm__ volatile( - "beqz %[top], 2f \n\t" - LOAD_WITH_OFFSET_X4(temp0, temp1, temp2, temp3, top, - 0, 4, 8, 12, - 0, 0, 0, 0, - 0) - "raddu.w.qb %[temp0], %[temp0] \n\t" - "raddu.w.qb %[temp1], %[temp1] \n\t" - "raddu.w.qb %[temp2], %[temp2] \n\t" - "raddu.w.qb %[temp3], %[temp3] \n\t" - "addu %[temp0], %[temp0], %[temp1] \n\t" - "addu %[temp2], %[temp2], %[temp3] \n\t" - "addu %[DC], %[temp0], %[temp2] \n\t" - "move %[DC1], %[DC] \n\t" - "beqz %[left], 1f \n\t" - LOAD_WITH_OFFSET_X4(temp0, temp1, temp2, temp3, left, - 0, 4, 8, 12, - 0, 0, 0, 0, - 0) - "raddu.w.qb %[temp0], %[temp0] \n\t" - "raddu.w.qb %[temp1], %[temp1] \n\t" - "raddu.w.qb %[temp2], %[temp2] \n\t" - "raddu.w.qb %[temp3], %[temp3] \n\t" - "addu %[temp0], %[temp0], %[temp1] \n\t" - "addu %[temp2], %[temp2], %[temp3] \n\t" - "addu %[DC1], %[temp0], %[temp2] \n\t" - "1: \n\t" - "addu %[DC], %[DC], %[DC1] \n\t" - "j 3f \n\t" - "2: \n\t" - "beqz %[left], 4f \n\t" - LOAD_WITH_OFFSET_X4(temp0, temp1, temp2, temp3, left, - 0, 4, 8, 12, - 0, 0, 0, 0, - 0) - "raddu.w.qb %[temp0], %[temp0] \n\t" - "raddu.w.qb %[temp1], %[temp1] \n\t" - "raddu.w.qb %[temp2], %[temp2] \n\t" - "raddu.w.qb %[temp3], %[temp3] \n\t" - "addu %[temp0], %[temp0], %[temp1] \n\t" - "addu %[temp2], %[temp2], %[temp3] \n\t" - "addu %[DC], %[temp0], %[temp2] \n\t" - "addu %[DC], %[DC], %[DC] \n\t" - "3: \n\t" - "shra_r.w %[DC], %[DC], 5 \n\t" - "j 5f \n\t" - "4: \n\t" - "li %[DC], 0x80 \n\t" - "5: \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [DC]"=&r"(DC), - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [DC1]"=&r"(DC1) - : [left]"r"(left), [top]"r"(top) - : "memory" - ); - - FILL_8_OR_16(dst, DC, 16); -} - -static WEBP_INLINE void DCMode8(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { - int DC, DC1; - int temp0, temp1, temp2, temp3; - - __asm__ volatile( - "beqz %[top], 2f \n\t" - "ulw %[temp0], 0(%[top]) \n\t" - "ulw %[temp1], 4(%[top]) \n\t" - "raddu.w.qb %[temp0], %[temp0] \n\t" - "raddu.w.qb %[temp1], %[temp1] \n\t" - "addu %[DC], %[temp0], %[temp1] \n\t" - "move %[DC1], %[DC] \n\t" - "beqz %[left], 1f \n\t" - "ulw %[temp2], 0(%[left]) \n\t" - "ulw %[temp3], 4(%[left]) \n\t" - "raddu.w.qb %[temp2], %[temp2] \n\t" - "raddu.w.qb %[temp3], %[temp3] \n\t" - "addu %[DC1], %[temp2], %[temp3] \n\t" - "1: \n\t" - "addu %[DC], %[DC], %[DC1] \n\t" - "j 3f \n\t" - "2: \n\t" - "beqz %[left], 4f \n\t" - "ulw %[temp2], 0(%[left]) \n\t" - "ulw %[temp3], 4(%[left]) \n\t" - "raddu.w.qb %[temp2], %[temp2] \n\t" - "raddu.w.qb %[temp3], %[temp3] \n\t" - "addu %[DC], %[temp2], %[temp3] \n\t" - "addu %[DC], %[DC], %[DC] \n\t" - "3: \n\t" - "shra_r.w %[DC], %[DC], 4 \n\t" - "j 5f \n\t" - "4: \n\t" - "li %[DC], 0x80 \n\t" - "5: \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [DC]"=&r"(DC), - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [DC1]"=&r"(DC1) - : [left]"r"(left), [top]"r"(top) - : "memory" - ); - - FILL_8_OR_16(dst, DC, 8); -} - -static void DC4(uint8_t* dst, const uint8_t* top) { - int temp0, temp1; - __asm__ volatile( - "ulw %[temp0], 0(%[top]) \n\t" - "ulw %[temp1], -5(%[top]) \n\t" - "raddu.w.qb %[temp0], %[temp0] \n\t" - "raddu.w.qb %[temp1], %[temp1] \n\t" - "addu %[temp0], %[temp0], %[temp1] \n\t" - "addiu %[temp0], %[temp0], 4 \n\t" - "srl %[temp0], %[temp0], 3 \n\t" - "replv.qb %[temp0], %[temp0] \n\t" - "usw %[temp0], 0*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp0], 1*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp0], 2*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp0], 3*" XSTR(BPS) "(%[dst]) \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1) - : [top]"r"(top), [dst]"r"(dst) - : "memory" - ); -} - -static void TM4(uint8_t* dst, const uint8_t* top) { - int a10, a32, temp0, temp1, temp2, temp3, temp4, temp5; - const int c35 = 0xff00ff; - __asm__ volatile ( - "lbu %[temp1], 0(%[top]) \n\t" - "lbu %[a10], 1(%[top]) \n\t" - "lbu %[temp2], 2(%[top]) \n\t" - "lbu %[a32], 3(%[top]) \n\t" - "ulw %[temp0], -5(%[top]) \n\t" - "lbu %[temp4], -1(%[top]) \n\t" - "append %[a10], %[temp1], 16 \n\t" - "append %[a32], %[temp2], 16 \n\t" - "replv.ph %[temp4], %[temp4] \n\t" - "shrl.ph %[temp1], %[temp0], 8 \n\t" - "and %[temp0], %[temp0], %[c35] \n\t" - "subu.ph %[temp1], %[temp1], %[temp4] \n\t" - "subu.ph %[temp0], %[temp0], %[temp4] \n\t" - "srl %[temp2], %[temp1], 16 \n\t" - "srl %[temp3], %[temp0], 16 \n\t" - "replv.ph %[temp2], %[temp2] \n\t" - "replv.ph %[temp3], %[temp3] \n\t" - "replv.ph %[temp4], %[temp1] \n\t" - "replv.ph %[temp5], %[temp0] \n\t" - "addu.ph %[temp0], %[temp3], %[a10] \n\t" - "addu.ph %[temp1], %[temp3], %[a32] \n\t" - "addu.ph %[temp3], %[temp2], %[a10] \n\t" - "addu.ph %[temp2], %[temp2], %[a32] \n\t" - "shll_s.ph %[temp0], %[temp0], 7 \n\t" - "shll_s.ph %[temp1], %[temp1], 7 \n\t" - "shll_s.ph %[temp3], %[temp3], 7 \n\t" - "shll_s.ph %[temp2], %[temp2], 7 \n\t" - "precrqu_s.qb.ph %[temp0], %[temp1], %[temp0] \n\t" - "precrqu_s.qb.ph %[temp1], %[temp2], %[temp3] \n\t" - "addu.ph %[temp2], %[temp5], %[a10] \n\t" - "addu.ph %[temp3], %[temp5], %[a32] \n\t" - "addu.ph %[temp5], %[temp4], %[a10] \n\t" - "addu.ph %[temp4], %[temp4], %[a32] \n\t" - "shll_s.ph %[temp2], %[temp2], 7 \n\t" - "shll_s.ph %[temp3], %[temp3], 7 \n\t" - "shll_s.ph %[temp4], %[temp4], 7 \n\t" - "shll_s.ph %[temp5], %[temp5], 7 \n\t" - "precrqu_s.qb.ph %[temp2], %[temp3], %[temp2] \n\t" - "precrqu_s.qb.ph %[temp3], %[temp4], %[temp5] \n\t" - "usw %[temp1], 0*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp0], 1*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp3], 2*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp2], 3*" XSTR(BPS) "(%[dst]) \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [a10]"=&r"(a10), [a32]"=&r"(a32) - : [c35]"r"(c35), [top]"r"(top), [dst]"r"(dst) - : "memory" - ); -} - -static void VE4(uint8_t* dst, const uint8_t* top) { - int temp0, temp1, temp2, temp3, temp4, temp5, temp6; - __asm__ volatile( - "ulw %[temp0], -1(%[top]) \n\t" - "ulh %[temp1], 3(%[top]) \n\t" - "preceu.ph.qbr %[temp2], %[temp0] \n\t" - "preceu.ph.qbl %[temp3], %[temp0] \n\t" - "preceu.ph.qbr %[temp4], %[temp1] \n\t" - "packrl.ph %[temp5], %[temp3], %[temp2] \n\t" - "packrl.ph %[temp6], %[temp4], %[temp3] \n\t" - "shll.ph %[temp5], %[temp5], 1 \n\t" - "shll.ph %[temp6], %[temp6], 1 \n\t" - "addq.ph %[temp2], %[temp5], %[temp2] \n\t" - "addq.ph %[temp6], %[temp6], %[temp4] \n\t" - "addq.ph %[temp2], %[temp2], %[temp3] \n\t" - "addq.ph %[temp6], %[temp6], %[temp3] \n\t" - "shra_r.ph %[temp2], %[temp2], 2 \n\t" - "shra_r.ph %[temp6], %[temp6], 2 \n\t" - "precr.qb.ph %[temp4], %[temp6], %[temp2] \n\t" - "usw %[temp4], 0*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp4], 1*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp4], 2*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp4], 3*" XSTR(BPS) "(%[dst]) \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6) - : [top]"r"(top), [dst]"r"(dst) - : "memory" - ); -} - -static void HE4(uint8_t* dst, const uint8_t* top) { - int temp0, temp1, temp2, temp3, temp4, temp5, temp6; - __asm__ volatile( - "ulw %[temp0], -4(%[top]) \n\t" - "lbu %[temp1], -5(%[top]) \n\t" - "preceu.ph.qbr %[temp2], %[temp0] \n\t" - "preceu.ph.qbl %[temp3], %[temp0] \n\t" - "replv.ph %[temp4], %[temp1] \n\t" - "packrl.ph %[temp5], %[temp3], %[temp2] \n\t" - "packrl.ph %[temp6], %[temp2], %[temp4] \n\t" - "shll.ph %[temp5], %[temp5], 1 \n\t" - "shll.ph %[temp6], %[temp6], 1 \n\t" - "addq.ph %[temp3], %[temp3], %[temp5] \n\t" - "addq.ph %[temp3], %[temp3], %[temp2] \n\t" - "addq.ph %[temp2], %[temp2], %[temp6] \n\t" - "addq.ph %[temp2], %[temp2], %[temp4] \n\t" - "shra_r.ph %[temp3], %[temp3], 2 \n\t" - "shra_r.ph %[temp2], %[temp2], 2 \n\t" - "replv.qb %[temp0], %[temp3] \n\t" - "replv.qb %[temp1], %[temp2] \n\t" - "srl %[temp3], %[temp3], 16 \n\t" - "srl %[temp2], %[temp2], 16 \n\t" - "replv.qb %[temp3], %[temp3] \n\t" - "replv.qb %[temp2], %[temp2] \n\t" - "usw %[temp3], 0*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp0], 1*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp2], 2*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp1], 3*" XSTR(BPS) "(%[dst]) \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6) - : [top]"r"(top), [dst]"r"(dst) - : "memory" - ); -} - -static void RD4(uint8_t* dst, const uint8_t* top) { - int temp0, temp1, temp2, temp3, temp4, temp5; - int temp6, temp7, temp8, temp9, temp10, temp11; - __asm__ volatile( - "ulw %[temp0], -5(%[top]) \n\t" - "ulw %[temp1], -1(%[top]) \n\t" - "preceu.ph.qbl %[temp2], %[temp0] \n\t" - "preceu.ph.qbr %[temp3], %[temp0] \n\t" - "preceu.ph.qbr %[temp4], %[temp1] \n\t" - "preceu.ph.qbl %[temp5], %[temp1] \n\t" - "packrl.ph %[temp6], %[temp2], %[temp3] \n\t" - "packrl.ph %[temp7], %[temp4], %[temp2] \n\t" - "packrl.ph %[temp8], %[temp5], %[temp4] \n\t" - "shll.ph %[temp6], %[temp6], 1 \n\t" - "addq.ph %[temp9], %[temp2], %[temp6] \n\t" - "shll.ph %[temp7], %[temp7], 1 \n\t" - "addq.ph %[temp9], %[temp9], %[temp3] \n\t" - "shll.ph %[temp8], %[temp8], 1 \n\t" - "shra_r.ph %[temp9], %[temp9], 2 \n\t" - "addq.ph %[temp10], %[temp4], %[temp7] \n\t" - "addq.ph %[temp11], %[temp5], %[temp8] \n\t" - "addq.ph %[temp10], %[temp10], %[temp2] \n\t" - "addq.ph %[temp11], %[temp11], %[temp4] \n\t" - "shra_r.ph %[temp10], %[temp10], 2 \n\t" - "shra_r.ph %[temp11], %[temp11], 2 \n\t" - "lbu %[temp0], 3(%[top]) \n\t" - "lbu %[temp1], 2(%[top]) \n\t" - "lbu %[temp2], 1(%[top]) \n\t" - "sll %[temp1], %[temp1], 1 \n\t" - "addu %[temp0], %[temp0], %[temp1] \n\t" - "addu %[temp0], %[temp0], %[temp2] \n\t" - "precr.qb.ph %[temp9], %[temp10], %[temp9] \n\t" - "shra_r.w %[temp0], %[temp0], 2 \n\t" - "precr.qb.ph %[temp10], %[temp11], %[temp10] \n\t" - "usw %[temp9], 3*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp10], 1*" XSTR(BPS) "(%[dst]) \n\t" - "prepend %[temp9], %[temp11], 8 \n\t" - "prepend %[temp10], %[temp0], 8 \n\t" - "usw %[temp9], 2*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp10], 0*" XSTR(BPS) "(%[dst]) \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11) - : [top]"r"(top), [dst]"r"(dst) - : "memory" - ); -} - -static void VR4(uint8_t* dst, const uint8_t* top) { - int temp0, temp1, temp2, temp3, temp4; - int temp5, temp6, temp7, temp8, temp9; - __asm__ volatile ( - "ulw %[temp0], -4(%[top]) \n\t" - "ulw %[temp1], 0(%[top]) \n\t" - "preceu.ph.qbl %[temp2], %[temp0] \n\t" - "preceu.ph.qbr %[temp0], %[temp0] \n\t" - "preceu.ph.qbla %[temp3], %[temp1] \n\t" - "preceu.ph.qbra %[temp1], %[temp1] \n\t" - "packrl.ph %[temp7], %[temp3], %[temp2] \n\t" - "addqh_r.ph %[temp4], %[temp1], %[temp3] \n\t" - "move %[temp6], %[temp1] \n\t" - "append %[temp1], %[temp2], 16 \n\t" - "shll.ph %[temp9], %[temp6], 1 \n\t" - "addqh_r.ph %[temp5], %[temp7], %[temp6] \n\t" - "shll.ph %[temp8], %[temp7], 1 \n\t" - "addu.ph %[temp3], %[temp7], %[temp3] \n\t" - "addu.ph %[temp1], %[temp1], %[temp6] \n\t" - "packrl.ph %[temp7], %[temp2], %[temp0] \n\t" - "addu.ph %[temp6], %[temp0], %[temp2] \n\t" - "addu.ph %[temp3], %[temp3], %[temp9] \n\t" - "addu.ph %[temp1], %[temp1], %[temp8] \n\t" - "shll.ph %[temp7], %[temp7], 1 \n\t" - "shra_r.ph %[temp3], %[temp3], 2 \n\t" - "shra_r.ph %[temp1], %[temp1], 2 \n\t" - "addu.ph %[temp6], %[temp6], %[temp7] \n\t" - "shra_r.ph %[temp6], %[temp6], 2 \n\t" - "precrq.ph.w %[temp8], %[temp4], %[temp5] \n\t" - "append %[temp4], %[temp5], 16 \n\t" - "precrq.ph.w %[temp2], %[temp3], %[temp1] \n\t" - "append %[temp3], %[temp1], 16 \n\t" - "precr.qb.ph %[temp8], %[temp8], %[temp4] \n\t" - "precr.qb.ph %[temp3], %[temp2], %[temp3] \n\t" - "usw %[temp8], 0*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp3], 1*" XSTR(BPS) "(%[dst]) \n\t" - "append %[temp3], %[temp6], 8 \n\t" - "srl %[temp6], %[temp6], 16 \n\t" - "append %[temp8], %[temp6], 8 \n\t" - "usw %[temp3], 3*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp8], 2*" XSTR(BPS) "(%[dst]) \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [temp9]"=&r"(temp9) - : [top]"r"(top), [dst]"r"(dst) - : "memory" - ); -} - -static void LD4(uint8_t* dst, const uint8_t* top) { - int temp0, temp1, temp2, temp3, temp4, temp5; - int temp6, temp7, temp8, temp9, temp10, temp11; - __asm__ volatile( - "ulw %[temp0], 0(%[top]) \n\t" - "ulw %[temp1], 4(%[top]) \n\t" - "preceu.ph.qbl %[temp2], %[temp0] \n\t" - "preceu.ph.qbr %[temp3], %[temp0] \n\t" - "preceu.ph.qbr %[temp4], %[temp1] \n\t" - "preceu.ph.qbl %[temp5], %[temp1] \n\t" - "packrl.ph %[temp6], %[temp2], %[temp3] \n\t" - "packrl.ph %[temp7], %[temp4], %[temp2] \n\t" - "packrl.ph %[temp8], %[temp5], %[temp4] \n\t" - "shll.ph %[temp6], %[temp6], 1 \n\t" - "addq.ph %[temp9], %[temp2], %[temp6] \n\t" - "shll.ph %[temp7], %[temp7], 1 \n\t" - "addq.ph %[temp9], %[temp9], %[temp3] \n\t" - "shll.ph %[temp8], %[temp8], 1 \n\t" - "shra_r.ph %[temp9], %[temp9], 2 \n\t" - "addq.ph %[temp10], %[temp4], %[temp7] \n\t" - "addq.ph %[temp11], %[temp5], %[temp8] \n\t" - "addq.ph %[temp10], %[temp10], %[temp2] \n\t" - "addq.ph %[temp11], %[temp11], %[temp4] \n\t" - "shra_r.ph %[temp10], %[temp10], 2 \n\t" - "shra_r.ph %[temp11], %[temp11], 2 \n\t" - "srl %[temp1], %[temp1], 24 \n\t" - "sll %[temp1], %[temp1], 1 \n\t" - "raddu.w.qb %[temp5], %[temp5] \n\t" - "precr.qb.ph %[temp9], %[temp10], %[temp9] \n\t" - "precr.qb.ph %[temp10], %[temp11], %[temp10] \n\t" - "addu %[temp1], %[temp1], %[temp5] \n\t" - "shra_r.w %[temp1], %[temp1], 2 \n\t" - "usw %[temp9], 0*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp10], 2*" XSTR(BPS) "(%[dst]) \n\t" - "prepend %[temp9], %[temp11], 8 \n\t" - "prepend %[temp10], %[temp1], 8 \n\t" - "usw %[temp9], 1*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp10], 3*" XSTR(BPS) "(%[dst]) \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11) - : [top]"r"(top), [dst]"r"(dst) - : "memory" - ); -} - -static void VL4(uint8_t* dst, const uint8_t* top) { - int temp0, temp1, temp2, temp3, temp4; - int temp5, temp6, temp7, temp8, temp9; - __asm__ volatile ( - "ulw %[temp0], 0(%[top]) \n\t" - "ulw %[temp1], 4(%[top]) \n\t" - "preceu.ph.qbla %[temp2], %[temp0] \n\t" - "preceu.ph.qbra %[temp0], %[temp0] \n\t" - "preceu.ph.qbl %[temp3], %[temp1] \n\t" - "preceu.ph.qbr %[temp1], %[temp1] \n\t" - "addqh_r.ph %[temp4], %[temp0], %[temp2] \n\t" - "packrl.ph %[temp7], %[temp1], %[temp0] \n\t" - "precrq.ph.w %[temp6], %[temp1], %[temp2] \n\t" - "shll.ph %[temp9], %[temp2], 1 \n\t" - "addqh_r.ph %[temp5], %[temp7], %[temp2] \n\t" - "shll.ph %[temp8], %[temp7], 1 \n\t" - "addu.ph %[temp2], %[temp2], %[temp6] \n\t" - "addu.ph %[temp0], %[temp0], %[temp7] \n\t" - "packrl.ph %[temp7], %[temp3], %[temp1] \n\t" - "addu.ph %[temp6], %[temp1], %[temp3] \n\t" - "addu.ph %[temp2], %[temp2], %[temp8] \n\t" - "addu.ph %[temp0], %[temp0], %[temp9] \n\t" - "shll.ph %[temp7], %[temp7], 1 \n\t" - "shra_r.ph %[temp2], %[temp2], 2 \n\t" - "shra_r.ph %[temp0], %[temp0], 2 \n\t" - "addu.ph %[temp6], %[temp6], %[temp7] \n\t" - "shra_r.ph %[temp6], %[temp6], 2 \n\t" - "precrq.ph.w %[temp8], %[temp5], %[temp4] \n\t" - "append %[temp5], %[temp4], 16 \n\t" - "precrq.ph.w %[temp3], %[temp2], %[temp0] \n\t" - "append %[temp2], %[temp0], 16 \n\t" - "precr.qb.ph %[temp8], %[temp8], %[temp5] \n\t" - "precr.qb.ph %[temp3], %[temp3], %[temp2] \n\t" - "usw %[temp8], 0*" XSTR(BPS) "(%[dst]) \n\t" - "prepend %[temp8], %[temp6], 8 \n\t" - "usw %[temp3], 1*" XSTR(BPS) "(%[dst]) \n\t" - "srl %[temp6], %[temp6], 16 \n\t" - "prepend %[temp3], %[temp6], 8 \n\t" - "usw %[temp8], 2*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp3], 3*" XSTR(BPS) "(%[dst]) \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [temp9]"=&r"(temp9) - : [top]"r"(top), [dst]"r"(dst) - : "memory" - ); -} - -static void HD4(uint8_t* dst, const uint8_t* top) { - int temp0, temp1, temp2, temp3, temp4; - int temp5, temp6, temp7, temp8, temp9; - __asm__ volatile ( - "ulw %[temp0], -5(%[top]) \n\t" - "ulw %[temp1], -1(%[top]) \n\t" - "preceu.ph.qbla %[temp2], %[temp0] \n\t" - "preceu.ph.qbra %[temp0], %[temp0] \n\t" - "preceu.ph.qbl %[temp3], %[temp1] \n\t" - "preceu.ph.qbr %[temp1], %[temp1] \n\t" - "addqh_r.ph %[temp4], %[temp0], %[temp2] \n\t" - "packrl.ph %[temp7], %[temp1], %[temp0] \n\t" - "precrq.ph.w %[temp6], %[temp1], %[temp2] \n\t" - "shll.ph %[temp9], %[temp2], 1 \n\t" - "addqh_r.ph %[temp5], %[temp7], %[temp2] \n\t" - "shll.ph %[temp8], %[temp7], 1 \n\t" - "addu.ph %[temp2], %[temp2], %[temp6] \n\t" - "addu.ph %[temp0], %[temp0], %[temp7] \n\t" - "packrl.ph %[temp7], %[temp3], %[temp1] \n\t" - "addu.ph %[temp6], %[temp1], %[temp3] \n\t" - "addu.ph %[temp2], %[temp2], %[temp8] \n\t" - "addu.ph %[temp0], %[temp0], %[temp9] \n\t" - "shll.ph %[temp7], %[temp7], 1 \n\t" - "shra_r.ph %[temp2], %[temp2], 2 \n\t" - "shra_r.ph %[temp0], %[temp0], 2 \n\t" - "addu.ph %[temp6], %[temp6], %[temp7] \n\t" - "shra_r.ph %[temp6], %[temp6], 2 \n\t" - "precrq.ph.w %[temp1], %[temp2], %[temp5] \n\t" - "precrq.ph.w %[temp3], %[temp0], %[temp4] \n\t" - "precr.qb.ph %[temp7], %[temp6], %[temp1] \n\t" - "precr.qb.ph %[temp6], %[temp1], %[temp3] \n\t" - "usw %[temp7], 0*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp6], 1*" XSTR(BPS) "(%[dst]) \n\t" - "append %[temp2], %[temp5], 16 \n\t" - "append %[temp0], %[temp4], 16 \n\t" - "precr.qb.ph %[temp5], %[temp3], %[temp2] \n\t" - "precr.qb.ph %[temp4], %[temp2], %[temp0] \n\t" - "usw %[temp5], 2*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp4], 3*" XSTR(BPS) "(%[dst]) \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [temp9]"=&r"(temp9) - : [top]"r"(top), [dst]"r"(dst) - : "memory" - ); -} - -static void HU4(uint8_t* dst, const uint8_t* top) { - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; - __asm__ volatile ( - "ulw %[temp0], -5(%[top]) \n\t" - "preceu.ph.qbl %[temp1], %[temp0] \n\t" - "preceu.ph.qbr %[temp2], %[temp0] \n\t" - "packrl.ph %[temp3], %[temp1], %[temp2] \n\t" - "replv.qb %[temp7], %[temp2] \n\t" - "addqh_r.ph %[temp4], %[temp1], %[temp3] \n\t" - "addqh_r.ph %[temp5], %[temp3], %[temp2] \n\t" - "shll.ph %[temp6], %[temp3], 1 \n\t" - "addu.ph %[temp3], %[temp2], %[temp3] \n\t" - "addu.ph %[temp6], %[temp1], %[temp6] \n\t" - "shll.ph %[temp0], %[temp2], 1 \n\t" - "addu.ph %[temp6], %[temp6], %[temp2] \n\t" - "addu.ph %[temp0], %[temp3], %[temp0] \n\t" - "shra_r.ph %[temp6], %[temp6], 2 \n\t" - "shra_r.ph %[temp0], %[temp0], 2 \n\t" - "packrl.ph %[temp3], %[temp6], %[temp5] \n\t" - "precrq.ph.w %[temp2], %[temp6], %[temp4] \n\t" - "append %[temp0], %[temp5], 16 \n\t" - "precr.qb.ph %[temp3], %[temp3], %[temp2] \n\t" - "usw %[temp3], 0*" XSTR(BPS) "(%[dst]) \n\t" - "precr.qb.ph %[temp1], %[temp7], %[temp0] \n\t" - "usw %[temp7], 3*" XSTR(BPS) "(%[dst]) \n\t" - "packrl.ph %[temp2], %[temp1], %[temp3] \n\t" - "usw %[temp1], 2*" XSTR(BPS) "(%[dst]) \n\t" - "usw %[temp2], 1*" XSTR(BPS) "(%[dst]) \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7) - : [top]"r"(top), [dst]"r"(dst) - : "memory" - ); -} - -//------------------------------------------------------------------------------ -// Chroma 8x8 prediction (paragraph 12.2) - -static void IntraChromaPreds(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { - // U block - DCMode8(C8DC8 + dst, left, top); - VerticalPred8(C8VE8 + dst, top); - HorizontalPred8(C8HE8 + dst, left); - TrueMotion8(C8TM8 + dst, left, top); - // V block - dst += 8; - if (top) top += 8; - if (left) left += 16; - DCMode8(C8DC8 + dst, left, top); - VerticalPred8(C8VE8 + dst, top); - HorizontalPred8(C8HE8 + dst, left); - TrueMotion8(C8TM8 + dst, left, top); -} - -//------------------------------------------------------------------------------ -// luma 16x16 prediction (paragraph 12.3) - -static void Intra16Preds(uint8_t* dst, - const uint8_t* left, const uint8_t* top) { - DCMode16(I16DC16 + dst, left, top); - VerticalPred16(I16VE16 + dst, top); - HorizontalPred16(I16HE16 + dst, left); - TrueMotion16(I16TM16 + dst, left, top); -} - -// Left samples are top[-5 .. -2], top_left is top[-1], top are -// located at top[0..3], and top right is top[4..7] -static void Intra4Preds(uint8_t* dst, const uint8_t* top) { - DC4(I4DC4 + dst, top); - TM4(I4TM4 + dst, top); - VE4(I4VE4 + dst, top); - HE4(I4HE4 + dst, top); - RD4(I4RD4 + dst, top); - VR4(I4VR4 + dst, top); - LD4(I4LD4 + dst, top); - VL4(I4VL4 + dst, top); - HD4(I4HD4 + dst, top); - HU4(I4HU4 + dst, top); -} - -//------------------------------------------------------------------------------ -// Metric - -#if !defined(WORK_AROUND_GCC) - -#define GET_SSE_INNER(A) \ - "lw %[temp0], " #A "(%[a]) \n\t" \ - "lw %[temp1], " #A "(%[b]) \n\t" \ - "preceu.ph.qbr %[temp2], %[temp0] \n\t" \ - "preceu.ph.qbl %[temp0], %[temp0] \n\t" \ - "preceu.ph.qbr %[temp3], %[temp1] \n\t" \ - "preceu.ph.qbl %[temp1], %[temp1] \n\t" \ - "subq.ph %[temp2], %[temp2], %[temp3] \n\t" \ - "subq.ph %[temp0], %[temp0], %[temp1] \n\t" \ - "dpa.w.ph $ac0, %[temp2], %[temp2] \n\t" \ - "dpa.w.ph $ac0, %[temp0], %[temp0] \n\t" - -#define GET_SSE(A, B, C, D) \ - GET_SSE_INNER(A) \ - GET_SSE_INNER(B) \ - GET_SSE_INNER(C) \ - GET_SSE_INNER(D) - -static int SSE16x16(const uint8_t* a, const uint8_t* b) { - int count; - int temp0, temp1, temp2, temp3; - __asm__ volatile ( - "mult $zero, $zero \n\t" - GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS) - GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS) - GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS) - GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS) - GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS) - GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS) - GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS) - GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS) - GET_SSE( 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS) - GET_SSE( 9 * BPS, 4 + 9 * BPS, 8 + 9 * BPS, 12 + 9 * BPS) - GET_SSE(10 * BPS, 4 + 10 * BPS, 8 + 10 * BPS, 12 + 10 * BPS) - GET_SSE(11 * BPS, 4 + 11 * BPS, 8 + 11 * BPS, 12 + 11 * BPS) - GET_SSE(12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS) - GET_SSE(13 * BPS, 4 + 13 * BPS, 8 + 13 * BPS, 12 + 13 * BPS) - GET_SSE(14 * BPS, 4 + 14 * BPS, 8 + 14 * BPS, 12 + 14 * BPS) - GET_SSE(15 * BPS, 4 + 15 * BPS, 8 + 15 * BPS, 12 + 15 * BPS) - "mflo %[count] \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [count]"=&r"(count) - : [a]"r"(a), [b]"r"(b) - : "memory", "hi", "lo" - ); - return count; -} - -static int SSE16x8(const uint8_t* a, const uint8_t* b) { - int count; - int temp0, temp1, temp2, temp3; - __asm__ volatile ( - "mult $zero, $zero \n\t" - GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS) - GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS) - GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS) - GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS) - GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS) - GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS) - GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS) - GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS) - "mflo %[count] \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [count]"=&r"(count) - : [a]"r"(a), [b]"r"(b) - : "memory", "hi", "lo" - ); - return count; -} - -static int SSE8x8(const uint8_t* a, const uint8_t* b) { - int count; - int temp0, temp1, temp2, temp3; - __asm__ volatile ( - "mult $zero, $zero \n\t" - GET_SSE(0 * BPS, 4 + 0 * BPS, 1 * BPS, 4 + 1 * BPS) - GET_SSE(2 * BPS, 4 + 2 * BPS, 3 * BPS, 4 + 3 * BPS) - GET_SSE(4 * BPS, 4 + 4 * BPS, 5 * BPS, 4 + 5 * BPS) - GET_SSE(6 * BPS, 4 + 6 * BPS, 7 * BPS, 4 + 7 * BPS) - "mflo %[count] \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [count]"=&r"(count) - : [a]"r"(a), [b]"r"(b) - : "memory", "hi", "lo" - ); - return count; -} - -static int SSE4x4(const uint8_t* a, const uint8_t* b) { - int count; - int temp0, temp1, temp2, temp3; - __asm__ volatile ( - "mult $zero, $zero \n\t" - GET_SSE(0 * BPS, 1 * BPS, 2 * BPS, 3 * BPS) - "mflo %[count] \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [count]"=&r"(count) - : [a]"r"(a), [b]"r"(b) - : "memory", "hi", "lo" - ); - return count; -} - -#undef GET_SSE -#undef GET_SSE_INNER - -#endif // !WORK_AROUND_GCC - -#undef FILL_8_OR_16 -#undef FILL_PART -#undef OUTPUT_EARLY_CLOBBER_REGS_17 -#undef MUL_HALF -#undef ABS_X8 -#undef ADD_SUB_HALVES_X4 - -//------------------------------------------------------------------------------ -// Quantization -// - -// macro for one pass through for loop in QuantizeBlock reading 2 values at time -// QUANTDIV macro inlined -// J - offset in bytes (kZigzag[n] * 2) -// K - offset in bytes (kZigzag[n] * 4) -// N - offset in bytes (n * 2) -// N1 - offset in bytes ((n + 1) * 2) -#define QUANTIZE_ONE(J, K, N, N1) \ - "ulw %[temp1], " #J "(%[ppin]) \n\t" \ - "ulw %[temp2], " #J "(%[ppsharpen]) \n\t" \ - "lhu %[temp3], " #K "(%[ppzthresh]) \n\t" \ - "lhu %[temp6], " #K "+4(%[ppzthresh]) \n\t" \ - "absq_s.ph %[temp4], %[temp1] \n\t" \ - "ins %[temp3], %[temp6], 16, 16 \n\t" \ - "addu.ph %[coeff], %[temp4], %[temp2] \n\t" \ - "shra.ph %[sign], %[temp1], 15 \n\t" \ - "li %[level], 0x10001 \n\t" \ - "cmp.lt.ph %[temp3], %[coeff] \n\t" \ - "lhu %[temp1], " #J "(%[ppiq]) \n\t" \ - "pick.ph %[temp5], %[level], $0 \n\t" \ - "lw %[temp2], " #K "(%[ppbias]) \n\t" \ - "beqz %[temp5], 0f \n\t" \ - "lhu %[temp3], " #J "(%[ppq]) \n\t" \ - "beq %[temp5], %[level], 1f \n\t" \ - "andi %[temp5], %[temp5], 0x1 \n\t" \ - "andi %[temp4], %[coeff], 0xffff \n\t" \ - "beqz %[temp5], 2f \n\t" \ - "mul %[level], %[temp4], %[temp1] \n\t" \ - "sh $0, " #J "+2(%[ppin]) \n\t" \ - "sh $0, " #N1 "(%[pout]) \n\t" \ - "addu %[level], %[level], %[temp2] \n\t" \ - "sra %[level], %[level], 17 \n\t" \ - "slt %[temp4], %[max_level], %[level] \n\t" \ - "movn %[level], %[max_level], %[temp4] \n\t" \ - "andi %[temp6], %[sign], 0xffff \n\t" \ - "xor %[level], %[level], %[temp6] \n\t" \ - "subu %[level], %[level], %[temp6] \n\t" \ - "mul %[temp5], %[level], %[temp3] \n\t" \ - "or %[ret], %[ret], %[level] \n\t" \ - "sh %[level], " #N "(%[pout]) \n\t" \ - "sh %[temp5], " #J "(%[ppin]) \n\t" \ - "j 3f \n\t" \ -"2: \n\t" \ - "lhu %[temp1], " #J "+2(%[ppiq]) \n\t" \ - "srl %[temp5], %[coeff], 16 \n\t" \ - "mul %[level], %[temp5], %[temp1] \n\t" \ - "lw %[temp2], " #K "+4(%[ppbias]) \n\t" \ - "lhu %[temp3], " #J "+2(%[ppq]) \n\t" \ - "addu %[level], %[level], %[temp2] \n\t" \ - "sra %[level], %[level], 17 \n\t" \ - "srl %[temp6], %[sign], 16 \n\t" \ - "slt %[temp4], %[max_level], %[level] \n\t" \ - "movn %[level], %[max_level], %[temp4] \n\t" \ - "xor %[level], %[level], %[temp6] \n\t" \ - "subu %[level], %[level], %[temp6] \n\t" \ - "mul %[temp5], %[level], %[temp3] \n\t" \ - "sh $0, " #J "(%[ppin]) \n\t" \ - "sh $0, " #N "(%[pout]) \n\t" \ - "or %[ret], %[ret], %[level] \n\t" \ - "sh %[temp5], " #J "+2(%[ppin]) \n\t" \ - "sh %[level], " #N1 "(%[pout]) \n\t" \ - "j 3f \n\t" \ -"1: \n\t" \ - "lhu %[temp1], " #J "(%[ppiq]) \n\t" \ - "lw %[temp2], " #K "(%[ppbias]) \n\t" \ - "ulw %[temp3], " #J "(%[ppq]) \n\t" \ - "andi %[temp5], %[coeff], 0xffff \n\t" \ - "srl %[temp0], %[coeff], 16 \n\t" \ - "lhu %[temp6], " #J "+2(%[ppiq]) \n\t" \ - "lw %[coeff], " #K "+4(%[ppbias]) \n\t" \ - "mul %[level], %[temp5], %[temp1] \n\t" \ - "mul %[temp4], %[temp0], %[temp6] \n\t" \ - "addu %[level], %[level], %[temp2] \n\t" \ - "addu %[temp4], %[temp4], %[coeff] \n\t" \ - "precrq.ph.w %[level], %[temp4], %[level] \n\t" \ - "shra.ph %[level], %[level], 1 \n\t" \ - "cmp.lt.ph %[max_level1],%[level] \n\t" \ - "pick.ph %[level], %[max_level], %[level] \n\t" \ - "xor %[level], %[level], %[sign] \n\t" \ - "subu.ph %[level], %[level], %[sign] \n\t" \ - "mul.ph %[temp3], %[level], %[temp3] \n\t" \ - "or %[ret], %[ret], %[level] \n\t" \ - "sh %[level], " #N "(%[pout]) \n\t" \ - "srl %[level], %[level], 16 \n\t" \ - "sh %[level], " #N1 "(%[pout]) \n\t" \ - "usw %[temp3], " #J "(%[ppin]) \n\t" \ - "j 3f \n\t" \ -"0: \n\t" \ - "sh $0, " #N "(%[pout]) \n\t" \ - "sh $0, " #N1 "(%[pout]) \n\t" \ - "usw $0, " #J "(%[ppin]) \n\t" \ -"3: \n\t" - -static int QuantizeBlock(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - int temp0, temp1, temp2, temp3, temp4, temp5,temp6; - int sign, coeff, level; - int max_level = MAX_LEVEL; - int max_level1 = max_level << 16 | max_level; - int ret = 0; - - int16_t* ppin = &in[0]; - int16_t* pout = &out[0]; - const uint16_t* ppsharpen = &mtx->sharpen_[0]; - const uint32_t* ppzthresh = &mtx->zthresh_[0]; - const uint16_t* ppq = &mtx->q_[0]; - const uint16_t* ppiq = &mtx->iq_[0]; - const uint32_t* ppbias = &mtx->bias_[0]; - - __asm__ volatile ( - QUANTIZE_ONE( 0, 0, 0, 2) - QUANTIZE_ONE( 4, 8, 10, 12) - QUANTIZE_ONE( 8, 16, 4, 8) - QUANTIZE_ONE(12, 24, 14, 24) - QUANTIZE_ONE(16, 32, 6, 16) - QUANTIZE_ONE(20, 40, 22, 26) - QUANTIZE_ONE(24, 48, 18, 20) - QUANTIZE_ONE(28, 56, 28, 30) - - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [sign]"=&r"(sign), [coeff]"=&r"(coeff), - [level]"=&r"(level), [temp6]"=&r"(temp6), [ret]"+&r"(ret) - : [ppin]"r"(ppin), [pout]"r"(pout), [max_level1]"r"(max_level1), - [ppiq]"r"(ppiq), [max_level]"r"(max_level), - [ppbias]"r"(ppbias), [ppzthresh]"r"(ppzthresh), - [ppsharpen]"r"(ppsharpen), [ppq]"r"(ppq) - : "memory", "hi", "lo" - ); - - return (ret != 0); -} - -static int Quantize2Blocks(int16_t in[32], int16_t out[32], - const VP8Matrix* const mtx) { - int nz; - nz = QuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0; - nz |= QuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1; - return nz; -} - -#undef QUANTIZE_ONE - -// macro for one horizontal pass in FTransformWHT -// temp0..temp7 holds tmp[0]..tmp[15] -// A, B, C, D - offset in bytes to load from in buffer -// TEMP0, TEMP1 - registers for corresponding tmp elements -#define HORIZONTAL_PASS_WHT(A, B, C, D, TEMP0, TEMP1) \ - "lh %[" #TEMP0 "], " #A "(%[in]) \n\t" \ - "lh %[" #TEMP1 "], " #B "(%[in]) \n\t" \ - "lh %[temp8], " #C "(%[in]) \n\t" \ - "lh %[temp9], " #D "(%[in]) \n\t" \ - "ins %[" #TEMP1 "], %[" #TEMP0 "], 16, 16 \n\t" \ - "ins %[temp9], %[temp8], 16, 16 \n\t" \ - "subq.ph %[temp8], %[" #TEMP1 "], %[temp9] \n\t" \ - "addq.ph %[temp9], %[" #TEMP1 "], %[temp9] \n\t" \ - "precrq.ph.w %[" #TEMP0 "], %[temp8], %[temp9] \n\t" \ - "append %[temp8], %[temp9], 16 \n\t" \ - "subq.ph %[" #TEMP1 "], %[" #TEMP0 "], %[temp8] \n\t" \ - "addq.ph %[" #TEMP0 "], %[" #TEMP0 "], %[temp8] \n\t" \ - "rotr %[" #TEMP1 "], %[" #TEMP1 "], 16 \n\t" - -// macro for one vertical pass in FTransformWHT -// temp0..temp7 holds tmp[0]..tmp[15] -// A, B, C, D - offsets in bytes to store to out buffer -// TEMP0, TEMP2, TEMP4 and TEMP6 - registers for corresponding tmp elements -#define VERTICAL_PASS_WHT(A, B, C, D, TEMP0, TEMP2, TEMP4, TEMP6) \ - "addq.ph %[temp8], %[" #TEMP0 "], %[" #TEMP4 "] \n\t" \ - "addq.ph %[temp9], %[" #TEMP2 "], %[" #TEMP6 "] \n\t" \ - "subq.ph %[" #TEMP2 "], %[" #TEMP2 "], %[" #TEMP6 "] \n\t" \ - "subq.ph %[" #TEMP6 "], %[" #TEMP0 "], %[" #TEMP4 "] \n\t" \ - "addqh.ph %[" #TEMP0 "], %[temp8], %[temp9] \n\t" \ - "subqh.ph %[" #TEMP4 "], %[" #TEMP6 "], %[" #TEMP2 "] \n\t" \ - "addqh.ph %[" #TEMP2 "], %[" #TEMP2 "], %[" #TEMP6 "] \n\t" \ - "subqh.ph %[" #TEMP6 "], %[temp8], %[temp9] \n\t" \ - "usw %[" #TEMP0 "], " #A "(%[out]) \n\t" \ - "usw %[" #TEMP2 "], " #B "(%[out]) \n\t" \ - "usw %[" #TEMP4 "], " #C "(%[out]) \n\t" \ - "usw %[" #TEMP6 "], " #D "(%[out]) \n\t" - -static void FTransformWHT(const int16_t* in, int16_t* out) { - int temp0, temp1, temp2, temp3, temp4; - int temp5, temp6, temp7, temp8, temp9; - - __asm__ volatile ( - HORIZONTAL_PASS_WHT( 0, 32, 64, 96, temp0, temp1) - HORIZONTAL_PASS_WHT(128, 160, 192, 224, temp2, temp3) - HORIZONTAL_PASS_WHT(256, 288, 320, 352, temp4, temp5) - HORIZONTAL_PASS_WHT(384, 416, 448, 480, temp6, temp7) - VERTICAL_PASS_WHT(0, 8, 16, 24, temp0, temp2, temp4, temp6) - VERTICAL_PASS_WHT(4, 12, 20, 28, temp1, temp3, temp5, temp7) - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), - [temp9]"=&r"(temp9) - : [in]"r"(in), [out]"r"(out) - : "memory" - ); -} - -#undef VERTICAL_PASS_WHT -#undef HORIZONTAL_PASS_WHT - -// macro for converting coefficients to bin -// convert 8 coeffs at time -// A, B, C, D - offsets in bytes to load from out buffer -#define CONVERT_COEFFS_TO_BIN(A, B, C, D) \ - "ulw %[temp0], " #A "(%[out]) \n\t" \ - "ulw %[temp1], " #B "(%[out]) \n\t" \ - "ulw %[temp2], " #C "(%[out]) \n\t" \ - "ulw %[temp3], " #D "(%[out]) \n\t" \ - "absq_s.ph %[temp0], %[temp0] \n\t" \ - "absq_s.ph %[temp1], %[temp1] \n\t" \ - "absq_s.ph %[temp2], %[temp2] \n\t" \ - "absq_s.ph %[temp3], %[temp3] \n\t" \ - /* TODO(skal): add rounding ? shra_r.ph : shra.ph */ \ - /* for following 4 instructions */ \ - "shra.ph %[temp0], %[temp0], 3 \n\t" \ - "shra.ph %[temp1], %[temp1], 3 \n\t" \ - "shra.ph %[temp2], %[temp2], 3 \n\t" \ - "shra.ph %[temp3], %[temp3], 3 \n\t" \ - "shll_s.ph %[temp0], %[temp0], 10 \n\t" \ - "shll_s.ph %[temp1], %[temp1], 10 \n\t" \ - "shll_s.ph %[temp2], %[temp2], 10 \n\t" \ - "shll_s.ph %[temp3], %[temp3], 10 \n\t" \ - "shrl.ph %[temp0], %[temp0], 10 \n\t" \ - "shrl.ph %[temp1], %[temp1], 10 \n\t" \ - "shrl.ph %[temp2], %[temp2], 10 \n\t" \ - "shrl.ph %[temp3], %[temp3], 10 \n\t" \ - "shll.ph %[temp0], %[temp0], 2 \n\t" \ - "shll.ph %[temp1], %[temp1], 2 \n\t" \ - "shll.ph %[temp2], %[temp2], 2 \n\t" \ - "shll.ph %[temp3], %[temp3], 2 \n\t" \ - "ext %[temp4], %[temp0], 0, 16 \n\t" \ - "ext %[temp0], %[temp0], 16, 16 \n\t" \ - "addu %[temp4], %[temp4], %[dist] \n\t" \ - "addu %[temp0], %[temp0], %[dist] \n\t" \ - "ext %[temp5], %[temp1], 0, 16 \n\t" \ - "lw %[temp8], 0(%[temp4]) \n\t" \ - "ext %[temp1], %[temp1], 16, 16 \n\t" \ - "addu %[temp5], %[temp5], %[dist] \n\t" \ - "addiu %[temp8], %[temp8], 1 \n\t" \ - "sw %[temp8], 0(%[temp4]) \n\t" \ - "lw %[temp8], 0(%[temp0]) \n\t" \ - "addu %[temp1], %[temp1], %[dist] \n\t" \ - "ext %[temp6], %[temp2], 0, 16 \n\t" \ - "addiu %[temp8], %[temp8], 1 \n\t" \ - "sw %[temp8], 0(%[temp0]) \n\t" \ - "lw %[temp8], 0(%[temp5]) \n\t" \ - "ext %[temp2], %[temp2], 16, 16 \n\t" \ - "addu %[temp6], %[temp6], %[dist] \n\t" \ - "addiu %[temp8], %[temp8], 1 \n\t" \ - "sw %[temp8], 0(%[temp5]) \n\t" \ - "lw %[temp8], 0(%[temp1]) \n\t" \ - "addu %[temp2], %[temp2], %[dist] \n\t" \ - "ext %[temp7], %[temp3], 0, 16 \n\t" \ - "addiu %[temp8], %[temp8], 1 \n\t" \ - "sw %[temp8], 0(%[temp1]) \n\t" \ - "lw %[temp8], 0(%[temp6]) \n\t" \ - "ext %[temp3], %[temp3], 16, 16 \n\t" \ - "addu %[temp7], %[temp7], %[dist] \n\t" \ - "addiu %[temp8], %[temp8], 1 \n\t" \ - "sw %[temp8], 0(%[temp6]) \n\t" \ - "lw %[temp8], 0(%[temp2]) \n\t" \ - "addu %[temp3], %[temp3], %[dist] \n\t" \ - "addiu %[temp8], %[temp8], 1 \n\t" \ - "sw %[temp8], 0(%[temp2]) \n\t" \ - "lw %[temp8], 0(%[temp7]) \n\t" \ - "addiu %[temp8], %[temp8], 1 \n\t" \ - "sw %[temp8], 0(%[temp7]) \n\t" \ - "lw %[temp8], 0(%[temp3]) \n\t" \ - "addiu %[temp8], %[temp8], 1 \n\t" \ - "sw %[temp8], 0(%[temp3]) \n\t" - -static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, - int start_block, int end_block, - VP8Histogram* const histo) { - int j; - int distribution[MAX_COEFF_THRESH + 1] = { 0 }; - const int max_coeff = (MAX_COEFF_THRESH << 16) + MAX_COEFF_THRESH; - for (j = start_block; j < end_block; ++j) { - int16_t out[16]; - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; - - VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); - - // Convert coefficients to bin. - __asm__ volatile ( - CONVERT_COEFFS_TO_BIN( 0, 4, 8, 12) - CONVERT_COEFFS_TO_BIN(16, 20, 24, 28) - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8) - : [dist]"r"(distribution), [out]"r"(out), [max_coeff]"r"(max_coeff) - : "memory" - ); - } - VP8SetHistogramData(distribution, histo); -} - -#undef CONVERT_COEFFS_TO_BIN - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8EncDspInitMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitMIPSdspR2(void) { - VP8FTransform = FTransform; - VP8ITransform = ITransform; - VP8TDisto4x4 = Disto4x4; - VP8TDisto16x16 = Disto16x16; - VP8EncPredLuma16 = Intra16Preds; - VP8EncPredChroma8 = IntraChromaPreds; - VP8EncPredLuma4 = Intra4Preds; -#if !defined(WORK_AROUND_GCC) - VP8SSE16x16 = SSE16x16; - VP8SSE8x8 = SSE8x8; - VP8SSE16x8 = SSE16x8; - VP8SSE4x4 = SSE4x4; -#endif - VP8EncQuantizeBlock = QuantizeBlock; - VP8EncQuantize2Blocks = Quantize2Blocks; - VP8FTransformWHT = FTransformWHT; - VP8CollectHistogram = CollectHistogram; -} - -#else // !WEBP_USE_MIPS_DSP_R2 - -WEBP_DSP_INIT_STUB(VP8EncDspInitMIPSdspR2) - -#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/Example/Pods/libwebp/src/dsp/enc_neon.c b/Example/Pods/libwebp/src/dsp/enc_neon.c deleted file mode 100644 index c2aef58e..00000000 --- a/Example/Pods/libwebp/src/dsp/enc_neon.c +++ /dev/null @@ -1,934 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// ARM NEON version of speed-critical encoding functions. -// -// adapted from libvpx (http://www.webmproject.org/code/) - -#include "./dsp.h" - -#if defined(WEBP_USE_NEON) - -#include - -#include "./neon.h" -#include "../enc/vp8enci.h" - -//------------------------------------------------------------------------------ -// Transforms (Paragraph 14.4) - -// Inverse transform. -// This code is pretty much the same as TransformOne in the dec_neon.c, except -// for subtraction to *ref. See the comments there for algorithmic explanations. - -static const int16_t kC1 = 20091; -static const int16_t kC2 = 17734; // half of kC2, actually. See comment above. - -// This code works but is *slower* than the inlined-asm version below -// (with gcc-4.6). So we disable it for now. Later, it'll be conditional to -// WEBP_USE_INTRINSICS define. -// With gcc-4.8, it's a little faster speed than inlined-assembly. -#if defined(WEBP_USE_INTRINSICS) - -// Treats 'v' as an uint8x8_t and zero extends to an int16x8_t. -static WEBP_INLINE int16x8_t ConvertU8ToS16(uint32x2_t v) { - return vreinterpretq_s16_u16(vmovl_u8(vreinterpret_u8_u32(v))); -} - -// Performs unsigned 8b saturation on 'dst01' and 'dst23' storing the result -// to the corresponding rows of 'dst'. -static WEBP_INLINE void SaturateAndStore4x4(uint8_t* const dst, - const int16x8_t dst01, - const int16x8_t dst23) { - // Unsigned saturate to 8b. - const uint8x8_t dst01_u8 = vqmovun_s16(dst01); - const uint8x8_t dst23_u8 = vqmovun_s16(dst23); - - // Store the results. - vst1_lane_u32((uint32_t*)(dst + 0 * BPS), vreinterpret_u32_u8(dst01_u8), 0); - vst1_lane_u32((uint32_t*)(dst + 1 * BPS), vreinterpret_u32_u8(dst01_u8), 1); - vst1_lane_u32((uint32_t*)(dst + 2 * BPS), vreinterpret_u32_u8(dst23_u8), 0); - vst1_lane_u32((uint32_t*)(dst + 3 * BPS), vreinterpret_u32_u8(dst23_u8), 1); -} - -static WEBP_INLINE void Add4x4(const int16x8_t row01, const int16x8_t row23, - const uint8_t* const ref, uint8_t* const dst) { - uint32x2_t dst01 = vdup_n_u32(0); - uint32x2_t dst23 = vdup_n_u32(0); - - // Load the source pixels. - dst01 = vld1_lane_u32((uint32_t*)(ref + 0 * BPS), dst01, 0); - dst23 = vld1_lane_u32((uint32_t*)(ref + 2 * BPS), dst23, 0); - dst01 = vld1_lane_u32((uint32_t*)(ref + 1 * BPS), dst01, 1); - dst23 = vld1_lane_u32((uint32_t*)(ref + 3 * BPS), dst23, 1); - - { - // Convert to 16b. - const int16x8_t dst01_s16 = ConvertU8ToS16(dst01); - const int16x8_t dst23_s16 = ConvertU8ToS16(dst23); - - // Descale with rounding. - const int16x8_t out01 = vrsraq_n_s16(dst01_s16, row01, 3); - const int16x8_t out23 = vrsraq_n_s16(dst23_s16, row23, 3); - // Add the inverse transform. - SaturateAndStore4x4(dst, out01, out23); - } -} - -static WEBP_INLINE void Transpose8x2(const int16x8_t in0, const int16x8_t in1, - int16x8x2_t* const out) { - // a0 a1 a2 a3 | b0 b1 b2 b3 => a0 b0 c0 d0 | a1 b1 c1 d1 - // c0 c1 c2 c3 | d0 d1 d2 d3 a2 b2 c2 d2 | a3 b3 c3 d3 - const int16x8x2_t tmp0 = vzipq_s16(in0, in1); // a0 c0 a1 c1 a2 c2 ... - // b0 d0 b1 d1 b2 d2 ... - *out = vzipq_s16(tmp0.val[0], tmp0.val[1]); -} - -static WEBP_INLINE void TransformPass(int16x8x2_t* const rows) { - // {rows} = in0 | in4 - // in8 | in12 - // B1 = in4 | in12 - const int16x8_t B1 = - vcombine_s16(vget_high_s16(rows->val[0]), vget_high_s16(rows->val[1])); - // C0 = kC1 * in4 | kC1 * in12 - // C1 = kC2 * in4 | kC2 * in12 - const int16x8_t C0 = vsraq_n_s16(B1, vqdmulhq_n_s16(B1, kC1), 1); - const int16x8_t C1 = vqdmulhq_n_s16(B1, kC2); - const int16x4_t a = vqadd_s16(vget_low_s16(rows->val[0]), - vget_low_s16(rows->val[1])); // in0 + in8 - const int16x4_t b = vqsub_s16(vget_low_s16(rows->val[0]), - vget_low_s16(rows->val[1])); // in0 - in8 - // c = kC2 * in4 - kC1 * in12 - // d = kC1 * in4 + kC2 * in12 - const int16x4_t c = vqsub_s16(vget_low_s16(C1), vget_high_s16(C0)); - const int16x4_t d = vqadd_s16(vget_low_s16(C0), vget_high_s16(C1)); - const int16x8_t D0 = vcombine_s16(a, b); // D0 = a | b - const int16x8_t D1 = vcombine_s16(d, c); // D1 = d | c - const int16x8_t E0 = vqaddq_s16(D0, D1); // a+d | b+c - const int16x8_t E_tmp = vqsubq_s16(D0, D1); // a-d | b-c - const int16x8_t E1 = vcombine_s16(vget_high_s16(E_tmp), vget_low_s16(E_tmp)); - Transpose8x2(E0, E1, rows); -} - -static void ITransformOne(const uint8_t* ref, - const int16_t* in, uint8_t* dst) { - int16x8x2_t rows; - INIT_VECTOR2(rows, vld1q_s16(in + 0), vld1q_s16(in + 8)); - TransformPass(&rows); - TransformPass(&rows); - Add4x4(rows.val[0], rows.val[1], ref, dst); -} - -#else - -static void ITransformOne(const uint8_t* ref, - const int16_t* in, uint8_t* dst) { - const int kBPS = BPS; - const int16_t kC1C2[] = { kC1, kC2, 0, 0 }; - - __asm__ volatile ( - "vld1.16 {q1, q2}, [%[in]] \n" - "vld1.16 {d0}, [%[kC1C2]] \n" - - // d2: in[0] - // d3: in[8] - // d4: in[4] - // d5: in[12] - "vswp d3, d4 \n" - - // q8 = {in[4], in[12]} * kC1 * 2 >> 16 - // q9 = {in[4], in[12]} * kC2 >> 16 - "vqdmulh.s16 q8, q2, d0[0] \n" - "vqdmulh.s16 q9, q2, d0[1] \n" - - // d22 = a = in[0] + in[8] - // d23 = b = in[0] - in[8] - "vqadd.s16 d22, d2, d3 \n" - "vqsub.s16 d23, d2, d3 \n" - - // q8 = in[4]/[12] * kC1 >> 16 - "vshr.s16 q8, q8, #1 \n" - - // Add {in[4], in[12]} back after the multiplication. - "vqadd.s16 q8, q2, q8 \n" - - // d20 = c = in[4]*kC2 - in[12]*kC1 - // d21 = d = in[4]*kC1 + in[12]*kC2 - "vqsub.s16 d20, d18, d17 \n" - "vqadd.s16 d21, d19, d16 \n" - - // d2 = tmp[0] = a + d - // d3 = tmp[1] = b + c - // d4 = tmp[2] = b - c - // d5 = tmp[3] = a - d - "vqadd.s16 d2, d22, d21 \n" - "vqadd.s16 d3, d23, d20 \n" - "vqsub.s16 d4, d23, d20 \n" - "vqsub.s16 d5, d22, d21 \n" - - "vzip.16 q1, q2 \n" - "vzip.16 q1, q2 \n" - - "vswp d3, d4 \n" - - // q8 = {tmp[4], tmp[12]} * kC1 * 2 >> 16 - // q9 = {tmp[4], tmp[12]} * kC2 >> 16 - "vqdmulh.s16 q8, q2, d0[0] \n" - "vqdmulh.s16 q9, q2, d0[1] \n" - - // d22 = a = tmp[0] + tmp[8] - // d23 = b = tmp[0] - tmp[8] - "vqadd.s16 d22, d2, d3 \n" - "vqsub.s16 d23, d2, d3 \n" - - "vshr.s16 q8, q8, #1 \n" - "vqadd.s16 q8, q2, q8 \n" - - // d20 = c = in[4]*kC2 - in[12]*kC1 - // d21 = d = in[4]*kC1 + in[12]*kC2 - "vqsub.s16 d20, d18, d17 \n" - "vqadd.s16 d21, d19, d16 \n" - - // d2 = tmp[0] = a + d - // d3 = tmp[1] = b + c - // d4 = tmp[2] = b - c - // d5 = tmp[3] = a - d - "vqadd.s16 d2, d22, d21 \n" - "vqadd.s16 d3, d23, d20 \n" - "vqsub.s16 d4, d23, d20 \n" - "vqsub.s16 d5, d22, d21 \n" - - "vld1.32 d6[0], [%[ref]], %[kBPS] \n" - "vld1.32 d6[1], [%[ref]], %[kBPS] \n" - "vld1.32 d7[0], [%[ref]], %[kBPS] \n" - "vld1.32 d7[1], [%[ref]], %[kBPS] \n" - - "sub %[ref], %[ref], %[kBPS], lsl #2 \n" - - // (val) + 4 >> 3 - "vrshr.s16 d2, d2, #3 \n" - "vrshr.s16 d3, d3, #3 \n" - "vrshr.s16 d4, d4, #3 \n" - "vrshr.s16 d5, d5, #3 \n" - - "vzip.16 q1, q2 \n" - "vzip.16 q1, q2 \n" - - // Must accumulate before saturating - "vmovl.u8 q8, d6 \n" - "vmovl.u8 q9, d7 \n" - - "vqadd.s16 q1, q1, q8 \n" - "vqadd.s16 q2, q2, q9 \n" - - "vqmovun.s16 d0, q1 \n" - "vqmovun.s16 d1, q2 \n" - - "vst1.32 d0[0], [%[dst]], %[kBPS] \n" - "vst1.32 d0[1], [%[dst]], %[kBPS] \n" - "vst1.32 d1[0], [%[dst]], %[kBPS] \n" - "vst1.32 d1[1], [%[dst]] \n" - - : [in] "+r"(in), [dst] "+r"(dst) // modified registers - : [kBPS] "r"(kBPS), [kC1C2] "r"(kC1C2), [ref] "r"(ref) // constants - : "memory", "q0", "q1", "q2", "q8", "q9", "q10", "q11" // clobbered - ); -} - -#endif // WEBP_USE_INTRINSICS - -static void ITransform(const uint8_t* ref, - const int16_t* in, uint8_t* dst, int do_two) { - ITransformOne(ref, in, dst); - if (do_two) { - ITransformOne(ref + 4, in + 16, dst + 4); - } -} - -// Load all 4x4 pixels into a single uint8x16_t variable. -static uint8x16_t Load4x4(const uint8_t* src) { - uint32x4_t out = vdupq_n_u32(0); - out = vld1q_lane_u32((const uint32_t*)(src + 0 * BPS), out, 0); - out = vld1q_lane_u32((const uint32_t*)(src + 1 * BPS), out, 1); - out = vld1q_lane_u32((const uint32_t*)(src + 2 * BPS), out, 2); - out = vld1q_lane_u32((const uint32_t*)(src + 3 * BPS), out, 3); - return vreinterpretq_u8_u32(out); -} - -// Forward transform. - -#if defined(WEBP_USE_INTRINSICS) - -static WEBP_INLINE void Transpose4x4_S16(const int16x4_t A, const int16x4_t B, - const int16x4_t C, const int16x4_t D, - int16x8_t* const out01, - int16x8_t* const out32) { - const int16x4x2_t AB = vtrn_s16(A, B); - const int16x4x2_t CD = vtrn_s16(C, D); - const int32x2x2_t tmp02 = vtrn_s32(vreinterpret_s32_s16(AB.val[0]), - vreinterpret_s32_s16(CD.val[0])); - const int32x2x2_t tmp13 = vtrn_s32(vreinterpret_s32_s16(AB.val[1]), - vreinterpret_s32_s16(CD.val[1])); - *out01 = vreinterpretq_s16_s64( - vcombine_s64(vreinterpret_s64_s32(tmp02.val[0]), - vreinterpret_s64_s32(tmp13.val[0]))); - *out32 = vreinterpretq_s16_s64( - vcombine_s64(vreinterpret_s64_s32(tmp13.val[1]), - vreinterpret_s64_s32(tmp02.val[1]))); -} - -static WEBP_INLINE int16x8_t DiffU8ToS16(const uint8x8_t a, - const uint8x8_t b) { - return vreinterpretq_s16_u16(vsubl_u8(a, b)); -} - -static void FTransform(const uint8_t* src, const uint8_t* ref, - int16_t* out) { - int16x8_t d0d1, d3d2; // working 4x4 int16 variables - { - const uint8x16_t S0 = Load4x4(src); - const uint8x16_t R0 = Load4x4(ref); - const int16x8_t D0D1 = DiffU8ToS16(vget_low_u8(S0), vget_low_u8(R0)); - const int16x8_t D2D3 = DiffU8ToS16(vget_high_u8(S0), vget_high_u8(R0)); - const int16x4_t D0 = vget_low_s16(D0D1); - const int16x4_t D1 = vget_high_s16(D0D1); - const int16x4_t D2 = vget_low_s16(D2D3); - const int16x4_t D3 = vget_high_s16(D2D3); - Transpose4x4_S16(D0, D1, D2, D3, &d0d1, &d3d2); - } - { // 1rst pass - const int32x4_t kCst937 = vdupq_n_s32(937); - const int32x4_t kCst1812 = vdupq_n_s32(1812); - const int16x8_t a0a1 = vaddq_s16(d0d1, d3d2); // d0+d3 | d1+d2 (=a0|a1) - const int16x8_t a3a2 = vsubq_s16(d0d1, d3d2); // d0-d3 | d1-d2 (=a3|a2) - const int16x8_t a0a1_2 = vshlq_n_s16(a0a1, 3); - const int16x4_t tmp0 = vadd_s16(vget_low_s16(a0a1_2), - vget_high_s16(a0a1_2)); - const int16x4_t tmp2 = vsub_s16(vget_low_s16(a0a1_2), - vget_high_s16(a0a1_2)); - const int32x4_t a3_2217 = vmull_n_s16(vget_low_s16(a3a2), 2217); - const int32x4_t a2_2217 = vmull_n_s16(vget_high_s16(a3a2), 2217); - const int32x4_t a2_p_a3 = vmlal_n_s16(a2_2217, vget_low_s16(a3a2), 5352); - const int32x4_t a3_m_a2 = vmlsl_n_s16(a3_2217, vget_high_s16(a3a2), 5352); - const int16x4_t tmp1 = vshrn_n_s32(vaddq_s32(a2_p_a3, kCst1812), 9); - const int16x4_t tmp3 = vshrn_n_s32(vaddq_s32(a3_m_a2, kCst937), 9); - Transpose4x4_S16(tmp0, tmp1, tmp2, tmp3, &d0d1, &d3d2); - } - { // 2nd pass - // the (1<<16) addition is for the replacement: a3!=0 <-> 1-(a3==0) - const int32x4_t kCst12000 = vdupq_n_s32(12000 + (1 << 16)); - const int32x4_t kCst51000 = vdupq_n_s32(51000); - const int16x8_t a0a1 = vaddq_s16(d0d1, d3d2); // d0+d3 | d1+d2 (=a0|a1) - const int16x8_t a3a2 = vsubq_s16(d0d1, d3d2); // d0-d3 | d1-d2 (=a3|a2) - const int16x4_t a0_k7 = vadd_s16(vget_low_s16(a0a1), vdup_n_s16(7)); - const int16x4_t out0 = vshr_n_s16(vadd_s16(a0_k7, vget_high_s16(a0a1)), 4); - const int16x4_t out2 = vshr_n_s16(vsub_s16(a0_k7, vget_high_s16(a0a1)), 4); - const int32x4_t a3_2217 = vmull_n_s16(vget_low_s16(a3a2), 2217); - const int32x4_t a2_2217 = vmull_n_s16(vget_high_s16(a3a2), 2217); - const int32x4_t a2_p_a3 = vmlal_n_s16(a2_2217, vget_low_s16(a3a2), 5352); - const int32x4_t a3_m_a2 = vmlsl_n_s16(a3_2217, vget_high_s16(a3a2), 5352); - const int16x4_t tmp1 = vaddhn_s32(a2_p_a3, kCst12000); - const int16x4_t out3 = vaddhn_s32(a3_m_a2, kCst51000); - const int16x4_t a3_eq_0 = - vreinterpret_s16_u16(vceq_s16(vget_low_s16(a3a2), vdup_n_s16(0))); - const int16x4_t out1 = vadd_s16(tmp1, a3_eq_0); - vst1_s16(out + 0, out0); - vst1_s16(out + 4, out1); - vst1_s16(out + 8, out2); - vst1_s16(out + 12, out3); - } -} - -#else - -// adapted from vp8/encoder/arm/neon/shortfdct_neon.asm -static const int16_t kCoeff16[] = { - 5352, 5352, 5352, 5352, 2217, 2217, 2217, 2217 -}; -static const int32_t kCoeff32[] = { - 1812, 1812, 1812, 1812, - 937, 937, 937, 937, - 12000, 12000, 12000, 12000, - 51000, 51000, 51000, 51000 -}; - -static void FTransform(const uint8_t* src, const uint8_t* ref, - int16_t* out) { - const int kBPS = BPS; - const uint8_t* src_ptr = src; - const uint8_t* ref_ptr = ref; - const int16_t* coeff16 = kCoeff16; - const int32_t* coeff32 = kCoeff32; - - __asm__ volatile ( - // load src into q4, q5 in high half - "vld1.8 {d8}, [%[src_ptr]], %[kBPS] \n" - "vld1.8 {d10}, [%[src_ptr]], %[kBPS] \n" - "vld1.8 {d9}, [%[src_ptr]], %[kBPS] \n" - "vld1.8 {d11}, [%[src_ptr]] \n" - - // load ref into q6, q7 in high half - "vld1.8 {d12}, [%[ref_ptr]], %[kBPS] \n" - "vld1.8 {d14}, [%[ref_ptr]], %[kBPS] \n" - "vld1.8 {d13}, [%[ref_ptr]], %[kBPS] \n" - "vld1.8 {d15}, [%[ref_ptr]] \n" - - // Pack the high values in to q4 and q6 - "vtrn.32 q4, q5 \n" - "vtrn.32 q6, q7 \n" - - // d[0-3] = src - ref - "vsubl.u8 q0, d8, d12 \n" - "vsubl.u8 q1, d9, d13 \n" - - // load coeff16 into q8(d16=5352, d17=2217) - "vld1.16 {q8}, [%[coeff16]] \n" - - // load coeff32 high half into q9 = 1812, q10 = 937 - "vld1.32 {q9, q10}, [%[coeff32]]! \n" - - // load coeff32 low half into q11=12000, q12=51000 - "vld1.32 {q11,q12}, [%[coeff32]] \n" - - // part 1 - // Transpose. Register dN is the same as dN in C - "vtrn.32 d0, d2 \n" - "vtrn.32 d1, d3 \n" - "vtrn.16 d0, d1 \n" - "vtrn.16 d2, d3 \n" - - "vadd.s16 d4, d0, d3 \n" // a0 = d0 + d3 - "vadd.s16 d5, d1, d2 \n" // a1 = d1 + d2 - "vsub.s16 d6, d1, d2 \n" // a2 = d1 - d2 - "vsub.s16 d7, d0, d3 \n" // a3 = d0 - d3 - - "vadd.s16 d0, d4, d5 \n" // a0 + a1 - "vshl.s16 d0, d0, #3 \n" // temp[0+i*4] = (a0+a1) << 3 - "vsub.s16 d2, d4, d5 \n" // a0 - a1 - "vshl.s16 d2, d2, #3 \n" // (temp[2+i*4] = (a0-a1) << 3 - - "vmlal.s16 q9, d7, d16 \n" // a3*5352 + 1812 - "vmlal.s16 q10, d7, d17 \n" // a3*2217 + 937 - "vmlal.s16 q9, d6, d17 \n" // a2*2217 + a3*5352 + 1812 - "vmlsl.s16 q10, d6, d16 \n" // a3*2217 + 937 - a2*5352 - - // temp[1+i*4] = (d2*2217 + d3*5352 + 1812) >> 9 - // temp[3+i*4] = (d3*2217 + 937 - d2*5352) >> 9 - "vshrn.s32 d1, q9, #9 \n" - "vshrn.s32 d3, q10, #9 \n" - - // part 2 - // transpose d0=ip[0], d1=ip[4], d2=ip[8], d3=ip[12] - "vtrn.32 d0, d2 \n" - "vtrn.32 d1, d3 \n" - "vtrn.16 d0, d1 \n" - "vtrn.16 d2, d3 \n" - - "vmov.s16 d26, #7 \n" - - "vadd.s16 d4, d0, d3 \n" // a1 = ip[0] + ip[12] - "vadd.s16 d5, d1, d2 \n" // b1 = ip[4] + ip[8] - "vsub.s16 d6, d1, d2 \n" // c1 = ip[4] - ip[8] - "vadd.s16 d4, d4, d26 \n" // a1 + 7 - "vsub.s16 d7, d0, d3 \n" // d1 = ip[0] - ip[12] - - "vadd.s16 d0, d4, d5 \n" // op[0] = a1 + b1 + 7 - "vsub.s16 d2, d4, d5 \n" // op[8] = a1 - b1 + 7 - - "vmlal.s16 q11, d7, d16 \n" // d1*5352 + 12000 - "vmlal.s16 q12, d7, d17 \n" // d1*2217 + 51000 - - "vceq.s16 d4, d7, #0 \n" - - "vshr.s16 d0, d0, #4 \n" - "vshr.s16 d2, d2, #4 \n" - - "vmlal.s16 q11, d6, d17 \n" // c1*2217 + d1*5352 + 12000 - "vmlsl.s16 q12, d6, d16 \n" // d1*2217 - c1*5352 + 51000 - - "vmvn d4, d4 \n" // !(d1 == 0) - // op[4] = (c1*2217 + d1*5352 + 12000)>>16 - "vshrn.s32 d1, q11, #16 \n" - // op[4] += (d1!=0) - "vsub.s16 d1, d1, d4 \n" - // op[12]= (d1*2217 - c1*5352 + 51000)>>16 - "vshrn.s32 d3, q12, #16 \n" - - // set result to out array - "vst1.16 {q0, q1}, [%[out]] \n" - : [src_ptr] "+r"(src_ptr), [ref_ptr] "+r"(ref_ptr), - [coeff32] "+r"(coeff32) // modified registers - : [kBPS] "r"(kBPS), [coeff16] "r"(coeff16), - [out] "r"(out) // constants - : "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", - "q10", "q11", "q12", "q13" // clobbered - ); -} - -#endif - -#define LOAD_LANE_16b(VALUE, LANE) do { \ - (VALUE) = vld1_lane_s16(src, (VALUE), (LANE)); \ - src += stride; \ -} while (0) - -static void FTransformWHT(const int16_t* src, int16_t* out) { - const int stride = 16; - const int16x4_t zero = vdup_n_s16(0); - int32x4x4_t tmp0; - int16x4x4_t in; - INIT_VECTOR4(in, zero, zero, zero, zero); - LOAD_LANE_16b(in.val[0], 0); - LOAD_LANE_16b(in.val[1], 0); - LOAD_LANE_16b(in.val[2], 0); - LOAD_LANE_16b(in.val[3], 0); - LOAD_LANE_16b(in.val[0], 1); - LOAD_LANE_16b(in.val[1], 1); - LOAD_LANE_16b(in.val[2], 1); - LOAD_LANE_16b(in.val[3], 1); - LOAD_LANE_16b(in.val[0], 2); - LOAD_LANE_16b(in.val[1], 2); - LOAD_LANE_16b(in.val[2], 2); - LOAD_LANE_16b(in.val[3], 2); - LOAD_LANE_16b(in.val[0], 3); - LOAD_LANE_16b(in.val[1], 3); - LOAD_LANE_16b(in.val[2], 3); - LOAD_LANE_16b(in.val[3], 3); - - { - // a0 = in[0 * 16] + in[2 * 16] - // a1 = in[1 * 16] + in[3 * 16] - // a2 = in[1 * 16] - in[3 * 16] - // a3 = in[0 * 16] - in[2 * 16] - const int32x4_t a0 = vaddl_s16(in.val[0], in.val[2]); - const int32x4_t a1 = vaddl_s16(in.val[1], in.val[3]); - const int32x4_t a2 = vsubl_s16(in.val[1], in.val[3]); - const int32x4_t a3 = vsubl_s16(in.val[0], in.val[2]); - tmp0.val[0] = vaddq_s32(a0, a1); - tmp0.val[1] = vaddq_s32(a3, a2); - tmp0.val[2] = vsubq_s32(a3, a2); - tmp0.val[3] = vsubq_s32(a0, a1); - } - { - const int32x4x4_t tmp1 = Transpose4x4(tmp0); - // a0 = tmp[0 + i] + tmp[ 8 + i] - // a1 = tmp[4 + i] + tmp[12 + i] - // a2 = tmp[4 + i] - tmp[12 + i] - // a3 = tmp[0 + i] - tmp[ 8 + i] - const int32x4_t a0 = vaddq_s32(tmp1.val[0], tmp1.val[2]); - const int32x4_t a1 = vaddq_s32(tmp1.val[1], tmp1.val[3]); - const int32x4_t a2 = vsubq_s32(tmp1.val[1], tmp1.val[3]); - const int32x4_t a3 = vsubq_s32(tmp1.val[0], tmp1.val[2]); - const int32x4_t b0 = vhaddq_s32(a0, a1); // (a0 + a1) >> 1 - const int32x4_t b1 = vhaddq_s32(a3, a2); // (a3 + a2) >> 1 - const int32x4_t b2 = vhsubq_s32(a3, a2); // (a3 - a2) >> 1 - const int32x4_t b3 = vhsubq_s32(a0, a1); // (a0 - a1) >> 1 - const int16x4_t out0 = vmovn_s32(b0); - const int16x4_t out1 = vmovn_s32(b1); - const int16x4_t out2 = vmovn_s32(b2); - const int16x4_t out3 = vmovn_s32(b3); - - vst1_s16(out + 0, out0); - vst1_s16(out + 4, out1); - vst1_s16(out + 8, out2); - vst1_s16(out + 12, out3); - } -} -#undef LOAD_LANE_16b - -//------------------------------------------------------------------------------ -// Texture distortion -// -// We try to match the spectral content (weighted) between source and -// reconstructed samples. - -// a 0123, b 0123 -// a 4567, b 4567 -// a 89ab, b 89ab -// a cdef, b cdef -// -// transpose -// -// a 048c, b 048c -// a 159d, b 159d -// a 26ae, b 26ae -// a 37bf, b 37bf -// -static WEBP_INLINE uint8x8x4_t DistoTranspose4x4U8(uint8x8x4_t d4_in) { - const uint8x8x2_t d2_tmp0 = vtrn_u8(d4_in.val[0], d4_in.val[1]); - const uint8x8x2_t d2_tmp1 = vtrn_u8(d4_in.val[2], d4_in.val[3]); - const uint16x4x2_t d2_tmp2 = vtrn_u16(vreinterpret_u16_u8(d2_tmp0.val[0]), - vreinterpret_u16_u8(d2_tmp1.val[0])); - const uint16x4x2_t d2_tmp3 = vtrn_u16(vreinterpret_u16_u8(d2_tmp0.val[1]), - vreinterpret_u16_u8(d2_tmp1.val[1])); - - d4_in.val[0] = vreinterpret_u8_u16(d2_tmp2.val[0]); - d4_in.val[2] = vreinterpret_u8_u16(d2_tmp2.val[1]); - d4_in.val[1] = vreinterpret_u8_u16(d2_tmp3.val[0]); - d4_in.val[3] = vreinterpret_u8_u16(d2_tmp3.val[1]); - return d4_in; -} - -static WEBP_INLINE int16x8x4_t DistoTranspose4x4S16(int16x8x4_t q4_in) { - const int16x8x2_t q2_tmp0 = vtrnq_s16(q4_in.val[0], q4_in.val[1]); - const int16x8x2_t q2_tmp1 = vtrnq_s16(q4_in.val[2], q4_in.val[3]); - const int32x4x2_t q2_tmp2 = vtrnq_s32(vreinterpretq_s32_s16(q2_tmp0.val[0]), - vreinterpretq_s32_s16(q2_tmp1.val[0])); - const int32x4x2_t q2_tmp3 = vtrnq_s32(vreinterpretq_s32_s16(q2_tmp0.val[1]), - vreinterpretq_s32_s16(q2_tmp1.val[1])); - q4_in.val[0] = vreinterpretq_s16_s32(q2_tmp2.val[0]); - q4_in.val[2] = vreinterpretq_s16_s32(q2_tmp2.val[1]); - q4_in.val[1] = vreinterpretq_s16_s32(q2_tmp3.val[0]); - q4_in.val[3] = vreinterpretq_s16_s32(q2_tmp3.val[1]); - return q4_in; -} - -static WEBP_INLINE int16x8x4_t DistoHorizontalPass(const uint8x8x4_t d4_in) { - // {a0, a1} = {in[0] + in[2], in[1] + in[3]} - // {a3, a2} = {in[0] - in[2], in[1] - in[3]} - const int16x8_t q_a0 = vreinterpretq_s16_u16(vaddl_u8(d4_in.val[0], - d4_in.val[2])); - const int16x8_t q_a1 = vreinterpretq_s16_u16(vaddl_u8(d4_in.val[1], - d4_in.val[3])); - const int16x8_t q_a3 = vreinterpretq_s16_u16(vsubl_u8(d4_in.val[0], - d4_in.val[2])); - const int16x8_t q_a2 = vreinterpretq_s16_u16(vsubl_u8(d4_in.val[1], - d4_in.val[3])); - int16x8x4_t q4_out; - // tmp[0] = a0 + a1 - // tmp[1] = a3 + a2 - // tmp[2] = a3 - a2 - // tmp[3] = a0 - a1 - INIT_VECTOR4(q4_out, - vaddq_s16(q_a0, q_a1), vaddq_s16(q_a3, q_a2), - vsubq_s16(q_a3, q_a2), vsubq_s16(q_a0, q_a1)); - return q4_out; -} - -static WEBP_INLINE int16x8x4_t DistoVerticalPass(int16x8x4_t q4_in) { - const int16x8_t q_a0 = vaddq_s16(q4_in.val[0], q4_in.val[2]); - const int16x8_t q_a1 = vaddq_s16(q4_in.val[1], q4_in.val[3]); - const int16x8_t q_a2 = vsubq_s16(q4_in.val[1], q4_in.val[3]); - const int16x8_t q_a3 = vsubq_s16(q4_in.val[0], q4_in.val[2]); - - q4_in.val[0] = vaddq_s16(q_a0, q_a1); - q4_in.val[1] = vaddq_s16(q_a3, q_a2); - q4_in.val[2] = vabdq_s16(q_a3, q_a2); - q4_in.val[3] = vabdq_s16(q_a0, q_a1); - q4_in.val[0] = vabsq_s16(q4_in.val[0]); - q4_in.val[1] = vabsq_s16(q4_in.val[1]); - return q4_in; -} - -static WEBP_INLINE int16x4x4_t DistoLoadW(const uint16_t* w) { - const uint16x8_t q_w07 = vld1q_u16(&w[0]); - const uint16x8_t q_w8f = vld1q_u16(&w[8]); - int16x4x4_t d4_w; - INIT_VECTOR4(d4_w, - vget_low_s16(vreinterpretq_s16_u16(q_w07)), - vget_high_s16(vreinterpretq_s16_u16(q_w07)), - vget_low_s16(vreinterpretq_s16_u16(q_w8f)), - vget_high_s16(vreinterpretq_s16_u16(q_w8f))); - return d4_w; -} - -static WEBP_INLINE int32x2_t DistoSum(const int16x8x4_t q4_in, - const int16x4x4_t d4_w) { - int32x2_t d_sum; - // sum += w[ 0] * abs(b0); - // sum += w[ 4] * abs(b1); - // sum += w[ 8] * abs(b2); - // sum += w[12] * abs(b3); - int32x4_t q_sum0 = vmull_s16(d4_w.val[0], vget_low_s16(q4_in.val[0])); - int32x4_t q_sum1 = vmull_s16(d4_w.val[1], vget_low_s16(q4_in.val[1])); - int32x4_t q_sum2 = vmull_s16(d4_w.val[2], vget_low_s16(q4_in.val[2])); - int32x4_t q_sum3 = vmull_s16(d4_w.val[3], vget_low_s16(q4_in.val[3])); - q_sum0 = vmlsl_s16(q_sum0, d4_w.val[0], vget_high_s16(q4_in.val[0])); - q_sum1 = vmlsl_s16(q_sum1, d4_w.val[1], vget_high_s16(q4_in.val[1])); - q_sum2 = vmlsl_s16(q_sum2, d4_w.val[2], vget_high_s16(q4_in.val[2])); - q_sum3 = vmlsl_s16(q_sum3, d4_w.val[3], vget_high_s16(q4_in.val[3])); - - q_sum0 = vaddq_s32(q_sum0, q_sum1); - q_sum2 = vaddq_s32(q_sum2, q_sum3); - q_sum2 = vaddq_s32(q_sum0, q_sum2); - d_sum = vpadd_s32(vget_low_s32(q_sum2), vget_high_s32(q_sum2)); - d_sum = vpadd_s32(d_sum, d_sum); - return d_sum; -} - -#define LOAD_LANE_32b(src, VALUE, LANE) \ - (VALUE) = vld1_lane_u32((const uint32_t*)(src), (VALUE), (LANE)) - -// Hadamard transform -// Returns the weighted sum of the absolute value of transformed coefficients. -static int Disto4x4(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - uint32x2_t d_in_ab_0123 = vdup_n_u32(0); - uint32x2_t d_in_ab_4567 = vdup_n_u32(0); - uint32x2_t d_in_ab_89ab = vdup_n_u32(0); - uint32x2_t d_in_ab_cdef = vdup_n_u32(0); - uint8x8x4_t d4_in; - - // load data a, b - LOAD_LANE_32b(a + 0 * BPS, d_in_ab_0123, 0); - LOAD_LANE_32b(a + 1 * BPS, d_in_ab_4567, 0); - LOAD_LANE_32b(a + 2 * BPS, d_in_ab_89ab, 0); - LOAD_LANE_32b(a + 3 * BPS, d_in_ab_cdef, 0); - LOAD_LANE_32b(b + 0 * BPS, d_in_ab_0123, 1); - LOAD_LANE_32b(b + 1 * BPS, d_in_ab_4567, 1); - LOAD_LANE_32b(b + 2 * BPS, d_in_ab_89ab, 1); - LOAD_LANE_32b(b + 3 * BPS, d_in_ab_cdef, 1); - INIT_VECTOR4(d4_in, - vreinterpret_u8_u32(d_in_ab_0123), - vreinterpret_u8_u32(d_in_ab_4567), - vreinterpret_u8_u32(d_in_ab_89ab), - vreinterpret_u8_u32(d_in_ab_cdef)); - - { - // horizontal pass - const uint8x8x4_t d4_t = DistoTranspose4x4U8(d4_in); - const int16x8x4_t q4_h = DistoHorizontalPass(d4_t); - const int16x4x4_t d4_w = DistoLoadW(w); - // vertical pass - const int16x8x4_t q4_t = DistoTranspose4x4S16(q4_h); - const int16x8x4_t q4_v = DistoVerticalPass(q4_t); - int32x2_t d_sum = DistoSum(q4_v, d4_w); - - // abs(sum2 - sum1) >> 5 - d_sum = vabs_s32(d_sum); - d_sum = vshr_n_s32(d_sum, 5); - return vget_lane_s32(d_sum, 0); - } -} -#undef LOAD_LANE_32b - -static int Disto16x16(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - int D = 0; - int x, y; - for (y = 0; y < 16 * BPS; y += 4 * BPS) { - for (x = 0; x < 16; x += 4) { - D += Disto4x4(a + x + y, b + x + y, w); - } - } - return D; -} - -//------------------------------------------------------------------------------ - -static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, - int start_block, int end_block, - VP8Histogram* const histo) { - const uint16x8_t max_coeff_thresh = vdupq_n_u16(MAX_COEFF_THRESH); - int j; - int distribution[MAX_COEFF_THRESH + 1] = { 0 }; - for (j = start_block; j < end_block; ++j) { - int16_t out[16]; - FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); - { - int k; - const int16x8_t a0 = vld1q_s16(out + 0); - const int16x8_t b0 = vld1q_s16(out + 8); - const uint16x8_t a1 = vreinterpretq_u16_s16(vabsq_s16(a0)); - const uint16x8_t b1 = vreinterpretq_u16_s16(vabsq_s16(b0)); - const uint16x8_t a2 = vshrq_n_u16(a1, 3); - const uint16x8_t b2 = vshrq_n_u16(b1, 3); - const uint16x8_t a3 = vminq_u16(a2, max_coeff_thresh); - const uint16x8_t b3 = vminq_u16(b2, max_coeff_thresh); - vst1q_s16(out + 0, vreinterpretq_s16_u16(a3)); - vst1q_s16(out + 8, vreinterpretq_s16_u16(b3)); - // Convert coefficients to bin. - for (k = 0; k < 16; ++k) { - ++distribution[out[k]]; - } - } - } - VP8SetHistogramData(distribution, histo); -} - -//------------------------------------------------------------------------------ - -static WEBP_INLINE void AccumulateSSE16(const uint8_t* const a, - const uint8_t* const b, - uint32x4_t* const sum) { - const uint8x16_t a0 = vld1q_u8(a); - const uint8x16_t b0 = vld1q_u8(b); - const uint8x16_t abs_diff = vabdq_u8(a0, b0); - uint16x8_t prod = vmull_u8(vget_low_u8(abs_diff), vget_low_u8(abs_diff)); - prod = vmlal_u8(prod, vget_high_u8(abs_diff), vget_high_u8(abs_diff)); - *sum = vpadalq_u16(*sum, prod); // pair-wise add and accumulate -} - -// Horizontal sum of all four uint32_t values in 'sum'. -static int SumToInt(uint32x4_t sum) { - const uint64x2_t sum2 = vpaddlq_u32(sum); - const uint64_t sum3 = vgetq_lane_u64(sum2, 0) + vgetq_lane_u64(sum2, 1); - return (int)sum3; -} - -static int SSE16x16(const uint8_t* a, const uint8_t* b) { - uint32x4_t sum = vdupq_n_u32(0); - int y; - for (y = 0; y < 16; ++y) { - AccumulateSSE16(a + y * BPS, b + y * BPS, &sum); - } - return SumToInt(sum); -} - -static int SSE16x8(const uint8_t* a, const uint8_t* b) { - uint32x4_t sum = vdupq_n_u32(0); - int y; - for (y = 0; y < 8; ++y) { - AccumulateSSE16(a + y * BPS, b + y * BPS, &sum); - } - return SumToInt(sum); -} - -static int SSE8x8(const uint8_t* a, const uint8_t* b) { - uint32x4_t sum = vdupq_n_u32(0); - int y; - for (y = 0; y < 8; ++y) { - const uint8x8_t a0 = vld1_u8(a + y * BPS); - const uint8x8_t b0 = vld1_u8(b + y * BPS); - const uint8x8_t abs_diff = vabd_u8(a0, b0); - const uint16x8_t prod = vmull_u8(abs_diff, abs_diff); - sum = vpadalq_u16(sum, prod); - } - return SumToInt(sum); -} - -static int SSE4x4(const uint8_t* a, const uint8_t* b) { - const uint8x16_t a0 = Load4x4(a); - const uint8x16_t b0 = Load4x4(b); - const uint8x16_t abs_diff = vabdq_u8(a0, b0); - uint16x8_t prod = vmull_u8(vget_low_u8(abs_diff), vget_low_u8(abs_diff)); - prod = vmlal_u8(prod, vget_high_u8(abs_diff), vget_high_u8(abs_diff)); - return SumToInt(vpaddlq_u16(prod)); -} - -//------------------------------------------------------------------------------ - -// Compilation with gcc-4.6.x is problematic for now. -#if !defined(WORK_AROUND_GCC) - -static int16x8_t Quantize(int16_t* const in, - const VP8Matrix* const mtx, int offset) { - const uint16x8_t sharp = vld1q_u16(&mtx->sharpen_[offset]); - const uint16x8_t q = vld1q_u16(&mtx->q_[offset]); - const uint16x8_t iq = vld1q_u16(&mtx->iq_[offset]); - const uint32x4_t bias0 = vld1q_u32(&mtx->bias_[offset + 0]); - const uint32x4_t bias1 = vld1q_u32(&mtx->bias_[offset + 4]); - - const int16x8_t a = vld1q_s16(in + offset); // in - const uint16x8_t b = vreinterpretq_u16_s16(vabsq_s16(a)); // coeff = abs(in) - const int16x8_t sign = vshrq_n_s16(a, 15); // sign - const uint16x8_t c = vaddq_u16(b, sharp); // + sharpen - const uint32x4_t m0 = vmull_u16(vget_low_u16(c), vget_low_u16(iq)); - const uint32x4_t m1 = vmull_u16(vget_high_u16(c), vget_high_u16(iq)); - const uint32x4_t m2 = vhaddq_u32(m0, bias0); - const uint32x4_t m3 = vhaddq_u32(m1, bias1); // (coeff * iQ + bias) >> 1 - const uint16x8_t c0 = vcombine_u16(vshrn_n_u32(m2, 16), - vshrn_n_u32(m3, 16)); // QFIX=17 = 16+1 - const uint16x8_t c1 = vminq_u16(c0, vdupq_n_u16(MAX_LEVEL)); - const int16x8_t c2 = veorq_s16(vreinterpretq_s16_u16(c1), sign); - const int16x8_t c3 = vsubq_s16(c2, sign); // restore sign - const int16x8_t c4 = vmulq_s16(c3, vreinterpretq_s16_u16(q)); - vst1q_s16(in + offset, c4); - assert(QFIX == 17); // this function can't work as is if QFIX != 16+1 - return c3; -} - -static const uint8_t kShuffles[4][8] = { - { 0, 1, 2, 3, 8, 9, 16, 17 }, - { 10, 11, 4, 5, 6, 7, 12, 13 }, - { 18, 19, 24, 25, 26, 27, 20, 21 }, - { 14, 15, 22, 23, 28, 29, 30, 31 } -}; - -static int QuantizeBlock(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - const int16x8_t out0 = Quantize(in, mtx, 0); - const int16x8_t out1 = Quantize(in, mtx, 8); - uint8x8x4_t shuffles; - // vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use - // non-standard versions there. -#if defined(__APPLE__) && defined(__aarch64__) && \ - defined(__apple_build_version__) && (__apple_build_version__< 6020037) - uint8x16x2_t all_out; - INIT_VECTOR2(all_out, vreinterpretq_u8_s16(out0), vreinterpretq_u8_s16(out1)); - INIT_VECTOR4(shuffles, - vtbl2q_u8(all_out, vld1_u8(kShuffles[0])), - vtbl2q_u8(all_out, vld1_u8(kShuffles[1])), - vtbl2q_u8(all_out, vld1_u8(kShuffles[2])), - vtbl2q_u8(all_out, vld1_u8(kShuffles[3]))); -#else - uint8x8x4_t all_out; - INIT_VECTOR4(all_out, - vreinterpret_u8_s16(vget_low_s16(out0)), - vreinterpret_u8_s16(vget_high_s16(out0)), - vreinterpret_u8_s16(vget_low_s16(out1)), - vreinterpret_u8_s16(vget_high_s16(out1))); - INIT_VECTOR4(shuffles, - vtbl4_u8(all_out, vld1_u8(kShuffles[0])), - vtbl4_u8(all_out, vld1_u8(kShuffles[1])), - vtbl4_u8(all_out, vld1_u8(kShuffles[2])), - vtbl4_u8(all_out, vld1_u8(kShuffles[3]))); -#endif - // Zigzag reordering - vst1_u8((uint8_t*)(out + 0), shuffles.val[0]); - vst1_u8((uint8_t*)(out + 4), shuffles.val[1]); - vst1_u8((uint8_t*)(out + 8), shuffles.val[2]); - vst1_u8((uint8_t*)(out + 12), shuffles.val[3]); - // test zeros - if (*(uint64_t*)(out + 0) != 0) return 1; - if (*(uint64_t*)(out + 4) != 0) return 1; - if (*(uint64_t*)(out + 8) != 0) return 1; - if (*(uint64_t*)(out + 12) != 0) return 1; - return 0; -} - -static int Quantize2Blocks(int16_t in[32], int16_t out[32], - const VP8Matrix* const mtx) { - int nz; - nz = QuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0; - nz |= QuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1; - return nz; -} - -#endif // !WORK_AROUND_GCC - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8EncDspInitNEON(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitNEON(void) { - VP8ITransform = ITransform; - VP8FTransform = FTransform; - - VP8FTransformWHT = FTransformWHT; - - VP8TDisto4x4 = Disto4x4; - VP8TDisto16x16 = Disto16x16; - VP8CollectHistogram = CollectHistogram; - VP8SSE16x16 = SSE16x16; - VP8SSE16x8 = SSE16x8; - VP8SSE8x8 = SSE8x8; - VP8SSE4x4 = SSE4x4; -#if !defined(WORK_AROUND_GCC) - VP8EncQuantizeBlock = QuantizeBlock; - VP8EncQuantize2Blocks = Quantize2Blocks; -#endif -} - -#else // !WEBP_USE_NEON - -WEBP_DSP_INIT_STUB(VP8EncDspInitNEON) - -#endif // WEBP_USE_NEON diff --git a/Example/Pods/libwebp/src/dsp/enc_sse2.c b/Example/Pods/libwebp/src/dsp/enc_sse2.c deleted file mode 100644 index 2333d2b0..00000000 --- a/Example/Pods/libwebp/src/dsp/enc_sse2.c +++ /dev/null @@ -1,1468 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// SSE2 version of speed-critical encoding functions. -// -// Author: Christian Duvivier (cduvivier@google.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE2) -#include // for abs() -#include - -#include "../enc/cost.h" -#include "../enc/vp8enci.h" - -//------------------------------------------------------------------------------ -// Quite useful macro for debugging. Left here for convenience. - -#if 0 -#include -static void PrintReg(const __m128i r, const char* const name, int size) { - int n; - union { - __m128i r; - uint8_t i8[16]; - uint16_t i16[8]; - uint32_t i32[4]; - uint64_t i64[2]; - } tmp; - tmp.r = r; - fprintf(stderr, "%s\t: ", name); - if (size == 8) { - for (n = 0; n < 16; ++n) fprintf(stderr, "%.2x ", tmp.i8[n]); - } else if (size == 16) { - for (n = 0; n < 8; ++n) fprintf(stderr, "%.4x ", tmp.i16[n]); - } else if (size == 32) { - for (n = 0; n < 4; ++n) fprintf(stderr, "%.8x ", tmp.i32[n]); - } else { - for (n = 0; n < 2; ++n) fprintf(stderr, "%.16lx ", tmp.i64[n]); - } - fprintf(stderr, "\n"); -} -#endif - -//------------------------------------------------------------------------------ -// Transforms (Paragraph 14.4) - -// Does one or two inverse transforms. -static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst, - int do_two) { - // This implementation makes use of 16-bit fixed point versions of two - // multiply constants: - // K1 = sqrt(2) * cos (pi/8) ~= 85627 / 2^16 - // K2 = sqrt(2) * sin (pi/8) ~= 35468 / 2^16 - // - // To be able to use signed 16-bit integers, we use the following trick to - // have constants within range: - // - Associated constants are obtained by subtracting the 16-bit fixed point - // version of one: - // k = K - (1 << 16) => K = k + (1 << 16) - // K1 = 85267 => k1 = 20091 - // K2 = 35468 => k2 = -30068 - // - The multiplication of a variable by a constant become the sum of the - // variable and the multiplication of that variable by the associated - // constant: - // (x * K) >> 16 = (x * (k + (1 << 16))) >> 16 = ((x * k ) >> 16) + x - const __m128i k1 = _mm_set1_epi16(20091); - const __m128i k2 = _mm_set1_epi16(-30068); - __m128i T0, T1, T2, T3; - - // Load and concatenate the transform coefficients (we'll do two inverse - // transforms in parallel). In the case of only one inverse transform, the - // second half of the vectors will just contain random value we'll never - // use nor store. - __m128i in0, in1, in2, in3; - { - in0 = _mm_loadl_epi64((const __m128i*)&in[0]); - in1 = _mm_loadl_epi64((const __m128i*)&in[4]); - in2 = _mm_loadl_epi64((const __m128i*)&in[8]); - in3 = _mm_loadl_epi64((const __m128i*)&in[12]); - // a00 a10 a20 a30 x x x x - // a01 a11 a21 a31 x x x x - // a02 a12 a22 a32 x x x x - // a03 a13 a23 a33 x x x x - if (do_two) { - const __m128i inB0 = _mm_loadl_epi64((const __m128i*)&in[16]); - const __m128i inB1 = _mm_loadl_epi64((const __m128i*)&in[20]); - const __m128i inB2 = _mm_loadl_epi64((const __m128i*)&in[24]); - const __m128i inB3 = _mm_loadl_epi64((const __m128i*)&in[28]); - in0 = _mm_unpacklo_epi64(in0, inB0); - in1 = _mm_unpacklo_epi64(in1, inB1); - in2 = _mm_unpacklo_epi64(in2, inB2); - in3 = _mm_unpacklo_epi64(in3, inB3); - // a00 a10 a20 a30 b00 b10 b20 b30 - // a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 - // a03 a13 a23 a33 b03 b13 b23 b33 - } - } - - // Vertical pass and subsequent transpose. - { - // First pass, c and d calculations are longer because of the "trick" - // multiplications. - const __m128i a = _mm_add_epi16(in0, in2); - const __m128i b = _mm_sub_epi16(in0, in2); - // c = MUL(in1, K2) - MUL(in3, K1) = MUL(in1, k2) - MUL(in3, k1) + in1 - in3 - const __m128i c1 = _mm_mulhi_epi16(in1, k2); - const __m128i c2 = _mm_mulhi_epi16(in3, k1); - const __m128i c3 = _mm_sub_epi16(in1, in3); - const __m128i c4 = _mm_sub_epi16(c1, c2); - const __m128i c = _mm_add_epi16(c3, c4); - // d = MUL(in1, K1) + MUL(in3, K2) = MUL(in1, k1) + MUL(in3, k2) + in1 + in3 - const __m128i d1 = _mm_mulhi_epi16(in1, k1); - const __m128i d2 = _mm_mulhi_epi16(in3, k2); - const __m128i d3 = _mm_add_epi16(in1, in3); - const __m128i d4 = _mm_add_epi16(d1, d2); - const __m128i d = _mm_add_epi16(d3, d4); - - // Second pass. - const __m128i tmp0 = _mm_add_epi16(a, d); - const __m128i tmp1 = _mm_add_epi16(b, c); - const __m128i tmp2 = _mm_sub_epi16(b, c); - const __m128i tmp3 = _mm_sub_epi16(a, d); - - // Transpose the two 4x4. - // a00 a01 a02 a03 b00 b01 b02 b03 - // a10 a11 a12 a13 b10 b11 b12 b13 - // a20 a21 a22 a23 b20 b21 b22 b23 - // a30 a31 a32 a33 b30 b31 b32 b33 - const __m128i transpose0_0 = _mm_unpacklo_epi16(tmp0, tmp1); - const __m128i transpose0_1 = _mm_unpacklo_epi16(tmp2, tmp3); - const __m128i transpose0_2 = _mm_unpackhi_epi16(tmp0, tmp1); - const __m128i transpose0_3 = _mm_unpackhi_epi16(tmp2, tmp3); - // a00 a10 a01 a11 a02 a12 a03 a13 - // a20 a30 a21 a31 a22 a32 a23 a33 - // b00 b10 b01 b11 b02 b12 b03 b13 - // b20 b30 b21 b31 b22 b32 b23 b33 - const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3); - const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3); - // a00 a10 a20 a30 a01 a11 a21 a31 - // b00 b10 b20 b30 b01 b11 b21 b31 - // a02 a12 a22 a32 a03 a13 a23 a33 - // b02 b12 a22 b32 b03 b13 b23 b33 - T0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1); - T1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1); - T2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3); - T3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3); - // a00 a10 a20 a30 b00 b10 b20 b30 - // a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 - // a03 a13 a23 a33 b03 b13 b23 b33 - } - - // Horizontal pass and subsequent transpose. - { - // First pass, c and d calculations are longer because of the "trick" - // multiplications. - const __m128i four = _mm_set1_epi16(4); - const __m128i dc = _mm_add_epi16(T0, four); - const __m128i a = _mm_add_epi16(dc, T2); - const __m128i b = _mm_sub_epi16(dc, T2); - // c = MUL(T1, K2) - MUL(T3, K1) = MUL(T1, k2) - MUL(T3, k1) + T1 - T3 - const __m128i c1 = _mm_mulhi_epi16(T1, k2); - const __m128i c2 = _mm_mulhi_epi16(T3, k1); - const __m128i c3 = _mm_sub_epi16(T1, T3); - const __m128i c4 = _mm_sub_epi16(c1, c2); - const __m128i c = _mm_add_epi16(c3, c4); - // d = MUL(T1, K1) + MUL(T3, K2) = MUL(T1, k1) + MUL(T3, k2) + T1 + T3 - const __m128i d1 = _mm_mulhi_epi16(T1, k1); - const __m128i d2 = _mm_mulhi_epi16(T3, k2); - const __m128i d3 = _mm_add_epi16(T1, T3); - const __m128i d4 = _mm_add_epi16(d1, d2); - const __m128i d = _mm_add_epi16(d3, d4); - - // Second pass. - const __m128i tmp0 = _mm_add_epi16(a, d); - const __m128i tmp1 = _mm_add_epi16(b, c); - const __m128i tmp2 = _mm_sub_epi16(b, c); - const __m128i tmp3 = _mm_sub_epi16(a, d); - const __m128i shifted0 = _mm_srai_epi16(tmp0, 3); - const __m128i shifted1 = _mm_srai_epi16(tmp1, 3); - const __m128i shifted2 = _mm_srai_epi16(tmp2, 3); - const __m128i shifted3 = _mm_srai_epi16(tmp3, 3); - - // Transpose the two 4x4. - // a00 a01 a02 a03 b00 b01 b02 b03 - // a10 a11 a12 a13 b10 b11 b12 b13 - // a20 a21 a22 a23 b20 b21 b22 b23 - // a30 a31 a32 a33 b30 b31 b32 b33 - const __m128i transpose0_0 = _mm_unpacklo_epi16(shifted0, shifted1); - const __m128i transpose0_1 = _mm_unpacklo_epi16(shifted2, shifted3); - const __m128i transpose0_2 = _mm_unpackhi_epi16(shifted0, shifted1); - const __m128i transpose0_3 = _mm_unpackhi_epi16(shifted2, shifted3); - // a00 a10 a01 a11 a02 a12 a03 a13 - // a20 a30 a21 a31 a22 a32 a23 a33 - // b00 b10 b01 b11 b02 b12 b03 b13 - // b20 b30 b21 b31 b22 b32 b23 b33 - const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3); - const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3); - // a00 a10 a20 a30 a01 a11 a21 a31 - // b00 b10 b20 b30 b01 b11 b21 b31 - // a02 a12 a22 a32 a03 a13 a23 a33 - // b02 b12 a22 b32 b03 b13 b23 b33 - T0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1); - T1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1); - T2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3); - T3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3); - // a00 a10 a20 a30 b00 b10 b20 b30 - // a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 - // a03 a13 a23 a33 b03 b13 b23 b33 - } - - // Add inverse transform to 'ref' and store. - { - const __m128i zero = _mm_setzero_si128(); - // Load the reference(s). - __m128i ref0, ref1, ref2, ref3; - if (do_two) { - // Load eight bytes/pixels per line. - ref0 = _mm_loadl_epi64((const __m128i*)&ref[0 * BPS]); - ref1 = _mm_loadl_epi64((const __m128i*)&ref[1 * BPS]); - ref2 = _mm_loadl_epi64((const __m128i*)&ref[2 * BPS]); - ref3 = _mm_loadl_epi64((const __m128i*)&ref[3 * BPS]); - } else { - // Load four bytes/pixels per line. - ref0 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[0 * BPS])); - ref1 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[1 * BPS])); - ref2 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[2 * BPS])); - ref3 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[3 * BPS])); - } - // Convert to 16b. - ref0 = _mm_unpacklo_epi8(ref0, zero); - ref1 = _mm_unpacklo_epi8(ref1, zero); - ref2 = _mm_unpacklo_epi8(ref2, zero); - ref3 = _mm_unpacklo_epi8(ref3, zero); - // Add the inverse transform(s). - ref0 = _mm_add_epi16(ref0, T0); - ref1 = _mm_add_epi16(ref1, T1); - ref2 = _mm_add_epi16(ref2, T2); - ref3 = _mm_add_epi16(ref3, T3); - // Unsigned saturate to 8b. - ref0 = _mm_packus_epi16(ref0, ref0); - ref1 = _mm_packus_epi16(ref1, ref1); - ref2 = _mm_packus_epi16(ref2, ref2); - ref3 = _mm_packus_epi16(ref3, ref3); - // Store the results. - if (do_two) { - // Store eight bytes/pixels per line. - _mm_storel_epi64((__m128i*)&dst[0 * BPS], ref0); - _mm_storel_epi64((__m128i*)&dst[1 * BPS], ref1); - _mm_storel_epi64((__m128i*)&dst[2 * BPS], ref2); - _mm_storel_epi64((__m128i*)&dst[3 * BPS], ref3); - } else { - // Store four bytes/pixels per line. - WebPUint32ToMem(&dst[0 * BPS], _mm_cvtsi128_si32(ref0)); - WebPUint32ToMem(&dst[1 * BPS], _mm_cvtsi128_si32(ref1)); - WebPUint32ToMem(&dst[2 * BPS], _mm_cvtsi128_si32(ref2)); - WebPUint32ToMem(&dst[3 * BPS], _mm_cvtsi128_si32(ref3)); - } - } -} - -static void FTransformPass1(const __m128i* const in01, - const __m128i* const in23, - __m128i* const out01, - __m128i* const out32) { - const __m128i k937 = _mm_set1_epi32(937); - const __m128i k1812 = _mm_set1_epi32(1812); - - const __m128i k88p = _mm_set_epi16(8, 8, 8, 8, 8, 8, 8, 8); - const __m128i k88m = _mm_set_epi16(-8, 8, -8, 8, -8, 8, -8, 8); - const __m128i k5352_2217p = _mm_set_epi16(2217, 5352, 2217, 5352, - 2217, 5352, 2217, 5352); - const __m128i k5352_2217m = _mm_set_epi16(-5352, 2217, -5352, 2217, - -5352, 2217, -5352, 2217); - - // *in01 = 00 01 10 11 02 03 12 13 - // *in23 = 20 21 30 31 22 23 32 33 - const __m128i shuf01_p = _mm_shufflehi_epi16(*in01, _MM_SHUFFLE(2, 3, 0, 1)); - const __m128i shuf23_p = _mm_shufflehi_epi16(*in23, _MM_SHUFFLE(2, 3, 0, 1)); - // 00 01 10 11 03 02 13 12 - // 20 21 30 31 23 22 33 32 - const __m128i s01 = _mm_unpacklo_epi64(shuf01_p, shuf23_p); - const __m128i s32 = _mm_unpackhi_epi64(shuf01_p, shuf23_p); - // 00 01 10 11 20 21 30 31 - // 03 02 13 12 23 22 33 32 - const __m128i a01 = _mm_add_epi16(s01, s32); - const __m128i a32 = _mm_sub_epi16(s01, s32); - // [d0 + d3 | d1 + d2 | ...] = [a0 a1 | a0' a1' | ... ] - // [d0 - d3 | d1 - d2 | ...] = [a3 a2 | a3' a2' | ... ] - - const __m128i tmp0 = _mm_madd_epi16(a01, k88p); // [ (a0 + a1) << 3, ... ] - const __m128i tmp2 = _mm_madd_epi16(a01, k88m); // [ (a0 - a1) << 3, ... ] - const __m128i tmp1_1 = _mm_madd_epi16(a32, k5352_2217p); - const __m128i tmp3_1 = _mm_madd_epi16(a32, k5352_2217m); - const __m128i tmp1_2 = _mm_add_epi32(tmp1_1, k1812); - const __m128i tmp3_2 = _mm_add_epi32(tmp3_1, k937); - const __m128i tmp1 = _mm_srai_epi32(tmp1_2, 9); - const __m128i tmp3 = _mm_srai_epi32(tmp3_2, 9); - const __m128i s03 = _mm_packs_epi32(tmp0, tmp2); - const __m128i s12 = _mm_packs_epi32(tmp1, tmp3); - const __m128i s_lo = _mm_unpacklo_epi16(s03, s12); // 0 1 0 1 0 1... - const __m128i s_hi = _mm_unpackhi_epi16(s03, s12); // 2 3 2 3 2 3 - const __m128i v23 = _mm_unpackhi_epi32(s_lo, s_hi); - *out01 = _mm_unpacklo_epi32(s_lo, s_hi); - *out32 = _mm_shuffle_epi32(v23, _MM_SHUFFLE(1, 0, 3, 2)); // 3 2 3 2 3 2.. -} - -static void FTransformPass2(const __m128i* const v01, const __m128i* const v32, - int16_t* out) { - const __m128i zero = _mm_setzero_si128(); - const __m128i seven = _mm_set1_epi16(7); - const __m128i k5352_2217 = _mm_set_epi16(5352, 2217, 5352, 2217, - 5352, 2217, 5352, 2217); - const __m128i k2217_5352 = _mm_set_epi16(2217, -5352, 2217, -5352, - 2217, -5352, 2217, -5352); - const __m128i k12000_plus_one = _mm_set1_epi32(12000 + (1 << 16)); - const __m128i k51000 = _mm_set1_epi32(51000); - - // Same operations are done on the (0,3) and (1,2) pairs. - // a0 = v0 + v3 - // a1 = v1 + v2 - // a3 = v0 - v3 - // a2 = v1 - v2 - const __m128i a01 = _mm_add_epi16(*v01, *v32); - const __m128i a32 = _mm_sub_epi16(*v01, *v32); - const __m128i a11 = _mm_unpackhi_epi64(a01, a01); - const __m128i a22 = _mm_unpackhi_epi64(a32, a32); - const __m128i a01_plus_7 = _mm_add_epi16(a01, seven); - - // d0 = (a0 + a1 + 7) >> 4; - // d2 = (a0 - a1 + 7) >> 4; - const __m128i c0 = _mm_add_epi16(a01_plus_7, a11); - const __m128i c2 = _mm_sub_epi16(a01_plus_7, a11); - const __m128i d0 = _mm_srai_epi16(c0, 4); - const __m128i d2 = _mm_srai_epi16(c2, 4); - - // f1 = ((b3 * 5352 + b2 * 2217 + 12000) >> 16) - // f3 = ((b3 * 2217 - b2 * 5352 + 51000) >> 16) - const __m128i b23 = _mm_unpacklo_epi16(a22, a32); - const __m128i c1 = _mm_madd_epi16(b23, k5352_2217); - const __m128i c3 = _mm_madd_epi16(b23, k2217_5352); - const __m128i d1 = _mm_add_epi32(c1, k12000_plus_one); - const __m128i d3 = _mm_add_epi32(c3, k51000); - const __m128i e1 = _mm_srai_epi32(d1, 16); - const __m128i e3 = _mm_srai_epi32(d3, 16); - const __m128i f1 = _mm_packs_epi32(e1, e1); - const __m128i f3 = _mm_packs_epi32(e3, e3); - // f1 = f1 + (a3 != 0); - // The compare will return (0xffff, 0) for (==0, !=0). To turn that into the - // desired (0, 1), we add one earlier through k12000_plus_one. - // -> f1 = f1 + 1 - (a3 == 0) - const __m128i g1 = _mm_add_epi16(f1, _mm_cmpeq_epi16(a32, zero)); - - const __m128i d0_g1 = _mm_unpacklo_epi64(d0, g1); - const __m128i d2_f3 = _mm_unpacklo_epi64(d2, f3); - _mm_storeu_si128((__m128i*)&out[0], d0_g1); - _mm_storeu_si128((__m128i*)&out[8], d2_f3); -} - -static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) { - const __m128i zero = _mm_setzero_si128(); - - // Load src and convert to 16b. - const __m128i src0 = _mm_loadl_epi64((const __m128i*)&src[0 * BPS]); - const __m128i src1 = _mm_loadl_epi64((const __m128i*)&src[1 * BPS]); - const __m128i src2 = _mm_loadl_epi64((const __m128i*)&src[2 * BPS]); - const __m128i src3 = _mm_loadl_epi64((const __m128i*)&src[3 * BPS]); - const __m128i src_0 = _mm_unpacklo_epi8(src0, zero); - const __m128i src_1 = _mm_unpacklo_epi8(src1, zero); - const __m128i src_2 = _mm_unpacklo_epi8(src2, zero); - const __m128i src_3 = _mm_unpacklo_epi8(src3, zero); - // Load ref and convert to 16b. - const __m128i ref0 = _mm_loadl_epi64((const __m128i*)&ref[0 * BPS]); - const __m128i ref1 = _mm_loadl_epi64((const __m128i*)&ref[1 * BPS]); - const __m128i ref2 = _mm_loadl_epi64((const __m128i*)&ref[2 * BPS]); - const __m128i ref3 = _mm_loadl_epi64((const __m128i*)&ref[3 * BPS]); - const __m128i ref_0 = _mm_unpacklo_epi8(ref0, zero); - const __m128i ref_1 = _mm_unpacklo_epi8(ref1, zero); - const __m128i ref_2 = _mm_unpacklo_epi8(ref2, zero); - const __m128i ref_3 = _mm_unpacklo_epi8(ref3, zero); - // Compute difference. -> 00 01 02 03 00 00 00 00 - const __m128i diff0 = _mm_sub_epi16(src_0, ref_0); - const __m128i diff1 = _mm_sub_epi16(src_1, ref_1); - const __m128i diff2 = _mm_sub_epi16(src_2, ref_2); - const __m128i diff3 = _mm_sub_epi16(src_3, ref_3); - - // Unpack and shuffle - // 00 01 02 03 0 0 0 0 - // 10 11 12 13 0 0 0 0 - // 20 21 22 23 0 0 0 0 - // 30 31 32 33 0 0 0 0 - const __m128i shuf01 = _mm_unpacklo_epi32(diff0, diff1); - const __m128i shuf23 = _mm_unpacklo_epi32(diff2, diff3); - __m128i v01, v32; - - // First pass - FTransformPass1(&shuf01, &shuf23, &v01, &v32); - - // Second pass - FTransformPass2(&v01, &v32, out); -} - -static void FTransform2(const uint8_t* src, const uint8_t* ref, int16_t* out) { - const __m128i zero = _mm_setzero_si128(); - - // Load src and convert to 16b. - const __m128i src0 = _mm_loadl_epi64((const __m128i*)&src[0 * BPS]); - const __m128i src1 = _mm_loadl_epi64((const __m128i*)&src[1 * BPS]); - const __m128i src2 = _mm_loadl_epi64((const __m128i*)&src[2 * BPS]); - const __m128i src3 = _mm_loadl_epi64((const __m128i*)&src[3 * BPS]); - const __m128i src_0 = _mm_unpacklo_epi8(src0, zero); - const __m128i src_1 = _mm_unpacklo_epi8(src1, zero); - const __m128i src_2 = _mm_unpacklo_epi8(src2, zero); - const __m128i src_3 = _mm_unpacklo_epi8(src3, zero); - // Load ref and convert to 16b. - const __m128i ref0 = _mm_loadl_epi64((const __m128i*)&ref[0 * BPS]); - const __m128i ref1 = _mm_loadl_epi64((const __m128i*)&ref[1 * BPS]); - const __m128i ref2 = _mm_loadl_epi64((const __m128i*)&ref[2 * BPS]); - const __m128i ref3 = _mm_loadl_epi64((const __m128i*)&ref[3 * BPS]); - const __m128i ref_0 = _mm_unpacklo_epi8(ref0, zero); - const __m128i ref_1 = _mm_unpacklo_epi8(ref1, zero); - const __m128i ref_2 = _mm_unpacklo_epi8(ref2, zero); - const __m128i ref_3 = _mm_unpacklo_epi8(ref3, zero); - // Compute difference. -> 00 01 02 03 00' 01' 02' 03' - const __m128i diff0 = _mm_sub_epi16(src_0, ref_0); - const __m128i diff1 = _mm_sub_epi16(src_1, ref_1); - const __m128i diff2 = _mm_sub_epi16(src_2, ref_2); - const __m128i diff3 = _mm_sub_epi16(src_3, ref_3); - - // Unpack and shuffle - // 00 01 02 03 0 0 0 0 - // 10 11 12 13 0 0 0 0 - // 20 21 22 23 0 0 0 0 - // 30 31 32 33 0 0 0 0 - const __m128i shuf01l = _mm_unpacklo_epi32(diff0, diff1); - const __m128i shuf23l = _mm_unpacklo_epi32(diff2, diff3); - const __m128i shuf01h = _mm_unpackhi_epi32(diff0, diff1); - const __m128i shuf23h = _mm_unpackhi_epi32(diff2, diff3); - __m128i v01l, v32l; - __m128i v01h, v32h; - - // First pass - FTransformPass1(&shuf01l, &shuf23l, &v01l, &v32l); - FTransformPass1(&shuf01h, &shuf23h, &v01h, &v32h); - - // Second pass - FTransformPass2(&v01l, &v32l, out + 0); - FTransformPass2(&v01h, &v32h, out + 16); -} - -static void FTransformWHTRow(const int16_t* const in, __m128i* const out) { - const __m128i kMult1 = _mm_set_epi16(0, 0, 0, 0, 1, 1, 1, 1); - const __m128i kMult2 = _mm_set_epi16(0, 0, 0, 0, -1, 1, -1, 1); - const __m128i src0 = _mm_loadl_epi64((__m128i*)&in[0 * 16]); - const __m128i src1 = _mm_loadl_epi64((__m128i*)&in[1 * 16]); - const __m128i src2 = _mm_loadl_epi64((__m128i*)&in[2 * 16]); - const __m128i src3 = _mm_loadl_epi64((__m128i*)&in[3 * 16]); - const __m128i A01 = _mm_unpacklo_epi16(src0, src1); // A0 A1 | ... - const __m128i A23 = _mm_unpacklo_epi16(src2, src3); // A2 A3 | ... - const __m128i B0 = _mm_adds_epi16(A01, A23); // a0 | a1 | ... - const __m128i B1 = _mm_subs_epi16(A01, A23); // a3 | a2 | ... - const __m128i C0 = _mm_unpacklo_epi32(B0, B1); // a0 | a1 | a3 | a2 - const __m128i C1 = _mm_unpacklo_epi32(B1, B0); // a3 | a2 | a0 | a1 - const __m128i D0 = _mm_madd_epi16(C0, kMult1); // out0, out1 - const __m128i D1 = _mm_madd_epi16(C1, kMult2); // out2, out3 - *out = _mm_unpacklo_epi64(D0, D1); -} - -static void FTransformWHT(const int16_t* in, int16_t* out) { - __m128i row0, row1, row2, row3; - FTransformWHTRow(in + 0 * 64, &row0); - FTransformWHTRow(in + 1 * 64, &row1); - FTransformWHTRow(in + 2 * 64, &row2); - FTransformWHTRow(in + 3 * 64, &row3); - - { - const __m128i a0 = _mm_add_epi32(row0, row2); - const __m128i a1 = _mm_add_epi32(row1, row3); - const __m128i a2 = _mm_sub_epi32(row1, row3); - const __m128i a3 = _mm_sub_epi32(row0, row2); - const __m128i b0 = _mm_srai_epi32(_mm_add_epi32(a0, a1), 1); - const __m128i b1 = _mm_srai_epi32(_mm_add_epi32(a3, a2), 1); - const __m128i b2 = _mm_srai_epi32(_mm_sub_epi32(a3, a2), 1); - const __m128i b3 = _mm_srai_epi32(_mm_sub_epi32(a0, a1), 1); - const __m128i out0 = _mm_packs_epi32(b0, b1); - const __m128i out1 = _mm_packs_epi32(b2, b3); - _mm_storeu_si128((__m128i*)&out[0], out0); - _mm_storeu_si128((__m128i*)&out[8], out1); - } -} - -//------------------------------------------------------------------------------ -// Compute susceptibility based on DCT-coeff histograms: -// the higher, the "easier" the macroblock is to compress. - -static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, - int start_block, int end_block, - VP8Histogram* const histo) { - const __m128i zero = _mm_setzero_si128(); - const __m128i max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH); - int j; - int distribution[MAX_COEFF_THRESH + 1] = { 0 }; - for (j = start_block; j < end_block; ++j) { - int16_t out[16]; - int k; - - FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); - - // Convert coefficients to bin (within out[]). - { - // Load. - const __m128i out0 = _mm_loadu_si128((__m128i*)&out[0]); - const __m128i out1 = _mm_loadu_si128((__m128i*)&out[8]); - const __m128i d0 = _mm_sub_epi16(zero, out0); - const __m128i d1 = _mm_sub_epi16(zero, out1); - const __m128i abs0 = _mm_max_epi16(out0, d0); // abs(v), 16b - const __m128i abs1 = _mm_max_epi16(out1, d1); - // v = abs(out) >> 3 - const __m128i v0 = _mm_srai_epi16(abs0, 3); - const __m128i v1 = _mm_srai_epi16(abs1, 3); - // bin = min(v, MAX_COEFF_THRESH) - const __m128i bin0 = _mm_min_epi16(v0, max_coeff_thresh); - const __m128i bin1 = _mm_min_epi16(v1, max_coeff_thresh); - // Store. - _mm_storeu_si128((__m128i*)&out[0], bin0); - _mm_storeu_si128((__m128i*)&out[8], bin1); - } - - // Convert coefficients to bin. - for (k = 0; k < 16; ++k) { - ++distribution[out[k]]; - } - } - VP8SetHistogramData(distribution, histo); -} - -//------------------------------------------------------------------------------ -// Intra predictions - -// helper for chroma-DC predictions -static WEBP_INLINE void Put8x8uv(uint8_t v, uint8_t* dst) { - int j; - const __m128i values = _mm_set1_epi8(v); - for (j = 0; j < 8; ++j) { - _mm_storel_epi64((__m128i*)(dst + j * BPS), values); - } -} - -static WEBP_INLINE void Put16(uint8_t v, uint8_t* dst) { - int j; - const __m128i values = _mm_set1_epi8(v); - for (j = 0; j < 16; ++j) { - _mm_store_si128((__m128i*)(dst + j * BPS), values); - } -} - -static WEBP_INLINE void Fill(uint8_t* dst, int value, int size) { - if (size == 4) { - int j; - for (j = 0; j < 4; ++j) { - memset(dst + j * BPS, value, 4); - } - } else if (size == 8) { - Put8x8uv(value, dst); - } else { - Put16(value, dst); - } -} - -static WEBP_INLINE void VE8uv(uint8_t* dst, const uint8_t* top) { - int j; - const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); - for (j = 0; j < 8; ++j) { - _mm_storel_epi64((__m128i*)(dst + j * BPS), top_values); - } -} - -static WEBP_INLINE void VE16(uint8_t* dst, const uint8_t* top) { - const __m128i top_values = _mm_load_si128((const __m128i*)top); - int j; - for (j = 0; j < 16; ++j) { - _mm_store_si128((__m128i*)(dst + j * BPS), top_values); - } -} - -static WEBP_INLINE void VerticalPred(uint8_t* dst, - const uint8_t* top, int size) { - if (top != NULL) { - if (size == 8) { - VE8uv(dst, top); - } else { - VE16(dst, top); - } - } else { - Fill(dst, 127, size); - } -} - -static WEBP_INLINE void HE8uv(uint8_t* dst, const uint8_t* left) { - int j; - for (j = 0; j < 8; ++j) { - const __m128i values = _mm_set1_epi8(left[j]); - _mm_storel_epi64((__m128i*)dst, values); - dst += BPS; - } -} - -static WEBP_INLINE void HE16(uint8_t* dst, const uint8_t* left) { - int j; - for (j = 0; j < 16; ++j) { - const __m128i values = _mm_set1_epi8(left[j]); - _mm_store_si128((__m128i*)dst, values); - dst += BPS; - } -} - -static WEBP_INLINE void HorizontalPred(uint8_t* dst, - const uint8_t* left, int size) { - if (left != NULL) { - if (size == 8) { - HE8uv(dst, left); - } else { - HE16(dst, left); - } - } else { - Fill(dst, 129, size); - } -} - -static WEBP_INLINE void TM(uint8_t* dst, const uint8_t* left, - const uint8_t* top, int size) { - const __m128i zero = _mm_setzero_si128(); - int y; - if (size == 8) { - const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); - const __m128i top_base = _mm_unpacklo_epi8(top_values, zero); - for (y = 0; y < 8; ++y, dst += BPS) { - const int val = left[y] - left[-1]; - const __m128i base = _mm_set1_epi16(val); - const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero); - _mm_storel_epi64((__m128i*)dst, out); - } - } else { - const __m128i top_values = _mm_load_si128((const __m128i*)top); - const __m128i top_base_0 = _mm_unpacklo_epi8(top_values, zero); - const __m128i top_base_1 = _mm_unpackhi_epi8(top_values, zero); - for (y = 0; y < 16; ++y, dst += BPS) { - const int val = left[y] - left[-1]; - const __m128i base = _mm_set1_epi16(val); - const __m128i out_0 = _mm_add_epi16(base, top_base_0); - const __m128i out_1 = _mm_add_epi16(base, top_base_1); - const __m128i out = _mm_packus_epi16(out_0, out_1); - _mm_store_si128((__m128i*)dst, out); - } - } -} - -static WEBP_INLINE void TrueMotion(uint8_t* dst, const uint8_t* left, - const uint8_t* top, int size) { - if (left != NULL) { - if (top != NULL) { - TM(dst, left, top, size); - } else { - HorizontalPred(dst, left, size); - } - } else { - // true motion without left samples (hence: with default 129 value) - // is equivalent to VE prediction where you just copy the top samples. - // Note that if top samples are not available, the default value is - // then 129, and not 127 as in the VerticalPred case. - if (top != NULL) { - VerticalPred(dst, top, size); - } else { - Fill(dst, 129, size); - } - } -} - -static WEBP_INLINE void DC8uv(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { - const __m128i zero = _mm_setzero_si128(); - const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); - const __m128i left_values = _mm_loadl_epi64((const __m128i*)left); - const __m128i sum_top = _mm_sad_epu8(top_values, zero); - const __m128i sum_left = _mm_sad_epu8(left_values, zero); - const int DC = _mm_cvtsi128_si32(sum_top) + _mm_cvtsi128_si32(sum_left) + 8; - Put8x8uv(DC >> 4, dst); -} - -static WEBP_INLINE void DC8uvNoLeft(uint8_t* dst, const uint8_t* top) { - const __m128i zero = _mm_setzero_si128(); - const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); - const __m128i sum = _mm_sad_epu8(top_values, zero); - const int DC = _mm_cvtsi128_si32(sum) + 4; - Put8x8uv(DC >> 3, dst); -} - -static WEBP_INLINE void DC8uvNoTop(uint8_t* dst, const uint8_t* left) { - // 'left' is contiguous so we can reuse the top summation. - DC8uvNoLeft(dst, left); -} - -static WEBP_INLINE void DC8uvNoTopLeft(uint8_t* dst) { - Put8x8uv(0x80, dst); -} - -static WEBP_INLINE void DC8uvMode(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { - if (top != NULL) { - if (left != NULL) { // top and left present - DC8uv(dst, left, top); - } else { // top, but no left - DC8uvNoLeft(dst, top); - } - } else if (left != NULL) { // left but no top - DC8uvNoTop(dst, left); - } else { // no top, no left, nothing. - DC8uvNoTopLeft(dst); - } -} - -static WEBP_INLINE void DC16(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { - const __m128i zero = _mm_setzero_si128(); - const __m128i top_row = _mm_load_si128((const __m128i*)top); - const __m128i left_row = _mm_load_si128((const __m128i*)left); - const __m128i sad8x2 = _mm_sad_epu8(top_row, zero); - // sum the two sads: sad8x2[0:1] + sad8x2[8:9] - const __m128i sum_top = _mm_add_epi16(sad8x2, _mm_shuffle_epi32(sad8x2, 2)); - const __m128i sad8x2_left = _mm_sad_epu8(left_row, zero); - // sum the two sads: sad8x2[0:1] + sad8x2[8:9] - const __m128i sum_left = - _mm_add_epi16(sad8x2_left, _mm_shuffle_epi32(sad8x2_left, 2)); - const int DC = _mm_cvtsi128_si32(sum_top) + _mm_cvtsi128_si32(sum_left) + 16; - Put16(DC >> 5, dst); -} - -static WEBP_INLINE void DC16NoLeft(uint8_t* dst, const uint8_t* top) { - const __m128i zero = _mm_setzero_si128(); - const __m128i top_row = _mm_load_si128((const __m128i*)top); - const __m128i sad8x2 = _mm_sad_epu8(top_row, zero); - // sum the two sads: sad8x2[0:1] + sad8x2[8:9] - const __m128i sum = _mm_add_epi16(sad8x2, _mm_shuffle_epi32(sad8x2, 2)); - const int DC = _mm_cvtsi128_si32(sum) + 8; - Put16(DC >> 4, dst); -} - -static WEBP_INLINE void DC16NoTop(uint8_t* dst, const uint8_t* left) { - // 'left' is contiguous so we can reuse the top summation. - DC16NoLeft(dst, left); -} - -static WEBP_INLINE void DC16NoTopLeft(uint8_t* dst) { - Put16(0x80, dst); -} - -static WEBP_INLINE void DC16Mode(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { - if (top != NULL) { - if (left != NULL) { // top and left present - DC16(dst, left, top); - } else { // top, but no left - DC16NoLeft(dst, top); - } - } else if (left != NULL) { // left but no top - DC16NoTop(dst, left); - } else { // no top, no left, nothing. - DC16NoTopLeft(dst); - } -} - -//------------------------------------------------------------------------------ -// 4x4 predictions - -#define DST(x, y) dst[(x) + (y) * BPS] -#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2) -#define AVG2(a, b) (((a) + (b) + 1) >> 1) - -// We use the following 8b-arithmetic tricks: -// (a + 2 * b + c + 2) >> 2 = (AC + b + 1) >> 1 -// where: AC = (a + c) >> 1 = [(a + c + 1) >> 1] - [(a^c) & 1] -// and: -// (a + 2 * b + c + 2) >> 2 = (AB + BC + 1) >> 1 - (ab|bc)&lsb -// where: AC = (a + b + 1) >> 1, BC = (b + c + 1) >> 1 -// and ab = a ^ b, bc = b ^ c, lsb = (AC^BC)&1 - -static WEBP_INLINE void VE4(uint8_t* dst, const uint8_t* top) { // vertical - const __m128i one = _mm_set1_epi8(1); - const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(top - 1)); - const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1); - const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2); - const __m128i a = _mm_avg_epu8(ABCDEFGH, CDEFGH00); - const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGH00), one); - const __m128i b = _mm_subs_epu8(a, lsb); - const __m128i avg = _mm_avg_epu8(b, BCDEFGH0); - const uint32_t vals = _mm_cvtsi128_si32(avg); - int i; - for (i = 0; i < 4; ++i) { - WebPUint32ToMem(dst + i * BPS, vals); - } -} - -static WEBP_INLINE void HE4(uint8_t* dst, const uint8_t* top) { // horizontal - const int X = top[-1]; - const int I = top[-2]; - const int J = top[-3]; - const int K = top[-4]; - const int L = top[-5]; - WebPUint32ToMem(dst + 0 * BPS, 0x01010101U * AVG3(X, I, J)); - WebPUint32ToMem(dst + 1 * BPS, 0x01010101U * AVG3(I, J, K)); - WebPUint32ToMem(dst + 2 * BPS, 0x01010101U * AVG3(J, K, L)); - WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(K, L, L)); -} - -static WEBP_INLINE void DC4(uint8_t* dst, const uint8_t* top) { - uint32_t dc = 4; - int i; - for (i = 0; i < 4; ++i) dc += top[i] + top[-5 + i]; - Fill(dst, dc >> 3, 4); -} - -static WEBP_INLINE void LD4(uint8_t* dst, const uint8_t* top) { // Down-Left - const __m128i one = _mm_set1_epi8(1); - const __m128i ABCDEFGH = _mm_loadl_epi64((const __m128i*)top); - const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1); - const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2); - const __m128i CDEFGHH0 = _mm_insert_epi16(CDEFGH00, top[7], 3); - const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, CDEFGHH0); - const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one); - const __m128i avg2 = _mm_subs_epu8(avg1, lsb); - const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0); - WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcdefg )); - WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); - WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); - WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); -} - -static WEBP_INLINE void VR4(uint8_t* dst, - const uint8_t* top) { // Vertical-Right - const __m128i one = _mm_set1_epi8(1); - const int I = top[-2]; - const int J = top[-3]; - const int K = top[-4]; - const int X = top[-1]; - const __m128i XABCD = _mm_loadl_epi64((const __m128i*)(top - 1)); - const __m128i ABCD0 = _mm_srli_si128(XABCD, 1); - const __m128i abcd = _mm_avg_epu8(XABCD, ABCD0); - const __m128i _XABCD = _mm_slli_si128(XABCD, 1); - const __m128i IXABCD = _mm_insert_epi16(_XABCD, I | (X << 8), 0); - const __m128i avg1 = _mm_avg_epu8(IXABCD, ABCD0); - const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one); - const __m128i avg2 = _mm_subs_epu8(avg1, lsb); - const __m128i efgh = _mm_avg_epu8(avg2, XABCD); - WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcd )); - WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( efgh )); - WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1))); - WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1))); - - // these two are hard to implement in SSE2, so we keep the C-version: - DST(0, 2) = AVG3(J, I, X); - DST(0, 3) = AVG3(K, J, I); -} - -static WEBP_INLINE void VL4(uint8_t* dst, - const uint8_t* top) { // Vertical-Left - const __m128i one = _mm_set1_epi8(1); - const __m128i ABCDEFGH = _mm_loadl_epi64((const __m128i*)top); - const __m128i BCDEFGH_ = _mm_srli_si128(ABCDEFGH, 1); - const __m128i CDEFGH__ = _mm_srli_si128(ABCDEFGH, 2); - const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, BCDEFGH_); - const __m128i avg2 = _mm_avg_epu8(CDEFGH__, BCDEFGH_); - const __m128i avg3 = _mm_avg_epu8(avg1, avg2); - const __m128i lsb1 = _mm_and_si128(_mm_xor_si128(avg1, avg2), one); - const __m128i ab = _mm_xor_si128(ABCDEFGH, BCDEFGH_); - const __m128i bc = _mm_xor_si128(CDEFGH__, BCDEFGH_); - const __m128i abbc = _mm_or_si128(ab, bc); - const __m128i lsb2 = _mm_and_si128(abbc, lsb1); - const __m128i avg4 = _mm_subs_epu8(avg3, lsb2); - const uint32_t extra_out = _mm_cvtsi128_si32(_mm_srli_si128(avg4, 4)); - WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( avg1 )); - WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( avg4 )); - WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1))); - WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1))); - - // these two are hard to get and irregular - DST(3, 2) = (extra_out >> 0) & 0xff; - DST(3, 3) = (extra_out >> 8) & 0xff; -} - -static WEBP_INLINE void RD4(uint8_t* dst, const uint8_t* top) { // Down-right - const __m128i one = _mm_set1_epi8(1); - const __m128i LKJIXABC = _mm_loadl_epi64((const __m128i*)(top - 5)); - const __m128i LKJIXABCD = _mm_insert_epi16(LKJIXABC, top[3], 4); - const __m128i KJIXABCD_ = _mm_srli_si128(LKJIXABCD, 1); - const __m128i JIXABCD__ = _mm_srli_si128(LKJIXABCD, 2); - const __m128i avg1 = _mm_avg_epu8(JIXABCD__, LKJIXABCD); - const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one); - const __m128i avg2 = _mm_subs_epu8(avg1, lsb); - const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_); - WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32( abcdefg )); - WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); - WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); - WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); -} - -static WEBP_INLINE void HU4(uint8_t* dst, const uint8_t* top) { - const int I = top[-2]; - const int J = top[-3]; - const int K = top[-4]; - const int L = top[-5]; - DST(0, 0) = AVG2(I, J); - DST(2, 0) = DST(0, 1) = AVG2(J, K); - DST(2, 1) = DST(0, 2) = AVG2(K, L); - DST(1, 0) = AVG3(I, J, K); - DST(3, 0) = DST(1, 1) = AVG3(J, K, L); - DST(3, 1) = DST(1, 2) = AVG3(K, L, L); - DST(3, 2) = DST(2, 2) = - DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L; -} - -static WEBP_INLINE void HD4(uint8_t* dst, const uint8_t* top) { - const int X = top[-1]; - const int I = top[-2]; - const int J = top[-3]; - const int K = top[-4]; - const int L = top[-5]; - const int A = top[0]; - const int B = top[1]; - const int C = top[2]; - - DST(0, 0) = DST(2, 1) = AVG2(I, X); - DST(0, 1) = DST(2, 2) = AVG2(J, I); - DST(0, 2) = DST(2, 3) = AVG2(K, J); - DST(0, 3) = AVG2(L, K); - - DST(3, 0) = AVG3(A, B, C); - DST(2, 0) = AVG3(X, A, B); - DST(1, 0) = DST(3, 1) = AVG3(I, X, A); - DST(1, 1) = DST(3, 2) = AVG3(J, I, X); - DST(1, 2) = DST(3, 3) = AVG3(K, J, I); - DST(1, 3) = AVG3(L, K, J); -} - -static WEBP_INLINE void TM4(uint8_t* dst, const uint8_t* top) { - const __m128i zero = _mm_setzero_si128(); - const __m128i top_values = _mm_cvtsi32_si128(WebPMemToUint32(top)); - const __m128i top_base = _mm_unpacklo_epi8(top_values, zero); - int y; - for (y = 0; y < 4; ++y, dst += BPS) { - const int val = top[-2 - y] - top[-1]; - const __m128i base = _mm_set1_epi16(val); - const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero); - WebPUint32ToMem(dst, _mm_cvtsi128_si32(out)); - } -} - -#undef DST -#undef AVG3 -#undef AVG2 - -//------------------------------------------------------------------------------ -// luma 4x4 prediction - -// Left samples are top[-5 .. -2], top_left is top[-1], top are -// located at top[0..3], and top right is top[4..7] -static void Intra4Preds(uint8_t* dst, const uint8_t* top) { - DC4(I4DC4 + dst, top); - TM4(I4TM4 + dst, top); - VE4(I4VE4 + dst, top); - HE4(I4HE4 + dst, top); - RD4(I4RD4 + dst, top); - VR4(I4VR4 + dst, top); - LD4(I4LD4 + dst, top); - VL4(I4VL4 + dst, top); - HD4(I4HD4 + dst, top); - HU4(I4HU4 + dst, top); -} - -//------------------------------------------------------------------------------ -// Chroma 8x8 prediction (paragraph 12.2) - -static void IntraChromaPreds(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { - // U block - DC8uvMode(C8DC8 + dst, left, top); - VerticalPred(C8VE8 + dst, top, 8); - HorizontalPred(C8HE8 + dst, left, 8); - TrueMotion(C8TM8 + dst, left, top, 8); - // V block - dst += 8; - if (top != NULL) top += 8; - if (left != NULL) left += 16; - DC8uvMode(C8DC8 + dst, left, top); - VerticalPred(C8VE8 + dst, top, 8); - HorizontalPred(C8HE8 + dst, left, 8); - TrueMotion(C8TM8 + dst, left, top, 8); -} - -//------------------------------------------------------------------------------ -// luma 16x16 prediction (paragraph 12.3) - -static void Intra16Preds(uint8_t* dst, - const uint8_t* left, const uint8_t* top) { - DC16Mode(I16DC16 + dst, left, top); - VerticalPred(I16VE16 + dst, top, 16); - HorizontalPred(I16HE16 + dst, left, 16); - TrueMotion(I16TM16 + dst, left, top, 16); -} - -//------------------------------------------------------------------------------ -// Metric - -static WEBP_INLINE void SubtractAndAccumulate(const __m128i a, const __m128i b, - __m128i* const sum) { - // take abs(a-b) in 8b - const __m128i a_b = _mm_subs_epu8(a, b); - const __m128i b_a = _mm_subs_epu8(b, a); - const __m128i abs_a_b = _mm_or_si128(a_b, b_a); - // zero-extend to 16b - const __m128i zero = _mm_setzero_si128(); - const __m128i C0 = _mm_unpacklo_epi8(abs_a_b, zero); - const __m128i C1 = _mm_unpackhi_epi8(abs_a_b, zero); - // multiply with self - const __m128i sum1 = _mm_madd_epi16(C0, C0); - const __m128i sum2 = _mm_madd_epi16(C1, C1); - *sum = _mm_add_epi32(sum1, sum2); -} - -static WEBP_INLINE int SSE_16xN(const uint8_t* a, const uint8_t* b, - int num_pairs) { - __m128i sum = _mm_setzero_si128(); - int32_t tmp[4]; - int i; - - for (i = 0; i < num_pairs; ++i) { - const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[BPS * 0]); - const __m128i b0 = _mm_loadu_si128((const __m128i*)&b[BPS * 0]); - const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[BPS * 1]); - const __m128i b1 = _mm_loadu_si128((const __m128i*)&b[BPS * 1]); - __m128i sum1, sum2; - SubtractAndAccumulate(a0, b0, &sum1); - SubtractAndAccumulate(a1, b1, &sum2); - sum = _mm_add_epi32(sum, _mm_add_epi32(sum1, sum2)); - a += 2 * BPS; - b += 2 * BPS; - } - _mm_storeu_si128((__m128i*)tmp, sum); - return (tmp[3] + tmp[2] + tmp[1] + tmp[0]); -} - -static int SSE16x16(const uint8_t* a, const uint8_t* b) { - return SSE_16xN(a, b, 8); -} - -static int SSE16x8(const uint8_t* a, const uint8_t* b) { - return SSE_16xN(a, b, 4); -} - -#define LOAD_8x16b(ptr) \ - _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i*)(ptr)), zero) - -static int SSE8x8(const uint8_t* a, const uint8_t* b) { - const __m128i zero = _mm_setzero_si128(); - int num_pairs = 4; - __m128i sum = zero; - int32_t tmp[4]; - while (num_pairs-- > 0) { - const __m128i a0 = LOAD_8x16b(&a[BPS * 0]); - const __m128i a1 = LOAD_8x16b(&a[BPS * 1]); - const __m128i b0 = LOAD_8x16b(&b[BPS * 0]); - const __m128i b1 = LOAD_8x16b(&b[BPS * 1]); - // subtract - const __m128i c0 = _mm_subs_epi16(a0, b0); - const __m128i c1 = _mm_subs_epi16(a1, b1); - // multiply/accumulate with self - const __m128i d0 = _mm_madd_epi16(c0, c0); - const __m128i d1 = _mm_madd_epi16(c1, c1); - // collect - const __m128i sum01 = _mm_add_epi32(d0, d1); - sum = _mm_add_epi32(sum, sum01); - a += 2 * BPS; - b += 2 * BPS; - } - _mm_storeu_si128((__m128i*)tmp, sum); - return (tmp[3] + tmp[2] + tmp[1] + tmp[0]); -} -#undef LOAD_8x16b - -static int SSE4x4(const uint8_t* a, const uint8_t* b) { - const __m128i zero = _mm_setzero_si128(); - - // Load values. Note that we read 8 pixels instead of 4, - // but the a/b buffers are over-allocated to that effect. - const __m128i a0 = _mm_loadl_epi64((const __m128i*)&a[BPS * 0]); - const __m128i a1 = _mm_loadl_epi64((const __m128i*)&a[BPS * 1]); - const __m128i a2 = _mm_loadl_epi64((const __m128i*)&a[BPS * 2]); - const __m128i a3 = _mm_loadl_epi64((const __m128i*)&a[BPS * 3]); - const __m128i b0 = _mm_loadl_epi64((const __m128i*)&b[BPS * 0]); - const __m128i b1 = _mm_loadl_epi64((const __m128i*)&b[BPS * 1]); - const __m128i b2 = _mm_loadl_epi64((const __m128i*)&b[BPS * 2]); - const __m128i b3 = _mm_loadl_epi64((const __m128i*)&b[BPS * 3]); - // Combine pair of lines. - const __m128i a01 = _mm_unpacklo_epi32(a0, a1); - const __m128i a23 = _mm_unpacklo_epi32(a2, a3); - const __m128i b01 = _mm_unpacklo_epi32(b0, b1); - const __m128i b23 = _mm_unpacklo_epi32(b2, b3); - // Convert to 16b. - const __m128i a01s = _mm_unpacklo_epi8(a01, zero); - const __m128i a23s = _mm_unpacklo_epi8(a23, zero); - const __m128i b01s = _mm_unpacklo_epi8(b01, zero); - const __m128i b23s = _mm_unpacklo_epi8(b23, zero); - // subtract, square and accumulate - const __m128i d0 = _mm_subs_epi16(a01s, b01s); - const __m128i d1 = _mm_subs_epi16(a23s, b23s); - const __m128i e0 = _mm_madd_epi16(d0, d0); - const __m128i e1 = _mm_madd_epi16(d1, d1); - const __m128i sum = _mm_add_epi32(e0, e1); - - int32_t tmp[4]; - _mm_storeu_si128((__m128i*)tmp, sum); - return (tmp[3] + tmp[2] + tmp[1] + tmp[0]); -} - -//------------------------------------------------------------------------------ -// Texture distortion -// -// We try to match the spectral content (weighted) between source and -// reconstructed samples. - -// Hadamard transform -// Returns the difference between the weighted sum of the absolute value of -// transformed coefficients. -static int TTransform(const uint8_t* inA, const uint8_t* inB, - const uint16_t* const w) { - int32_t sum[4]; - __m128i tmp_0, tmp_1, tmp_2, tmp_3; - const __m128i zero = _mm_setzero_si128(); - - // Load, combine and transpose inputs. - { - const __m128i inA_0 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 0]); - const __m128i inA_1 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 1]); - const __m128i inA_2 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 2]); - const __m128i inA_3 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 3]); - const __m128i inB_0 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 0]); - const __m128i inB_1 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 1]); - const __m128i inB_2 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 2]); - const __m128i inB_3 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 3]); - - // Combine inA and inB (we'll do two transforms in parallel). - const __m128i inAB_0 = _mm_unpacklo_epi8(inA_0, inB_0); - const __m128i inAB_1 = _mm_unpacklo_epi8(inA_1, inB_1); - const __m128i inAB_2 = _mm_unpacklo_epi8(inA_2, inB_2); - const __m128i inAB_3 = _mm_unpacklo_epi8(inA_3, inB_3); - // a00 b00 a01 b01 a02 b03 a03 b03 0 0 0 0 0 0 0 0 - // a10 b10 a11 b11 a12 b12 a13 b13 0 0 0 0 0 0 0 0 - // a20 b20 a21 b21 a22 b22 a23 b23 0 0 0 0 0 0 0 0 - // a30 b30 a31 b31 a32 b32 a33 b33 0 0 0 0 0 0 0 0 - - // Transpose the two 4x4, discarding the filling zeroes. - const __m128i transpose0_0 = _mm_unpacklo_epi8(inAB_0, inAB_2); - const __m128i transpose0_1 = _mm_unpacklo_epi8(inAB_1, inAB_3); - // a00 a20 b00 b20 a01 a21 b01 b21 a02 a22 b02 b22 a03 a23 b03 b23 - // a10 a30 b10 b30 a11 a31 b11 b31 a12 a32 b12 b32 a13 a33 b13 b33 - const __m128i transpose1_0 = _mm_unpacklo_epi8(transpose0_0, transpose0_1); - const __m128i transpose1_1 = _mm_unpackhi_epi8(transpose0_0, transpose0_1); - // a00 a10 a20 a30 b00 b10 b20 b30 a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 a03 a13 a23 a33 b03 b13 b23 b33 - - // Convert to 16b. - tmp_0 = _mm_unpacklo_epi8(transpose1_0, zero); - tmp_1 = _mm_unpackhi_epi8(transpose1_0, zero); - tmp_2 = _mm_unpacklo_epi8(transpose1_1, zero); - tmp_3 = _mm_unpackhi_epi8(transpose1_1, zero); - // a00 a10 a20 a30 b00 b10 b20 b30 - // a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 - // a03 a13 a23 a33 b03 b13 b23 b33 - } - - // Horizontal pass and subsequent transpose. - { - // Calculate a and b (two 4x4 at once). - const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2); - const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3); - const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3); - const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2); - const __m128i b0 = _mm_add_epi16(a0, a1); - const __m128i b1 = _mm_add_epi16(a3, a2); - const __m128i b2 = _mm_sub_epi16(a3, a2); - const __m128i b3 = _mm_sub_epi16(a0, a1); - // a00 a01 a02 a03 b00 b01 b02 b03 - // a10 a11 a12 a13 b10 b11 b12 b13 - // a20 a21 a22 a23 b20 b21 b22 b23 - // a30 a31 a32 a33 b30 b31 b32 b33 - - // Transpose the two 4x4. - const __m128i transpose0_0 = _mm_unpacklo_epi16(b0, b1); - const __m128i transpose0_1 = _mm_unpacklo_epi16(b2, b3); - const __m128i transpose0_2 = _mm_unpackhi_epi16(b0, b1); - const __m128i transpose0_3 = _mm_unpackhi_epi16(b2, b3); - // a00 a10 a01 a11 a02 a12 a03 a13 - // a20 a30 a21 a31 a22 a32 a23 a33 - // b00 b10 b01 b11 b02 b12 b03 b13 - // b20 b30 b21 b31 b22 b32 b23 b33 - const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3); - const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3); - // a00 a10 a20 a30 a01 a11 a21 a31 - // b00 b10 b20 b30 b01 b11 b21 b31 - // a02 a12 a22 a32 a03 a13 a23 a33 - // b02 b12 a22 b32 b03 b13 b23 b33 - tmp_0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1); - tmp_1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1); - tmp_2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3); - tmp_3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3); - // a00 a10 a20 a30 b00 b10 b20 b30 - // a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 - // a03 a13 a23 a33 b03 b13 b23 b33 - } - - // Vertical pass and difference of weighted sums. - { - // Load all inputs. - const __m128i w_0 = _mm_loadu_si128((const __m128i*)&w[0]); - const __m128i w_8 = _mm_loadu_si128((const __m128i*)&w[8]); - - // Calculate a and b (two 4x4 at once). - const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2); - const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3); - const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3); - const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2); - const __m128i b0 = _mm_add_epi16(a0, a1); - const __m128i b1 = _mm_add_epi16(a3, a2); - const __m128i b2 = _mm_sub_epi16(a3, a2); - const __m128i b3 = _mm_sub_epi16(a0, a1); - - // Separate the transforms of inA and inB. - __m128i A_b0 = _mm_unpacklo_epi64(b0, b1); - __m128i A_b2 = _mm_unpacklo_epi64(b2, b3); - __m128i B_b0 = _mm_unpackhi_epi64(b0, b1); - __m128i B_b2 = _mm_unpackhi_epi64(b2, b3); - - { - const __m128i d0 = _mm_sub_epi16(zero, A_b0); - const __m128i d1 = _mm_sub_epi16(zero, A_b2); - const __m128i d2 = _mm_sub_epi16(zero, B_b0); - const __m128i d3 = _mm_sub_epi16(zero, B_b2); - A_b0 = _mm_max_epi16(A_b0, d0); // abs(v), 16b - A_b2 = _mm_max_epi16(A_b2, d1); - B_b0 = _mm_max_epi16(B_b0, d2); - B_b2 = _mm_max_epi16(B_b2, d3); - } - - // weighted sums - A_b0 = _mm_madd_epi16(A_b0, w_0); - A_b2 = _mm_madd_epi16(A_b2, w_8); - B_b0 = _mm_madd_epi16(B_b0, w_0); - B_b2 = _mm_madd_epi16(B_b2, w_8); - A_b0 = _mm_add_epi32(A_b0, A_b2); - B_b0 = _mm_add_epi32(B_b0, B_b2); - - // difference of weighted sums - A_b0 = _mm_sub_epi32(A_b0, B_b0); - _mm_storeu_si128((__m128i*)&sum[0], A_b0); - } - return sum[0] + sum[1] + sum[2] + sum[3]; -} - -static int Disto4x4(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - const int diff_sum = TTransform(a, b, w); - return abs(diff_sum) >> 5; -} - -static int Disto16x16(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - int D = 0; - int x, y; - for (y = 0; y < 16 * BPS; y += 4 * BPS) { - for (x = 0; x < 16; x += 4) { - D += Disto4x4(a + x + y, b + x + y, w); - } - } - return D; -} - -//------------------------------------------------------------------------------ -// Quantization -// - -static WEBP_INLINE int DoQuantizeBlock(int16_t in[16], int16_t out[16], - const uint16_t* const sharpen, - const VP8Matrix* const mtx) { - const __m128i max_coeff_2047 = _mm_set1_epi16(MAX_LEVEL); - const __m128i zero = _mm_setzero_si128(); - __m128i coeff0, coeff8; - __m128i out0, out8; - __m128i packed_out; - - // Load all inputs. - __m128i in0 = _mm_loadu_si128((__m128i*)&in[0]); - __m128i in8 = _mm_loadu_si128((__m128i*)&in[8]); - const __m128i iq0 = _mm_loadu_si128((const __m128i*)&mtx->iq_[0]); - const __m128i iq8 = _mm_loadu_si128((const __m128i*)&mtx->iq_[8]); - const __m128i q0 = _mm_loadu_si128((const __m128i*)&mtx->q_[0]); - const __m128i q8 = _mm_loadu_si128((const __m128i*)&mtx->q_[8]); - - // extract sign(in) (0x0000 if positive, 0xffff if negative) - const __m128i sign0 = _mm_cmpgt_epi16(zero, in0); - const __m128i sign8 = _mm_cmpgt_epi16(zero, in8); - - // coeff = abs(in) = (in ^ sign) - sign - coeff0 = _mm_xor_si128(in0, sign0); - coeff8 = _mm_xor_si128(in8, sign8); - coeff0 = _mm_sub_epi16(coeff0, sign0); - coeff8 = _mm_sub_epi16(coeff8, sign8); - - // coeff = abs(in) + sharpen - if (sharpen != NULL) { - const __m128i sharpen0 = _mm_loadu_si128((const __m128i*)&sharpen[0]); - const __m128i sharpen8 = _mm_loadu_si128((const __m128i*)&sharpen[8]); - coeff0 = _mm_add_epi16(coeff0, sharpen0); - coeff8 = _mm_add_epi16(coeff8, sharpen8); - } - - // out = (coeff * iQ + B) >> QFIX - { - // doing calculations with 32b precision (QFIX=17) - // out = (coeff * iQ) - const __m128i coeff_iQ0H = _mm_mulhi_epu16(coeff0, iq0); - const __m128i coeff_iQ0L = _mm_mullo_epi16(coeff0, iq0); - const __m128i coeff_iQ8H = _mm_mulhi_epu16(coeff8, iq8); - const __m128i coeff_iQ8L = _mm_mullo_epi16(coeff8, iq8); - __m128i out_00 = _mm_unpacklo_epi16(coeff_iQ0L, coeff_iQ0H); - __m128i out_04 = _mm_unpackhi_epi16(coeff_iQ0L, coeff_iQ0H); - __m128i out_08 = _mm_unpacklo_epi16(coeff_iQ8L, coeff_iQ8H); - __m128i out_12 = _mm_unpackhi_epi16(coeff_iQ8L, coeff_iQ8H); - // out = (coeff * iQ + B) - const __m128i bias_00 = _mm_loadu_si128((const __m128i*)&mtx->bias_[0]); - const __m128i bias_04 = _mm_loadu_si128((const __m128i*)&mtx->bias_[4]); - const __m128i bias_08 = _mm_loadu_si128((const __m128i*)&mtx->bias_[8]); - const __m128i bias_12 = _mm_loadu_si128((const __m128i*)&mtx->bias_[12]); - out_00 = _mm_add_epi32(out_00, bias_00); - out_04 = _mm_add_epi32(out_04, bias_04); - out_08 = _mm_add_epi32(out_08, bias_08); - out_12 = _mm_add_epi32(out_12, bias_12); - // out = QUANTDIV(coeff, iQ, B, QFIX) - out_00 = _mm_srai_epi32(out_00, QFIX); - out_04 = _mm_srai_epi32(out_04, QFIX); - out_08 = _mm_srai_epi32(out_08, QFIX); - out_12 = _mm_srai_epi32(out_12, QFIX); - - // pack result as 16b - out0 = _mm_packs_epi32(out_00, out_04); - out8 = _mm_packs_epi32(out_08, out_12); - - // if (coeff > 2047) coeff = 2047 - out0 = _mm_min_epi16(out0, max_coeff_2047); - out8 = _mm_min_epi16(out8, max_coeff_2047); - } - - // get sign back (if (sign[j]) out_n = -out_n) - out0 = _mm_xor_si128(out0, sign0); - out8 = _mm_xor_si128(out8, sign8); - out0 = _mm_sub_epi16(out0, sign0); - out8 = _mm_sub_epi16(out8, sign8); - - // in = out * Q - in0 = _mm_mullo_epi16(out0, q0); - in8 = _mm_mullo_epi16(out8, q8); - - _mm_storeu_si128((__m128i*)&in[0], in0); - _mm_storeu_si128((__m128i*)&in[8], in8); - - // zigzag the output before storing it. - // - // The zigzag pattern can almost be reproduced with a small sequence of - // shuffles. After it, we only need to swap the 7th (ending up in third - // position instead of twelfth) and 8th values. - { - __m128i outZ0, outZ8; - outZ0 = _mm_shufflehi_epi16(out0, _MM_SHUFFLE(2, 1, 3, 0)); - outZ0 = _mm_shuffle_epi32 (outZ0, _MM_SHUFFLE(3, 1, 2, 0)); - outZ0 = _mm_shufflehi_epi16(outZ0, _MM_SHUFFLE(3, 1, 0, 2)); - outZ8 = _mm_shufflelo_epi16(out8, _MM_SHUFFLE(3, 0, 2, 1)); - outZ8 = _mm_shuffle_epi32 (outZ8, _MM_SHUFFLE(3, 1, 2, 0)); - outZ8 = _mm_shufflelo_epi16(outZ8, _MM_SHUFFLE(1, 3, 2, 0)); - _mm_storeu_si128((__m128i*)&out[0], outZ0); - _mm_storeu_si128((__m128i*)&out[8], outZ8); - packed_out = _mm_packs_epi16(outZ0, outZ8); - } - { - const int16_t outZ_12 = out[12]; - const int16_t outZ_3 = out[3]; - out[3] = outZ_12; - out[12] = outZ_3; - } - - // detect if all 'out' values are zeroes or not - return (_mm_movemask_epi8(_mm_cmpeq_epi8(packed_out, zero)) != 0xffff); -} - -static int QuantizeBlock(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - return DoQuantizeBlock(in, out, &mtx->sharpen_[0], mtx); -} - -static int QuantizeBlockWHT(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - return DoQuantizeBlock(in, out, NULL, mtx); -} - -static int Quantize2Blocks(int16_t in[32], int16_t out[32], - const VP8Matrix* const mtx) { - int nz; - const uint16_t* const sharpen = &mtx->sharpen_[0]; - nz = DoQuantizeBlock(in + 0 * 16, out + 0 * 16, sharpen, mtx) << 0; - nz |= DoQuantizeBlock(in + 1 * 16, out + 1 * 16, sharpen, mtx) << 1; - return nz; -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8EncDspInitSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitSSE2(void) { - VP8CollectHistogram = CollectHistogram; - VP8EncPredLuma16 = Intra16Preds; - VP8EncPredChroma8 = IntraChromaPreds; - VP8EncPredLuma4 = Intra4Preds; - VP8EncQuantizeBlock = QuantizeBlock; - VP8EncQuantize2Blocks = Quantize2Blocks; - VP8EncQuantizeBlockWHT = QuantizeBlockWHT; - VP8ITransform = ITransform; - VP8FTransform = FTransform; - VP8FTransform2 = FTransform2; - VP8FTransformWHT = FTransformWHT; - VP8SSE16x16 = SSE16x16; - VP8SSE16x8 = SSE16x8; - VP8SSE8x8 = SSE8x8; - VP8SSE4x4 = SSE4x4; - VP8TDisto4x4 = Disto4x4; - VP8TDisto16x16 = Disto16x16; -} - -#else // !WEBP_USE_SSE2 - -WEBP_DSP_INIT_STUB(VP8EncDspInitSSE2) - -#endif // WEBP_USE_SSE2 diff --git a/Example/Pods/libwebp/src/dsp/enc_sse41.c b/Example/Pods/libwebp/src/dsp/enc_sse41.c deleted file mode 100644 index 65c01aef..00000000 --- a/Example/Pods/libwebp/src/dsp/enc_sse41.c +++ /dev/null @@ -1,373 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// SSE4 version of some encoding functions. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE41) -#include -#include // for abs() - -#include "../enc/vp8enci.h" - -//------------------------------------------------------------------------------ -// Compute susceptibility based on DCT-coeff histograms. - -static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, - int start_block, int end_block, - VP8Histogram* const histo) { - const __m128i max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH); - int j; - int distribution[MAX_COEFF_THRESH + 1] = { 0 }; - for (j = start_block; j < end_block; ++j) { - int16_t out[16]; - int k; - - VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); - - // Convert coefficients to bin (within out[]). - { - // Load. - const __m128i out0 = _mm_loadu_si128((__m128i*)&out[0]); - const __m128i out1 = _mm_loadu_si128((__m128i*)&out[8]); - // v = abs(out) >> 3 - const __m128i abs0 = _mm_abs_epi16(out0); - const __m128i abs1 = _mm_abs_epi16(out1); - const __m128i v0 = _mm_srai_epi16(abs0, 3); - const __m128i v1 = _mm_srai_epi16(abs1, 3); - // bin = min(v, MAX_COEFF_THRESH) - const __m128i bin0 = _mm_min_epi16(v0, max_coeff_thresh); - const __m128i bin1 = _mm_min_epi16(v1, max_coeff_thresh); - // Store. - _mm_storeu_si128((__m128i*)&out[0], bin0); - _mm_storeu_si128((__m128i*)&out[8], bin1); - } - - // Convert coefficients to bin. - for (k = 0; k < 16; ++k) { - ++distribution[out[k]]; - } - } - VP8SetHistogramData(distribution, histo); -} - -//------------------------------------------------------------------------------ -// Texture distortion -// -// We try to match the spectral content (weighted) between source and -// reconstructed samples. - -// Hadamard transform -// Returns the difference between the weighted sum of the absolute value of -// transformed coefficients. -static int TTransform(const uint8_t* inA, const uint8_t* inB, - const uint16_t* const w) { - __m128i tmp_0, tmp_1, tmp_2, tmp_3; - - // Load, combine and transpose inputs. - { - const __m128i inA_0 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 0]); - const __m128i inA_1 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 1]); - const __m128i inA_2 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 2]); - const __m128i inA_3 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 3]); - const __m128i inB_0 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 0]); - const __m128i inB_1 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 1]); - const __m128i inB_2 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 2]); - const __m128i inB_3 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 3]); - - // Combine inA and inB (we'll do two transforms in parallel). - const __m128i inAB_0 = _mm_unpacklo_epi8(inA_0, inB_0); - const __m128i inAB_1 = _mm_unpacklo_epi8(inA_1, inB_1); - const __m128i inAB_2 = _mm_unpacklo_epi8(inA_2, inB_2); - const __m128i inAB_3 = _mm_unpacklo_epi8(inA_3, inB_3); - // a00 b00 a01 b01 a02 b03 a03 b03 0 0 0 0 0 0 0 0 - // a10 b10 a11 b11 a12 b12 a13 b13 0 0 0 0 0 0 0 0 - // a20 b20 a21 b21 a22 b22 a23 b23 0 0 0 0 0 0 0 0 - // a30 b30 a31 b31 a32 b32 a33 b33 0 0 0 0 0 0 0 0 - - // Transpose the two 4x4, discarding the filling zeroes. - const __m128i transpose0_0 = _mm_unpacklo_epi8(inAB_0, inAB_2); - const __m128i transpose0_1 = _mm_unpacklo_epi8(inAB_1, inAB_3); - // a00 a20 b00 b20 a01 a21 b01 b21 a02 a22 b02 b22 a03 a23 b03 b23 - // a10 a30 b10 b30 a11 a31 b11 b31 a12 a32 b12 b32 a13 a33 b13 b33 - const __m128i transpose1_0 = _mm_unpacklo_epi8(transpose0_0, transpose0_1); - const __m128i transpose1_1 = _mm_unpackhi_epi8(transpose0_0, transpose0_1); - // a00 a10 a20 a30 b00 b10 b20 b30 a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 a03 a13 a23 a33 b03 b13 b23 b33 - - // Convert to 16b. - tmp_0 = _mm_cvtepu8_epi16(transpose1_0); - tmp_1 = _mm_cvtepu8_epi16(_mm_srli_si128(transpose1_0, 8)); - tmp_2 = _mm_cvtepu8_epi16(transpose1_1); - tmp_3 = _mm_cvtepu8_epi16(_mm_srli_si128(transpose1_1, 8)); - // a00 a10 a20 a30 b00 b10 b20 b30 - // a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 - // a03 a13 a23 a33 b03 b13 b23 b33 - } - - // Horizontal pass and subsequent transpose. - { - // Calculate a and b (two 4x4 at once). - const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2); - const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3); - const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3); - const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2); - const __m128i b0 = _mm_add_epi16(a0, a1); - const __m128i b1 = _mm_add_epi16(a3, a2); - const __m128i b2 = _mm_sub_epi16(a3, a2); - const __m128i b3 = _mm_sub_epi16(a0, a1); - // a00 a01 a02 a03 b00 b01 b02 b03 - // a10 a11 a12 a13 b10 b11 b12 b13 - // a20 a21 a22 a23 b20 b21 b22 b23 - // a30 a31 a32 a33 b30 b31 b32 b33 - - // Transpose the two 4x4. - const __m128i transpose0_0 = _mm_unpacklo_epi16(b0, b1); - const __m128i transpose0_1 = _mm_unpacklo_epi16(b2, b3); - const __m128i transpose0_2 = _mm_unpackhi_epi16(b0, b1); - const __m128i transpose0_3 = _mm_unpackhi_epi16(b2, b3); - // a00 a10 a01 a11 a02 a12 a03 a13 - // a20 a30 a21 a31 a22 a32 a23 a33 - // b00 b10 b01 b11 b02 b12 b03 b13 - // b20 b30 b21 b31 b22 b32 b23 b33 - const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3); - const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1); - const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3); - // a00 a10 a20 a30 a01 a11 a21 a31 - // b00 b10 b20 b30 b01 b11 b21 b31 - // a02 a12 a22 a32 a03 a13 a23 a33 - // b02 b12 a22 b32 b03 b13 b23 b33 - tmp_0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1); - tmp_1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1); - tmp_2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3); - tmp_3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3); - // a00 a10 a20 a30 b00 b10 b20 b30 - // a01 a11 a21 a31 b01 b11 b21 b31 - // a02 a12 a22 a32 b02 b12 b22 b32 - // a03 a13 a23 a33 b03 b13 b23 b33 - } - - // Vertical pass and difference of weighted sums. - { - // Load all inputs. - const __m128i w_0 = _mm_loadu_si128((const __m128i*)&w[0]); - const __m128i w_8 = _mm_loadu_si128((const __m128i*)&w[8]); - - // Calculate a and b (two 4x4 at once). - const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2); - const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3); - const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3); - const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2); - const __m128i b0 = _mm_add_epi16(a0, a1); - const __m128i b1 = _mm_add_epi16(a3, a2); - const __m128i b2 = _mm_sub_epi16(a3, a2); - const __m128i b3 = _mm_sub_epi16(a0, a1); - - // Separate the transforms of inA and inB. - __m128i A_b0 = _mm_unpacklo_epi64(b0, b1); - __m128i A_b2 = _mm_unpacklo_epi64(b2, b3); - __m128i B_b0 = _mm_unpackhi_epi64(b0, b1); - __m128i B_b2 = _mm_unpackhi_epi64(b2, b3); - - A_b0 = _mm_abs_epi16(A_b0); - A_b2 = _mm_abs_epi16(A_b2); - B_b0 = _mm_abs_epi16(B_b0); - B_b2 = _mm_abs_epi16(B_b2); - - // weighted sums - A_b0 = _mm_madd_epi16(A_b0, w_0); - A_b2 = _mm_madd_epi16(A_b2, w_8); - B_b0 = _mm_madd_epi16(B_b0, w_0); - B_b2 = _mm_madd_epi16(B_b2, w_8); - A_b0 = _mm_add_epi32(A_b0, A_b2); - B_b0 = _mm_add_epi32(B_b0, B_b2); - - // difference of weighted sums - A_b2 = _mm_sub_epi32(A_b0, B_b0); - // cascading summation of the differences - B_b0 = _mm_hadd_epi32(A_b2, A_b2); - B_b2 = _mm_hadd_epi32(B_b0, B_b0); - return _mm_cvtsi128_si32(B_b2); - } -} - -static int Disto4x4(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - const int diff_sum = TTransform(a, b, w); - return abs(diff_sum) >> 5; -} - -static int Disto16x16(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - int D = 0; - int x, y; - for (y = 0; y < 16 * BPS; y += 4 * BPS) { - for (x = 0; x < 16; x += 4) { - D += Disto4x4(a + x + y, b + x + y, w); - } - } - return D; -} - -//------------------------------------------------------------------------------ -// Quantization -// - -// Generates a pshufb constant for shuffling 16b words. -#define PSHUFB_CST(A,B,C,D,E,F,G,H) \ - _mm_set_epi8(2 * (H) + 1, 2 * (H) + 0, 2 * (G) + 1, 2 * (G) + 0, \ - 2 * (F) + 1, 2 * (F) + 0, 2 * (E) + 1, 2 * (E) + 0, \ - 2 * (D) + 1, 2 * (D) + 0, 2 * (C) + 1, 2 * (C) + 0, \ - 2 * (B) + 1, 2 * (B) + 0, 2 * (A) + 1, 2 * (A) + 0) - -static WEBP_INLINE int DoQuantizeBlock(int16_t in[16], int16_t out[16], - const uint16_t* const sharpen, - const VP8Matrix* const mtx) { - const __m128i max_coeff_2047 = _mm_set1_epi16(MAX_LEVEL); - const __m128i zero = _mm_setzero_si128(); - __m128i out0, out8; - __m128i packed_out; - - // Load all inputs. - __m128i in0 = _mm_loadu_si128((__m128i*)&in[0]); - __m128i in8 = _mm_loadu_si128((__m128i*)&in[8]); - const __m128i iq0 = _mm_loadu_si128((const __m128i*)&mtx->iq_[0]); - const __m128i iq8 = _mm_loadu_si128((const __m128i*)&mtx->iq_[8]); - const __m128i q0 = _mm_loadu_si128((const __m128i*)&mtx->q_[0]); - const __m128i q8 = _mm_loadu_si128((const __m128i*)&mtx->q_[8]); - - // coeff = abs(in) - __m128i coeff0 = _mm_abs_epi16(in0); - __m128i coeff8 = _mm_abs_epi16(in8); - - // coeff = abs(in) + sharpen - if (sharpen != NULL) { - const __m128i sharpen0 = _mm_loadu_si128((const __m128i*)&sharpen[0]); - const __m128i sharpen8 = _mm_loadu_si128((const __m128i*)&sharpen[8]); - coeff0 = _mm_add_epi16(coeff0, sharpen0); - coeff8 = _mm_add_epi16(coeff8, sharpen8); - } - - // out = (coeff * iQ + B) >> QFIX - { - // doing calculations with 32b precision (QFIX=17) - // out = (coeff * iQ) - const __m128i coeff_iQ0H = _mm_mulhi_epu16(coeff0, iq0); - const __m128i coeff_iQ0L = _mm_mullo_epi16(coeff0, iq0); - const __m128i coeff_iQ8H = _mm_mulhi_epu16(coeff8, iq8); - const __m128i coeff_iQ8L = _mm_mullo_epi16(coeff8, iq8); - __m128i out_00 = _mm_unpacklo_epi16(coeff_iQ0L, coeff_iQ0H); - __m128i out_04 = _mm_unpackhi_epi16(coeff_iQ0L, coeff_iQ0H); - __m128i out_08 = _mm_unpacklo_epi16(coeff_iQ8L, coeff_iQ8H); - __m128i out_12 = _mm_unpackhi_epi16(coeff_iQ8L, coeff_iQ8H); - // out = (coeff * iQ + B) - const __m128i bias_00 = _mm_loadu_si128((const __m128i*)&mtx->bias_[0]); - const __m128i bias_04 = _mm_loadu_si128((const __m128i*)&mtx->bias_[4]); - const __m128i bias_08 = _mm_loadu_si128((const __m128i*)&mtx->bias_[8]); - const __m128i bias_12 = _mm_loadu_si128((const __m128i*)&mtx->bias_[12]); - out_00 = _mm_add_epi32(out_00, bias_00); - out_04 = _mm_add_epi32(out_04, bias_04); - out_08 = _mm_add_epi32(out_08, bias_08); - out_12 = _mm_add_epi32(out_12, bias_12); - // out = QUANTDIV(coeff, iQ, B, QFIX) - out_00 = _mm_srai_epi32(out_00, QFIX); - out_04 = _mm_srai_epi32(out_04, QFIX); - out_08 = _mm_srai_epi32(out_08, QFIX); - out_12 = _mm_srai_epi32(out_12, QFIX); - - // pack result as 16b - out0 = _mm_packs_epi32(out_00, out_04); - out8 = _mm_packs_epi32(out_08, out_12); - - // if (coeff > 2047) coeff = 2047 - out0 = _mm_min_epi16(out0, max_coeff_2047); - out8 = _mm_min_epi16(out8, max_coeff_2047); - } - - // put sign back - out0 = _mm_sign_epi16(out0, in0); - out8 = _mm_sign_epi16(out8, in8); - - // in = out * Q - in0 = _mm_mullo_epi16(out0, q0); - in8 = _mm_mullo_epi16(out8, q8); - - _mm_storeu_si128((__m128i*)&in[0], in0); - _mm_storeu_si128((__m128i*)&in[8], in8); - - // zigzag the output before storing it. The re-ordering is: - // 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15 - // -> 0 1 4[8]5 2 3 6 | 9 12 13 10 [7]11 14 15 - // There's only two misplaced entries ([8] and [7]) that are crossing the - // reg's boundaries. - // We use pshufb instead of pshuflo/pshufhi. - { - const __m128i kCst_lo = PSHUFB_CST(0, 1, 4, -1, 5, 2, 3, 6); - const __m128i kCst_7 = PSHUFB_CST(-1, -1, -1, -1, 7, -1, -1, -1); - const __m128i tmp_lo = _mm_shuffle_epi8(out0, kCst_lo); - const __m128i tmp_7 = _mm_shuffle_epi8(out0, kCst_7); // extract #7 - const __m128i kCst_hi = PSHUFB_CST(1, 4, 5, 2, -1, 3, 6, 7); - const __m128i kCst_8 = PSHUFB_CST(-1, -1, -1, 0, -1, -1, -1, -1); - const __m128i tmp_hi = _mm_shuffle_epi8(out8, kCst_hi); - const __m128i tmp_8 = _mm_shuffle_epi8(out8, kCst_8); // extract #8 - const __m128i out_z0 = _mm_or_si128(tmp_lo, tmp_8); - const __m128i out_z8 = _mm_or_si128(tmp_hi, tmp_7); - _mm_storeu_si128((__m128i*)&out[0], out_z0); - _mm_storeu_si128((__m128i*)&out[8], out_z8); - packed_out = _mm_packs_epi16(out_z0, out_z8); - } - - // detect if all 'out' values are zeroes or not - return (_mm_movemask_epi8(_mm_cmpeq_epi8(packed_out, zero)) != 0xffff); -} - -#undef PSHUFB_CST - -static int QuantizeBlock(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - return DoQuantizeBlock(in, out, &mtx->sharpen_[0], mtx); -} - -static int QuantizeBlockWHT(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - return DoQuantizeBlock(in, out, NULL, mtx); -} - -static int Quantize2Blocks(int16_t in[32], int16_t out[32], - const VP8Matrix* const mtx) { - int nz; - const uint16_t* const sharpen = &mtx->sharpen_[0]; - nz = DoQuantizeBlock(in + 0 * 16, out + 0 * 16, sharpen, mtx) << 0; - nz |= DoQuantizeBlock(in + 1 * 16, out + 1 * 16, sharpen, mtx) << 1; - return nz; -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8EncDspInitSSE41(void); -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitSSE41(void) { - VP8CollectHistogram = CollectHistogram; - VP8EncQuantizeBlock = QuantizeBlock; - VP8EncQuantize2Blocks = Quantize2Blocks; - VP8EncQuantizeBlockWHT = QuantizeBlockWHT; - VP8TDisto4x4 = Disto4x4; - VP8TDisto16x16 = Disto16x16; -} - -#else // !WEBP_USE_SSE41 - -WEBP_DSP_INIT_STUB(VP8EncDspInitSSE41) - -#endif // WEBP_USE_SSE41 diff --git a/Example/Pods/libwebp/src/dsp/filters.c b/Example/Pods/libwebp/src/dsp/filters.c deleted file mode 100644 index 5c30f2e4..00000000 --- a/Example/Pods/libwebp/src/dsp/filters.c +++ /dev/null @@ -1,240 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Spatial prediction using various filters -// -// Author: Urvang (urvang@google.com) - -#include "./dsp.h" -#include -#include -#include - -//------------------------------------------------------------------------------ -// Helpful macro. - -# define SANITY_CHECK(in, out) \ - assert(in != NULL); \ - assert(out != NULL); \ - assert(width > 0); \ - assert(height > 0); \ - assert(stride >= width); \ - assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ - (void)height; // Silence unused warning. - -static WEBP_INLINE void PredictLine(const uint8_t* src, const uint8_t* pred, - uint8_t* dst, int length, int inverse) { - int i; - if (inverse) { - for (i = 0; i < length; ++i) dst[i] = src[i] + pred[i]; - } else { - for (i = 0; i < length; ++i) dst[i] = src[i] - pred[i]; - } -} - -//------------------------------------------------------------------------------ -// Horizontal filter. - -static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { - const uint8_t* preds; - const size_t start_offset = row * stride; - const int last_row = row + num_rows; - SANITY_CHECK(in, out); - in += start_offset; - out += start_offset; - preds = inverse ? out : in; - - if (row == 0) { - // Leftmost pixel is the same as input for topmost scanline. - out[0] = in[0]; - PredictLine(in + 1, preds, out + 1, width - 1, inverse); - row = 1; - preds += stride; - in += stride; - out += stride; - } - - // Filter line-by-line. - while (row < last_row) { - // Leftmost pixel is predicted from above. - PredictLine(in, preds - stride, out, 1, inverse); - PredictLine(in + 1, preds, out + 1, width - 1, inverse); - ++row; - preds += stride; - in += stride; - out += stride; - } -} - -//------------------------------------------------------------------------------ -// Vertical filter. - -static WEBP_INLINE void DoVerticalFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { - const uint8_t* preds; - const size_t start_offset = row * stride; - const int last_row = row + num_rows; - SANITY_CHECK(in, out); - in += start_offset; - out += start_offset; - preds = inverse ? out : in; - - if (row == 0) { - // Very first top-left pixel is copied. - out[0] = in[0]; - // Rest of top scan-line is left-predicted. - PredictLine(in + 1, preds, out + 1, width - 1, inverse); - row = 1; - in += stride; - out += stride; - } else { - // We are starting from in-between. Make sure 'preds' points to prev row. - preds -= stride; - } - - // Filter line-by-line. - while (row < last_row) { - PredictLine(in, preds, out, width, inverse); - ++row; - preds += stride; - in += stride; - out += stride; - } -} - -//------------------------------------------------------------------------------ -// Gradient filter. - -static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) { - const int g = a + b - c; - return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit -} - -static WEBP_INLINE void DoGradientFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { - const uint8_t* preds; - const size_t start_offset = row * stride; - const int last_row = row + num_rows; - SANITY_CHECK(in, out); - in += start_offset; - out += start_offset; - preds = inverse ? out : in; - - // left prediction for top scan-line - if (row == 0) { - out[0] = in[0]; - PredictLine(in + 1, preds, out + 1, width - 1, inverse); - row = 1; - preds += stride; - in += stride; - out += stride; - } - - // Filter line-by-line. - while (row < last_row) { - int w; - // leftmost pixel: predict from above. - PredictLine(in, preds - stride, out, 1, inverse); - for (w = 1; w < width; ++w) { - const int pred = GradientPredictor(preds[w - 1], - preds[w - stride], - preds[w - stride - 1]); - out[w] = in[w] + (inverse ? pred : -pred); - } - ++row; - preds += stride; - in += stride; - out += stride; - } -} - -#undef SANITY_CHECK - -//------------------------------------------------------------------------------ - -static void HorizontalFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoHorizontalFilter(data, width, height, stride, 0, height, 0, filtered_data); -} - -static void VerticalFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoVerticalFilter(data, width, height, stride, 0, height, 0, filtered_data); -} - - -static void GradientFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoGradientFilter(data, width, height, stride, 0, height, 0, filtered_data); -} - - -//------------------------------------------------------------------------------ - -static void VerticalUnfilter(int width, int height, int stride, int row, - int num_rows, uint8_t* data) { - DoVerticalFilter(data, width, height, stride, row, num_rows, 1, data); -} - -static void HorizontalUnfilter(int width, int height, int stride, int row, - int num_rows, uint8_t* data) { - DoHorizontalFilter(data, width, height, stride, row, num_rows, 1, data); -} - -static void GradientUnfilter(int width, int height, int stride, int row, - int num_rows, uint8_t* data) { - DoGradientFilter(data, width, height, stride, row, num_rows, 1, data); -} - -//------------------------------------------------------------------------------ -// Init function - -WebPFilterFunc WebPFilters[WEBP_FILTER_LAST]; -WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST]; - -extern void VP8FiltersInitMIPSdspR2(void); -extern void VP8FiltersInitSSE2(void); - -static volatile VP8CPUInfo filters_last_cpuinfo_used = - (VP8CPUInfo)&filters_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInit(void) { - if (filters_last_cpuinfo_used == VP8GetCPUInfo) return; - - WebPUnfilters[WEBP_FILTER_NONE] = NULL; - WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter; - WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter; - WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter; - - WebPFilters[WEBP_FILTER_NONE] = NULL; - WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter; - WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter; - WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter; - - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - VP8FiltersInitSSE2(); - } -#endif -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - VP8FiltersInitMIPSdspR2(); - } -#endif - } - filters_last_cpuinfo_used = VP8GetCPUInfo; -} diff --git a/Example/Pods/libwebp/src/dsp/filters_mips_dsp_r2.c b/Example/Pods/libwebp/src/dsp/filters_mips_dsp_r2.c deleted file mode 100644 index 8134af51..00000000 --- a/Example/Pods/libwebp/src/dsp/filters_mips_dsp_r2.c +++ /dev/null @@ -1,405 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Spatial prediction using various filters -// -// Author(s): Branimir Vasic (branimir.vasic@imgtec.com) -// Djordje Pesut (djordje.pesut@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS_DSP_R2) - -#include "../dsp/dsp.h" -#include -#include -#include - -//------------------------------------------------------------------------------ -// Helpful macro. - -# define SANITY_CHECK(in, out) \ - assert(in != NULL); \ - assert(out != NULL); \ - assert(width > 0); \ - assert(height > 0); \ - assert(stride >= width); \ - assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ - (void)height; // Silence unused warning. - -// if INVERSE -// preds == &dst[-1] == &src[-1] -// else -// preds == &src[-1] != &dst[-1] -#define DO_PREDICT_LINE(SRC, DST, LENGTH, INVERSE) do { \ - const uint8_t* psrc = (uint8_t*)(SRC); \ - uint8_t* pdst = (uint8_t*)(DST); \ - const int ilength = (int)(LENGTH); \ - int temp0, temp1, temp2, temp3, temp4, temp5, temp6; \ - __asm__ volatile ( \ - ".set push \n\t" \ - ".set noreorder \n\t" \ - "srl %[temp0], %[length], 0x2 \n\t" \ - "beqz %[temp0], 4f \n\t" \ - " andi %[temp6], %[length], 0x3 \n\t" \ - ".if " #INVERSE " \n\t" \ - "lbu %[temp1], -1(%[src]) \n\t" \ - "1: \n\t" \ - "lbu %[temp2], 0(%[src]) \n\t" \ - "lbu %[temp3], 1(%[src]) \n\t" \ - "lbu %[temp4], 2(%[src]) \n\t" \ - "lbu %[temp5], 3(%[src]) \n\t" \ - "addiu %[src], %[src], 4 \n\t" \ - "addiu %[temp0], %[temp0], -1 \n\t" \ - "addu %[temp2], %[temp2], %[temp1] \n\t" \ - "addu %[temp3], %[temp3], %[temp2] \n\t" \ - "addu %[temp4], %[temp4], %[temp3] \n\t" \ - "addu %[temp1], %[temp5], %[temp4] \n\t" \ - "sb %[temp2], -4(%[src]) \n\t" \ - "sb %[temp3], -3(%[src]) \n\t" \ - "sb %[temp4], -2(%[src]) \n\t" \ - "bnez %[temp0], 1b \n\t" \ - " sb %[temp1], -1(%[src]) \n\t" \ - ".else \n\t" \ - "1: \n\t" \ - "ulw %[temp1], -1(%[src]) \n\t" \ - "ulw %[temp2], 0(%[src]) \n\t" \ - "addiu %[src], %[src], 4 \n\t" \ - "addiu %[temp0], %[temp0], -1 \n\t" \ - "subu.qb %[temp3], %[temp2], %[temp1] \n\t" \ - "usw %[temp3], 0(%[dst]) \n\t" \ - "bnez %[temp0], 1b \n\t" \ - " addiu %[dst], %[dst], 4 \n\t" \ - ".endif \n\t" \ - "4: \n\t" \ - "beqz %[temp6], 3f \n\t" \ - " nop \n\t" \ - "2: \n\t" \ - "lbu %[temp1], -1(%[src]) \n\t" \ - "lbu %[temp2], 0(%[src]) \n\t" \ - "addiu %[src], %[src], 1 \n\t" \ - ".if " #INVERSE " \n\t" \ - "addu %[temp3], %[temp1], %[temp2] \n\t" \ - "sb %[temp3], -1(%[src]) \n\t" \ - ".else \n\t" \ - "subu %[temp3], %[temp1], %[temp2] \n\t" \ - "sb %[temp3], 0(%[dst]) \n\t" \ - ".endif \n\t" \ - "addiu %[temp6], %[temp6], -1 \n\t" \ - "bnez %[temp6], 2b \n\t" \ - " addiu %[dst], %[dst], 1 \n\t" \ - "3: \n\t" \ - ".set pop \n\t" \ - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \ - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \ - [temp6]"=&r"(temp6), [dst]"+&r"(pdst), [src]"+&r"(psrc) \ - : [length]"r"(ilength) \ - : "memory" \ - ); \ - } while (0) - -static WEBP_INLINE void PredictLine(const uint8_t* src, uint8_t* dst, - int length, int inverse) { - if (inverse) { - DO_PREDICT_LINE(src, dst, length, 1); - } else { - DO_PREDICT_LINE(src, dst, length, 0); - } -} - -#define DO_PREDICT_LINE_VERTICAL(SRC, PRED, DST, LENGTH, INVERSE) do { \ - const uint8_t* psrc = (uint8_t*)(SRC); \ - const uint8_t* ppred = (uint8_t*)(PRED); \ - uint8_t* pdst = (uint8_t*)(DST); \ - const int ilength = (int)(LENGTH); \ - int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; \ - __asm__ volatile ( \ - ".set push \n\t" \ - ".set noreorder \n\t" \ - "srl %[temp0], %[length], 0x3 \n\t" \ - "beqz %[temp0], 4f \n\t" \ - " andi %[temp7], %[length], 0x7 \n\t" \ - "1: \n\t" \ - "ulw %[temp1], 0(%[src]) \n\t" \ - "ulw %[temp2], 0(%[pred]) \n\t" \ - "ulw %[temp3], 4(%[src]) \n\t" \ - "ulw %[temp4], 4(%[pred]) \n\t" \ - "addiu %[src], %[src], 8 \n\t" \ - ".if " #INVERSE " \n\t" \ - "addu.qb %[temp5], %[temp1], %[temp2] \n\t" \ - "addu.qb %[temp6], %[temp3], %[temp4] \n\t" \ - ".else \n\t" \ - "subu.qb %[temp5], %[temp1], %[temp2] \n\t" \ - "subu.qb %[temp6], %[temp3], %[temp4] \n\t" \ - ".endif \n\t" \ - "addiu %[pred], %[pred], 8 \n\t" \ - "usw %[temp5], 0(%[dst]) \n\t" \ - "usw %[temp6], 4(%[dst]) \n\t" \ - "addiu %[temp0], %[temp0], -1 \n\t" \ - "bnez %[temp0], 1b \n\t" \ - " addiu %[dst], %[dst], 8 \n\t" \ - "4: \n\t" \ - "beqz %[temp7], 3f \n\t" \ - " nop \n\t" \ - "2: \n\t" \ - "lbu %[temp1], 0(%[src]) \n\t" \ - "lbu %[temp2], 0(%[pred]) \n\t" \ - "addiu %[src], %[src], 1 \n\t" \ - "addiu %[pred], %[pred], 1 \n\t" \ - ".if " #INVERSE " \n\t" \ - "addu %[temp3], %[temp1], %[temp2] \n\t" \ - ".else \n\t" \ - "subu %[temp3], %[temp1], %[temp2] \n\t" \ - ".endif \n\t" \ - "sb %[temp3], 0(%[dst]) \n\t" \ - "addiu %[temp7], %[temp7], -1 \n\t" \ - "bnez %[temp7], 2b \n\t" \ - " addiu %[dst], %[dst], 1 \n\t" \ - "3: \n\t" \ - ".set pop \n\t" \ - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \ - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \ - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [pred]"+&r"(ppred), \ - [dst]"+&r"(pdst), [src]"+&r"(psrc) \ - : [length]"r"(ilength) \ - : "memory" \ - ); \ - } while (0) - -#define PREDICT_LINE_ONE_PASS(SRC, PRED, DST, INVERSE) do { \ - int temp1, temp2, temp3; \ - __asm__ volatile ( \ - "lbu %[temp1], 0(%[src]) \n\t" \ - "lbu %[temp2], 0(%[pred]) \n\t" \ - ".if " #INVERSE " \n\t" \ - "addu %[temp3], %[temp1], %[temp2] \n\t" \ - ".else \n\t" \ - "subu %[temp3], %[temp1], %[temp2] \n\t" \ - ".endif \n\t" \ - "sb %[temp3], 0(%[dst]) \n\t" \ - : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3) \ - : [pred]"r"((PRED)), [dst]"r"((DST)), [src]"r"((SRC)) \ - : "memory" \ - ); \ - } while (0) - -//------------------------------------------------------------------------------ -// Horizontal filter. - -#define FILTER_LINE_BY_LINE(INVERSE) do { \ - while (row < last_row) { \ - PREDICT_LINE_ONE_PASS(in, preds - stride, out, INVERSE); \ - DO_PREDICT_LINE(in + 1, out + 1, width - 1, INVERSE); \ - ++row; \ - preds += stride; \ - in += stride; \ - out += stride; \ - } \ - } while (0) - -static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { - const uint8_t* preds; - const size_t start_offset = row * stride; - const int last_row = row + num_rows; - SANITY_CHECK(in, out); - in += start_offset; - out += start_offset; - preds = inverse ? out : in; - - if (row == 0) { - // Leftmost pixel is the same as input for topmost scanline. - out[0] = in[0]; - PredictLine(in + 1, out + 1, width - 1, inverse); - row = 1; - preds += stride; - in += stride; - out += stride; - } - - // Filter line-by-line. - if (inverse) { - FILTER_LINE_BY_LINE(1); - } else { - FILTER_LINE_BY_LINE(0); - } -} - -#undef FILTER_LINE_BY_LINE - -static void HorizontalFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoHorizontalFilter(data, width, height, stride, 0, height, 0, filtered_data); -} - -static void HorizontalUnfilter(int width, int height, int stride, int row, - int num_rows, uint8_t* data) { - DoHorizontalFilter(data, width, height, stride, row, num_rows, 1, data); -} - -//------------------------------------------------------------------------------ -// Vertical filter. - -#define FILTER_LINE_BY_LINE(INVERSE) do { \ - while (row < last_row) { \ - DO_PREDICT_LINE_VERTICAL(in, preds, out, width, INVERSE); \ - ++row; \ - preds += stride; \ - in += stride; \ - out += stride; \ - } \ - } while (0) - -static WEBP_INLINE void DoVerticalFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { - const uint8_t* preds; - const size_t start_offset = row * stride; - const int last_row = row + num_rows; - SANITY_CHECK(in, out); - in += start_offset; - out += start_offset; - preds = inverse ? out : in; - - if (row == 0) { - // Very first top-left pixel is copied. - out[0] = in[0]; - // Rest of top scan-line is left-predicted. - PredictLine(in + 1, out + 1, width - 1, inverse); - row = 1; - in += stride; - out += stride; - } else { - // We are starting from in-between. Make sure 'preds' points to prev row. - preds -= stride; - } - - // Filter line-by-line. - if (inverse) { - FILTER_LINE_BY_LINE(1); - } else { - FILTER_LINE_BY_LINE(0); - } -} - -#undef FILTER_LINE_BY_LINE -#undef DO_PREDICT_LINE_VERTICAL - -static void VerticalFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoVerticalFilter(data, width, height, stride, 0, height, 0, filtered_data); -} - -static void VerticalUnfilter(int width, int height, int stride, int row, - int num_rows, uint8_t* data) { - DoVerticalFilter(data, width, height, stride, row, num_rows, 1, data); -} - -//------------------------------------------------------------------------------ -// Gradient filter. - -static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) { - int temp0; - __asm__ volatile ( - "addu %[temp0], %[a], %[b] \n\t" - "subu %[temp0], %[temp0], %[c] \n\t" - "shll_s.w %[temp0], %[temp0], 23 \n\t" - "precrqu_s.qb.ph %[temp0], %[temp0], $zero \n\t" - "srl %[temp0], %[temp0], 24 \n\t" - : [temp0]"=&r"(temp0) - : [a]"r"(a),[b]"r"(b),[c]"r"(c) - ); - return temp0; -} - -#define FILTER_LINE_BY_LINE(INVERSE, PREDS, OPERATION) do { \ - while (row < last_row) { \ - int w; \ - PREDICT_LINE_ONE_PASS(in, PREDS - stride, out, INVERSE); \ - for (w = 1; w < width; ++w) { \ - const int pred = GradientPredictor(PREDS[w - 1], \ - PREDS[w - stride], \ - PREDS[w - stride - 1]); \ - out[w] = in[w] OPERATION pred; \ - } \ - ++row; \ - in += stride; \ - out += stride; \ - } \ - } while (0) - -static WEBP_INLINE void DoGradientFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { - const uint8_t* preds; - const size_t start_offset = row * stride; - const int last_row = row + num_rows; - SANITY_CHECK(in, out); - in += start_offset; - out += start_offset; - preds = inverse ? out : in; - - // left prediction for top scan-line - if (row == 0) { - out[0] = in[0]; - PredictLine(in + 1, out + 1, width - 1, inverse); - row = 1; - preds += stride; - in += stride; - out += stride; - } - - // Filter line-by-line. - if (inverse) { - FILTER_LINE_BY_LINE(1, out, +); - } else { - FILTER_LINE_BY_LINE(0, in, -); - } -} - -#undef FILTER_LINE_BY_LINE - -static void GradientFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoGradientFilter(data, width, height, stride, 0, height, 0, filtered_data); -} - -static void GradientUnfilter(int width, int height, int stride, int row, - int num_rows, uint8_t* data) { - DoGradientFilter(data, width, height, stride, row, num_rows, 1, data); -} - -#undef PREDICT_LINE_ONE_PASS -#undef DO_PREDICT_LINE -#undef SANITY_CHECK - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8FiltersInitMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitMIPSdspR2(void) { - WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter; - WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter; - WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter; - - WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter; - WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter; - WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter; -} - -#else // !WEBP_USE_MIPS_DSP_R2 - -WEBP_DSP_INIT_STUB(VP8FiltersInitMIPSdspR2) - -#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/Example/Pods/libwebp/src/dsp/filters_sse2.c b/Example/Pods/libwebp/src/dsp/filters_sse2.c deleted file mode 100644 index bf93342e..00000000 --- a/Example/Pods/libwebp/src/dsp/filters_sse2.c +++ /dev/null @@ -1,352 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// SSE2 variant of alpha filters -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE2) - -#include -#include -#include -#include - -//------------------------------------------------------------------------------ -// Helpful macro. - -# define SANITY_CHECK(in, out) \ - assert(in != NULL); \ - assert(out != NULL); \ - assert(width > 0); \ - assert(height > 0); \ - assert(stride >= width); \ - assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ - (void)height; // Silence unused warning. - -static void PredictLineTop(const uint8_t* src, const uint8_t* pred, - uint8_t* dst, int length, int inverse) { - int i; - const int max_pos = length & ~31; - assert(length >= 0); - if (inverse) { - for (i = 0; i < max_pos; i += 32) { - const __m128i A0 = _mm_loadu_si128((const __m128i*)&src[i + 0]); - const __m128i A1 = _mm_loadu_si128((const __m128i*)&src[i + 16]); - const __m128i B0 = _mm_loadu_si128((const __m128i*)&pred[i + 0]); - const __m128i B1 = _mm_loadu_si128((const __m128i*)&pred[i + 16]); - const __m128i C0 = _mm_add_epi8(A0, B0); - const __m128i C1 = _mm_add_epi8(A1, B1); - _mm_storeu_si128((__m128i*)&dst[i + 0], C0); - _mm_storeu_si128((__m128i*)&dst[i + 16], C1); - } - for (; i < length; ++i) dst[i] = src[i] + pred[i]; - } else { - for (i = 0; i < max_pos; i += 32) { - const __m128i A0 = _mm_loadu_si128((const __m128i*)&src[i + 0]); - const __m128i A1 = _mm_loadu_si128((const __m128i*)&src[i + 16]); - const __m128i B0 = _mm_loadu_si128((const __m128i*)&pred[i + 0]); - const __m128i B1 = _mm_loadu_si128((const __m128i*)&pred[i + 16]); - const __m128i C0 = _mm_sub_epi8(A0, B0); - const __m128i C1 = _mm_sub_epi8(A1, B1); - _mm_storeu_si128((__m128i*)&dst[i + 0], C0); - _mm_storeu_si128((__m128i*)&dst[i + 16], C1); - } - for (; i < length; ++i) dst[i] = src[i] - pred[i]; - } -} - -// Special case for left-based prediction (when preds==dst-1 or preds==src-1). -static void PredictLineLeft(const uint8_t* src, uint8_t* dst, int length, - int inverse) { - int i; - if (length <= 0) return; - if (inverse) { - const int max_pos = length & ~7; - __m128i last = _mm_set_epi32(0, 0, 0, dst[-1]); - for (i = 0; i < max_pos; i += 8) { - const __m128i A0 = _mm_loadl_epi64((const __m128i*)(src + i)); - const __m128i A1 = _mm_add_epi8(A0, last); - const __m128i A2 = _mm_slli_si128(A1, 1); - const __m128i A3 = _mm_add_epi8(A1, A2); - const __m128i A4 = _mm_slli_si128(A3, 2); - const __m128i A5 = _mm_add_epi8(A3, A4); - const __m128i A6 = _mm_slli_si128(A5, 4); - const __m128i A7 = _mm_add_epi8(A5, A6); - _mm_storel_epi64((__m128i*)(dst + i), A7); - last = _mm_srli_epi64(A7, 56); - } - for (; i < length; ++i) dst[i] = src[i] + dst[i - 1]; - } else { - const int max_pos = length & ~31; - for (i = 0; i < max_pos; i += 32) { - const __m128i A0 = _mm_loadu_si128((const __m128i*)(src + i + 0 )); - const __m128i B0 = _mm_loadu_si128((const __m128i*)(src + i + 0 - 1)); - const __m128i A1 = _mm_loadu_si128((const __m128i*)(src + i + 16 )); - const __m128i B1 = _mm_loadu_si128((const __m128i*)(src + i + 16 - 1)); - const __m128i C0 = _mm_sub_epi8(A0, B0); - const __m128i C1 = _mm_sub_epi8(A1, B1); - _mm_storeu_si128((__m128i*)(dst + i + 0), C0); - _mm_storeu_si128((__m128i*)(dst + i + 16), C1); - } - for (; i < length; ++i) dst[i] = src[i] - src[i - 1]; - } -} - -static void PredictLineC(const uint8_t* src, const uint8_t* pred, - uint8_t* dst, int length, int inverse) { - int i; - if (inverse) { - for (i = 0; i < length; ++i) dst[i] = src[i] + pred[i]; - } else { - for (i = 0; i < length; ++i) dst[i] = src[i] - pred[i]; - } -} - -//------------------------------------------------------------------------------ -// Horizontal filter. - -static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { - const uint8_t* preds; - const size_t start_offset = row * stride; - const int last_row = row + num_rows; - SANITY_CHECK(in, out); - in += start_offset; - out += start_offset; - preds = inverse ? out : in; - - if (row == 0) { - // Leftmost pixel is the same as input for topmost scanline. - out[0] = in[0]; - PredictLineLeft(in + 1, out + 1, width - 1, inverse); - row = 1; - preds += stride; - in += stride; - out += stride; - } - - // Filter line-by-line. - while (row < last_row) { - // Leftmost pixel is predicted from above. - PredictLineC(in, preds - stride, out, 1, inverse); - PredictLineLeft(in + 1, out + 1, width - 1, inverse); - ++row; - preds += stride; - in += stride; - out += stride; - } -} - -//------------------------------------------------------------------------------ -// Vertical filter. - -static WEBP_INLINE void DoVerticalFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { - const uint8_t* preds; - const size_t start_offset = row * stride; - const int last_row = row + num_rows; - SANITY_CHECK(in, out); - in += start_offset; - out += start_offset; - preds = inverse ? out : in; - - if (row == 0) { - // Very first top-left pixel is copied. - out[0] = in[0]; - // Rest of top scan-line is left-predicted. - PredictLineLeft(in + 1, out + 1, width - 1, inverse); - row = 1; - in += stride; - out += stride; - } else { - // We are starting from in-between. Make sure 'preds' points to prev row. - preds -= stride; - } - - // Filter line-by-line. - while (row < last_row) { - PredictLineTop(in, preds, out, width, inverse); - ++row; - preds += stride; - in += stride; - out += stride; - } -} - -//------------------------------------------------------------------------------ -// Gradient filter. - -static WEBP_INLINE int GradientPredictorC(uint8_t a, uint8_t b, uint8_t c) { - const int g = a + b - c; - return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit -} - -static void GradientPredictDirect(const uint8_t* const row, - const uint8_t* const top, - uint8_t* const out, int length) { - const int max_pos = length & ~7; - int i; - const __m128i zero = _mm_setzero_si128(); - for (i = 0; i < max_pos; i += 8) { - const __m128i A0 = _mm_loadl_epi64((const __m128i*)&row[i - 1]); - const __m128i B0 = _mm_loadl_epi64((const __m128i*)&top[i]); - const __m128i C0 = _mm_loadl_epi64((const __m128i*)&top[i - 1]); - const __m128i D = _mm_loadl_epi64((const __m128i*)&row[i]); - const __m128i A1 = _mm_unpacklo_epi8(A0, zero); - const __m128i B1 = _mm_unpacklo_epi8(B0, zero); - const __m128i C1 = _mm_unpacklo_epi8(C0, zero); - const __m128i E = _mm_add_epi16(A1, B1); - const __m128i F = _mm_sub_epi16(E, C1); - const __m128i G = _mm_packus_epi16(F, zero); - const __m128i H = _mm_sub_epi8(D, G); - _mm_storel_epi64((__m128i*)(out + i), H); - } - for (; i < length; ++i) { - out[i] = row[i] - GradientPredictorC(row[i - 1], top[i], top[i - 1]); - } -} - -static void GradientPredictInverse(const uint8_t* const in, - const uint8_t* const top, - uint8_t* const row, int length) { - if (length > 0) { - int i; - const int max_pos = length & ~7; - const __m128i zero = _mm_setzero_si128(); - __m128i A = _mm_set_epi32(0, 0, 0, row[-1]); // left sample - for (i = 0; i < max_pos; i += 8) { - const __m128i tmp0 = _mm_loadl_epi64((const __m128i*)&top[i]); - const __m128i tmp1 = _mm_loadl_epi64((const __m128i*)&top[i - 1]); - const __m128i B = _mm_unpacklo_epi8(tmp0, zero); - const __m128i C = _mm_unpacklo_epi8(tmp1, zero); - const __m128i tmp2 = _mm_loadl_epi64((const __m128i*)&in[i]); - const __m128i D = _mm_unpacklo_epi8(tmp2, zero); // base input - const __m128i E = _mm_sub_epi16(B, C); // unclipped gradient basis B - C - __m128i out = zero; // accumulator for output - __m128i mask_hi = _mm_set_epi32(0, 0, 0, 0xff); - int k = 8; - while (1) { - const __m128i tmp3 = _mm_add_epi16(A, E); // delta = A + B - C - const __m128i tmp4 = _mm_min_epi16(tmp3, mask_hi); - const __m128i tmp5 = _mm_max_epi16(tmp4, zero); // clipped delta - const __m128i tmp6 = _mm_add_epi16(tmp5, D); // add to in[] values - A = _mm_and_si128(tmp6, mask_hi); // 1-complement clip - out = _mm_or_si128(out, A); // accumulate output - if (--k == 0) break; - A = _mm_slli_si128(A, 2); // rotate left sample - mask_hi = _mm_slli_si128(mask_hi, 2); // rotate mask - } - A = _mm_srli_si128(A, 14); // prepare left sample for next iteration - _mm_storel_epi64((__m128i*)&row[i], _mm_packus_epi16(out, zero)); - } - for (; i < length; ++i) { - row[i] = in[i] + GradientPredictorC(row[i - 1], top[i], top[i - 1]); - } - } -} - -static WEBP_INLINE void DoGradientFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { - const size_t start_offset = row * stride; - const int last_row = row + num_rows; - SANITY_CHECK(in, out); - in += start_offset; - out += start_offset; - - // left prediction for top scan-line - if (row == 0) { - out[0] = in[0]; - PredictLineLeft(in + 1, out + 1, width - 1, inverse); - row = 1; - in += stride; - out += stride; - } - - // Filter line-by-line. - while (row < last_row) { - if (inverse) { - PredictLineC(in, out - stride, out, 1, inverse); // predict from above - GradientPredictInverse(in + 1, out + 1 - stride, out + 1, width - 1); - } else { - PredictLineC(in, in - stride, out, 1, inverse); - GradientPredictDirect(in + 1, in + 1 - stride, out + 1, width - 1); - } - ++row; - in += stride; - out += stride; - } -} - -#undef SANITY_CHECK - -//------------------------------------------------------------------------------ - -static void HorizontalFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoHorizontalFilter(data, width, height, stride, 0, height, 0, filtered_data); -} - -static void VerticalFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoVerticalFilter(data, width, height, stride, 0, height, 0, filtered_data); -} - - -static void GradientFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoGradientFilter(data, width, height, stride, 0, height, 0, filtered_data); -} - - -//------------------------------------------------------------------------------ - -static void VerticalUnfilter(int width, int height, int stride, int row, - int num_rows, uint8_t* data) { - DoVerticalFilter(data, width, height, stride, row, num_rows, 1, data); -} - -static void HorizontalUnfilter(int width, int height, int stride, int row, - int num_rows, uint8_t* data) { - DoHorizontalFilter(data, width, height, stride, row, num_rows, 1, data); -} - -static void GradientUnfilter(int width, int height, int stride, int row, - int num_rows, uint8_t* data) { - DoGradientFilter(data, width, height, stride, row, num_rows, 1, data); -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8FiltersInitSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitSSE2(void) { - WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter; - WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter; - WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter; - - WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter; - WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter; - WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter; -} - -#else // !WEBP_USE_SSE2 - -WEBP_DSP_INIT_STUB(VP8FiltersInitSSE2) - -#endif // WEBP_USE_SSE2 diff --git a/Example/Pods/libwebp/src/dsp/lossless.c b/Example/Pods/libwebp/src/dsp/lossless.c deleted file mode 100644 index 71ae9d4a..00000000 --- a/Example/Pods/libwebp/src/dsp/lossless.c +++ /dev/null @@ -1,635 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Image transforms and color space conversion methods for lossless decoder. -// -// Authors: Vikas Arora (vikaas.arora@gmail.com) -// Jyrki Alakuijala (jyrki@google.com) -// Urvang Joshi (urvang@google.com) - -#include "./dsp.h" - -#include -#include -#include "../dec/vp8li.h" -#include "../utils/endian_inl.h" -#include "./lossless.h" - -#define MAX_DIFF_COST (1e30f) - -//------------------------------------------------------------------------------ -// Image transforms. - -// In-place sum of each component with mod 256. -static WEBP_INLINE void AddPixelsEq(uint32_t* a, uint32_t b) { - const uint32_t alpha_and_green = (*a & 0xff00ff00u) + (b & 0xff00ff00u); - const uint32_t red_and_blue = (*a & 0x00ff00ffu) + (b & 0x00ff00ffu); - *a = (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu); -} - -static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) { - return (((a0 ^ a1) & 0xfefefefeu) >> 1) + (a0 & a1); -} - -static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) { - return Average2(Average2(a0, a2), a1); -} - -static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1, - uint32_t a2, uint32_t a3) { - return Average2(Average2(a0, a1), Average2(a2, a3)); -} - -static WEBP_INLINE uint32_t Clip255(uint32_t a) { - if (a < 256) { - return a; - } - // return 0, when a is a negative integer. - // return 255, when a is positive. - return ~a >> 24; -} - -static WEBP_INLINE int AddSubtractComponentFull(int a, int b, int c) { - return Clip255(a + b - c); -} - -static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1, - uint32_t c2) { - const int a = AddSubtractComponentFull(c0 >> 24, c1 >> 24, c2 >> 24); - const int r = AddSubtractComponentFull((c0 >> 16) & 0xff, - (c1 >> 16) & 0xff, - (c2 >> 16) & 0xff); - const int g = AddSubtractComponentFull((c0 >> 8) & 0xff, - (c1 >> 8) & 0xff, - (c2 >> 8) & 0xff); - const int b = AddSubtractComponentFull(c0 & 0xff, c1 & 0xff, c2 & 0xff); - return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b; -} - -static WEBP_INLINE int AddSubtractComponentHalf(int a, int b) { - return Clip255(a + (a - b) / 2); -} - -static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1, - uint32_t c2) { - const uint32_t ave = Average2(c0, c1); - const int a = AddSubtractComponentHalf(ave >> 24, c2 >> 24); - const int r = AddSubtractComponentHalf((ave >> 16) & 0xff, (c2 >> 16) & 0xff); - const int g = AddSubtractComponentHalf((ave >> 8) & 0xff, (c2 >> 8) & 0xff); - const int b = AddSubtractComponentHalf((ave >> 0) & 0xff, (c2 >> 0) & 0xff); - return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b; -} - -// gcc-4.9 on ARM generates incorrect code in Select() when Sub3() is inlined. -#if defined(__arm__) && LOCAL_GCC_VERSION == 0x409 -# define LOCAL_INLINE __attribute__ ((noinline)) -#else -# define LOCAL_INLINE WEBP_INLINE -#endif - -static LOCAL_INLINE int Sub3(int a, int b, int c) { - const int pb = b - c; - const int pa = a - c; - return abs(pb) - abs(pa); -} - -#undef LOCAL_INLINE - -static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) { - const int pa_minus_pb = - Sub3((a >> 24) , (b >> 24) , (c >> 24) ) + - Sub3((a >> 16) & 0xff, (b >> 16) & 0xff, (c >> 16) & 0xff) + - Sub3((a >> 8) & 0xff, (b >> 8) & 0xff, (c >> 8) & 0xff) + - Sub3((a ) & 0xff, (b ) & 0xff, (c ) & 0xff); - return (pa_minus_pb <= 0) ? a : b; -} - -//------------------------------------------------------------------------------ -// Predictors - -static uint32_t Predictor0(uint32_t left, const uint32_t* const top) { - (void)top; - (void)left; - return ARGB_BLACK; -} -static uint32_t Predictor1(uint32_t left, const uint32_t* const top) { - (void)top; - return left; -} -static uint32_t Predictor2(uint32_t left, const uint32_t* const top) { - (void)left; - return top[0]; -} -static uint32_t Predictor3(uint32_t left, const uint32_t* const top) { - (void)left; - return top[1]; -} -static uint32_t Predictor4(uint32_t left, const uint32_t* const top) { - (void)left; - return top[-1]; -} -static uint32_t Predictor5(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average3(left, top[0], top[1]); - return pred; -} -static uint32_t Predictor6(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2(left, top[-1]); - return pred; -} -static uint32_t Predictor7(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2(left, top[0]); - return pred; -} -static uint32_t Predictor8(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2(top[-1], top[0]); - (void)left; - return pred; -} -static uint32_t Predictor9(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2(top[0], top[1]); - (void)left; - return pred; -} -static uint32_t Predictor10(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average4(left, top[-1], top[0], top[1]); - return pred; -} -static uint32_t Predictor11(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Select(top[0], left, top[-1]); - return pred; -} -static uint32_t Predictor12(uint32_t left, const uint32_t* const top) { - const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]); - return pred; -} -static uint32_t Predictor13(uint32_t left, const uint32_t* const top) { - const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]); - return pred; -} - -//------------------------------------------------------------------------------ - -// Inverse prediction. -static void PredictorInverseTransform(const VP8LTransform* const transform, - int y_start, int y_end, uint32_t* data) { - const int width = transform->xsize_; - if (y_start == 0) { // First Row follows the L (mode=1) mode. - int x; - const uint32_t pred0 = Predictor0(data[-1], NULL); - AddPixelsEq(data, pred0); - for (x = 1; x < width; ++x) { - const uint32_t pred1 = Predictor1(data[x - 1], NULL); - AddPixelsEq(data + x, pred1); - } - data += width; - ++y_start; - } - - { - int y = y_start; - const int tile_width = 1 << transform->bits_; - const int mask = tile_width - 1; - const int safe_width = width & ~mask; - const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_); - const uint32_t* pred_mode_base = - transform->data_ + (y >> transform->bits_) * tiles_per_row; - - while (y < y_end) { - const uint32_t pred2 = Predictor2(data[-1], data - width); - const uint32_t* pred_mode_src = pred_mode_base; - VP8LPredictorFunc pred_func; - int x = 1; - int t = 1; - // First pixel follows the T (mode=2) mode. - AddPixelsEq(data, pred2); - // .. the rest: - while (x < safe_width) { - pred_func = VP8LPredictors[((*pred_mode_src++) >> 8) & 0xf]; - for (; t < tile_width; ++t, ++x) { - const uint32_t pred = pred_func(data[x - 1], data + x - width); - AddPixelsEq(data + x, pred); - } - t = 0; - } - if (x < width) { - pred_func = VP8LPredictors[((*pred_mode_src++) >> 8) & 0xf]; - for (; x < width; ++x) { - const uint32_t pred = pred_func(data[x - 1], data + x - width); - AddPixelsEq(data + x, pred); - } - } - data += width; - ++y; - if ((y & mask) == 0) { // Use the same mask, since tiles are squares. - pred_mode_base += tiles_per_row; - } - } - } -} - -// Add green to blue and red channels (i.e. perform the inverse transform of -// 'subtract green'). -void VP8LAddGreenToBlueAndRed_C(uint32_t* data, int num_pixels) { - int i; - for (i = 0; i < num_pixels; ++i) { - const uint32_t argb = data[i]; - const uint32_t green = ((argb >> 8) & 0xff); - uint32_t red_blue = (argb & 0x00ff00ffu); - red_blue += (green << 16) | green; - red_blue &= 0x00ff00ffu; - data[i] = (argb & 0xff00ff00u) | red_blue; - } -} - -static WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred, - int8_t color) { - return (uint32_t)((int)(color_pred) * color) >> 5; -} - -static WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code, - VP8LMultipliers* const m) { - m->green_to_red_ = (color_code >> 0) & 0xff; - m->green_to_blue_ = (color_code >> 8) & 0xff; - m->red_to_blue_ = (color_code >> 16) & 0xff; -} - -void VP8LTransformColorInverse_C(const VP8LMultipliers* const m, uint32_t* data, - int num_pixels) { - int i; - for (i = 0; i < num_pixels; ++i) { - const uint32_t argb = data[i]; - const uint32_t green = argb >> 8; - const uint32_t red = argb >> 16; - uint32_t new_red = red; - uint32_t new_blue = argb; - new_red += ColorTransformDelta(m->green_to_red_, green); - new_red &= 0xff; - new_blue += ColorTransformDelta(m->green_to_blue_, green); - new_blue += ColorTransformDelta(m->red_to_blue_, new_red); - new_blue &= 0xff; - data[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue); - } -} - -// Color space inverse transform. -static void ColorSpaceInverseTransform(const VP8LTransform* const transform, - int y_start, int y_end, uint32_t* data) { - const int width = transform->xsize_; - const int tile_width = 1 << transform->bits_; - const int mask = tile_width - 1; - const int safe_width = width & ~mask; - const int remaining_width = width - safe_width; - const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_); - int y = y_start; - const uint32_t* pred_row = - transform->data_ + (y >> transform->bits_) * tiles_per_row; - - while (y < y_end) { - const uint32_t* pred = pred_row; - VP8LMultipliers m = { 0, 0, 0 }; - const uint32_t* const data_safe_end = data + safe_width; - const uint32_t* const data_end = data + width; - while (data < data_safe_end) { - ColorCodeToMultipliers(*pred++, &m); - VP8LTransformColorInverse(&m, data, tile_width); - data += tile_width; - } - if (data < data_end) { // Left-overs using C-version. - ColorCodeToMultipliers(*pred++, &m); - VP8LTransformColorInverse(&m, data, remaining_width); - data += remaining_width; - } - ++y; - if ((y & mask) == 0) pred_row += tiles_per_row; - } -} - -// Separate out pixels packed together using pixel-bundling. -// We define two methods for ARGB data (uint32_t) and alpha-only data (uint8_t). -#define COLOR_INDEX_INVERSE(FUNC_NAME, F_NAME, STATIC_DECL, TYPE, BIT_SUFFIX, \ - GET_INDEX, GET_VALUE) \ -static void F_NAME(const TYPE* src, const uint32_t* const color_map, \ - TYPE* dst, int y_start, int y_end, int width) { \ - int y; \ - for (y = y_start; y < y_end; ++y) { \ - int x; \ - for (x = 0; x < width; ++x) { \ - *dst++ = GET_VALUE(color_map[GET_INDEX(*src++)]); \ - } \ - } \ -} \ -STATIC_DECL void FUNC_NAME(const VP8LTransform* const transform, \ - int y_start, int y_end, const TYPE* src, \ - TYPE* dst) { \ - int y; \ - const int bits_per_pixel = 8 >> transform->bits_; \ - const int width = transform->xsize_; \ - const uint32_t* const color_map = transform->data_; \ - if (bits_per_pixel < 8) { \ - const int pixels_per_byte = 1 << transform->bits_; \ - const int count_mask = pixels_per_byte - 1; \ - const uint32_t bit_mask = (1 << bits_per_pixel) - 1; \ - for (y = y_start; y < y_end; ++y) { \ - uint32_t packed_pixels = 0; \ - int x; \ - for (x = 0; x < width; ++x) { \ - /* We need to load fresh 'packed_pixels' once every */ \ - /* 'pixels_per_byte' increments of x. Fortunately, pixels_per_byte */ \ - /* is a power of 2, so can just use a mask for that, instead of */ \ - /* decrementing a counter. */ \ - if ((x & count_mask) == 0) packed_pixels = GET_INDEX(*src++); \ - *dst++ = GET_VALUE(color_map[packed_pixels & bit_mask]); \ - packed_pixels >>= bits_per_pixel; \ - } \ - } \ - } else { \ - VP8LMapColor##BIT_SUFFIX(src, color_map, dst, y_start, y_end, width); \ - } \ -} - -COLOR_INDEX_INVERSE(ColorIndexInverseTransform, MapARGB, static, uint32_t, 32b, - VP8GetARGBIndex, VP8GetARGBValue) -COLOR_INDEX_INVERSE(VP8LColorIndexInverseTransformAlpha, MapAlpha, , uint8_t, - 8b, VP8GetAlphaIndex, VP8GetAlphaValue) - -#undef COLOR_INDEX_INVERSE - -void VP8LInverseTransform(const VP8LTransform* const transform, - int row_start, int row_end, - const uint32_t* const in, uint32_t* const out) { - const int width = transform->xsize_; - assert(row_start < row_end); - assert(row_end <= transform->ysize_); - switch (transform->type_) { - case SUBTRACT_GREEN: - VP8LAddGreenToBlueAndRed(out, (row_end - row_start) * width); - break; - case PREDICTOR_TRANSFORM: - PredictorInverseTransform(transform, row_start, row_end, out); - if (row_end != transform->ysize_) { - // The last predicted row in this iteration will be the top-pred row - // for the first row in next iteration. - memcpy(out - width, out + (row_end - row_start - 1) * width, - width * sizeof(*out)); - } - break; - case CROSS_COLOR_TRANSFORM: - ColorSpaceInverseTransform(transform, row_start, row_end, out); - break; - case COLOR_INDEXING_TRANSFORM: - if (in == out && transform->bits_ > 0) { - // Move packed pixels to the end of unpacked region, so that unpacking - // can occur seamlessly. - // Also, note that this is the only transform that applies on - // the effective width of VP8LSubSampleSize(xsize_, bits_). All other - // transforms work on effective width of xsize_. - const int out_stride = (row_end - row_start) * width; - const int in_stride = (row_end - row_start) * - VP8LSubSampleSize(transform->xsize_, transform->bits_); - uint32_t* const src = out + out_stride - in_stride; - memmove(src, out, in_stride * sizeof(*src)); - ColorIndexInverseTransform(transform, row_start, row_end, src, out); - } else { - ColorIndexInverseTransform(transform, row_start, row_end, in, out); - } - break; - } -} - -//------------------------------------------------------------------------------ -// Color space conversion. - -static int is_big_endian(void) { - static const union { - uint16_t w; - uint8_t b[2]; - } tmp = { 1 }; - return (tmp.b[0] != 1); -} - -void VP8LConvertBGRAToRGB_C(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const uint32_t* const src_end = src + num_pixels; - while (src < src_end) { - const uint32_t argb = *src++; - *dst++ = (argb >> 16) & 0xff; - *dst++ = (argb >> 8) & 0xff; - *dst++ = (argb >> 0) & 0xff; - } -} - -void VP8LConvertBGRAToRGBA_C(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const uint32_t* const src_end = src + num_pixels; - while (src < src_end) { - const uint32_t argb = *src++; - *dst++ = (argb >> 16) & 0xff; - *dst++ = (argb >> 8) & 0xff; - *dst++ = (argb >> 0) & 0xff; - *dst++ = (argb >> 24) & 0xff; - } -} - -void VP8LConvertBGRAToRGBA4444_C(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const uint32_t* const src_end = src + num_pixels; - while (src < src_end) { - const uint32_t argb = *src++; - const uint8_t rg = ((argb >> 16) & 0xf0) | ((argb >> 12) & 0xf); - const uint8_t ba = ((argb >> 0) & 0xf0) | ((argb >> 28) & 0xf); -#ifdef WEBP_SWAP_16BIT_CSP - *dst++ = ba; - *dst++ = rg; -#else - *dst++ = rg; - *dst++ = ba; -#endif - } -} - -void VP8LConvertBGRAToRGB565_C(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const uint32_t* const src_end = src + num_pixels; - while (src < src_end) { - const uint32_t argb = *src++; - const uint8_t rg = ((argb >> 16) & 0xf8) | ((argb >> 13) & 0x7); - const uint8_t gb = ((argb >> 5) & 0xe0) | ((argb >> 3) & 0x1f); -#ifdef WEBP_SWAP_16BIT_CSP - *dst++ = gb; - *dst++ = rg; -#else - *dst++ = rg; - *dst++ = gb; -#endif - } -} - -void VP8LConvertBGRAToBGR_C(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const uint32_t* const src_end = src + num_pixels; - while (src < src_end) { - const uint32_t argb = *src++; - *dst++ = (argb >> 0) & 0xff; - *dst++ = (argb >> 8) & 0xff; - *dst++ = (argb >> 16) & 0xff; - } -} - -static void CopyOrSwap(const uint32_t* src, int num_pixels, uint8_t* dst, - int swap_on_big_endian) { - if (is_big_endian() == swap_on_big_endian) { - const uint32_t* const src_end = src + num_pixels; - while (src < src_end) { - const uint32_t argb = *src++; - -#if !defined(WORDS_BIGENDIAN) -#if !defined(WEBP_REFERENCE_IMPLEMENTATION) - WebPUint32ToMem(dst, BSwap32(argb)); -#else // WEBP_REFERENCE_IMPLEMENTATION - dst[0] = (argb >> 24) & 0xff; - dst[1] = (argb >> 16) & 0xff; - dst[2] = (argb >> 8) & 0xff; - dst[3] = (argb >> 0) & 0xff; -#endif -#else // WORDS_BIGENDIAN - dst[0] = (argb >> 0) & 0xff; - dst[1] = (argb >> 8) & 0xff; - dst[2] = (argb >> 16) & 0xff; - dst[3] = (argb >> 24) & 0xff; -#endif - dst += sizeof(argb); - } - } else { - memcpy(dst, src, num_pixels * sizeof(*src)); - } -} - -void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels, - WEBP_CSP_MODE out_colorspace, uint8_t* const rgba) { - switch (out_colorspace) { - case MODE_RGB: - VP8LConvertBGRAToRGB(in_data, num_pixels, rgba); - break; - case MODE_RGBA: - VP8LConvertBGRAToRGBA(in_data, num_pixels, rgba); - break; - case MODE_rgbA: - VP8LConvertBGRAToRGBA(in_data, num_pixels, rgba); - WebPApplyAlphaMultiply(rgba, 0, num_pixels, 1, 0); - break; - case MODE_BGR: - VP8LConvertBGRAToBGR(in_data, num_pixels, rgba); - break; - case MODE_BGRA: - CopyOrSwap(in_data, num_pixels, rgba, 1); - break; - case MODE_bgrA: - CopyOrSwap(in_data, num_pixels, rgba, 1); - WebPApplyAlphaMultiply(rgba, 0, num_pixels, 1, 0); - break; - case MODE_ARGB: - CopyOrSwap(in_data, num_pixels, rgba, 0); - break; - case MODE_Argb: - CopyOrSwap(in_data, num_pixels, rgba, 0); - WebPApplyAlphaMultiply(rgba, 1, num_pixels, 1, 0); - break; - case MODE_RGBA_4444: - VP8LConvertBGRAToRGBA4444(in_data, num_pixels, rgba); - break; - case MODE_rgbA_4444: - VP8LConvertBGRAToRGBA4444(in_data, num_pixels, rgba); - WebPApplyAlphaMultiply4444(rgba, num_pixels, 1, 0); - break; - case MODE_RGB_565: - VP8LConvertBGRAToRGB565(in_data, num_pixels, rgba); - break; - default: - assert(0); // Code flow should not reach here. - } -} - -//------------------------------------------------------------------------------ - -VP8LProcessBlueAndRedFunc VP8LAddGreenToBlueAndRed; -VP8LPredictorFunc VP8LPredictors[16]; - -VP8LTransformColorFunc VP8LTransformColorInverse; - -VP8LConvertFunc VP8LConvertBGRAToRGB; -VP8LConvertFunc VP8LConvertBGRAToRGBA; -VP8LConvertFunc VP8LConvertBGRAToRGBA4444; -VP8LConvertFunc VP8LConvertBGRAToRGB565; -VP8LConvertFunc VP8LConvertBGRAToBGR; - -VP8LMapARGBFunc VP8LMapColor32b; -VP8LMapAlphaFunc VP8LMapColor8b; - -extern void VP8LDspInitSSE2(void); -extern void VP8LDspInitNEON(void); -extern void VP8LDspInitMIPSdspR2(void); - -static volatile VP8CPUInfo lossless_last_cpuinfo_used = - (VP8CPUInfo)&lossless_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInit(void) { - if (lossless_last_cpuinfo_used == VP8GetCPUInfo) return; - - VP8LPredictors[0] = Predictor0; - VP8LPredictors[1] = Predictor1; - VP8LPredictors[2] = Predictor2; - VP8LPredictors[3] = Predictor3; - VP8LPredictors[4] = Predictor4; - VP8LPredictors[5] = Predictor5; - VP8LPredictors[6] = Predictor6; - VP8LPredictors[7] = Predictor7; - VP8LPredictors[8] = Predictor8; - VP8LPredictors[9] = Predictor9; - VP8LPredictors[10] = Predictor10; - VP8LPredictors[11] = Predictor11; - VP8LPredictors[12] = Predictor12; - VP8LPredictors[13] = Predictor13; - VP8LPredictors[14] = Predictor0; // <- padding security sentinels - VP8LPredictors[15] = Predictor0; - - VP8LAddGreenToBlueAndRed = VP8LAddGreenToBlueAndRed_C; - - VP8LTransformColorInverse = VP8LTransformColorInverse_C; - - VP8LConvertBGRAToRGB = VP8LConvertBGRAToRGB_C; - VP8LConvertBGRAToRGBA = VP8LConvertBGRAToRGBA_C; - VP8LConvertBGRAToRGBA4444 = VP8LConvertBGRAToRGBA4444_C; - VP8LConvertBGRAToRGB565 = VP8LConvertBGRAToRGB565_C; - VP8LConvertBGRAToBGR = VP8LConvertBGRAToBGR_C; - - VP8LMapColor32b = MapARGB; - VP8LMapColor8b = MapAlpha; - - // If defined, use CPUInfo() to overwrite some pointers with faster versions. - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - VP8LDspInitSSE2(); - } -#endif -#if defined(WEBP_USE_NEON) - if (VP8GetCPUInfo(kNEON)) { - VP8LDspInitNEON(); - } -#endif -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - VP8LDspInitMIPSdspR2(); - } -#endif - } - lossless_last_cpuinfo_used = VP8GetCPUInfo; -} - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/dsp/lossless.h b/Example/Pods/libwebp/src/dsp/lossless.h deleted file mode 100644 index e063bdd1..00000000 --- a/Example/Pods/libwebp/src/dsp/lossless.h +++ /dev/null @@ -1,348 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Image transforms and color space conversion methods for lossless decoder. -// -// Authors: Vikas Arora (vikaas.arora@gmail.com) -// Jyrki Alakuijala (jyrki@google.com) - -#ifndef WEBP_DSP_LOSSLESS_H_ -#define WEBP_DSP_LOSSLESS_H_ - -#include "../webp/types.h" -#include "../webp/decode.h" - -#include "../enc/histogram.h" -#include "../utils/utils.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef WEBP_EXPERIMENTAL_FEATURES -#include "../enc/delta_palettization.h" -#endif // WEBP_EXPERIMENTAL_FEATURES - -//------------------------------------------------------------------------------ -// Decoding - -typedef uint32_t (*VP8LPredictorFunc)(uint32_t left, const uint32_t* const top); -extern VP8LPredictorFunc VP8LPredictors[16]; - -typedef void (*VP8LProcessBlueAndRedFunc)(uint32_t* argb_data, int num_pixels); -extern VP8LProcessBlueAndRedFunc VP8LAddGreenToBlueAndRed; - -typedef struct { - // Note: the members are uint8_t, so that any negative values are - // automatically converted to "mod 256" values. - uint8_t green_to_red_; - uint8_t green_to_blue_; - uint8_t red_to_blue_; -} VP8LMultipliers; -typedef void (*VP8LTransformColorFunc)(const VP8LMultipliers* const m, - uint32_t* argb_data, int num_pixels); -extern VP8LTransformColorFunc VP8LTransformColorInverse; - -struct VP8LTransform; // Defined in dec/vp8li.h. - -// Performs inverse transform of data given transform information, start and end -// rows. Transform will be applied to rows [row_start, row_end[. -// The *in and *out pointers refer to source and destination data respectively -// corresponding to the intermediate row (row_start). -void VP8LInverseTransform(const struct VP8LTransform* const transform, - int row_start, int row_end, - const uint32_t* const in, uint32_t* const out); - -// Color space conversion. -typedef void (*VP8LConvertFunc)(const uint32_t* src, int num_pixels, - uint8_t* dst); -extern VP8LConvertFunc VP8LConvertBGRAToRGB; -extern VP8LConvertFunc VP8LConvertBGRAToRGBA; -extern VP8LConvertFunc VP8LConvertBGRAToRGBA4444; -extern VP8LConvertFunc VP8LConvertBGRAToRGB565; -extern VP8LConvertFunc VP8LConvertBGRAToBGR; - -// Converts from BGRA to other color spaces. -void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels, - WEBP_CSP_MODE out_colorspace, uint8_t* const rgba); - -// color mapping related functions. -static WEBP_INLINE uint32_t VP8GetARGBIndex(uint32_t idx) { - return (idx >> 8) & 0xff; -} - -static WEBP_INLINE uint8_t VP8GetAlphaIndex(uint8_t idx) { - return idx; -} - -static WEBP_INLINE uint32_t VP8GetARGBValue(uint32_t val) { - return val; -} - -static WEBP_INLINE uint8_t VP8GetAlphaValue(uint32_t val) { - return (val >> 8) & 0xff; -} - -typedef void (*VP8LMapARGBFunc)(const uint32_t* src, - const uint32_t* const color_map, - uint32_t* dst, int y_start, - int y_end, int width); -typedef void (*VP8LMapAlphaFunc)(const uint8_t* src, - const uint32_t* const color_map, - uint8_t* dst, int y_start, - int y_end, int width); - -extern VP8LMapARGBFunc VP8LMapColor32b; -extern VP8LMapAlphaFunc VP8LMapColor8b; - -// Similar to the static method ColorIndexInverseTransform() that is part of -// lossless.c, but used only for alpha decoding. It takes uint8_t (rather than -// uint32_t) arguments for 'src' and 'dst'. -void VP8LColorIndexInverseTransformAlpha( - const struct VP8LTransform* const transform, int y_start, int y_end, - const uint8_t* src, uint8_t* dst); - -// Expose some C-only fallback functions -void VP8LTransformColorInverse_C(const VP8LMultipliers* const m, - uint32_t* data, int num_pixels); - -void VP8LConvertBGRAToRGB_C(const uint32_t* src, int num_pixels, uint8_t* dst); -void VP8LConvertBGRAToRGBA_C(const uint32_t* src, int num_pixels, uint8_t* dst); -void VP8LConvertBGRAToRGBA4444_C(const uint32_t* src, - int num_pixels, uint8_t* dst); -void VP8LConvertBGRAToRGB565_C(const uint32_t* src, - int num_pixels, uint8_t* dst); -void VP8LConvertBGRAToBGR_C(const uint32_t* src, int num_pixels, uint8_t* dst); -void VP8LAddGreenToBlueAndRed_C(uint32_t* data, int num_pixels); - -// Must be called before calling any of the above methods. -void VP8LDspInit(void); - -//------------------------------------------------------------------------------ -// Encoding - -extern VP8LProcessBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed; -extern VP8LTransformColorFunc VP8LTransformColor; -typedef void (*VP8LCollectColorBlueTransformsFunc)( - const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_blue, int red_to_blue, int histo[]); -extern VP8LCollectColorBlueTransformsFunc VP8LCollectColorBlueTransforms; - -typedef void (*VP8LCollectColorRedTransformsFunc)( - const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_red, int histo[]); -extern VP8LCollectColorRedTransformsFunc VP8LCollectColorRedTransforms; - -// Expose some C-only fallback functions -void VP8LTransformColor_C(const VP8LMultipliers* const m, - uint32_t* data, int num_pixels); -void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels); -void VP8LCollectColorRedTransforms_C(const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_red, int histo[]); -void VP8LCollectColorBlueTransforms_C(const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_blue, int red_to_blue, - int histo[]); - -//------------------------------------------------------------------------------ -// Image transforms. - -void VP8LResidualImage(int width, int height, int bits, int low_effort, - uint32_t* const argb, uint32_t* const argb_scratch, - uint32_t* const image, int exact); - -void VP8LColorSpaceTransform(int width, int height, int bits, int quality, - uint32_t* const argb, uint32_t* image); - -//------------------------------------------------------------------------------ -// Misc methods. - -// Computes sampled size of 'size' when sampling using 'sampling bits'. -static WEBP_INLINE uint32_t VP8LSubSampleSize(uint32_t size, - uint32_t sampling_bits) { - return (size + (1 << sampling_bits) - 1) >> sampling_bits; -} - -// ----------------------------------------------------------------------------- -// Faster logarithm for integers. Small values use a look-up table. - -// The threshold till approximate version of log_2 can be used. -// Practically, we can get rid of the call to log() as the two values match to -// very high degree (the ratio of these two is 0.99999x). -// Keeping a high threshold for now. -#define APPROX_LOG_WITH_CORRECTION_MAX 65536 -#define APPROX_LOG_MAX 4096 -#define LOG_2_RECIPROCAL 1.44269504088896338700465094007086 -#define LOG_LOOKUP_IDX_MAX 256 -extern const float kLog2Table[LOG_LOOKUP_IDX_MAX]; -extern const float kSLog2Table[LOG_LOOKUP_IDX_MAX]; -typedef float (*VP8LFastLog2SlowFunc)(uint32_t v); - -extern VP8LFastLog2SlowFunc VP8LFastLog2Slow; -extern VP8LFastLog2SlowFunc VP8LFastSLog2Slow; - -static WEBP_INLINE float VP8LFastLog2(uint32_t v) { - return (v < LOG_LOOKUP_IDX_MAX) ? kLog2Table[v] : VP8LFastLog2Slow(v); -} -// Fast calculation of v * log2(v) for integer input. -static WEBP_INLINE float VP8LFastSLog2(uint32_t v) { - return (v < LOG_LOOKUP_IDX_MAX) ? kSLog2Table[v] : VP8LFastSLog2Slow(v); -} - -// ----------------------------------------------------------------------------- -// Huffman-cost related functions. - -typedef double (*VP8LCostFunc)(const uint32_t* population, int length); -typedef double (*VP8LCostCombinedFunc)(const uint32_t* X, const uint32_t* Y, - int length); -typedef float (*VP8LCombinedShannonEntropyFunc)(const int X[256], - const int Y[256]); - -extern VP8LCostFunc VP8LExtraCost; -extern VP8LCostCombinedFunc VP8LExtraCostCombined; -extern VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy; - -typedef struct { // small struct to hold counters - int counts[2]; // index: 0=zero steak, 1=non-zero streak - int streaks[2][2]; // [zero/non-zero][streak<3 / streak>=3] -} VP8LStreaks; - -typedef VP8LStreaks (*VP8LCostCombinedCountFunc)(const uint32_t* X, - const uint32_t* Y, int length); - -extern VP8LCostCombinedCountFunc VP8LHuffmanCostCombinedCount; - -typedef struct { // small struct to hold bit entropy results - double entropy; // entropy - uint32_t sum; // sum of the population - int nonzeros; // number of non-zero elements in the population - uint32_t max_val; // maximum value in the population - uint32_t nonzero_code; // index of the last non-zero in the population -} VP8LBitEntropy; - -void VP8LBitEntropyInit(VP8LBitEntropy* const entropy); - -// Get the combined symbol bit entropy and Huffman cost stats for the -// distributions 'X' and 'Y'. Those results can then be refined according to -// codec specific heuristics. -void VP8LGetCombinedEntropyUnrefined(const uint32_t* const X, - const uint32_t* const Y, int length, - VP8LBitEntropy* const bit_entropy, - VP8LStreaks* const stats); -// Get the entropy for the distribution 'X'. -void VP8LGetEntropyUnrefined(const uint32_t* const X, int length, - VP8LBitEntropy* const bit_entropy, - VP8LStreaks* const stats); - -void VP8LBitsEntropyUnrefined(const uint32_t* const array, int n, - VP8LBitEntropy* const entropy); - -typedef void (*GetEntropyUnrefinedHelperFunc)(uint32_t val, int i, - uint32_t* const val_prev, - int* const i_prev, - VP8LBitEntropy* const bit_entropy, - VP8LStreaks* const stats); -// Internal function used by VP8LGet*EntropyUnrefined. -extern GetEntropyUnrefinedHelperFunc VP8LGetEntropyUnrefinedHelper; - -typedef void (*VP8LHistogramAddFunc)(const VP8LHistogram* const a, - const VP8LHistogram* const b, - VP8LHistogram* const out); -extern VP8LHistogramAddFunc VP8LHistogramAdd; - -// ----------------------------------------------------------------------------- -// PrefixEncode() - -static WEBP_INLINE int VP8LBitsLog2Ceiling(uint32_t n) { - const int log_floor = BitsLog2Floor(n); - if (n == (n & ~(n - 1))) // zero or a power of two. - return log_floor; - else - return log_floor + 1; -} - -// Splitting of distance and length codes into prefixes and -// extra bits. The prefixes are encoded with an entropy code -// while the extra bits are stored just as normal bits. -static WEBP_INLINE void VP8LPrefixEncodeBitsNoLUT(int distance, int* const code, - int* const extra_bits) { - const int highest_bit = BitsLog2Floor(--distance); - const int second_highest_bit = (distance >> (highest_bit - 1)) & 1; - *extra_bits = highest_bit - 1; - *code = 2 * highest_bit + second_highest_bit; -} - -static WEBP_INLINE void VP8LPrefixEncodeNoLUT(int distance, int* const code, - int* const extra_bits, - int* const extra_bits_value) { - const int highest_bit = BitsLog2Floor(--distance); - const int second_highest_bit = (distance >> (highest_bit - 1)) & 1; - *extra_bits = highest_bit - 1; - *extra_bits_value = distance & ((1 << *extra_bits) - 1); - *code = 2 * highest_bit + second_highest_bit; -} - -#define PREFIX_LOOKUP_IDX_MAX 512 -typedef struct { - int8_t code_; - int8_t extra_bits_; -} VP8LPrefixCode; - -// These tables are derived using VP8LPrefixEncodeNoLUT. -extern const VP8LPrefixCode kPrefixEncodeCode[PREFIX_LOOKUP_IDX_MAX]; -extern const uint8_t kPrefixEncodeExtraBitsValue[PREFIX_LOOKUP_IDX_MAX]; -static WEBP_INLINE void VP8LPrefixEncodeBits(int distance, int* const code, - int* const extra_bits) { - if (distance < PREFIX_LOOKUP_IDX_MAX) { - const VP8LPrefixCode prefix_code = kPrefixEncodeCode[distance]; - *code = prefix_code.code_; - *extra_bits = prefix_code.extra_bits_; - } else { - VP8LPrefixEncodeBitsNoLUT(distance, code, extra_bits); - } -} - -static WEBP_INLINE void VP8LPrefixEncode(int distance, int* const code, - int* const extra_bits, - int* const extra_bits_value) { - if (distance < PREFIX_LOOKUP_IDX_MAX) { - const VP8LPrefixCode prefix_code = kPrefixEncodeCode[distance]; - *code = prefix_code.code_; - *extra_bits = prefix_code.extra_bits_; - *extra_bits_value = kPrefixEncodeExtraBitsValue[distance]; - } else { - VP8LPrefixEncodeNoLUT(distance, code, extra_bits, extra_bits_value); - } -} - -// In-place difference of each component with mod 256. -static WEBP_INLINE uint32_t VP8LSubPixels(uint32_t a, uint32_t b) { - const uint32_t alpha_and_green = - 0x00ff00ffu + (a & 0xff00ff00u) - (b & 0xff00ff00u); - const uint32_t red_and_blue = - 0xff00ff00u + (a & 0x00ff00ffu) - (b & 0x00ff00ffu); - return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu); -} - -void VP8LBundleColorMap(const uint8_t* const row, int width, - int xbits, uint32_t* const dst); - -// Must be called before calling any of the above methods. -void VP8LEncDspInit(void); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // WEBP_DSP_LOSSLESS_H_ diff --git a/Example/Pods/libwebp/src/dsp/lossless_enc.c b/Example/Pods/libwebp/src/dsp/lossless_enc.c deleted file mode 100644 index 2eafa3da..00000000 --- a/Example/Pods/libwebp/src/dsp/lossless_enc.c +++ /dev/null @@ -1,1215 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Image transform methods for lossless encoder. -// -// Authors: Vikas Arora (vikaas.arora@gmail.com) -// Jyrki Alakuijala (jyrki@google.com) -// Urvang Joshi (urvang@google.com) - -#include "./dsp.h" - -#include -#include -#include "../dec/vp8li.h" -#include "../utils/endian_inl.h" -#include "./lossless.h" -#include "./yuv.h" - -#define MAX_DIFF_COST (1e30f) - -static const int kPredLowEffort = 11; -static const uint32_t kMaskAlpha = 0xff000000; - -// lookup table for small values of log2(int) -const float kLog2Table[LOG_LOOKUP_IDX_MAX] = { - 0.0000000000000000f, 0.0000000000000000f, - 1.0000000000000000f, 1.5849625007211560f, - 2.0000000000000000f, 2.3219280948873621f, - 2.5849625007211560f, 2.8073549220576041f, - 3.0000000000000000f, 3.1699250014423121f, - 3.3219280948873621f, 3.4594316186372973f, - 3.5849625007211560f, 3.7004397181410921f, - 3.8073549220576041f, 3.9068905956085187f, - 4.0000000000000000f, 4.0874628412503390f, - 4.1699250014423121f, 4.2479275134435852f, - 4.3219280948873626f, 4.3923174227787606f, - 4.4594316186372973f, 4.5235619560570130f, - 4.5849625007211560f, 4.6438561897747243f, - 4.7004397181410917f, 4.7548875021634682f, - 4.8073549220576037f, 4.8579809951275718f, - 4.9068905956085187f, 4.9541963103868749f, - 5.0000000000000000f, 5.0443941193584533f, - 5.0874628412503390f, 5.1292830169449663f, - 5.1699250014423121f, 5.2094533656289501f, - 5.2479275134435852f, 5.2854022188622487f, - 5.3219280948873626f, 5.3575520046180837f, - 5.3923174227787606f, 5.4262647547020979f, - 5.4594316186372973f, 5.4918530963296747f, - 5.5235619560570130f, 5.5545888516776376f, - 5.5849625007211560f, 5.6147098441152083f, - 5.6438561897747243f, 5.6724253419714951f, - 5.7004397181410917f, 5.7279204545631987f, - 5.7548875021634682f, 5.7813597135246599f, - 5.8073549220576037f, 5.8328900141647412f, - 5.8579809951275718f, 5.8826430493618415f, - 5.9068905956085187f, 5.9307373375628866f, - 5.9541963103868749f, 5.9772799234999167f, - 6.0000000000000000f, 6.0223678130284543f, - 6.0443941193584533f, 6.0660891904577720f, - 6.0874628412503390f, 6.1085244567781691f, - 6.1292830169449663f, 6.1497471195046822f, - 6.1699250014423121f, 6.1898245588800175f, - 6.2094533656289501f, 6.2288186904958804f, - 6.2479275134435852f, 6.2667865406949010f, - 6.2854022188622487f, 6.3037807481771030f, - 6.3219280948873626f, 6.3398500028846243f, - 6.3575520046180837f, 6.3750394313469245f, - 6.3923174227787606f, 6.4093909361377017f, - 6.4262647547020979f, 6.4429434958487279f, - 6.4594316186372973f, 6.4757334309663976f, - 6.4918530963296747f, 6.5077946401986963f, - 6.5235619560570130f, 6.5391588111080309f, - 6.5545888516776376f, 6.5698556083309478f, - 6.5849625007211560f, 6.5999128421871278f, - 6.6147098441152083f, 6.6293566200796094f, - 6.6438561897747243f, 6.6582114827517946f, - 6.6724253419714951f, 6.6865005271832185f, - 6.7004397181410917f, 6.7142455176661224f, - 6.7279204545631987f, 6.7414669864011464f, - 6.7548875021634682f, 6.7681843247769259f, - 6.7813597135246599f, 6.7944158663501061f, - 6.8073549220576037f, 6.8201789624151878f, - 6.8328900141647412f, 6.8454900509443747f, - 6.8579809951275718f, 6.8703647195834047f, - 6.8826430493618415f, 6.8948177633079437f, - 6.9068905956085187f, 6.9188632372745946f, - 6.9307373375628866f, 6.9425145053392398f, - 6.9541963103868749f, 6.9657842846620869f, - 6.9772799234999167f, 6.9886846867721654f, - 7.0000000000000000f, 7.0112272554232539f, - 7.0223678130284543f, 7.0334230015374501f, - 7.0443941193584533f, 7.0552824355011898f, - 7.0660891904577720f, 7.0768155970508308f, - 7.0874628412503390f, 7.0980320829605263f, - 7.1085244567781691f, 7.1189410727235076f, - 7.1292830169449663f, 7.1395513523987936f, - 7.1497471195046822f, 7.1598713367783890f, - 7.1699250014423121f, 7.1799090900149344f, - 7.1898245588800175f, 7.1996723448363644f, - 7.2094533656289501f, 7.2191685204621611f, - 7.2288186904958804f, 7.2384047393250785f, - 7.2479275134435852f, 7.2573878426926521f, - 7.2667865406949010f, 7.2761244052742375f, - 7.2854022188622487f, 7.2946207488916270f, - 7.3037807481771030f, 7.3128829552843557f, - 7.3219280948873626f, 7.3309168781146167f, - 7.3398500028846243f, 7.3487281542310771f, - 7.3575520046180837f, 7.3663222142458160f, - 7.3750394313469245f, 7.3837042924740519f, - 7.3923174227787606f, 7.4008794362821843f, - 7.4093909361377017f, 7.4178525148858982f, - 7.4262647547020979f, 7.4346282276367245f, - 7.4429434958487279f, 7.4512111118323289f, - 7.4594316186372973f, 7.4676055500829976f, - 7.4757334309663976f, 7.4838157772642563f, - 7.4918530963296747f, 7.4998458870832056f, - 7.5077946401986963f, 7.5156998382840427f, - 7.5235619560570130f, 7.5313814605163118f, - 7.5391588111080309f, 7.5468944598876364f, - 7.5545888516776376f, 7.5622424242210728f, - 7.5698556083309478f, 7.5774288280357486f, - 7.5849625007211560f, 7.5924570372680806f, - 7.5999128421871278f, 7.6073303137496104f, - 7.6147098441152083f, 7.6220518194563764f, - 7.6293566200796094f, 7.6366246205436487f, - 7.6438561897747243f, 7.6510516911789281f, - 7.6582114827517946f, 7.6653359171851764f, - 7.6724253419714951f, 7.6794800995054464f, - 7.6865005271832185f, 7.6934869574993252f, - 7.7004397181410917f, 7.7073591320808825f, - 7.7142455176661224f, 7.7210991887071855f, - 7.7279204545631987f, 7.7347096202258383f, - 7.7414669864011464f, 7.7481928495894605f, - 7.7548875021634682f, 7.7615512324444795f, - 7.7681843247769259f, 7.7747870596011736f, - 7.7813597135246599f, 7.7879025593914317f, - 7.7944158663501061f, 7.8008998999203047f, - 7.8073549220576037f, 7.8137811912170374f, - 7.8201789624151878f, 7.8265484872909150f, - 7.8328900141647412f, 7.8392037880969436f, - 7.8454900509443747f, 7.8517490414160571f, - 7.8579809951275718f, 7.8641861446542797f, - 7.8703647195834047f, 7.8765169465649993f, - 7.8826430493618415f, 7.8887432488982591f, - 7.8948177633079437f, 7.9008668079807486f, - 7.9068905956085187f, 7.9128893362299619f, - 7.9188632372745946f, 7.9248125036057812f, - 7.9307373375628866f, 7.9366379390025709f, - 7.9425145053392398f, 7.9483672315846778f, - 7.9541963103868749f, 7.9600019320680805f, - 7.9657842846620869f, 7.9715435539507719f, - 7.9772799234999167f, 7.9829935746943103f, - 7.9886846867721654f, 7.9943534368588577f -}; - -const float kSLog2Table[LOG_LOOKUP_IDX_MAX] = { - 0.00000000f, 0.00000000f, 2.00000000f, 4.75488750f, - 8.00000000f, 11.60964047f, 15.50977500f, 19.65148445f, - 24.00000000f, 28.52932501f, 33.21928095f, 38.05374781f, - 43.01955001f, 48.10571634f, 53.30296891f, 58.60335893f, - 64.00000000f, 69.48686830f, 75.05865003f, 80.71062276f, - 86.43856190f, 92.23866588f, 98.10749561f, 104.04192499f, - 110.03910002f, 116.09640474f, 122.21143267f, 128.38196256f, - 134.60593782f, 140.88144886f, 147.20671787f, 153.58008562f, - 160.00000000f, 166.46500594f, 172.97373660f, 179.52490559f, - 186.11730005f, 192.74977453f, 199.42124551f, 206.13068654f, - 212.87712380f, 219.65963219f, 226.47733176f, 233.32938445f, - 240.21499122f, 247.13338933f, 254.08384998f, 261.06567603f, - 268.07820003f, 275.12078236f, 282.19280949f, 289.29369244f, - 296.42286534f, 303.57978409f, 310.76392512f, 317.97478424f, - 325.21187564f, 332.47473081f, 339.76289772f, 347.07593991f, - 354.41343574f, 361.77497759f, 369.16017124f, 376.56863518f, - 384.00000000f, 391.45390785f, 398.93001188f, 406.42797576f, - 413.94747321f, 421.48818752f, 429.04981119f, 436.63204548f, - 444.23460010f, 451.85719280f, 459.49954906f, 467.16140179f, - 474.84249102f, 482.54256363f, 490.26137307f, 497.99867911f, - 505.75424759f, 513.52785023f, 521.31926438f, 529.12827280f, - 536.95466351f, 544.79822957f, 552.65876890f, 560.53608414f, - 568.42998244f, 576.34027536f, 584.26677867f, 592.20931226f, - 600.16769996f, 608.14176943f, 616.13135206f, 624.13628279f, - 632.15640007f, 640.19154569f, 648.24156472f, 656.30630539f, - 664.38561898f, 672.47935976f, 680.58738488f, 688.70955430f, - 696.84573069f, 704.99577935f, 713.15956818f, 721.33696754f, - 729.52785023f, 737.73209140f, 745.94956849f, 754.18016116f, - 762.42375127f, 770.68022275f, 778.94946161f, 787.23135586f, - 795.52579543f, 803.83267219f, 812.15187982f, 820.48331383f, - 828.82687147f, 837.18245171f, 845.54995518f, 853.92928416f, - 862.32034249f, 870.72303558f, 879.13727036f, 887.56295522f, - 896.00000000f, 904.44831595f, 912.90781569f, 921.37841320f, - 929.86002376f, 938.35256392f, 946.85595152f, 955.37010560f, - 963.89494641f, 972.43039537f, 980.97637504f, 989.53280911f, - 998.09962237f, 1006.67674069f, 1015.26409097f, 1023.86160116f, - 1032.46920021f, 1041.08681805f, 1049.71438560f, 1058.35183469f, - 1066.99909811f, 1075.65610955f, 1084.32280357f, 1092.99911564f, - 1101.68498204f, 1110.38033993f, 1119.08512727f, 1127.79928282f, - 1136.52274614f, 1145.25545758f, 1153.99735821f, 1162.74838989f, - 1171.50849518f, 1180.27761738f, 1189.05570047f, 1197.84268914f, - 1206.63852876f, 1215.44316535f, 1224.25654560f, 1233.07861684f, - 1241.90932703f, 1250.74862473f, 1259.59645914f, 1268.45278005f, - 1277.31753781f, 1286.19068338f, 1295.07216828f, 1303.96194457f, - 1312.85996488f, 1321.76618236f, 1330.68055071f, 1339.60302413f, - 1348.53355734f, 1357.47210556f, 1366.41862452f, 1375.37307041f, - 1384.33539991f, 1393.30557020f, 1402.28353887f, 1411.26926400f, - 1420.26270412f, 1429.26381818f, 1438.27256558f, 1447.28890615f, - 1456.31280014f, 1465.34420819f, 1474.38309138f, 1483.42941118f, - 1492.48312945f, 1501.54420843f, 1510.61261078f, 1519.68829949f, - 1528.77123795f, 1537.86138993f, 1546.95871952f, 1556.06319119f, - 1565.17476976f, 1574.29342040f, 1583.41910860f, 1592.55180020f, - 1601.69146137f, 1610.83805860f, 1619.99155871f, 1629.15192882f, - 1638.31913637f, 1647.49314911f, 1656.67393509f, 1665.86146266f, - 1675.05570047f, 1684.25661744f, 1693.46418280f, 1702.67836605f, - 1711.89913698f, 1721.12646563f, 1730.36032233f, 1739.60067768f, - 1748.84750254f, 1758.10076802f, 1767.36044551f, 1776.62650662f, - 1785.89892323f, 1795.17766747f, 1804.46271172f, 1813.75402857f, - 1823.05159087f, 1832.35537170f, 1841.66534438f, 1850.98148244f, - 1860.30375965f, 1869.63214999f, 1878.96662767f, 1888.30716711f, - 1897.65374295f, 1907.00633003f, 1916.36490342f, 1925.72943838f, - 1935.09991037f, 1944.47629506f, 1953.85856831f, 1963.24670620f, - 1972.64068498f, 1982.04048108f, 1991.44607117f, 2000.85743204f, - 2010.27454072f, 2019.69737440f, 2029.12591044f, 2038.56012640f -}; - -const VP8LPrefixCode kPrefixEncodeCode[PREFIX_LOOKUP_IDX_MAX] = { - { 0, 0}, { 0, 0}, { 1, 0}, { 2, 0}, { 3, 0}, { 4, 1}, { 4, 1}, { 5, 1}, - { 5, 1}, { 6, 2}, { 6, 2}, { 6, 2}, { 6, 2}, { 7, 2}, { 7, 2}, { 7, 2}, - { 7, 2}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, - { 8, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, - { 9, 3}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, - {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, - {10, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, - {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, - {11, 4}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, - {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, - {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, - {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, - {12, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, - {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, - {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, - {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, - {13, 5}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, - {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, - {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, - {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, - {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, - {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, - {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, - {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, - {14, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, - {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, - {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, - {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, - {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, - {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, - {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, - {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, - {15, 6}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, - {16, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, - {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, -}; - -const uint8_t kPrefixEncodeExtraBitsValue[PREFIX_LOOKUP_IDX_MAX] = { - 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, - 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126 -}; - -static float FastSLog2Slow(uint32_t v) { - assert(v >= LOG_LOOKUP_IDX_MAX); - if (v < APPROX_LOG_WITH_CORRECTION_MAX) { - int log_cnt = 0; - uint32_t y = 1; - int correction = 0; - const float v_f = (float)v; - const uint32_t orig_v = v; - do { - ++log_cnt; - v = v >> 1; - y = y << 1; - } while (v >= LOG_LOOKUP_IDX_MAX); - // vf = (2^log_cnt) * Xf; where y = 2^log_cnt and Xf < 256 - // Xf = floor(Xf) * (1 + (v % y) / v) - // log2(Xf) = log2(floor(Xf)) + log2(1 + (v % y) / v) - // The correction factor: log(1 + d) ~ d; for very small d values, so - // log2(1 + (v % y) / v) ~ LOG_2_RECIPROCAL * (v % y)/v - // LOG_2_RECIPROCAL ~ 23/16 - correction = (23 * (orig_v & (y - 1))) >> 4; - return v_f * (kLog2Table[v] + log_cnt) + correction; - } else { - return (float)(LOG_2_RECIPROCAL * v * log((double)v)); - } -} - -static float FastLog2Slow(uint32_t v) { - assert(v >= LOG_LOOKUP_IDX_MAX); - if (v < APPROX_LOG_WITH_CORRECTION_MAX) { - int log_cnt = 0; - uint32_t y = 1; - const uint32_t orig_v = v; - double log_2; - do { - ++log_cnt; - v = v >> 1; - y = y << 1; - } while (v >= LOG_LOOKUP_IDX_MAX); - log_2 = kLog2Table[v] + log_cnt; - if (orig_v >= APPROX_LOG_MAX) { - // Since the division is still expensive, add this correction factor only - // for large values of 'v'. - const int correction = (23 * (orig_v & (y - 1))) >> 4; - log_2 += (double)correction / orig_v; - } - return (float)log_2; - } else { - return (float)(LOG_2_RECIPROCAL * log((double)v)); - } -} - -// Mostly used to reduce code size + readability -static WEBP_INLINE int GetMin(int a, int b) { return (a > b) ? b : a; } - -//------------------------------------------------------------------------------ -// Methods to calculate Entropy (Shannon). - -static float PredictionCostSpatial(const int counts[256], int weight_0, - double exp_val) { - const int significant_symbols = 256 >> 4; - const double exp_decay_factor = 0.6; - double bits = weight_0 * counts[0]; - int i; - for (i = 1; i < significant_symbols; ++i) { - bits += exp_val * (counts[i] + counts[256 - i]); - exp_val *= exp_decay_factor; - } - return (float)(-0.1 * bits); -} - -// Compute the combined Shanon's entropy for distribution {X} and {X+Y} -static float CombinedShannonEntropy(const int X[256], const int Y[256]) { - int i; - double retval = 0.; - int sumX = 0, sumXY = 0; - for (i = 0; i < 256; ++i) { - const int x = X[i]; - if (x != 0) { - const int xy = x + Y[i]; - sumX += x; - retval -= VP8LFastSLog2(x); - sumXY += xy; - retval -= VP8LFastSLog2(xy); - } else if (Y[i] != 0) { - sumXY += Y[i]; - retval -= VP8LFastSLog2(Y[i]); - } - } - retval += VP8LFastSLog2(sumX) + VP8LFastSLog2(sumXY); - return (float)retval; -} - -static float PredictionCostSpatialHistogram(const int accumulated[4][256], - const int tile[4][256]) { - int i; - double retval = 0; - for (i = 0; i < 4; ++i) { - const double kExpValue = 0.94; - retval += PredictionCostSpatial(tile[i], 1, kExpValue); - retval += VP8LCombinedShannonEntropy(tile[i], accumulated[i]); - } - return (float)retval; -} - -void VP8LBitEntropyInit(VP8LBitEntropy* const entropy) { - entropy->entropy = 0.; - entropy->sum = 0; - entropy->nonzeros = 0; - entropy->max_val = 0; - entropy->nonzero_code = VP8L_NON_TRIVIAL_SYM; -} - -void VP8LBitsEntropyUnrefined(const uint32_t* const array, int n, - VP8LBitEntropy* const entropy) { - int i; - - VP8LBitEntropyInit(entropy); - - for (i = 0; i < n; ++i) { - if (array[i] != 0) { - entropy->sum += array[i]; - entropy->nonzero_code = i; - ++entropy->nonzeros; - entropy->entropy -= VP8LFastSLog2(array[i]); - if (entropy->max_val < array[i]) { - entropy->max_val = array[i]; - } - } - } - entropy->entropy += VP8LFastSLog2(entropy->sum); -} - -static WEBP_INLINE void GetEntropyUnrefinedHelper( - uint32_t val, int i, uint32_t* const val_prev, int* const i_prev, - VP8LBitEntropy* const bit_entropy, VP8LStreaks* const stats) { - const int streak = i - *i_prev; - - // Gather info for the bit entropy. - if (*val_prev != 0) { - bit_entropy->sum += (*val_prev) * streak; - bit_entropy->nonzeros += streak; - bit_entropy->nonzero_code = *i_prev; - bit_entropy->entropy -= VP8LFastSLog2(*val_prev) * streak; - if (bit_entropy->max_val < *val_prev) { - bit_entropy->max_val = *val_prev; - } - } - - // Gather info for the Huffman cost. - stats->counts[*val_prev != 0] += (streak > 3); - stats->streaks[*val_prev != 0][(streak > 3)] += streak; - - *val_prev = val; - *i_prev = i; -} - -void VP8LGetEntropyUnrefined(const uint32_t* const X, int length, - VP8LBitEntropy* const bit_entropy, - VP8LStreaks* const stats) { - int i; - int i_prev = 0; - uint32_t x_prev = X[0]; - - memset(stats, 0, sizeof(*stats)); - VP8LBitEntropyInit(bit_entropy); - - for (i = 1; i < length; ++i) { - const uint32_t x = X[i]; - if (x != x_prev) { - VP8LGetEntropyUnrefinedHelper(x, i, &x_prev, &i_prev, bit_entropy, stats); - } - } - VP8LGetEntropyUnrefinedHelper(0, i, &x_prev, &i_prev, bit_entropy, stats); - - bit_entropy->entropy += VP8LFastSLog2(bit_entropy->sum); -} - -void VP8LGetCombinedEntropyUnrefined(const uint32_t* const X, - const uint32_t* const Y, int length, - VP8LBitEntropy* const bit_entropy, - VP8LStreaks* const stats) { - int i = 1; - int i_prev = 0; - uint32_t xy_prev = X[0] + Y[0]; - - memset(stats, 0, sizeof(*stats)); - VP8LBitEntropyInit(bit_entropy); - - for (i = 1; i < length; ++i) { - const uint32_t xy = X[i] + Y[i]; - if (xy != xy_prev) { - VP8LGetEntropyUnrefinedHelper(xy, i, &xy_prev, &i_prev, bit_entropy, - stats); - } - } - VP8LGetEntropyUnrefinedHelper(0, i, &xy_prev, &i_prev, bit_entropy, stats); - - bit_entropy->entropy += VP8LFastSLog2(bit_entropy->sum); -} - -static WEBP_INLINE void UpdateHisto(int histo_argb[4][256], uint32_t argb) { - ++histo_argb[0][argb >> 24]; - ++histo_argb[1][(argb >> 16) & 0xff]; - ++histo_argb[2][(argb >> 8) & 0xff]; - ++histo_argb[3][argb & 0xff]; -} - -//------------------------------------------------------------------------------ - -static WEBP_INLINE uint32_t Predict(VP8LPredictorFunc pred_func, - int x, int y, - const uint32_t* current_row, - const uint32_t* upper_row) { - if (y == 0) { - return (x == 0) ? ARGB_BLACK : current_row[x - 1]; // Left. - } else if (x == 0) { - return upper_row[x]; // Top. - } else { - return pred_func(current_row[x - 1], upper_row + x); - } -} - -// Returns best predictor and updates the accumulated histogram. -static int GetBestPredictorForTile(int width, int height, - int tile_x, int tile_y, int bits, - int accumulated[4][256], - const uint32_t* const argb_scratch, - int exact) { - const int kNumPredModes = 14; - const int col_start = tile_x << bits; - const int row_start = tile_y << bits; - const int tile_size = 1 << bits; - const int max_y = GetMin(tile_size, height - row_start); - const int max_x = GetMin(tile_size, width - col_start); - float best_diff = MAX_DIFF_COST; - int best_mode = 0; - int mode; - int histo_stack_1[4][256]; - int histo_stack_2[4][256]; - // Need pointers to be able to swap arrays. - int (*histo_argb)[256] = histo_stack_1; - int (*best_histo)[256] = histo_stack_2; - - int i, j; - for (mode = 0; mode < kNumPredModes; ++mode) { - const uint32_t* current_row = argb_scratch; - const VP8LPredictorFunc pred_func = VP8LPredictors[mode]; - float cur_diff; - int y; - memset(histo_argb, 0, sizeof(histo_stack_1)); - for (y = 0; y < max_y; ++y) { - int x; - const int row = row_start + y; - const uint32_t* const upper_row = current_row; - current_row = upper_row + width; - for (x = 0; x < max_x; ++x) { - const int col = col_start + x; - const uint32_t predict = - Predict(pred_func, col, row, current_row, upper_row); - uint32_t residual = VP8LSubPixels(current_row[col], predict); - if (!exact && (current_row[col] & kMaskAlpha) == 0) { - residual &= kMaskAlpha; // See CopyTileWithPrediction. - } - UpdateHisto(histo_argb, residual); - } - } - cur_diff = PredictionCostSpatialHistogram( - (const int (*)[256])accumulated, (const int (*)[256])histo_argb); - if (cur_diff < best_diff) { - int (*tmp)[256] = histo_argb; - histo_argb = best_histo; - best_histo = tmp; - best_diff = cur_diff; - best_mode = mode; - } - } - - for (i = 0; i < 4; i++) { - for (j = 0; j < 256; j++) { - accumulated[i][j] += best_histo[i][j]; - } - } - - return best_mode; -} - -static void CopyImageWithPrediction(int width, int height, - int bits, uint32_t* const modes, - uint32_t* const argb_scratch, - uint32_t* const argb, - int low_effort, int exact) { - const int tiles_per_row = VP8LSubSampleSize(width, bits); - const int mask = (1 << bits) - 1; - // The row size is one pixel longer to allow the top right pixel to point to - // the leftmost pixel of the next row when at the right edge. - uint32_t* current_row = argb_scratch; - uint32_t* upper_row = argb_scratch + width + 1; - int y; - VP8LPredictorFunc pred_func = - low_effort ? VP8LPredictors[kPredLowEffort] : NULL; - - for (y = 0; y < height; ++y) { - int x; - uint32_t* tmp = upper_row; - upper_row = current_row; - current_row = tmp; - memcpy(current_row, argb + y * width, sizeof(*current_row) * width); - current_row[width] = (y + 1 < height) ? argb[(y + 1) * width] : ARGB_BLACK; - - if (low_effort) { - for (x = 0; x < width; ++x) { - const uint32_t predict = - Predict(pred_func, x, y, current_row, upper_row); - argb[y * width + x] = VP8LSubPixels(current_row[x], predict); - } - } else { - for (x = 0; x < width; ++x) { - uint32_t predict, residual; - if ((x & mask) == 0) { - const int mode = - (modes[(y >> bits) * tiles_per_row + (x >> bits)] >> 8) & 0xff; - pred_func = VP8LPredictors[mode]; - } - predict = Predict(pred_func, x, y, current_row, upper_row); - residual = VP8LSubPixels(current_row[x], predict); - if (!exact && (current_row[x] & kMaskAlpha) == 0) { - // If alpha is 0, cleanup RGB. We can choose the RGB values of the - // residual for best compression. The prediction of alpha itself can - // be non-zero and must be kept though. We choose RGB of the residual - // to be 0. - residual &= kMaskAlpha; - // Update input image so that next predictions use correct RGB value. - current_row[x] = predict & ~kMaskAlpha; - if (x == 0 && y != 0) upper_row[width] = current_row[x]; - } - argb[y * width + x] = residual; - } - } - } -} - -void VP8LResidualImage(int width, int height, int bits, int low_effort, - uint32_t* const argb, uint32_t* const argb_scratch, - uint32_t* const image, int exact) { - const int max_tile_size = 1 << bits; - const int tiles_per_row = VP8LSubSampleSize(width, bits); - const int tiles_per_col = VP8LSubSampleSize(height, bits); - uint32_t* const upper_row = argb_scratch; - uint32_t* const current_tile_rows = argb_scratch + width; - int tile_y; - int histo[4][256]; - if (low_effort) { - int i; - for (i = 0; i < tiles_per_row * tiles_per_col; ++i) { - image[i] = ARGB_BLACK | (kPredLowEffort << 8); - } - } else { - memset(histo, 0, sizeof(histo)); - for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) { - const int tile_y_offset = tile_y * max_tile_size; - const int this_tile_height = - (tile_y < tiles_per_col - 1) ? max_tile_size : height - tile_y_offset; - int tile_x; - if (tile_y > 0) { - memcpy(upper_row, current_tile_rows + (max_tile_size - 1) * width, - width * sizeof(*upper_row)); - } - memcpy(current_tile_rows, &argb[tile_y_offset * width], - this_tile_height * width * sizeof(*current_tile_rows)); - for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) { - const int pred = GetBestPredictorForTile(width, height, tile_x, tile_y, - bits, (int (*)[256])histo, argb_scratch, exact); - image[tile_y * tiles_per_row + tile_x] = ARGB_BLACK | (pred << 8); - } - } - } - - CopyImageWithPrediction(width, height, bits, - image, argb_scratch, argb, low_effort, exact); -} - -void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels) { - int i; - for (i = 0; i < num_pixels; ++i) { - const uint32_t argb = argb_data[i]; - const uint32_t green = (argb >> 8) & 0xff; - const uint32_t new_r = (((argb >> 16) & 0xff) - green) & 0xff; - const uint32_t new_b = ((argb & 0xff) - green) & 0xff; - argb_data[i] = (argb & 0xff00ff00) | (new_r << 16) | new_b; - } -} - -static WEBP_INLINE void MultipliersClear(VP8LMultipliers* const m) { - m->green_to_red_ = 0; - m->green_to_blue_ = 0; - m->red_to_blue_ = 0; -} - -static WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred, - int8_t color) { - return (uint32_t)((int)(color_pred) * color) >> 5; -} - -static WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code, - VP8LMultipliers* const m) { - m->green_to_red_ = (color_code >> 0) & 0xff; - m->green_to_blue_ = (color_code >> 8) & 0xff; - m->red_to_blue_ = (color_code >> 16) & 0xff; -} - -static WEBP_INLINE uint32_t MultipliersToColorCode( - const VP8LMultipliers* const m) { - return 0xff000000u | - ((uint32_t)(m->red_to_blue_) << 16) | - ((uint32_t)(m->green_to_blue_) << 8) | - m->green_to_red_; -} - -void VP8LTransformColor_C(const VP8LMultipliers* const m, uint32_t* data, - int num_pixels) { - int i; - for (i = 0; i < num_pixels; ++i) { - const uint32_t argb = data[i]; - const uint32_t green = argb >> 8; - const uint32_t red = argb >> 16; - uint32_t new_red = red; - uint32_t new_blue = argb; - new_red -= ColorTransformDelta(m->green_to_red_, green); - new_red &= 0xff; - new_blue -= ColorTransformDelta(m->green_to_blue_, green); - new_blue -= ColorTransformDelta(m->red_to_blue_, red); - new_blue &= 0xff; - data[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue); - } -} - -static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red, - uint32_t argb) { - const uint32_t green = argb >> 8; - uint32_t new_red = argb >> 16; - new_red -= ColorTransformDelta(green_to_red, green); - return (new_red & 0xff); -} - -static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue, - uint8_t red_to_blue, - uint32_t argb) { - const uint32_t green = argb >> 8; - const uint32_t red = argb >> 16; - uint8_t new_blue = argb; - new_blue -= ColorTransformDelta(green_to_blue, green); - new_blue -= ColorTransformDelta(red_to_blue, red); - return (new_blue & 0xff); -} - -static float PredictionCostCrossColor(const int accumulated[256], - const int counts[256]) { - // Favor low entropy, locally and globally. - // Favor small absolute values for PredictionCostSpatial - static const double kExpValue = 2.4; - return VP8LCombinedShannonEntropy(counts, accumulated) + - PredictionCostSpatial(counts, 3, kExpValue); -} - -void VP8LCollectColorRedTransforms_C(const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_red, int histo[]) { - while (tile_height-- > 0) { - int x; - for (x = 0; x < tile_width; ++x) { - ++histo[TransformColorRed(green_to_red, argb[x])]; - } - argb += stride; - } -} - -static float GetPredictionCostCrossColorRed( - const uint32_t* argb, int stride, int tile_width, int tile_height, - VP8LMultipliers prev_x, VP8LMultipliers prev_y, int green_to_red, - const int accumulated_red_histo[256]) { - int histo[256] = { 0 }; - float cur_diff; - - VP8LCollectColorRedTransforms(argb, stride, tile_width, tile_height, - green_to_red, histo); - - cur_diff = PredictionCostCrossColor(accumulated_red_histo, histo); - if ((uint8_t)green_to_red == prev_x.green_to_red_) { - cur_diff -= 3; // favor keeping the areas locally similar - } - if ((uint8_t)green_to_red == prev_y.green_to_red_) { - cur_diff -= 3; // favor keeping the areas locally similar - } - if (green_to_red == 0) { - cur_diff -= 3; - } - return cur_diff; -} - -static void GetBestGreenToRed( - const uint32_t* argb, int stride, int tile_width, int tile_height, - VP8LMultipliers prev_x, VP8LMultipliers prev_y, int quality, - const int accumulated_red_histo[256], VP8LMultipliers* const best_tx) { - const int kMaxIters = 4 + ((7 * quality) >> 8); // in range [4..6] - int green_to_red_best = 0; - int iter, offset; - float best_diff = GetPredictionCostCrossColorRed( - argb, stride, tile_width, tile_height, prev_x, prev_y, - green_to_red_best, accumulated_red_histo); - for (iter = 0; iter < kMaxIters; ++iter) { - // ColorTransformDelta is a 3.5 bit fixed point, so 32 is equal to - // one in color computation. Having initial delta here as 1 is sufficient - // to explore the range of (-2, 2). - const int delta = 32 >> iter; - // Try a negative and a positive delta from the best known value. - for (offset = -delta; offset <= delta; offset += 2 * delta) { - const int green_to_red_cur = offset + green_to_red_best; - const float cur_diff = GetPredictionCostCrossColorRed( - argb, stride, tile_width, tile_height, prev_x, prev_y, - green_to_red_cur, accumulated_red_histo); - if (cur_diff < best_diff) { - best_diff = cur_diff; - green_to_red_best = green_to_red_cur; - } - } - } - best_tx->green_to_red_ = green_to_red_best; -} - -void VP8LCollectColorBlueTransforms_C(const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_blue, int red_to_blue, - int histo[]) { - while (tile_height-- > 0) { - int x; - for (x = 0; x < tile_width; ++x) { - ++histo[TransformColorBlue(green_to_blue, red_to_blue, argb[x])]; - } - argb += stride; - } -} - -static float GetPredictionCostCrossColorBlue( - const uint32_t* argb, int stride, int tile_width, int tile_height, - VP8LMultipliers prev_x, VP8LMultipliers prev_y, - int green_to_blue, int red_to_blue, const int accumulated_blue_histo[256]) { - int histo[256] = { 0 }; - float cur_diff; - - VP8LCollectColorBlueTransforms(argb, stride, tile_width, tile_height, - green_to_blue, red_to_blue, histo); - - cur_diff = PredictionCostCrossColor(accumulated_blue_histo, histo); - if ((uint8_t)green_to_blue == prev_x.green_to_blue_) { - cur_diff -= 3; // favor keeping the areas locally similar - } - if ((uint8_t)green_to_blue == prev_y.green_to_blue_) { - cur_diff -= 3; // favor keeping the areas locally similar - } - if ((uint8_t)red_to_blue == prev_x.red_to_blue_) { - cur_diff -= 3; // favor keeping the areas locally similar - } - if ((uint8_t)red_to_blue == prev_y.red_to_blue_) { - cur_diff -= 3; // favor keeping the areas locally similar - } - if (green_to_blue == 0) { - cur_diff -= 3; - } - if (red_to_blue == 0) { - cur_diff -= 3; - } - return cur_diff; -} - -#define kGreenRedToBlueNumAxis 8 -#define kGreenRedToBlueMaxIters 7 -static void GetBestGreenRedToBlue( - const uint32_t* argb, int stride, int tile_width, int tile_height, - VP8LMultipliers prev_x, VP8LMultipliers prev_y, int quality, - const int accumulated_blue_histo[256], - VP8LMultipliers* const best_tx) { - const int8_t offset[kGreenRedToBlueNumAxis][2] = - {{0, -1}, {0, 1}, {-1, 0}, {1, 0}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}}; - const int8_t delta_lut[kGreenRedToBlueMaxIters] = { 16, 16, 8, 4, 2, 2, 2 }; - const int iters = - (quality < 25) ? 1 : (quality > 50) ? kGreenRedToBlueMaxIters : 4; - int green_to_blue_best = 0; - int red_to_blue_best = 0; - int iter; - // Initial value at origin: - float best_diff = GetPredictionCostCrossColorBlue( - argb, stride, tile_width, tile_height, prev_x, prev_y, - green_to_blue_best, red_to_blue_best, accumulated_blue_histo); - for (iter = 0; iter < iters; ++iter) { - const int delta = delta_lut[iter]; - int axis; - for (axis = 0; axis < kGreenRedToBlueNumAxis; ++axis) { - const int green_to_blue_cur = - offset[axis][0] * delta + green_to_blue_best; - const int red_to_blue_cur = offset[axis][1] * delta + red_to_blue_best; - const float cur_diff = GetPredictionCostCrossColorBlue( - argb, stride, tile_width, tile_height, prev_x, prev_y, - green_to_blue_cur, red_to_blue_cur, accumulated_blue_histo); - if (cur_diff < best_diff) { - best_diff = cur_diff; - green_to_blue_best = green_to_blue_cur; - red_to_blue_best = red_to_blue_cur; - } - if (quality < 25 && iter == 4) { - // Only axis aligned diffs for lower quality. - break; // next iter. - } - } - if (delta == 2 && green_to_blue_best == 0 && red_to_blue_best == 0) { - // Further iterations would not help. - break; // out of iter-loop. - } - } - best_tx->green_to_blue_ = green_to_blue_best; - best_tx->red_to_blue_ = red_to_blue_best; -} -#undef kGreenRedToBlueMaxIters -#undef kGreenRedToBlueNumAxis - -static VP8LMultipliers GetBestColorTransformForTile( - int tile_x, int tile_y, int bits, - VP8LMultipliers prev_x, - VP8LMultipliers prev_y, - int quality, int xsize, int ysize, - const int accumulated_red_histo[256], - const int accumulated_blue_histo[256], - const uint32_t* const argb) { - const int max_tile_size = 1 << bits; - const int tile_y_offset = tile_y * max_tile_size; - const int tile_x_offset = tile_x * max_tile_size; - const int all_x_max = GetMin(tile_x_offset + max_tile_size, xsize); - const int all_y_max = GetMin(tile_y_offset + max_tile_size, ysize); - const int tile_width = all_x_max - tile_x_offset; - const int tile_height = all_y_max - tile_y_offset; - const uint32_t* const tile_argb = argb + tile_y_offset * xsize - + tile_x_offset; - VP8LMultipliers best_tx; - MultipliersClear(&best_tx); - - GetBestGreenToRed(tile_argb, xsize, tile_width, tile_height, - prev_x, prev_y, quality, accumulated_red_histo, &best_tx); - GetBestGreenRedToBlue(tile_argb, xsize, tile_width, tile_height, - prev_x, prev_y, quality, accumulated_blue_histo, - &best_tx); - return best_tx; -} - -static void CopyTileWithColorTransform(int xsize, int ysize, - int tile_x, int tile_y, - int max_tile_size, - VP8LMultipliers color_transform, - uint32_t* argb) { - const int xscan = GetMin(max_tile_size, xsize - tile_x); - int yscan = GetMin(max_tile_size, ysize - tile_y); - argb += tile_y * xsize + tile_x; - while (yscan-- > 0) { - VP8LTransformColor(&color_transform, argb, xscan); - argb += xsize; - } -} - -void VP8LColorSpaceTransform(int width, int height, int bits, int quality, - uint32_t* const argb, uint32_t* image) { - const int max_tile_size = 1 << bits; - const int tile_xsize = VP8LSubSampleSize(width, bits); - const int tile_ysize = VP8LSubSampleSize(height, bits); - int accumulated_red_histo[256] = { 0 }; - int accumulated_blue_histo[256] = { 0 }; - int tile_x, tile_y; - VP8LMultipliers prev_x, prev_y; - MultipliersClear(&prev_y); - MultipliersClear(&prev_x); - for (tile_y = 0; tile_y < tile_ysize; ++tile_y) { - for (tile_x = 0; tile_x < tile_xsize; ++tile_x) { - int y; - const int tile_x_offset = tile_x * max_tile_size; - const int tile_y_offset = tile_y * max_tile_size; - const int all_x_max = GetMin(tile_x_offset + max_tile_size, width); - const int all_y_max = GetMin(tile_y_offset + max_tile_size, height); - const int offset = tile_y * tile_xsize + tile_x; - if (tile_y != 0) { - ColorCodeToMultipliers(image[offset - tile_xsize], &prev_y); - } - prev_x = GetBestColorTransformForTile(tile_x, tile_y, bits, - prev_x, prev_y, - quality, width, height, - accumulated_red_histo, - accumulated_blue_histo, - argb); - image[offset] = MultipliersToColorCode(&prev_x); - CopyTileWithColorTransform(width, height, tile_x_offset, tile_y_offset, - max_tile_size, prev_x, argb); - - // Gather accumulated histogram data. - for (y = tile_y_offset; y < all_y_max; ++y) { - int ix = y * width + tile_x_offset; - const int ix_end = ix + all_x_max - tile_x_offset; - for (; ix < ix_end; ++ix) { - const uint32_t pix = argb[ix]; - if (ix >= 2 && - pix == argb[ix - 2] && - pix == argb[ix - 1]) { - continue; // repeated pixels are handled by backward references - } - if (ix >= width + 2 && - argb[ix - 2] == argb[ix - width - 2] && - argb[ix - 1] == argb[ix - width - 1] && - pix == argb[ix - width]) { - continue; // repeated pixels are handled by backward references - } - ++accumulated_red_histo[(pix >> 16) & 0xff]; - ++accumulated_blue_histo[(pix >> 0) & 0xff]; - } - } - } - } -} - -//------------------------------------------------------------------------------ -// Bundles multiple (1, 2, 4 or 8) pixels into a single pixel. -void VP8LBundleColorMap(const uint8_t* const row, int width, - int xbits, uint32_t* const dst) { - int x; - if (xbits > 0) { - const int bit_depth = 1 << (3 - xbits); - const int mask = (1 << xbits) - 1; - uint32_t code = 0xff000000; - for (x = 0; x < width; ++x) { - const int xsub = x & mask; - if (xsub == 0) { - code = 0xff000000; - } - code |= row[x] << (8 + bit_depth * xsub); - dst[x >> xbits] = code; - } - } else { - for (x = 0; x < width; ++x) dst[x] = 0xff000000 | (row[x] << 8); - } -} - -//------------------------------------------------------------------------------ - -static double ExtraCost(const uint32_t* population, int length) { - int i; - double cost = 0.; - for (i = 2; i < length - 2; ++i) cost += (i >> 1) * population[i + 2]; - return cost; -} - -static double ExtraCostCombined(const uint32_t* X, const uint32_t* Y, - int length) { - int i; - double cost = 0.; - for (i = 2; i < length - 2; ++i) { - const int xy = X[i + 2] + Y[i + 2]; - cost += (i >> 1) * xy; - } - return cost; -} - -//------------------------------------------------------------------------------ - -static void HistogramAdd(const VP8LHistogram* const a, - const VP8LHistogram* const b, - VP8LHistogram* const out) { - int i; - const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_); - assert(a->palette_code_bits_ == b->palette_code_bits_); - if (b != out) { - for (i = 0; i < literal_size; ++i) { - out->literal_[i] = a->literal_[i] + b->literal_[i]; - } - for (i = 0; i < NUM_DISTANCE_CODES; ++i) { - out->distance_[i] = a->distance_[i] + b->distance_[i]; - } - for (i = 0; i < NUM_LITERAL_CODES; ++i) { - out->red_[i] = a->red_[i] + b->red_[i]; - out->blue_[i] = a->blue_[i] + b->blue_[i]; - out->alpha_[i] = a->alpha_[i] + b->alpha_[i]; - } - } else { - for (i = 0; i < literal_size; ++i) { - out->literal_[i] += a->literal_[i]; - } - for (i = 0; i < NUM_DISTANCE_CODES; ++i) { - out->distance_[i] += a->distance_[i]; - } - for (i = 0; i < NUM_LITERAL_CODES; ++i) { - out->red_[i] += a->red_[i]; - out->blue_[i] += a->blue_[i]; - out->alpha_[i] += a->alpha_[i]; - } - } -} - -//------------------------------------------------------------------------------ - -VP8LProcessBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed; - -VP8LTransformColorFunc VP8LTransformColor; - -VP8LCollectColorBlueTransformsFunc VP8LCollectColorBlueTransforms; -VP8LCollectColorRedTransformsFunc VP8LCollectColorRedTransforms; - -VP8LFastLog2SlowFunc VP8LFastLog2Slow; -VP8LFastLog2SlowFunc VP8LFastSLog2Slow; - -VP8LCostFunc VP8LExtraCost; -VP8LCostCombinedFunc VP8LExtraCostCombined; -VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy; - -GetEntropyUnrefinedHelperFunc VP8LGetEntropyUnrefinedHelper; - -VP8LHistogramAddFunc VP8LHistogramAdd; - -extern void VP8LEncDspInitSSE2(void); -extern void VP8LEncDspInitSSE41(void); -extern void VP8LEncDspInitNEON(void); -extern void VP8LEncDspInitMIPS32(void); -extern void VP8LEncDspInitMIPSdspR2(void); - -static volatile VP8CPUInfo lossless_enc_last_cpuinfo_used = - (VP8CPUInfo)&lossless_enc_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInit(void) { - if (lossless_enc_last_cpuinfo_used == VP8GetCPUInfo) return; - - VP8LDspInit(); - - VP8LSubtractGreenFromBlueAndRed = VP8LSubtractGreenFromBlueAndRed_C; - - VP8LTransformColor = VP8LTransformColor_C; - - VP8LCollectColorBlueTransforms = VP8LCollectColorBlueTransforms_C; - VP8LCollectColorRedTransforms = VP8LCollectColorRedTransforms_C; - - VP8LFastLog2Slow = FastLog2Slow; - VP8LFastSLog2Slow = FastSLog2Slow; - - VP8LExtraCost = ExtraCost; - VP8LExtraCostCombined = ExtraCostCombined; - VP8LCombinedShannonEntropy = CombinedShannonEntropy; - - VP8LGetEntropyUnrefinedHelper = GetEntropyUnrefinedHelper; - - VP8LHistogramAdd = HistogramAdd; - - // If defined, use CPUInfo() to overwrite some pointers with faster versions. - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - VP8LEncDspInitSSE2(); -#if defined(WEBP_USE_SSE41) - if (VP8GetCPUInfo(kSSE4_1)) { - VP8LEncDspInitSSE41(); - } -#endif - } -#endif -#if defined(WEBP_USE_NEON) - if (VP8GetCPUInfo(kNEON)) { - VP8LEncDspInitNEON(); - } -#endif -#if defined(WEBP_USE_MIPS32) - if (VP8GetCPUInfo(kMIPS32)) { - VP8LEncDspInitMIPS32(); - } -#endif -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - VP8LEncDspInitMIPSdspR2(); - } -#endif - } - lossless_enc_last_cpuinfo_used = VP8GetCPUInfo; -} - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/dsp/lossless_enc_mips32.c b/Example/Pods/libwebp/src/dsp/lossless_enc_mips32.c deleted file mode 100644 index 49c666d4..00000000 --- a/Example/Pods/libwebp/src/dsp/lossless_enc_mips32.c +++ /dev/null @@ -1,386 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// MIPS version of lossless functions -// -// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) -// Jovan Zelincevic (jovan.zelincevic@imgtec.com) - -#include "./dsp.h" -#include "./lossless.h" - -#if defined(WEBP_USE_MIPS32) - -#include -#include -#include -#include - -static float FastSLog2Slow(uint32_t v) { - assert(v >= LOG_LOOKUP_IDX_MAX); - if (v < APPROX_LOG_WITH_CORRECTION_MAX) { - uint32_t log_cnt, y, correction; - const int c24 = 24; - const float v_f = (float)v; - uint32_t temp; - - // Xf = 256 = 2^8 - // log_cnt is index of leading one in upper 24 bits - __asm__ volatile( - "clz %[log_cnt], %[v] \n\t" - "addiu %[y], $zero, 1 \n\t" - "subu %[log_cnt], %[c24], %[log_cnt] \n\t" - "sllv %[y], %[y], %[log_cnt] \n\t" - "srlv %[temp], %[v], %[log_cnt] \n\t" - : [log_cnt]"=&r"(log_cnt), [y]"=&r"(y), - [temp]"=r"(temp) - : [c24]"r"(c24), [v]"r"(v) - ); - - // vf = (2^log_cnt) * Xf; where y = 2^log_cnt and Xf < 256 - // Xf = floor(Xf) * (1 + (v % y) / v) - // log2(Xf) = log2(floor(Xf)) + log2(1 + (v % y) / v) - // The correction factor: log(1 + d) ~ d; for very small d values, so - // log2(1 + (v % y) / v) ~ LOG_2_RECIPROCAL * (v % y)/v - // LOG_2_RECIPROCAL ~ 23/16 - - // (v % y) = (v % 2^log_cnt) = v & (2^log_cnt - 1) - correction = (23 * (v & (y - 1))) >> 4; - return v_f * (kLog2Table[temp] + log_cnt) + correction; - } else { - return (float)(LOG_2_RECIPROCAL * v * log((double)v)); - } -} - -static float FastLog2Slow(uint32_t v) { - assert(v >= LOG_LOOKUP_IDX_MAX); - if (v < APPROX_LOG_WITH_CORRECTION_MAX) { - uint32_t log_cnt, y; - const int c24 = 24; - double log_2; - uint32_t temp; - - __asm__ volatile( - "clz %[log_cnt], %[v] \n\t" - "addiu %[y], $zero, 1 \n\t" - "subu %[log_cnt], %[c24], %[log_cnt] \n\t" - "sllv %[y], %[y], %[log_cnt] \n\t" - "srlv %[temp], %[v], %[log_cnt] \n\t" - : [log_cnt]"=&r"(log_cnt), [y]"=&r"(y), - [temp]"=r"(temp) - : [c24]"r"(c24), [v]"r"(v) - ); - - log_2 = kLog2Table[temp] + log_cnt; - if (v >= APPROX_LOG_MAX) { - // Since the division is still expensive, add this correction factor only - // for large values of 'v'. - - const uint32_t correction = (23 * (v & (y - 1))) >> 4; - log_2 += (double)correction / v; - } - return (float)log_2; - } else { - return (float)(LOG_2_RECIPROCAL * log((double)v)); - } -} - -// C version of this function: -// int i = 0; -// int64_t cost = 0; -// const uint32_t* pop = &population[4]; -// const uint32_t* LoopEnd = &population[length]; -// while (pop != LoopEnd) { -// ++i; -// cost += i * *pop; -// cost += i * *(pop + 1); -// pop += 2; -// } -// return (double)cost; -static double ExtraCost(const uint32_t* const population, int length) { - int i, temp0, temp1; - const uint32_t* pop = &population[4]; - const uint32_t* const LoopEnd = &population[length]; - - __asm__ volatile( - "mult $zero, $zero \n\t" - "xor %[i], %[i], %[i] \n\t" - "beq %[pop], %[LoopEnd], 2f \n\t" - "1: \n\t" - "lw %[temp0], 0(%[pop]) \n\t" - "lw %[temp1], 4(%[pop]) \n\t" - "addiu %[i], %[i], 1 \n\t" - "addiu %[pop], %[pop], 8 \n\t" - "madd %[i], %[temp0] \n\t" - "madd %[i], %[temp1] \n\t" - "bne %[pop], %[LoopEnd], 1b \n\t" - "2: \n\t" - "mfhi %[temp0] \n\t" - "mflo %[temp1] \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), - [i]"=&r"(i), [pop]"+r"(pop) - : [LoopEnd]"r"(LoopEnd) - : "memory", "hi", "lo" - ); - - return (double)((int64_t)temp0 << 32 | temp1); -} - -// C version of this function: -// int i = 0; -// int64_t cost = 0; -// const uint32_t* pX = &X[4]; -// const uint32_t* pY = &Y[4]; -// const uint32_t* LoopEnd = &X[length]; -// while (pX != LoopEnd) { -// const uint32_t xy0 = *pX + *pY; -// const uint32_t xy1 = *(pX + 1) + *(pY + 1); -// ++i; -// cost += i * xy0; -// cost += i * xy1; -// pX += 2; -// pY += 2; -// } -// return (double)cost; -static double ExtraCostCombined(const uint32_t* const X, - const uint32_t* const Y, int length) { - int i, temp0, temp1, temp2, temp3; - const uint32_t* pX = &X[4]; - const uint32_t* pY = &Y[4]; - const uint32_t* const LoopEnd = &X[length]; - - __asm__ volatile( - "mult $zero, $zero \n\t" - "xor %[i], %[i], %[i] \n\t" - "beq %[pX], %[LoopEnd], 2f \n\t" - "1: \n\t" - "lw %[temp0], 0(%[pX]) \n\t" - "lw %[temp1], 0(%[pY]) \n\t" - "lw %[temp2], 4(%[pX]) \n\t" - "lw %[temp3], 4(%[pY]) \n\t" - "addiu %[i], %[i], 1 \n\t" - "addu %[temp0], %[temp0], %[temp1] \n\t" - "addu %[temp2], %[temp2], %[temp3] \n\t" - "addiu %[pX], %[pX], 8 \n\t" - "addiu %[pY], %[pY], 8 \n\t" - "madd %[i], %[temp0] \n\t" - "madd %[i], %[temp2] \n\t" - "bne %[pX], %[LoopEnd], 1b \n\t" - "2: \n\t" - "mfhi %[temp0] \n\t" - "mflo %[temp1] \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), - [i]"=&r"(i), [pX]"+r"(pX), [pY]"+r"(pY) - : [LoopEnd]"r"(LoopEnd) - : "memory", "hi", "lo" - ); - - return (double)((int64_t)temp0 << 32 | temp1); -} - -#define HUFFMAN_COST_PASS \ - __asm__ volatile( \ - "sll %[temp1], %[temp0], 3 \n\t" \ - "addiu %[temp3], %[streak], -3 \n\t" \ - "addu %[temp2], %[pstreaks], %[temp1] \n\t" \ - "blez %[temp3], 1f \n\t" \ - "srl %[temp1], %[temp1], 1 \n\t" \ - "addu %[temp3], %[pcnts], %[temp1] \n\t" \ - "lw %[temp0], 4(%[temp2]) \n\t" \ - "lw %[temp1], 0(%[temp3]) \n\t" \ - "addu %[temp0], %[temp0], %[streak] \n\t" \ - "addiu %[temp1], %[temp1], 1 \n\t" \ - "sw %[temp0], 4(%[temp2]) \n\t" \ - "sw %[temp1], 0(%[temp3]) \n\t" \ - "b 2f \n\t" \ - "1: \n\t" \ - "lw %[temp0], 0(%[temp2]) \n\t" \ - "addu %[temp0], %[temp0], %[streak] \n\t" \ - "sw %[temp0], 0(%[temp2]) \n\t" \ - "2: \n\t" \ - : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \ - [temp3]"=&r"(temp3), [temp0]"+r"(temp0) \ - : [pstreaks]"r"(pstreaks), [pcnts]"r"(pcnts), \ - [streak]"r"(streak) \ - : "memory" \ - ); - -// Returns the various RLE counts -static WEBP_INLINE void GetEntropyUnrefinedHelper( - uint32_t val, int i, uint32_t* const val_prev, int* const i_prev, - VP8LBitEntropy* const bit_entropy, VP8LStreaks* const stats) { - int* const pstreaks = &stats->streaks[0][0]; - int* const pcnts = &stats->counts[0]; - int temp0, temp1, temp2, temp3; - const int streak = i - *i_prev; - - // Gather info for the bit entropy. - if (*val_prev != 0) { - bit_entropy->sum += (*val_prev) * streak; - bit_entropy->nonzeros += streak; - bit_entropy->nonzero_code = *i_prev; - bit_entropy->entropy -= VP8LFastSLog2(*val_prev) * streak; - if (bit_entropy->max_val < *val_prev) { - bit_entropy->max_val = *val_prev; - } - } - - // Gather info for the Huffman cost. - temp0 = (*val_prev != 0); - HUFFMAN_COST_PASS - - *val_prev = val; - *i_prev = i; -} - -#define ASM_START \ - __asm__ volatile( \ - ".set push \n\t" \ - ".set at \n\t" \ - ".set macro \n\t" \ - "1: \n\t" - -// P2 = P0 + P1 -// A..D - offsets -// E - temp variable to tell macro -// if pointer should be incremented -// literal_ and successive histograms could be unaligned -// so we must use ulw and usw -#define ADD_TO_OUT(A, B, C, D, E, P0, P1, P2) \ - "ulw %[temp0], " #A "(%[" #P0 "]) \n\t" \ - "ulw %[temp1], " #B "(%[" #P0 "]) \n\t" \ - "ulw %[temp2], " #C "(%[" #P0 "]) \n\t" \ - "ulw %[temp3], " #D "(%[" #P0 "]) \n\t" \ - "ulw %[temp4], " #A "(%[" #P1 "]) \n\t" \ - "ulw %[temp5], " #B "(%[" #P1 "]) \n\t" \ - "ulw %[temp6], " #C "(%[" #P1 "]) \n\t" \ - "ulw %[temp7], " #D "(%[" #P1 "]) \n\t" \ - "addu %[temp4], %[temp4], %[temp0] \n\t" \ - "addu %[temp5], %[temp5], %[temp1] \n\t" \ - "addu %[temp6], %[temp6], %[temp2] \n\t" \ - "addu %[temp7], %[temp7], %[temp3] \n\t" \ - "addiu %[" #P0 "], %[" #P0 "], 16 \n\t" \ - ".if " #E " == 1 \n\t" \ - "addiu %[" #P1 "], %[" #P1 "], 16 \n\t" \ - ".endif \n\t" \ - "usw %[temp4], " #A "(%[" #P2 "]) \n\t" \ - "usw %[temp5], " #B "(%[" #P2 "]) \n\t" \ - "usw %[temp6], " #C "(%[" #P2 "]) \n\t" \ - "usw %[temp7], " #D "(%[" #P2 "]) \n\t" \ - "addiu %[" #P2 "], %[" #P2 "], 16 \n\t" \ - "bne %[" #P0 "], %[LoopEnd], 1b \n\t" \ - ".set pop \n\t" \ - -#define ASM_END_COMMON_0 \ - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), \ - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), \ - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \ - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), \ - [pa]"+r"(pa), [pout]"+r"(pout) - -#define ASM_END_COMMON_1 \ - : [LoopEnd]"r"(LoopEnd) \ - : "memory", "at" \ - ); - -#define ASM_END_0 \ - ASM_END_COMMON_0 \ - , [pb]"+r"(pb) \ - ASM_END_COMMON_1 - -#define ASM_END_1 \ - ASM_END_COMMON_0 \ - ASM_END_COMMON_1 - -#define ADD_VECTOR(A, B, OUT, SIZE, EXTRA_SIZE) do { \ - const uint32_t* pa = (const uint32_t*)(A); \ - const uint32_t* pb = (const uint32_t*)(B); \ - uint32_t* pout = (uint32_t*)(OUT); \ - const uint32_t* const LoopEnd = pa + (SIZE); \ - assert((SIZE) % 4 == 0); \ - ASM_START \ - ADD_TO_OUT(0, 4, 8, 12, 1, pa, pb, pout) \ - ASM_END_0 \ - if ((EXTRA_SIZE) > 0) { \ - const int last = (EXTRA_SIZE); \ - int i; \ - for (i = 0; i < last; ++i) pout[i] = pa[i] + pb[i]; \ - } \ -} while (0) - -#define ADD_VECTOR_EQ(A, OUT, SIZE, EXTRA_SIZE) do { \ - const uint32_t* pa = (const uint32_t*)(A); \ - uint32_t* pout = (uint32_t*)(OUT); \ - const uint32_t* const LoopEnd = pa + (SIZE); \ - assert((SIZE) % 4 == 0); \ - ASM_START \ - ADD_TO_OUT(0, 4, 8, 12, 0, pa, pout, pout) \ - ASM_END_1 \ - if ((EXTRA_SIZE) > 0) { \ - const int last = (EXTRA_SIZE); \ - int i; \ - for (i = 0; i < last; ++i) pout[i] += pa[i]; \ - } \ -} while (0) - -static void HistogramAdd(const VP8LHistogram* const a, - const VP8LHistogram* const b, - VP8LHistogram* const out) { - uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; - const int extra_cache_size = VP8LHistogramNumCodes(a->palette_code_bits_) - - (NUM_LITERAL_CODES + NUM_LENGTH_CODES); - assert(a->palette_code_bits_ == b->palette_code_bits_); - - if (b != out) { - ADD_VECTOR(a->literal_, b->literal_, out->literal_, - NUM_LITERAL_CODES + NUM_LENGTH_CODES, extra_cache_size); - ADD_VECTOR(a->distance_, b->distance_, out->distance_, - NUM_DISTANCE_CODES, 0); - ADD_VECTOR(a->red_, b->red_, out->red_, NUM_LITERAL_CODES, 0); - ADD_VECTOR(a->blue_, b->blue_, out->blue_, NUM_LITERAL_CODES, 0); - ADD_VECTOR(a->alpha_, b->alpha_, out->alpha_, NUM_LITERAL_CODES, 0); - } else { - ADD_VECTOR_EQ(a->literal_, out->literal_, - NUM_LITERAL_CODES + NUM_LENGTH_CODES, extra_cache_size); - ADD_VECTOR_EQ(a->distance_, out->distance_, NUM_DISTANCE_CODES, 0); - ADD_VECTOR_EQ(a->red_, out->red_, NUM_LITERAL_CODES, 0); - ADD_VECTOR_EQ(a->blue_, out->blue_, NUM_LITERAL_CODES, 0); - ADD_VECTOR_EQ(a->alpha_, out->alpha_, NUM_LITERAL_CODES, 0); - } -} - -#undef ADD_VECTOR_EQ -#undef ADD_VECTOR -#undef ASM_END_1 -#undef ASM_END_0 -#undef ASM_END_COMMON_1 -#undef ASM_END_COMMON_0 -#undef ADD_TO_OUT -#undef ASM_START - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8LEncDspInitMIPS32(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMIPS32(void) { - VP8LFastSLog2Slow = FastSLog2Slow; - VP8LFastLog2Slow = FastLog2Slow; - VP8LExtraCost = ExtraCost; - VP8LExtraCostCombined = ExtraCostCombined; - VP8LGetEntropyUnrefinedHelper = GetEntropyUnrefinedHelper; - VP8LHistogramAdd = HistogramAdd; -} - -#else // !WEBP_USE_MIPS32 - -WEBP_DSP_INIT_STUB(VP8LEncDspInitMIPS32) - -#endif // WEBP_USE_MIPS32 diff --git a/Example/Pods/libwebp/src/dsp/lossless_enc_mips_dsp_r2.c b/Example/Pods/libwebp/src/dsp/lossless_enc_mips_dsp_r2.c deleted file mode 100644 index 0abf3c4f..00000000 --- a/Example/Pods/libwebp/src/dsp/lossless_enc_mips_dsp_r2.c +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Image transform methods for lossless encoder. -// -// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) -// Jovan Zelincevic (jovan.zelincevic@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS_DSP_R2) - -#include "./lossless.h" - -static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, - int num_pixels) { - uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; - uint32_t* const p_loop1_end = argb_data + (num_pixels & ~3); - uint32_t* const p_loop2_end = p_loop1_end + (num_pixels & 3); - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "beq %[argb_data], %[p_loop1_end], 3f \n\t" - " nop \n\t" - "0: \n\t" - "lw %[temp0], 0(%[argb_data]) \n\t" - "lw %[temp1], 4(%[argb_data]) \n\t" - "lw %[temp2], 8(%[argb_data]) \n\t" - "lw %[temp3], 12(%[argb_data]) \n\t" - "ext %[temp4], %[temp0], 8, 8 \n\t" - "ext %[temp5], %[temp1], 8, 8 \n\t" - "ext %[temp6], %[temp2], 8, 8 \n\t" - "ext %[temp7], %[temp3], 8, 8 \n\t" - "addiu %[argb_data], %[argb_data], 16 \n\t" - "replv.ph %[temp4], %[temp4] \n\t" - "replv.ph %[temp5], %[temp5] \n\t" - "replv.ph %[temp6], %[temp6] \n\t" - "replv.ph %[temp7], %[temp7] \n\t" - "subu.qb %[temp0], %[temp0], %[temp4] \n\t" - "subu.qb %[temp1], %[temp1], %[temp5] \n\t" - "subu.qb %[temp2], %[temp2], %[temp6] \n\t" - "subu.qb %[temp3], %[temp3], %[temp7] \n\t" - "sw %[temp0], -16(%[argb_data]) \n\t" - "sw %[temp1], -12(%[argb_data]) \n\t" - "sw %[temp2], -8(%[argb_data]) \n\t" - "bne %[argb_data], %[p_loop1_end], 0b \n\t" - " sw %[temp3], -4(%[argb_data]) \n\t" - "3: \n\t" - "beq %[argb_data], %[p_loop2_end], 2f \n\t" - " nop \n\t" - "1: \n\t" - "lw %[temp0], 0(%[argb_data]) \n\t" - "addiu %[argb_data], %[argb_data], 4 \n\t" - "ext %[temp4], %[temp0], 8, 8 \n\t" - "replv.ph %[temp4], %[temp4] \n\t" - "subu.qb %[temp0], %[temp0], %[temp4] \n\t" - "bne %[argb_data], %[p_loop2_end], 1b \n\t" - " sw %[temp0], -4(%[argb_data]) \n\t" - "2: \n\t" - ".set pop \n\t" - : [argb_data]"+&r"(argb_data), [temp0]"=&r"(temp0), - [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6), - [temp7]"=&r"(temp7) - : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) - : "memory" - ); -} - -static WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred, - int8_t color) { - return (uint32_t)((int)(color_pred) * color) >> 5; -} - -static void TransformColor(const VP8LMultipliers* const m, uint32_t* data, - int num_pixels) { - int temp0, temp1, temp2, temp3, temp4, temp5; - uint32_t argb, argb1, new_red, new_red1; - const uint32_t G_to_R = m->green_to_red_; - const uint32_t G_to_B = m->green_to_blue_; - const uint32_t R_to_B = m->red_to_blue_; - uint32_t* const p_loop_end = data + (num_pixels & ~1); - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "beq %[data], %[p_loop_end], 1f \n\t" - " nop \n\t" - "replv.ph %[temp0], %[G_to_R] \n\t" - "replv.ph %[temp1], %[G_to_B] \n\t" - "replv.ph %[temp2], %[R_to_B] \n\t" - "shll.ph %[temp0], %[temp0], 8 \n\t" - "shll.ph %[temp1], %[temp1], 8 \n\t" - "shll.ph %[temp2], %[temp2], 8 \n\t" - "shra.ph %[temp0], %[temp0], 8 \n\t" - "shra.ph %[temp1], %[temp1], 8 \n\t" - "shra.ph %[temp2], %[temp2], 8 \n\t" - "0: \n\t" - "lw %[argb], 0(%[data]) \n\t" - "lw %[argb1], 4(%[data]) \n\t" - "lhu %[new_red], 2(%[data]) \n\t" - "lhu %[new_red1], 6(%[data]) \n\t" - "precrq.qb.ph %[temp3], %[argb], %[argb1] \n\t" - "precr.qb.ph %[temp4], %[argb], %[argb1] \n\t" - "preceu.ph.qbra %[temp3], %[temp3] \n\t" - "preceu.ph.qbla %[temp4], %[temp4] \n\t" - "shll.ph %[temp3], %[temp3], 8 \n\t" - "shll.ph %[temp4], %[temp4], 8 \n\t" - "shra.ph %[temp3], %[temp3], 8 \n\t" - "shra.ph %[temp4], %[temp4], 8 \n\t" - "mul.ph %[temp5], %[temp3], %[temp0] \n\t" - "mul.ph %[temp3], %[temp3], %[temp1] \n\t" - "mul.ph %[temp4], %[temp4], %[temp2] \n\t" - "addiu %[data], %[data], 8 \n\t" - "ins %[new_red1], %[new_red], 16, 16 \n\t" - "ins %[argb1], %[argb], 16, 16 \n\t" - "shra.ph %[temp5], %[temp5], 5 \n\t" - "shra.ph %[temp3], %[temp3], 5 \n\t" - "shra.ph %[temp4], %[temp4], 5 \n\t" - "subu.ph %[new_red1], %[new_red1], %[temp5] \n\t" - "subu.ph %[argb1], %[argb1], %[temp3] \n\t" - "preceu.ph.qbra %[temp5], %[new_red1] \n\t" - "subu.ph %[argb1], %[argb1], %[temp4] \n\t" - "preceu.ph.qbra %[temp3], %[argb1] \n\t" - "sb %[temp5], -2(%[data]) \n\t" - "sb %[temp3], -4(%[data]) \n\t" - "sra %[temp5], %[temp5], 16 \n\t" - "sra %[temp3], %[temp3], 16 \n\t" - "sb %[temp5], -6(%[data]) \n\t" - "bne %[data], %[p_loop_end], 0b \n\t" - " sb %[temp3], -8(%[data]) \n\t" - "1: \n\t" - ".set pop \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [new_red1]"=&r"(new_red1), [new_red]"=&r"(new_red), - [argb]"=&r"(argb), [argb1]"=&r"(argb1), [data]"+&r"(data) - : [G_to_R]"r"(G_to_R), [R_to_B]"r"(R_to_B), - [G_to_B]"r"(G_to_B), [p_loop_end]"r"(p_loop_end) - : "memory", "hi", "lo" - ); - - if (num_pixels & 1) { - const uint32_t argb_ = data[0]; - const uint32_t green = argb_ >> 8; - const uint32_t red = argb_ >> 16; - uint32_t new_blue = argb_; - new_red = red; - new_red -= ColorTransformDelta(m->green_to_red_, green); - new_red &= 0xff; - new_blue -= ColorTransformDelta(m->green_to_blue_, green); - new_blue -= ColorTransformDelta(m->red_to_blue_, red); - new_blue &= 0xff; - data[0] = (argb_ & 0xff00ff00u) | (new_red << 16) | (new_blue); - } -} - -static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue, - uint8_t red_to_blue, - uint32_t argb) { - const uint32_t green = argb >> 8; - const uint32_t red = argb >> 16; - uint8_t new_blue = argb; - new_blue -= ColorTransformDelta(green_to_blue, green); - new_blue -= ColorTransformDelta(red_to_blue, red); - return (new_blue & 0xff); -} - -static void CollectColorBlueTransforms(const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_blue, int red_to_blue, - int histo[]) { - const int rtb = (red_to_blue << 16) | (red_to_blue & 0xffff); - const int gtb = (green_to_blue << 16) | (green_to_blue & 0xffff); - const uint32_t mask = 0xff00ffu; - while (tile_height-- > 0) { - int x; - const uint32_t* p_argb = argb; - argb += stride; - for (x = 0; x < (tile_width >> 1); ++x) { - int temp0, temp1, temp2, temp3, temp4, temp5, temp6; - __asm__ volatile ( - "lw %[temp0], 0(%[p_argb]) \n\t" - "lw %[temp1], 4(%[p_argb]) \n\t" - "precr.qb.ph %[temp2], %[temp0], %[temp1] \n\t" - "ins %[temp1], %[temp0], 16, 16 \n\t" - "shra.ph %[temp2], %[temp2], 8 \n\t" - "shra.ph %[temp3], %[temp1], 8 \n\t" - "mul.ph %[temp5], %[temp2], %[rtb] \n\t" - "mul.ph %[temp6], %[temp3], %[gtb] \n\t" - "and %[temp4], %[temp1], %[mask] \n\t" - "addiu %[p_argb], %[p_argb], 8 \n\t" - "shra.ph %[temp5], %[temp5], 5 \n\t" - "shra.ph %[temp6], %[temp6], 5 \n\t" - "subu.qb %[temp2], %[temp4], %[temp5] \n\t" - "subu.qb %[temp2], %[temp2], %[temp6] \n\t" - : [p_argb]"+&r"(p_argb), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), - [temp5]"=&r"(temp5), [temp6]"=&r"(temp6) - : [rtb]"r"(rtb), [gtb]"r"(gtb), [mask]"r"(mask) - : "memory", "hi", "lo" - ); - ++histo[(uint8_t)(temp2 >> 16)]; - ++histo[(uint8_t)temp2]; - } - if (tile_width & 1) { - ++histo[TransformColorBlue(green_to_blue, red_to_blue, *p_argb)]; - } - } -} - -static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red, - uint32_t argb) { - const uint32_t green = argb >> 8; - uint32_t new_red = argb >> 16; - new_red -= ColorTransformDelta(green_to_red, green); - return (new_red & 0xff); -} - -static void CollectColorRedTransforms(const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_red, int histo[]) { - const int gtr = (green_to_red << 16) | (green_to_red & 0xffff); - while (tile_height-- > 0) { - int x; - const uint32_t* p_argb = argb; - argb += stride; - for (x = 0; x < (tile_width >> 1); ++x) { - int temp0, temp1, temp2, temp3, temp4; - __asm__ volatile ( - "lw %[temp0], 0(%[p_argb]) \n\t" - "lw %[temp1], 4(%[p_argb]) \n\t" - "precrq.ph.w %[temp4], %[temp0], %[temp1] \n\t" - "ins %[temp1], %[temp0], 16, 16 \n\t" - "shra.ph %[temp3], %[temp1], 8 \n\t" - "mul.ph %[temp2], %[temp3], %[gtr] \n\t" - "addiu %[p_argb], %[p_argb], 8 \n\t" - "shra.ph %[temp2], %[temp2], 5 \n\t" - "subu.qb %[temp2], %[temp4], %[temp2] \n\t" - : [p_argb]"+&r"(p_argb), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4) - : [gtr]"r"(gtr) - : "memory", "hi", "lo" - ); - ++histo[(uint8_t)(temp2 >> 16)]; - ++histo[(uint8_t)temp2]; - } - if (tile_width & 1) { - ++histo[TransformColorRed(green_to_red, *p_argb)]; - } - } -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8LEncDspInitMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMIPSdspR2(void) { - VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed; - VP8LTransformColor = TransformColor; - VP8LCollectColorBlueTransforms = CollectColorBlueTransforms; - VP8LCollectColorRedTransforms = CollectColorRedTransforms; -} - -#else // !WEBP_USE_MIPS_DSP_R2 - -WEBP_DSP_INIT_STUB(VP8LEncDspInitMIPSdspR2) - -#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/Example/Pods/libwebp/src/dsp/lossless_enc_neon.c b/Example/Pods/libwebp/src/dsp/lossless_enc_neon.c deleted file mode 100644 index 4c56f259..00000000 --- a/Example/Pods/libwebp/src/dsp/lossless_enc_neon.c +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// NEON variant of methods for lossless encoder -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_NEON) - -#include - -#include "./lossless.h" -#include "./neon.h" - -//------------------------------------------------------------------------------ -// Subtract-Green Transform - -// vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use -// non-standard versions there. -#if defined(__APPLE__) && defined(__aarch64__) && \ - defined(__apple_build_version__) && (__apple_build_version__< 6020037) -#define USE_VTBLQ -#endif - -#ifdef USE_VTBLQ -// 255 = byte will be zeroed -static const uint8_t kGreenShuffle[16] = { - 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255 -}; - -static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb, - const uint8x16_t shuffle) { - return vcombine_u8(vtbl1q_u8(argb, vget_low_u8(shuffle)), - vtbl1q_u8(argb, vget_high_u8(shuffle))); -} -#else // !USE_VTBLQ -// 255 = byte will be zeroed -static const uint8_t kGreenShuffle[8] = { 1, 255, 1, 255, 5, 255, 5, 255 }; - -static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb, - const uint8x8_t shuffle) { - return vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle), - vtbl1_u8(vget_high_u8(argb), shuffle)); -} -#endif // USE_VTBLQ - -static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) { - const uint32_t* const end = argb_data + (num_pixels & ~3); -#ifdef USE_VTBLQ - const uint8x16_t shuffle = vld1q_u8(kGreenShuffle); -#else - const uint8x8_t shuffle = vld1_u8(kGreenShuffle); -#endif - for (; argb_data < end; argb_data += 4) { - const uint8x16_t argb = vld1q_u8((uint8_t*)argb_data); - const uint8x16_t greens = DoGreenShuffle(argb, shuffle); - vst1q_u8((uint8_t*)argb_data, vsubq_u8(argb, greens)); - } - // fallthrough and finish off with plain-C - VP8LSubtractGreenFromBlueAndRed_C(argb_data, num_pixels & 3); -} - -//------------------------------------------------------------------------------ -// Color Transform - -static void TransformColor(const VP8LMultipliers* const m, - uint32_t* argb_data, int num_pixels) { - // sign-extended multiplying constants, pre-shifted by 6. -#define CST(X) (((int16_t)(m->X << 8)) >> 6) - const int16_t rb[8] = { - CST(green_to_blue_), CST(green_to_red_), - CST(green_to_blue_), CST(green_to_red_), - CST(green_to_blue_), CST(green_to_red_), - CST(green_to_blue_), CST(green_to_red_) - }; - const int16x8_t mults_rb = vld1q_s16(rb); - const int16_t b2[8] = { - 0, CST(red_to_blue_), 0, CST(red_to_blue_), - 0, CST(red_to_blue_), 0, CST(red_to_blue_), - }; - const int16x8_t mults_b2 = vld1q_s16(b2); -#undef CST -#ifdef USE_VTBLQ - static const uint8_t kg0g0[16] = { - 255, 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13 - }; - const uint8x16_t shuffle = vld1q_u8(kg0g0); -#else - static const uint8_t k0g0g[8] = { 255, 1, 255, 1, 255, 5, 255, 5 }; - const uint8x8_t shuffle = vld1_u8(k0g0g); -#endif - const uint32x4_t mask_rb = vdupq_n_u32(0x00ff00ffu); // red-blue masks - int i; - for (i = 0; i + 4 <= num_pixels; i += 4) { - const uint8x16_t in = vld1q_u8((uint8_t*)(argb_data + i)); - // 0 g 0 g - const uint8x16_t greens = DoGreenShuffle(in, shuffle); - // x dr x db1 - const int16x8_t A = vqdmulhq_s16(vreinterpretq_s16_u8(greens), mults_rb); - // r 0 b 0 - const int16x8_t B = vshlq_n_s16(vreinterpretq_s16_u8(in), 8); - // x db2 0 0 - const int16x8_t C = vqdmulhq_s16(B, mults_b2); - // 0 0 x db2 - const uint32x4_t D = vshrq_n_u32(vreinterpretq_u32_s16(C), 16); - // x dr x db - const int8x16_t E = vaddq_s8(vreinterpretq_s8_u32(D), - vreinterpretq_s8_s16(A)); - // 0 dr 0 db - const uint32x4_t F = vandq_u32(vreinterpretq_u32_s8(E), mask_rb); - const int8x16_t out = vsubq_s8(vreinterpretq_s8_u8(in), - vreinterpretq_s8_u32(F)); - vst1q_s8((int8_t*)(argb_data + i), out); - } - // fallthrough and finish off with plain-C - VP8LTransformColor_C(m, argb_data + i, num_pixels - i); -} - -#undef USE_VTBLQ - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8LEncDspInitNEON(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitNEON(void) { - VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed; - VP8LTransformColor = TransformColor; -} - -#else // !WEBP_USE_NEON - -WEBP_DSP_INIT_STUB(VP8LEncDspInitNEON) - -#endif // WEBP_USE_NEON diff --git a/Example/Pods/libwebp/src/dsp/lossless_enc_sse2.c b/Example/Pods/libwebp/src/dsp/lossless_enc_sse2.c deleted file mode 100644 index e8c98341..00000000 --- a/Example/Pods/libwebp/src/dsp/lossless_enc_sse2.c +++ /dev/null @@ -1,345 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// SSE2 variant of methods for lossless encoder -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE2) -#include -#include -#include "./lossless.h" - -// For sign-extended multiplying constants, pre-shifted by 5: -#define CST_5b(X) (((int16_t)((uint16_t)X << 8)) >> 5) - -//------------------------------------------------------------------------------ -// Subtract-Green Transform - -static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) { - int i; - for (i = 0; i + 4 <= num_pixels; i += 4) { - const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb - const __m128i A = _mm_srli_epi16(in, 8); // 0 a 0 g - const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0)); - const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // 0g0g - const __m128i out = _mm_sub_epi8(in, C); - _mm_storeu_si128((__m128i*)&argb_data[i], out); - } - // fallthrough and finish off with plain-C - VP8LSubtractGreenFromBlueAndRed_C(argb_data + i, num_pixels - i); -} - -//------------------------------------------------------------------------------ -// Color Transform - -static void TransformColor(const VP8LMultipliers* const m, - uint32_t* argb_data, int num_pixels) { - const __m128i mults_rb = _mm_set_epi16( - CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_), - CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_), - CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_), - CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_)); - const __m128i mults_b2 = _mm_set_epi16( - CST_5b(m->red_to_blue_), 0, CST_5b(m->red_to_blue_), 0, - CST_5b(m->red_to_blue_), 0, CST_5b(m->red_to_blue_), 0); - const __m128i mask_ag = _mm_set1_epi32(0xff00ff00); // alpha-green masks - const __m128i mask_rb = _mm_set1_epi32(0x00ff00ff); // red-blue masks - int i; - for (i = 0; i + 4 <= num_pixels; i += 4) { - const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb - const __m128i A = _mm_and_si128(in, mask_ag); // a 0 g 0 - const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0)); - const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // g0g0 - const __m128i D = _mm_mulhi_epi16(C, mults_rb); // x dr x db1 - const __m128i E = _mm_slli_epi16(in, 8); // r 0 b 0 - const __m128i F = _mm_mulhi_epi16(E, mults_b2); // x db2 0 0 - const __m128i G = _mm_srli_epi32(F, 16); // 0 0 x db2 - const __m128i H = _mm_add_epi8(G, D); // x dr x db - const __m128i I = _mm_and_si128(H, mask_rb); // 0 dr 0 db - const __m128i out = _mm_sub_epi8(in, I); - _mm_storeu_si128((__m128i*)&argb_data[i], out); - } - // fallthrough and finish off with plain-C - VP8LTransformColor_C(m, argb_data + i, num_pixels - i); -} - -//------------------------------------------------------------------------------ -#define SPAN 8 -static void CollectColorBlueTransforms(const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_blue, int red_to_blue, - int histo[]) { - const __m128i mults_r = _mm_set_epi16( - CST_5b(red_to_blue), 0, CST_5b(red_to_blue), 0, - CST_5b(red_to_blue), 0, CST_5b(red_to_blue), 0); - const __m128i mults_g = _mm_set_epi16( - 0, CST_5b(green_to_blue), 0, CST_5b(green_to_blue), - 0, CST_5b(green_to_blue), 0, CST_5b(green_to_blue)); - const __m128i mask_g = _mm_set1_epi32(0x00ff00); // green mask - const __m128i mask_b = _mm_set1_epi32(0x0000ff); // blue mask - int y; - for (y = 0; y < tile_height; ++y) { - const uint32_t* const src = argb + y * stride; - int i, x; - for (x = 0; x + SPAN <= tile_width; x += SPAN) { - uint16_t values[SPAN]; - const __m128i in0 = _mm_loadu_si128((__m128i*)&src[x + 0]); - const __m128i in1 = _mm_loadu_si128((__m128i*)&src[x + SPAN / 2]); - const __m128i A0 = _mm_slli_epi16(in0, 8); // r 0 | b 0 - const __m128i A1 = _mm_slli_epi16(in1, 8); - const __m128i B0 = _mm_and_si128(in0, mask_g); // 0 0 | g 0 - const __m128i B1 = _mm_and_si128(in1, mask_g); - const __m128i C0 = _mm_mulhi_epi16(A0, mults_r); // x db | 0 0 - const __m128i C1 = _mm_mulhi_epi16(A1, mults_r); - const __m128i D0 = _mm_mulhi_epi16(B0, mults_g); // 0 0 | x db - const __m128i D1 = _mm_mulhi_epi16(B1, mults_g); - const __m128i E0 = _mm_sub_epi8(in0, D0); // x x | x b' - const __m128i E1 = _mm_sub_epi8(in1, D1); - const __m128i F0 = _mm_srli_epi32(C0, 16); // 0 0 | x db - const __m128i F1 = _mm_srli_epi32(C1, 16); - const __m128i G0 = _mm_sub_epi8(E0, F0); // 0 0 | x b' - const __m128i G1 = _mm_sub_epi8(E1, F1); - const __m128i H0 = _mm_and_si128(G0, mask_b); // 0 0 | 0 b - const __m128i H1 = _mm_and_si128(G1, mask_b); - const __m128i I = _mm_packs_epi32(H0, H1); // 0 b' | 0 b' - _mm_storeu_si128((__m128i*)values, I); - for (i = 0; i < SPAN; ++i) ++histo[values[i]]; - } - } - { - const int left_over = tile_width & (SPAN - 1); - if (left_over > 0) { - VP8LCollectColorBlueTransforms_C(argb + tile_width - left_over, stride, - left_over, tile_height, - green_to_blue, red_to_blue, histo); - } - } -} - -static void CollectColorRedTransforms(const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_red, int histo[]) { - const __m128i mults_g = _mm_set_epi16( - 0, CST_5b(green_to_red), 0, CST_5b(green_to_red), - 0, CST_5b(green_to_red), 0, CST_5b(green_to_red)); - const __m128i mask_g = _mm_set1_epi32(0x00ff00); // green mask - const __m128i mask = _mm_set1_epi32(0xff); - - int y; - for (y = 0; y < tile_height; ++y) { - const uint32_t* const src = argb + y * stride; - int i, x; - for (x = 0; x + SPAN <= tile_width; x += SPAN) { - uint16_t values[SPAN]; - const __m128i in0 = _mm_loadu_si128((__m128i*)&src[x + 0]); - const __m128i in1 = _mm_loadu_si128((__m128i*)&src[x + SPAN / 2]); - const __m128i A0 = _mm_and_si128(in0, mask_g); // 0 0 | g 0 - const __m128i A1 = _mm_and_si128(in1, mask_g); - const __m128i B0 = _mm_srli_epi32(in0, 16); // 0 0 | x r - const __m128i B1 = _mm_srli_epi32(in1, 16); - const __m128i C0 = _mm_mulhi_epi16(A0, mults_g); // 0 0 | x dr - const __m128i C1 = _mm_mulhi_epi16(A1, mults_g); - const __m128i E0 = _mm_sub_epi8(B0, C0); // x x | x r' - const __m128i E1 = _mm_sub_epi8(B1, C1); - const __m128i F0 = _mm_and_si128(E0, mask); // 0 0 | 0 r' - const __m128i F1 = _mm_and_si128(E1, mask); - const __m128i I = _mm_packs_epi32(F0, F1); - _mm_storeu_si128((__m128i*)values, I); - for (i = 0; i < SPAN; ++i) ++histo[values[i]]; - } - } - { - const int left_over = tile_width & (SPAN - 1); - if (left_over > 0) { - VP8LCollectColorRedTransforms_C(argb + tile_width - left_over, stride, - left_over, tile_height, - green_to_red, histo); - } - } -} -#undef SPAN - -//------------------------------------------------------------------------------ - -#define LINE_SIZE 16 // 8 or 16 -static void AddVector(const uint32_t* a, const uint32_t* b, uint32_t* out, - int size) { - int i; - assert(size % LINE_SIZE == 0); - for (i = 0; i < size; i += LINE_SIZE) { - const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i + 0]); - const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]); -#if (LINE_SIZE == 16) - const __m128i a2 = _mm_loadu_si128((const __m128i*)&a[i + 8]); - const __m128i a3 = _mm_loadu_si128((const __m128i*)&a[i + 12]); -#endif - const __m128i b0 = _mm_loadu_si128((const __m128i*)&b[i + 0]); - const __m128i b1 = _mm_loadu_si128((const __m128i*)&b[i + 4]); -#if (LINE_SIZE == 16) - const __m128i b2 = _mm_loadu_si128((const __m128i*)&b[i + 8]); - const __m128i b3 = _mm_loadu_si128((const __m128i*)&b[i + 12]); -#endif - _mm_storeu_si128((__m128i*)&out[i + 0], _mm_add_epi32(a0, b0)); - _mm_storeu_si128((__m128i*)&out[i + 4], _mm_add_epi32(a1, b1)); -#if (LINE_SIZE == 16) - _mm_storeu_si128((__m128i*)&out[i + 8], _mm_add_epi32(a2, b2)); - _mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3)); -#endif - } -} - -static void AddVectorEq(const uint32_t* a, uint32_t* out, int size) { - int i; - assert(size % LINE_SIZE == 0); - for (i = 0; i < size; i += LINE_SIZE) { - const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i + 0]); - const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]); -#if (LINE_SIZE == 16) - const __m128i a2 = _mm_loadu_si128((const __m128i*)&a[i + 8]); - const __m128i a3 = _mm_loadu_si128((const __m128i*)&a[i + 12]); -#endif - const __m128i b0 = _mm_loadu_si128((const __m128i*)&out[i + 0]); - const __m128i b1 = _mm_loadu_si128((const __m128i*)&out[i + 4]); -#if (LINE_SIZE == 16) - const __m128i b2 = _mm_loadu_si128((const __m128i*)&out[i + 8]); - const __m128i b3 = _mm_loadu_si128((const __m128i*)&out[i + 12]); -#endif - _mm_storeu_si128((__m128i*)&out[i + 0], _mm_add_epi32(a0, b0)); - _mm_storeu_si128((__m128i*)&out[i + 4], _mm_add_epi32(a1, b1)); -#if (LINE_SIZE == 16) - _mm_storeu_si128((__m128i*)&out[i + 8], _mm_add_epi32(a2, b2)); - _mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3)); -#endif - } -} -#undef LINE_SIZE - -// Note we are adding uint32_t's as *signed* int32's (using _mm_add_epi32). But -// that's ok since the histogram values are less than 1<<28 (max picture size). -static void HistogramAdd(const VP8LHistogram* const a, - const VP8LHistogram* const b, - VP8LHistogram* const out) { - int i; - const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_); - assert(a->palette_code_bits_ == b->palette_code_bits_); - if (b != out) { - AddVector(a->literal_, b->literal_, out->literal_, NUM_LITERAL_CODES); - AddVector(a->red_, b->red_, out->red_, NUM_LITERAL_CODES); - AddVector(a->blue_, b->blue_, out->blue_, NUM_LITERAL_CODES); - AddVector(a->alpha_, b->alpha_, out->alpha_, NUM_LITERAL_CODES); - } else { - AddVectorEq(a->literal_, out->literal_, NUM_LITERAL_CODES); - AddVectorEq(a->red_, out->red_, NUM_LITERAL_CODES); - AddVectorEq(a->blue_, out->blue_, NUM_LITERAL_CODES); - AddVectorEq(a->alpha_, out->alpha_, NUM_LITERAL_CODES); - } - for (i = NUM_LITERAL_CODES; i < literal_size; ++i) { - out->literal_[i] = a->literal_[i] + b->literal_[i]; - } - for (i = 0; i < NUM_DISTANCE_CODES; ++i) { - out->distance_[i] = a->distance_[i] + b->distance_[i]; - } -} - -//------------------------------------------------------------------------------ -// Entropy - -// Checks whether the X or Y contribution is worth computing and adding. -// Used in loop unrolling. -#define ANALYZE_X_OR_Y(x_or_y, j) \ - do { \ - if (x_or_y[i + j] != 0) retval -= VP8LFastSLog2(x_or_y[i + j]); \ - } while (0) - -// Checks whether the X + Y contribution is worth computing and adding. -// Used in loop unrolling. -#define ANALYZE_XY(j) \ - do { \ - if (tmp[j] != 0) { \ - retval -= VP8LFastSLog2(tmp[j]); \ - ANALYZE_X_OR_Y(X, j); \ - } \ - } while (0) - -static float CombinedShannonEntropy(const int X[256], const int Y[256]) { - int i; - double retval = 0.; - int sumX, sumXY; - int32_t tmp[4]; - __m128i zero = _mm_setzero_si128(); - // Sums up X + Y, 4 ints at a time (and will merge it at the end for sumXY). - __m128i sumXY_128 = zero; - __m128i sumX_128 = zero; - - for (i = 0; i < 256; i += 4) { - const __m128i x = _mm_loadu_si128((const __m128i*)(X + i)); - const __m128i y = _mm_loadu_si128((const __m128i*)(Y + i)); - - // Check if any X is non-zero: this actually provides a speedup as X is - // usually sparse. - if (_mm_movemask_epi8(_mm_cmpeq_epi32(x, zero)) != 0xFFFF) { - const __m128i xy_128 = _mm_add_epi32(x, y); - sumXY_128 = _mm_add_epi32(sumXY_128, xy_128); - - sumX_128 = _mm_add_epi32(sumX_128, x); - - // Analyze the different X + Y. - _mm_storeu_si128((__m128i*)tmp, xy_128); - - ANALYZE_XY(0); - ANALYZE_XY(1); - ANALYZE_XY(2); - ANALYZE_XY(3); - } else { - // X is fully 0, so only deal with Y. - sumXY_128 = _mm_add_epi32(sumXY_128, y); - - ANALYZE_X_OR_Y(Y, 0); - ANALYZE_X_OR_Y(Y, 1); - ANALYZE_X_OR_Y(Y, 2); - ANALYZE_X_OR_Y(Y, 3); - } - } - - // Sum up sumX_128 to get sumX. - _mm_storeu_si128((__m128i*)tmp, sumX_128); - sumX = tmp[3] + tmp[2] + tmp[1] + tmp[0]; - - // Sum up sumXY_128 to get sumXY. - _mm_storeu_si128((__m128i*)tmp, sumXY_128); - sumXY = tmp[3] + tmp[2] + tmp[1] + tmp[0]; - - retval += VP8LFastSLog2(sumX) + VP8LFastSLog2(sumXY); - return (float)retval; -} -#undef ANALYZE_X_OR_Y -#undef ANALYZE_XY - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8LEncDspInitSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE2(void) { - VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed; - VP8LTransformColor = TransformColor; - VP8LCollectColorBlueTransforms = CollectColorBlueTransforms; - VP8LCollectColorRedTransforms = CollectColorRedTransforms; - VP8LHistogramAdd = HistogramAdd; - VP8LCombinedShannonEntropy = CombinedShannonEntropy; -} - -#else // !WEBP_USE_SSE2 - -WEBP_DSP_INIT_STUB(VP8LEncDspInitSSE2) - -#endif // WEBP_USE_SSE2 diff --git a/Example/Pods/libwebp/src/dsp/lossless_enc_sse41.c b/Example/Pods/libwebp/src/dsp/lossless_enc_sse41.c deleted file mode 100644 index 3e493198..00000000 --- a/Example/Pods/libwebp/src/dsp/lossless_enc_sse41.c +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// SSE4.1 variant of methods for lossless encoder -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE41) -#include -#include -#include "./lossless.h" - -//------------------------------------------------------------------------------ -// Subtract-Green Transform - -static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) { - int i; - const __m128i kCstShuffle = _mm_set_epi8(-1, 13, -1, 13, -1, 9, -1, 9, - -1, 5, -1, 5, -1, 1, -1, 1); - for (i = 0; i + 4 <= num_pixels; i += 4) { - const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); - const __m128i in_0g0g = _mm_shuffle_epi8(in, kCstShuffle); - const __m128i out = _mm_sub_epi8(in, in_0g0g); - _mm_storeu_si128((__m128i*)&argb_data[i], out); - } - // fallthrough and finish off with plain-C - VP8LSubtractGreenFromBlueAndRed_C(argb_data + i, num_pixels - i); -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8LEncDspInitSSE41(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE41(void) { - VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed; -} - -#else // !WEBP_USE_SSE41 - -WEBP_DSP_INIT_STUB(VP8LEncDspInitSSE41) - -#endif // WEBP_USE_SSE41 diff --git a/Example/Pods/libwebp/src/dsp/lossless_mips_dsp_r2.c b/Example/Pods/libwebp/src/dsp/lossless_mips_dsp_r2.c deleted file mode 100644 index 90aed7f1..00000000 --- a/Example/Pods/libwebp/src/dsp/lossless_mips_dsp_r2.c +++ /dev/null @@ -1,680 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Image transforms and color space conversion methods for lossless decoder. -// -// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) -// Jovan Zelincevic (jovan.zelincevic@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS_DSP_R2) - -#include "./lossless.h" - -#define MAP_COLOR_FUNCS(FUNC_NAME, TYPE, GET_INDEX, GET_VALUE) \ -static void FUNC_NAME(const TYPE* src, \ - const uint32_t* const color_map, \ - TYPE* dst, int y_start, int y_end, \ - int width) { \ - int y; \ - for (y = y_start; y < y_end; ++y) { \ - int x; \ - for (x = 0; x < (width >> 2); ++x) { \ - int tmp1, tmp2, tmp3, tmp4; \ - __asm__ volatile ( \ - ".ifc " #TYPE ", uint8_t \n\t" \ - "lbu %[tmp1], 0(%[src]) \n\t" \ - "lbu %[tmp2], 1(%[src]) \n\t" \ - "lbu %[tmp3], 2(%[src]) \n\t" \ - "lbu %[tmp4], 3(%[src]) \n\t" \ - "addiu %[src], %[src], 4 \n\t" \ - ".endif \n\t" \ - ".ifc " #TYPE ", uint32_t \n\t" \ - "lw %[tmp1], 0(%[src]) \n\t" \ - "lw %[tmp2], 4(%[src]) \n\t" \ - "lw %[tmp3], 8(%[src]) \n\t" \ - "lw %[tmp4], 12(%[src]) \n\t" \ - "ext %[tmp1], %[tmp1], 8, 8 \n\t" \ - "ext %[tmp2], %[tmp2], 8, 8 \n\t" \ - "ext %[tmp3], %[tmp3], 8, 8 \n\t" \ - "ext %[tmp4], %[tmp4], 8, 8 \n\t" \ - "addiu %[src], %[src], 16 \n\t" \ - ".endif \n\t" \ - "sll %[tmp1], %[tmp1], 2 \n\t" \ - "sll %[tmp2], %[tmp2], 2 \n\t" \ - "sll %[tmp3], %[tmp3], 2 \n\t" \ - "sll %[tmp4], %[tmp4], 2 \n\t" \ - "lwx %[tmp1], %[tmp1](%[color_map]) \n\t" \ - "lwx %[tmp2], %[tmp2](%[color_map]) \n\t" \ - "lwx %[tmp3], %[tmp3](%[color_map]) \n\t" \ - "lwx %[tmp4], %[tmp4](%[color_map]) \n\t" \ - ".ifc " #TYPE ", uint8_t \n\t" \ - "ext %[tmp1], %[tmp1], 8, 8 \n\t" \ - "ext %[tmp2], %[tmp2], 8, 8 \n\t" \ - "ext %[tmp3], %[tmp3], 8, 8 \n\t" \ - "ext %[tmp4], %[tmp4], 8, 8 \n\t" \ - "sb %[tmp1], 0(%[dst]) \n\t" \ - "sb %[tmp2], 1(%[dst]) \n\t" \ - "sb %[tmp3], 2(%[dst]) \n\t" \ - "sb %[tmp4], 3(%[dst]) \n\t" \ - "addiu %[dst], %[dst], 4 \n\t" \ - ".endif \n\t" \ - ".ifc " #TYPE ", uint32_t \n\t" \ - "sw %[tmp1], 0(%[dst]) \n\t" \ - "sw %[tmp2], 4(%[dst]) \n\t" \ - "sw %[tmp3], 8(%[dst]) \n\t" \ - "sw %[tmp4], 12(%[dst]) \n\t" \ - "addiu %[dst], %[dst], 16 \n\t" \ - ".endif \n\t" \ - : [tmp1]"=&r"(tmp1), [tmp2]"=&r"(tmp2), [tmp3]"=&r"(tmp3), \ - [tmp4]"=&r"(tmp4), [src]"+&r"(src), [dst]"+r"(dst) \ - : [color_map]"r"(color_map) \ - : "memory" \ - ); \ - } \ - for (x = 0; x < (width & 3); ++x) { \ - *dst++ = GET_VALUE(color_map[GET_INDEX(*src++)]); \ - } \ - } \ -} - -MAP_COLOR_FUNCS(MapARGB, uint32_t, VP8GetARGBIndex, VP8GetARGBValue) -MAP_COLOR_FUNCS(MapAlpha, uint8_t, VP8GetAlphaIndex, VP8GetAlphaValue) - -#undef MAP_COLOR_FUNCS - -static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1, - uint32_t c2) { - int temp0, temp1, temp2, temp3, temp4, temp5; - __asm__ volatile ( - "preceu.ph.qbr %[temp1], %[c0] \n\t" - "preceu.ph.qbl %[temp2], %[c0] \n\t" - "preceu.ph.qbr %[temp3], %[c1] \n\t" - "preceu.ph.qbl %[temp4], %[c1] \n\t" - "preceu.ph.qbr %[temp5], %[c2] \n\t" - "preceu.ph.qbl %[temp0], %[c2] \n\t" - "subq.ph %[temp3], %[temp3], %[temp5] \n\t" - "subq.ph %[temp4], %[temp4], %[temp0] \n\t" - "addq.ph %[temp1], %[temp1], %[temp3] \n\t" - "addq.ph %[temp2], %[temp2], %[temp4] \n\t" - "shll_s.ph %[temp1], %[temp1], 7 \n\t" - "shll_s.ph %[temp2], %[temp2], 7 \n\t" - "precrqu_s.qb.ph %[temp2], %[temp2], %[temp1] \n\t" - : [temp0]"=r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5) - : [c0]"r"(c0), [c1]"r"(c1), [c2]"r"(c2) - : "memory" - ); - return temp2; -} - -static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1, - uint32_t c2) { - int temp0, temp1, temp2, temp3, temp4, temp5; - __asm__ volatile ( - "adduh.qb %[temp5], %[c0], %[c1] \n\t" - "preceu.ph.qbr %[temp3], %[c2] \n\t" - "preceu.ph.qbr %[temp1], %[temp5] \n\t" - "preceu.ph.qbl %[temp2], %[temp5] \n\t" - "preceu.ph.qbl %[temp4], %[c2] \n\t" - "subq.ph %[temp3], %[temp1], %[temp3] \n\t" - "subq.ph %[temp4], %[temp2], %[temp4] \n\t" - "shrl.ph %[temp5], %[temp3], 15 \n\t" - "shrl.ph %[temp0], %[temp4], 15 \n\t" - "addq.ph %[temp3], %[temp3], %[temp5] \n\t" - "addq.ph %[temp4], %[temp0], %[temp4] \n\t" - "shra.ph %[temp3], %[temp3], 1 \n\t" - "shra.ph %[temp4], %[temp4], 1 \n\t" - "addq.ph %[temp1], %[temp1], %[temp3] \n\t" - "addq.ph %[temp2], %[temp2], %[temp4] \n\t" - "shll_s.ph %[temp1], %[temp1], 7 \n\t" - "shll_s.ph %[temp2], %[temp2], 7 \n\t" - "precrqu_s.qb.ph %[temp1], %[temp2], %[temp1] \n\t" - : [temp0]"=r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=r"(temp4), [temp5]"=&r"(temp5) - : [c0]"r"(c0), [c1]"r"(c1), [c2]"r"(c2) - : "memory" - ); - return temp1; -} - -static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) { - int temp0, temp1, temp2, temp3, temp4, temp5; - __asm__ volatile ( - "cmpgdu.lt.qb %[temp1], %[c], %[b] \n\t" - "pick.qb %[temp1], %[b], %[c] \n\t" - "pick.qb %[temp2], %[c], %[b] \n\t" - "cmpgdu.lt.qb %[temp4], %[c], %[a] \n\t" - "pick.qb %[temp4], %[a], %[c] \n\t" - "pick.qb %[temp5], %[c], %[a] \n\t" - "subu.qb %[temp3], %[temp1], %[temp2] \n\t" - "subu.qb %[temp0], %[temp4], %[temp5] \n\t" - "raddu.w.qb %[temp3], %[temp3] \n\t" - "raddu.w.qb %[temp0], %[temp0] \n\t" - "subu %[temp3], %[temp3], %[temp0] \n\t" - "slti %[temp0], %[temp3], 0x1 \n\t" - "movz %[a], %[b], %[temp0] \n\t" - : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp0]"=&r"(temp0), - [a]"+&r"(a) - : [b]"r"(b), [c]"r"(c) - ); - return a; -} - -static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) { - __asm__ volatile ( - "adduh.qb %[a0], %[a0], %[a1] \n\t" - : [a0]"+r"(a0) - : [a1]"r"(a1) - ); - return a0; -} - -static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) { - return Average2(Average2(a0, a2), a1); -} - -static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1, - uint32_t a2, uint32_t a3) { - return Average2(Average2(a0, a1), Average2(a2, a3)); -} - -static uint32_t Predictor5(uint32_t left, const uint32_t* const top) { - return Average3(left, top[0], top[1]); -} - -static uint32_t Predictor6(uint32_t left, const uint32_t* const top) { - return Average2(left, top[-1]); -} - -static uint32_t Predictor7(uint32_t left, const uint32_t* const top) { - return Average2(left, top[0]); -} - -static uint32_t Predictor8(uint32_t left, const uint32_t* const top) { - (void)left; - return Average2(top[-1], top[0]); -} - -static uint32_t Predictor9(uint32_t left, const uint32_t* const top) { - (void)left; - return Average2(top[0], top[1]); -} - -static uint32_t Predictor10(uint32_t left, const uint32_t* const top) { - return Average4(left, top[-1], top[0], top[1]); -} - -static uint32_t Predictor11(uint32_t left, const uint32_t* const top) { - return Select(top[0], left, top[-1]); -} - -static uint32_t Predictor12(uint32_t left, const uint32_t* const top) { - return ClampedAddSubtractFull(left, top[0], top[-1]); -} - -static uint32_t Predictor13(uint32_t left, const uint32_t* const top) { - return ClampedAddSubtractHalf(left, top[0], top[-1]); -} - -// Add green to blue and red channels (i.e. perform the inverse transform of -// 'subtract green'). -static void AddGreenToBlueAndRed(uint32_t* data, int num_pixels) { - uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; - uint32_t* const p_loop1_end = data + (num_pixels & ~3); - uint32_t* const p_loop2_end = data + num_pixels; - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "beq %[data], %[p_loop1_end], 3f \n\t" - " nop \n\t" - "0: \n\t" - "lw %[temp0], 0(%[data]) \n\t" - "lw %[temp1], 4(%[data]) \n\t" - "lw %[temp2], 8(%[data]) \n\t" - "lw %[temp3], 12(%[data]) \n\t" - "ext %[temp4], %[temp0], 8, 8 \n\t" - "ext %[temp5], %[temp1], 8, 8 \n\t" - "ext %[temp6], %[temp2], 8, 8 \n\t" - "ext %[temp7], %[temp3], 8, 8 \n\t" - "addiu %[data], %[data], 16 \n\t" - "replv.ph %[temp4], %[temp4] \n\t" - "replv.ph %[temp5], %[temp5] \n\t" - "replv.ph %[temp6], %[temp6] \n\t" - "replv.ph %[temp7], %[temp7] \n\t" - "addu.qb %[temp0], %[temp0], %[temp4] \n\t" - "addu.qb %[temp1], %[temp1], %[temp5] \n\t" - "addu.qb %[temp2], %[temp2], %[temp6] \n\t" - "addu.qb %[temp3], %[temp3], %[temp7] \n\t" - "sw %[temp0], -16(%[data]) \n\t" - "sw %[temp1], -12(%[data]) \n\t" - "sw %[temp2], -8(%[data]) \n\t" - "bne %[data], %[p_loop1_end], 0b \n\t" - " sw %[temp3], -4(%[data]) \n\t" - "3: \n\t" - "beq %[data], %[p_loop2_end], 2f \n\t" - " nop \n\t" - "1: \n\t" - "lw %[temp0], 0(%[data]) \n\t" - "addiu %[data], %[data], 4 \n\t" - "ext %[temp4], %[temp0], 8, 8 \n\t" - "replv.ph %[temp4], %[temp4] \n\t" - "addu.qb %[temp0], %[temp0], %[temp4] \n\t" - "bne %[data], %[p_loop2_end], 1b \n\t" - " sw %[temp0], -4(%[data]) \n\t" - "2: \n\t" - ".set pop \n\t" - : [data]"+&r"(data), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), - [temp5]"=&r"(temp5), [temp6]"=&r"(temp6), [temp7]"=&r"(temp7) - : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) - : "memory" - ); -} - -static void TransformColorInverse(const VP8LMultipliers* const m, - uint32_t* data, int num_pixels) { - int temp0, temp1, temp2, temp3, temp4, temp5; - uint32_t argb, argb1, new_red; - const uint32_t G_to_R = m->green_to_red_; - const uint32_t G_to_B = m->green_to_blue_; - const uint32_t R_to_B = m->red_to_blue_; - uint32_t* const p_loop_end = data + (num_pixels & ~1); - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "beq %[data], %[p_loop_end], 1f \n\t" - " nop \n\t" - "replv.ph %[temp0], %[G_to_R] \n\t" - "replv.ph %[temp1], %[G_to_B] \n\t" - "replv.ph %[temp2], %[R_to_B] \n\t" - "shll.ph %[temp0], %[temp0], 8 \n\t" - "shll.ph %[temp1], %[temp1], 8 \n\t" - "shll.ph %[temp2], %[temp2], 8 \n\t" - "shra.ph %[temp0], %[temp0], 8 \n\t" - "shra.ph %[temp1], %[temp1], 8 \n\t" - "shra.ph %[temp2], %[temp2], 8 \n\t" - "0: \n\t" - "lw %[argb], 0(%[data]) \n\t" - "lw %[argb1], 4(%[data]) \n\t" - "addiu %[data], %[data], 8 \n\t" - "precrq.qb.ph %[temp3], %[argb], %[argb1] \n\t" - "preceu.ph.qbra %[temp3], %[temp3] \n\t" - "shll.ph %[temp3], %[temp3], 8 \n\t" - "shra.ph %[temp3], %[temp3], 8 \n\t" - "mul.ph %[temp5], %[temp3], %[temp0] \n\t" - "mul.ph %[temp3], %[temp3], %[temp1] \n\t" - "precrq.ph.w %[new_red], %[argb], %[argb1] \n\t" - "ins %[argb1], %[argb], 16, 16 \n\t" - "shra.ph %[temp5], %[temp5], 5 \n\t" - "shra.ph %[temp3], %[temp3], 5 \n\t" - "addu.ph %[new_red], %[new_red], %[temp5] \n\t" - "addu.ph %[argb1], %[argb1], %[temp3] \n\t" - "preceu.ph.qbra %[temp5], %[new_red] \n\t" - "shll.ph %[temp4], %[temp5], 8 \n\t" - "shra.ph %[temp4], %[temp4], 8 \n\t" - "mul.ph %[temp4], %[temp4], %[temp2] \n\t" - "sb %[temp5], -2(%[data]) \n\t" - "sra %[temp5], %[temp5], 16 \n\t" - "shra.ph %[temp4], %[temp4], 5 \n\t" - "addu.ph %[argb1], %[argb1], %[temp4] \n\t" - "preceu.ph.qbra %[temp3], %[argb1] \n\t" - "sb %[temp5], -6(%[data]) \n\t" - "sb %[temp3], -4(%[data]) \n\t" - "sra %[temp3], %[temp3], 16 \n\t" - "bne %[data], %[p_loop_end], 0b \n\t" - " sb %[temp3], -8(%[data]) \n\t" - "1: \n\t" - ".set pop \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [new_red]"=&r"(new_red), [argb]"=&r"(argb), - [argb1]"=&r"(argb1), [data]"+&r"(data) - : [G_to_R]"r"(G_to_R), [R_to_B]"r"(R_to_B), - [G_to_B]"r"(G_to_B), [p_loop_end]"r"(p_loop_end) - : "memory", "hi", "lo" - ); - - // Fall-back to C-version for left-overs. - if (num_pixels & 1) VP8LTransformColorInverse_C(m, data, 1); -} - -static void ConvertBGRAToRGB(const uint32_t* src, - int num_pixels, uint8_t* dst) { - int temp0, temp1, temp2, temp3; - const uint32_t* const p_loop1_end = src + (num_pixels & ~3); - const uint32_t* const p_loop2_end = src + num_pixels; - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "beq %[src], %[p_loop1_end], 3f \n\t" - " nop \n\t" - "0: \n\t" - "lw %[temp3], 12(%[src]) \n\t" - "lw %[temp2], 8(%[src]) \n\t" - "lw %[temp1], 4(%[src]) \n\t" - "lw %[temp0], 0(%[src]) \n\t" - "ins %[temp3], %[temp2], 24, 8 \n\t" - "sll %[temp2], %[temp2], 8 \n\t" - "rotr %[temp3], %[temp3], 16 \n\t" - "ins %[temp2], %[temp1], 0, 16 \n\t" - "sll %[temp1], %[temp1], 8 \n\t" - "wsbh %[temp3], %[temp3] \n\t" - "balign %[temp0], %[temp1], 1 \n\t" - "wsbh %[temp2], %[temp2] \n\t" - "wsbh %[temp0], %[temp0] \n\t" - "usw %[temp3], 8(%[dst]) \n\t" - "rotr %[temp0], %[temp0], 16 \n\t" - "usw %[temp2], 4(%[dst]) \n\t" - "addiu %[src], %[src], 16 \n\t" - "usw %[temp0], 0(%[dst]) \n\t" - "bne %[src], %[p_loop1_end], 0b \n\t" - " addiu %[dst], %[dst], 12 \n\t" - "3: \n\t" - "beq %[src], %[p_loop2_end], 2f \n\t" - " nop \n\t" - "1: \n\t" - "lw %[temp0], 0(%[src]) \n\t" - "addiu %[src], %[src], 4 \n\t" - "wsbh %[temp1], %[temp0] \n\t" - "addiu %[dst], %[dst], 3 \n\t" - "ush %[temp1], -2(%[dst]) \n\t" - "sra %[temp0], %[temp0], 16 \n\t" - "bne %[src], %[p_loop2_end], 1b \n\t" - " sb %[temp0], -3(%[dst]) \n\t" - "2: \n\t" - ".set pop \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [dst]"+&r"(dst), [src]"+&r"(src) - : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) - : "memory" - ); -} - -static void ConvertBGRAToRGBA(const uint32_t* src, - int num_pixels, uint8_t* dst) { - int temp0, temp1, temp2, temp3; - const uint32_t* const p_loop1_end = src + (num_pixels & ~3); - const uint32_t* const p_loop2_end = src + num_pixels; - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "beq %[src], %[p_loop1_end], 3f \n\t" - " nop \n\t" - "0: \n\t" - "lw %[temp0], 0(%[src]) \n\t" - "lw %[temp1], 4(%[src]) \n\t" - "lw %[temp2], 8(%[src]) \n\t" - "lw %[temp3], 12(%[src]) \n\t" - "wsbh %[temp0], %[temp0] \n\t" - "wsbh %[temp1], %[temp1] \n\t" - "wsbh %[temp2], %[temp2] \n\t" - "wsbh %[temp3], %[temp3] \n\t" - "addiu %[src], %[src], 16 \n\t" - "balign %[temp0], %[temp0], 1 \n\t" - "balign %[temp1], %[temp1], 1 \n\t" - "balign %[temp2], %[temp2], 1 \n\t" - "balign %[temp3], %[temp3], 1 \n\t" - "usw %[temp0], 0(%[dst]) \n\t" - "usw %[temp1], 4(%[dst]) \n\t" - "usw %[temp2], 8(%[dst]) \n\t" - "usw %[temp3], 12(%[dst]) \n\t" - "bne %[src], %[p_loop1_end], 0b \n\t" - " addiu %[dst], %[dst], 16 \n\t" - "3: \n\t" - "beq %[src], %[p_loop2_end], 2f \n\t" - " nop \n\t" - "1: \n\t" - "lw %[temp0], 0(%[src]) \n\t" - "wsbh %[temp0], %[temp0] \n\t" - "addiu %[src], %[src], 4 \n\t" - "balign %[temp0], %[temp0], 1 \n\t" - "usw %[temp0], 0(%[dst]) \n\t" - "bne %[src], %[p_loop2_end], 1b \n\t" - " addiu %[dst], %[dst], 4 \n\t" - "2: \n\t" - ".set pop \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [dst]"+&r"(dst), [src]"+&r"(src) - : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) - : "memory" - ); -} - -static void ConvertBGRAToRGBA4444(const uint32_t* src, - int num_pixels, uint8_t* dst) { - int temp0, temp1, temp2, temp3, temp4, temp5; - const uint32_t* const p_loop1_end = src + (num_pixels & ~3); - const uint32_t* const p_loop2_end = src + num_pixels; - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "beq %[src], %[p_loop1_end], 3f \n\t" - " nop \n\t" - "0: \n\t" - "lw %[temp0], 0(%[src]) \n\t" - "lw %[temp1], 4(%[src]) \n\t" - "lw %[temp2], 8(%[src]) \n\t" - "lw %[temp3], 12(%[src]) \n\t" - "ext %[temp4], %[temp0], 28, 4 \n\t" - "ext %[temp5], %[temp0], 12, 4 \n\t" - "ins %[temp0], %[temp4], 0, 4 \n\t" - "ext %[temp4], %[temp1], 28, 4 \n\t" - "ins %[temp0], %[temp5], 16, 4 \n\t" - "ext %[temp5], %[temp1], 12, 4 \n\t" - "ins %[temp1], %[temp4], 0, 4 \n\t" - "ext %[temp4], %[temp2], 28, 4 \n\t" - "ins %[temp1], %[temp5], 16, 4 \n\t" - "ext %[temp5], %[temp2], 12, 4 \n\t" - "ins %[temp2], %[temp4], 0, 4 \n\t" - "ext %[temp4], %[temp3], 28, 4 \n\t" - "ins %[temp2], %[temp5], 16, 4 \n\t" - "ext %[temp5], %[temp3], 12, 4 \n\t" - "ins %[temp3], %[temp4], 0, 4 \n\t" - "precr.qb.ph %[temp1], %[temp1], %[temp0] \n\t" - "ins %[temp3], %[temp5], 16, 4 \n\t" - "addiu %[src], %[src], 16 \n\t" - "precr.qb.ph %[temp3], %[temp3], %[temp2] \n\t" -#ifdef WEBP_SWAP_16BIT_CSP - "usw %[temp1], 0(%[dst]) \n\t" - "usw %[temp3], 4(%[dst]) \n\t" -#else - "wsbh %[temp1], %[temp1] \n\t" - "wsbh %[temp3], %[temp3] \n\t" - "usw %[temp1], 0(%[dst]) \n\t" - "usw %[temp3], 4(%[dst]) \n\t" -#endif - "bne %[src], %[p_loop1_end], 0b \n\t" - " addiu %[dst], %[dst], 8 \n\t" - "3: \n\t" - "beq %[src], %[p_loop2_end], 2f \n\t" - " nop \n\t" - "1: \n\t" - "lw %[temp0], 0(%[src]) \n\t" - "ext %[temp4], %[temp0], 28, 4 \n\t" - "ext %[temp5], %[temp0], 12, 4 \n\t" - "ins %[temp0], %[temp4], 0, 4 \n\t" - "ins %[temp0], %[temp5], 16, 4 \n\t" - "addiu %[src], %[src], 4 \n\t" - "precr.qb.ph %[temp0], %[temp0], %[temp0] \n\t" -#ifdef WEBP_SWAP_16BIT_CSP - "ush %[temp0], 0(%[dst]) \n\t" -#else - "wsbh %[temp0], %[temp0] \n\t" - "ush %[temp0], 0(%[dst]) \n\t" -#endif - "bne %[src], %[p_loop2_end], 1b \n\t" - " addiu %[dst], %[dst], 2 \n\t" - "2: \n\t" - ".set pop \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [dst]"+&r"(dst), [src]"+&r"(src) - : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) - : "memory" - ); -} - -static void ConvertBGRAToRGB565(const uint32_t* src, - int num_pixels, uint8_t* dst) { - int temp0, temp1, temp2, temp3, temp4, temp5; - const uint32_t* const p_loop1_end = src + (num_pixels & ~3); - const uint32_t* const p_loop2_end = src + num_pixels; - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "beq %[src], %[p_loop1_end], 3f \n\t" - " nop \n\t" - "0: \n\t" - "lw %[temp0], 0(%[src]) \n\t" - "lw %[temp1], 4(%[src]) \n\t" - "lw %[temp2], 8(%[src]) \n\t" - "lw %[temp3], 12(%[src]) \n\t" - "ext %[temp4], %[temp0], 8, 16 \n\t" - "ext %[temp5], %[temp0], 5, 11 \n\t" - "ext %[temp0], %[temp0], 3, 5 \n\t" - "ins %[temp4], %[temp5], 0, 11 \n\t" - "ext %[temp5], %[temp1], 5, 11 \n\t" - "ins %[temp4], %[temp0], 0, 5 \n\t" - "ext %[temp0], %[temp1], 8, 16 \n\t" - "ext %[temp1], %[temp1], 3, 5 \n\t" - "ins %[temp0], %[temp5], 0, 11 \n\t" - "ext %[temp5], %[temp2], 5, 11 \n\t" - "ins %[temp0], %[temp1], 0, 5 \n\t" - "ext %[temp1], %[temp2], 8, 16 \n\t" - "ext %[temp2], %[temp2], 3, 5 \n\t" - "ins %[temp1], %[temp5], 0, 11 \n\t" - "ext %[temp5], %[temp3], 5, 11 \n\t" - "ins %[temp1], %[temp2], 0, 5 \n\t" - "ext %[temp2], %[temp3], 8, 16 \n\t" - "ext %[temp3], %[temp3], 3, 5 \n\t" - "ins %[temp2], %[temp5], 0, 11 \n\t" - "append %[temp0], %[temp4], 16 \n\t" - "ins %[temp2], %[temp3], 0, 5 \n\t" - "addiu %[src], %[src], 16 \n\t" - "append %[temp2], %[temp1], 16 \n\t" -#ifdef WEBP_SWAP_16BIT_CSP - "usw %[temp0], 0(%[dst]) \n\t" - "usw %[temp2], 4(%[dst]) \n\t" -#else - "wsbh %[temp0], %[temp0] \n\t" - "wsbh %[temp2], %[temp2] \n\t" - "usw %[temp0], 0(%[dst]) \n\t" - "usw %[temp2], 4(%[dst]) \n\t" -#endif - "bne %[src], %[p_loop1_end], 0b \n\t" - " addiu %[dst], %[dst], 8 \n\t" - "3: \n\t" - "beq %[src], %[p_loop2_end], 2f \n\t" - " nop \n\t" - "1: \n\t" - "lw %[temp0], 0(%[src]) \n\t" - "ext %[temp4], %[temp0], 8, 16 \n\t" - "ext %[temp5], %[temp0], 5, 11 \n\t" - "ext %[temp0], %[temp0], 3, 5 \n\t" - "ins %[temp4], %[temp5], 0, 11 \n\t" - "addiu %[src], %[src], 4 \n\t" - "ins %[temp4], %[temp0], 0, 5 \n\t" -#ifdef WEBP_SWAP_16BIT_CSP - "ush %[temp4], 0(%[dst]) \n\t" -#else - "wsbh %[temp4], %[temp4] \n\t" - "ush %[temp4], 0(%[dst]) \n\t" -#endif - "bne %[src], %[p_loop2_end], 1b \n\t" - " addiu %[dst], %[dst], 2 \n\t" - "2: \n\t" - ".set pop \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), - [dst]"+&r"(dst), [src]"+&r"(src) - : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) - : "memory" - ); -} - -static void ConvertBGRAToBGR(const uint32_t* src, - int num_pixels, uint8_t* dst) { - int temp0, temp1, temp2, temp3; - const uint32_t* const p_loop1_end = src + (num_pixels & ~3); - const uint32_t* const p_loop2_end = src + num_pixels; - __asm__ volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "beq %[src], %[p_loop1_end], 3f \n\t" - " nop \n\t" - "0: \n\t" - "lw %[temp0], 0(%[src]) \n\t" - "lw %[temp1], 4(%[src]) \n\t" - "lw %[temp2], 8(%[src]) \n\t" - "lw %[temp3], 12(%[src]) \n\t" - "ins %[temp0], %[temp1], 24, 8 \n\t" - "sra %[temp1], %[temp1], 8 \n\t" - "ins %[temp1], %[temp2], 16, 16 \n\t" - "sll %[temp2], %[temp2], 8 \n\t" - "balign %[temp3], %[temp2], 1 \n\t" - "addiu %[src], %[src], 16 \n\t" - "usw %[temp0], 0(%[dst]) \n\t" - "usw %[temp1], 4(%[dst]) \n\t" - "usw %[temp3], 8(%[dst]) \n\t" - "bne %[src], %[p_loop1_end], 0b \n\t" - " addiu %[dst], %[dst], 12 \n\t" - "3: \n\t" - "beq %[src], %[p_loop2_end], 2f \n\t" - " nop \n\t" - "1: \n\t" - "lw %[temp0], 0(%[src]) \n\t" - "addiu %[src], %[src], 4 \n\t" - "addiu %[dst], %[dst], 3 \n\t" - "ush %[temp0], -3(%[dst]) \n\t" - "sra %[temp0], %[temp0], 16 \n\t" - "bne %[src], %[p_loop2_end], 1b \n\t" - " sb %[temp0], -1(%[dst]) \n\t" - "2: \n\t" - ".set pop \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), - [temp3]"=&r"(temp3), [dst]"+&r"(dst), [src]"+&r"(src) - : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) - : "memory" - ); -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8LDspInitMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitMIPSdspR2(void) { - VP8LMapColor32b = MapARGB; - VP8LMapColor8b = MapAlpha; - VP8LPredictors[5] = Predictor5; - VP8LPredictors[6] = Predictor6; - VP8LPredictors[7] = Predictor7; - VP8LPredictors[8] = Predictor8; - VP8LPredictors[9] = Predictor9; - VP8LPredictors[10] = Predictor10; - VP8LPredictors[11] = Predictor11; - VP8LPredictors[12] = Predictor12; - VP8LPredictors[13] = Predictor13; - VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed; - VP8LTransformColorInverse = TransformColorInverse; - VP8LConvertBGRAToRGB = ConvertBGRAToRGB; - VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA; - VP8LConvertBGRAToRGBA4444 = ConvertBGRAToRGBA4444; - VP8LConvertBGRAToRGB565 = ConvertBGRAToRGB565; - VP8LConvertBGRAToBGR = ConvertBGRAToBGR; -} - -#else // !WEBP_USE_MIPS_DSP_R2 - -WEBP_DSP_INIT_STUB(VP8LDspInitMIPSdspR2) - -#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/Example/Pods/libwebp/src/dsp/lossless_neon.c b/Example/Pods/libwebp/src/dsp/lossless_neon.c deleted file mode 100644 index 6faccb8f..00000000 --- a/Example/Pods/libwebp/src/dsp/lossless_neon.c +++ /dev/null @@ -1,269 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// NEON variant of methods for lossless decoder -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_NEON) - -#include - -#include "./lossless.h" -#include "./neon.h" - -//------------------------------------------------------------------------------ -// Colorspace conversion functions - -#if !defined(WORK_AROUND_GCC) -// gcc 4.6.0 had some trouble (NDK-r9) with this code. We only use it for -// gcc-4.8.x at least. -static void ConvertBGRAToRGBA(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const uint32_t* const end = src + (num_pixels & ~15); - for (; src < end; src += 16) { - uint8x16x4_t pixel = vld4q_u8((uint8_t*)src); - // swap B and R. (VSWP d0,d2 has no intrinsics equivalent!) - const uint8x16_t tmp = pixel.val[0]; - pixel.val[0] = pixel.val[2]; - pixel.val[2] = tmp; - vst4q_u8(dst, pixel); - dst += 64; - } - VP8LConvertBGRAToRGBA_C(src, num_pixels & 15, dst); // left-overs -} - -static void ConvertBGRAToBGR(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const uint32_t* const end = src + (num_pixels & ~15); - for (; src < end; src += 16) { - const uint8x16x4_t pixel = vld4q_u8((uint8_t*)src); - const uint8x16x3_t tmp = { { pixel.val[0], pixel.val[1], pixel.val[2] } }; - vst3q_u8(dst, tmp); - dst += 48; - } - VP8LConvertBGRAToBGR_C(src, num_pixels & 15, dst); // left-overs -} - -static void ConvertBGRAToRGB(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const uint32_t* const end = src + (num_pixels & ~15); - for (; src < end; src += 16) { - const uint8x16x4_t pixel = vld4q_u8((uint8_t*)src); - const uint8x16x3_t tmp = { { pixel.val[2], pixel.val[1], pixel.val[0] } }; - vst3q_u8(dst, tmp); - dst += 48; - } - VP8LConvertBGRAToRGB_C(src, num_pixels & 15, dst); // left-overs -} - -#else // WORK_AROUND_GCC - -// gcc-4.6.0 fallback - -static const uint8_t kRGBAShuffle[8] = { 2, 1, 0, 3, 6, 5, 4, 7 }; - -static void ConvertBGRAToRGBA(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const uint32_t* const end = src + (num_pixels & ~1); - const uint8x8_t shuffle = vld1_u8(kRGBAShuffle); - for (; src < end; src += 2) { - const uint8x8_t pixels = vld1_u8((uint8_t*)src); - vst1_u8(dst, vtbl1_u8(pixels, shuffle)); - dst += 8; - } - VP8LConvertBGRAToRGBA_C(src, num_pixels & 1, dst); // left-overs -} - -static const uint8_t kBGRShuffle[3][8] = { - { 0, 1, 2, 4, 5, 6, 8, 9 }, - { 10, 12, 13, 14, 16, 17, 18, 20 }, - { 21, 22, 24, 25, 26, 28, 29, 30 } -}; - -static void ConvertBGRAToBGR(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const uint32_t* const end = src + (num_pixels & ~7); - const uint8x8_t shuffle0 = vld1_u8(kBGRShuffle[0]); - const uint8x8_t shuffle1 = vld1_u8(kBGRShuffle[1]); - const uint8x8_t shuffle2 = vld1_u8(kBGRShuffle[2]); - for (; src < end; src += 8) { - uint8x8x4_t pixels; - INIT_VECTOR4(pixels, - vld1_u8((const uint8_t*)(src + 0)), - vld1_u8((const uint8_t*)(src + 2)), - vld1_u8((const uint8_t*)(src + 4)), - vld1_u8((const uint8_t*)(src + 6))); - vst1_u8(dst + 0, vtbl4_u8(pixels, shuffle0)); - vst1_u8(dst + 8, vtbl4_u8(pixels, shuffle1)); - vst1_u8(dst + 16, vtbl4_u8(pixels, shuffle2)); - dst += 8 * 3; - } - VP8LConvertBGRAToBGR_C(src, num_pixels & 7, dst); // left-overs -} - -static const uint8_t kRGBShuffle[3][8] = { - { 2, 1, 0, 6, 5, 4, 10, 9 }, - { 8, 14, 13, 12, 18, 17, 16, 22 }, - { 21, 20, 26, 25, 24, 30, 29, 28 } -}; - -static void ConvertBGRAToRGB(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const uint32_t* const end = src + (num_pixels & ~7); - const uint8x8_t shuffle0 = vld1_u8(kRGBShuffle[0]); - const uint8x8_t shuffle1 = vld1_u8(kRGBShuffle[1]); - const uint8x8_t shuffle2 = vld1_u8(kRGBShuffle[2]); - for (; src < end; src += 8) { - uint8x8x4_t pixels; - INIT_VECTOR4(pixels, - vld1_u8((const uint8_t*)(src + 0)), - vld1_u8((const uint8_t*)(src + 2)), - vld1_u8((const uint8_t*)(src + 4)), - vld1_u8((const uint8_t*)(src + 6))); - vst1_u8(dst + 0, vtbl4_u8(pixels, shuffle0)); - vst1_u8(dst + 8, vtbl4_u8(pixels, shuffle1)); - vst1_u8(dst + 16, vtbl4_u8(pixels, shuffle2)); - dst += 8 * 3; - } - VP8LConvertBGRAToRGB_C(src, num_pixels & 7, dst); // left-overs -} - -#endif // !WORK_AROUND_GCC - -//------------------------------------------------------------------------------ -// Subtract-Green Transform - -// vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use -// non-standard versions there. -#if defined(__APPLE__) && defined(__aarch64__) && \ - defined(__apple_build_version__) && (__apple_build_version__< 6020037) -#define USE_VTBLQ -#endif - -#ifdef USE_VTBLQ -// 255 = byte will be zeroed -static const uint8_t kGreenShuffle[16] = { - 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255 -}; - -static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb, - const uint8x16_t shuffle) { - return vcombine_u8(vtbl1q_u8(argb, vget_low_u8(shuffle)), - vtbl1q_u8(argb, vget_high_u8(shuffle))); -} -#else // !USE_VTBLQ -// 255 = byte will be zeroed -static const uint8_t kGreenShuffle[8] = { 1, 255, 1, 255, 5, 255, 5, 255 }; - -static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb, - const uint8x8_t shuffle) { - return vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle), - vtbl1_u8(vget_high_u8(argb), shuffle)); -} -#endif // USE_VTBLQ - -static void AddGreenToBlueAndRed(uint32_t* argb_data, int num_pixels) { - const uint32_t* const end = argb_data + (num_pixels & ~3); -#ifdef USE_VTBLQ - const uint8x16_t shuffle = vld1q_u8(kGreenShuffle); -#else - const uint8x8_t shuffle = vld1_u8(kGreenShuffle); -#endif - for (; argb_data < end; argb_data += 4) { - const uint8x16_t argb = vld1q_u8((uint8_t*)argb_data); - const uint8x16_t greens = DoGreenShuffle(argb, shuffle); - vst1q_u8((uint8_t*)argb_data, vaddq_u8(argb, greens)); - } - // fallthrough and finish off with plain-C - VP8LAddGreenToBlueAndRed_C(argb_data, num_pixels & 3); -} - -//------------------------------------------------------------------------------ -// Color Transform - -static void TransformColorInverse(const VP8LMultipliers* const m, - uint32_t* argb_data, int num_pixels) { - // sign-extended multiplying constants, pre-shifted by 6. -#define CST(X) (((int16_t)(m->X << 8)) >> 6) - const int16_t rb[8] = { - CST(green_to_blue_), CST(green_to_red_), - CST(green_to_blue_), CST(green_to_red_), - CST(green_to_blue_), CST(green_to_red_), - CST(green_to_blue_), CST(green_to_red_) - }; - const int16x8_t mults_rb = vld1q_s16(rb); - const int16_t b2[8] = { - 0, CST(red_to_blue_), 0, CST(red_to_blue_), - 0, CST(red_to_blue_), 0, CST(red_to_blue_), - }; - const int16x8_t mults_b2 = vld1q_s16(b2); -#undef CST -#ifdef USE_VTBLQ - static const uint8_t kg0g0[16] = { - 255, 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13 - }; - const uint8x16_t shuffle = vld1q_u8(kg0g0); -#else - static const uint8_t k0g0g[8] = { 255, 1, 255, 1, 255, 5, 255, 5 }; - const uint8x8_t shuffle = vld1_u8(k0g0g); -#endif - const uint32x4_t mask_ag = vdupq_n_u32(0xff00ff00u); - int i; - for (i = 0; i + 4 <= num_pixels; i += 4) { - const uint8x16_t in = vld1q_u8((uint8_t*)(argb_data + i)); - const uint32x4_t a0g0 = vandq_u32(vreinterpretq_u32_u8(in), mask_ag); - // 0 g 0 g - const uint8x16_t greens = DoGreenShuffle(in, shuffle); - // x dr x db1 - const int16x8_t A = vqdmulhq_s16(vreinterpretq_s16_u8(greens), mults_rb); - // x r' x b' - const int8x16_t B = vaddq_s8(vreinterpretq_s8_u8(in), - vreinterpretq_s8_s16(A)); - // r' 0 b' 0 - const int16x8_t C = vshlq_n_s16(vreinterpretq_s16_s8(B), 8); - // x db2 0 0 - const int16x8_t D = vqdmulhq_s16(C, mults_b2); - // 0 x db2 0 - const uint32x4_t E = vshrq_n_u32(vreinterpretq_u32_s16(D), 8); - // r' x b'' 0 - const int8x16_t F = vaddq_s8(vreinterpretq_s8_u32(E), - vreinterpretq_s8_s16(C)); - // 0 r' 0 b'' - const uint16x8_t G = vshrq_n_u16(vreinterpretq_u16_s8(F), 8); - const uint32x4_t out = vorrq_u32(vreinterpretq_u32_u16(G), a0g0); - vst1q_u32(argb_data + i, out); - } - // Fall-back to C-version for left-overs. - VP8LTransformColorInverse_C(m, argb_data + i, num_pixels - i); -} - -#undef USE_VTBLQ - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8LDspInitNEON(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitNEON(void) { - VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA; - VP8LConvertBGRAToBGR = ConvertBGRAToBGR; - VP8LConvertBGRAToRGB = ConvertBGRAToRGB; - - VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed; - VP8LTransformColorInverse = TransformColorInverse; -} - -#else // !WEBP_USE_NEON - -WEBP_DSP_INIT_STUB(VP8LDspInitNEON) - -#endif // WEBP_USE_NEON diff --git a/Example/Pods/libwebp/src/dsp/lossless_sse2.c b/Example/Pods/libwebp/src/dsp/lossless_sse2.c deleted file mode 100644 index 2d016c29..00000000 --- a/Example/Pods/libwebp/src/dsp/lossless_sse2.c +++ /dev/null @@ -1,372 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// SSE2 variant of methods for lossless decoder -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE2) -#include -#include -#include "./lossless.h" - -//------------------------------------------------------------------------------ -// Predictor Transform - -static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1, - uint32_t c2) { - const __m128i zero = _mm_setzero_si128(); - const __m128i C0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c0), zero); - const __m128i C1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c1), zero); - const __m128i C2 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c2), zero); - const __m128i V1 = _mm_add_epi16(C0, C1); - const __m128i V2 = _mm_sub_epi16(V1, C2); - const __m128i b = _mm_packus_epi16(V2, V2); - const uint32_t output = _mm_cvtsi128_si32(b); - return output; -} - -static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1, - uint32_t c2) { - const __m128i zero = _mm_setzero_si128(); - const __m128i C0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c0), zero); - const __m128i C1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c1), zero); - const __m128i B0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c2), zero); - const __m128i avg = _mm_add_epi16(C1, C0); - const __m128i A0 = _mm_srli_epi16(avg, 1); - const __m128i A1 = _mm_sub_epi16(A0, B0); - const __m128i BgtA = _mm_cmpgt_epi16(B0, A0); - const __m128i A2 = _mm_sub_epi16(A1, BgtA); - const __m128i A3 = _mm_srai_epi16(A2, 1); - const __m128i A4 = _mm_add_epi16(A0, A3); - const __m128i A5 = _mm_packus_epi16(A4, A4); - const uint32_t output = _mm_cvtsi128_si32(A5); - return output; -} - -static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) { - int pa_minus_pb; - const __m128i zero = _mm_setzero_si128(); - const __m128i A0 = _mm_cvtsi32_si128(a); - const __m128i B0 = _mm_cvtsi32_si128(b); - const __m128i C0 = _mm_cvtsi32_si128(c); - const __m128i AC0 = _mm_subs_epu8(A0, C0); - const __m128i CA0 = _mm_subs_epu8(C0, A0); - const __m128i BC0 = _mm_subs_epu8(B0, C0); - const __m128i CB0 = _mm_subs_epu8(C0, B0); - const __m128i AC = _mm_or_si128(AC0, CA0); - const __m128i BC = _mm_or_si128(BC0, CB0); - const __m128i pa = _mm_unpacklo_epi8(AC, zero); // |a - c| - const __m128i pb = _mm_unpacklo_epi8(BC, zero); // |b - c| - const __m128i diff = _mm_sub_epi16(pb, pa); - { - int16_t out[8]; - _mm_storeu_si128((__m128i*)out, diff); - pa_minus_pb = out[0] + out[1] + out[2] + out[3]; - } - return (pa_minus_pb <= 0) ? a : b; -} - -static WEBP_INLINE __m128i Average2_128i(uint32_t a0, uint32_t a1) { - const __m128i zero = _mm_setzero_si128(); - const __m128i A0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(a0), zero); - const __m128i A1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(a1), zero); - const __m128i sum = _mm_add_epi16(A1, A0); - const __m128i avg = _mm_srli_epi16(sum, 1); - return avg; -} - -static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) { - const __m128i avg = Average2_128i(a0, a1); - const __m128i A2 = _mm_packus_epi16(avg, avg); - const uint32_t output = _mm_cvtsi128_si32(A2); - return output; -} - -static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) { - const __m128i zero = _mm_setzero_si128(); - const __m128i avg1 = Average2_128i(a0, a2); - const __m128i A1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(a1), zero); - const __m128i sum = _mm_add_epi16(avg1, A1); - const __m128i avg2 = _mm_srli_epi16(sum, 1); - const __m128i A2 = _mm_packus_epi16(avg2, avg2); - const uint32_t output = _mm_cvtsi128_si32(A2); - return output; -} - -static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1, - uint32_t a2, uint32_t a3) { - const __m128i avg1 = Average2_128i(a0, a1); - const __m128i avg2 = Average2_128i(a2, a3); - const __m128i sum = _mm_add_epi16(avg2, avg1); - const __m128i avg3 = _mm_srli_epi16(sum, 1); - const __m128i A0 = _mm_packus_epi16(avg3, avg3); - const uint32_t output = _mm_cvtsi128_si32(A0); - return output; -} - -static uint32_t Predictor5(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average3(left, top[0], top[1]); - return pred; -} -static uint32_t Predictor6(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2(left, top[-1]); - return pred; -} -static uint32_t Predictor7(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2(left, top[0]); - return pred; -} -static uint32_t Predictor8(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2(top[-1], top[0]); - (void)left; - return pred; -} -static uint32_t Predictor9(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2(top[0], top[1]); - (void)left; - return pred; -} -static uint32_t Predictor10(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average4(left, top[-1], top[0], top[1]); - return pred; -} -static uint32_t Predictor11(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Select(top[0], left, top[-1]); - return pred; -} -static uint32_t Predictor12(uint32_t left, const uint32_t* const top) { - const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]); - return pred; -} -static uint32_t Predictor13(uint32_t left, const uint32_t* const top) { - const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]); - return pred; -} - -//------------------------------------------------------------------------------ -// Subtract-Green Transform - -static void AddGreenToBlueAndRed(uint32_t* argb_data, int num_pixels) { - int i; - for (i = 0; i + 4 <= num_pixels; i += 4) { - const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb - const __m128i A = _mm_srli_epi16(in, 8); // 0 a 0 g - const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0)); - const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // 0g0g - const __m128i out = _mm_add_epi8(in, C); - _mm_storeu_si128((__m128i*)&argb_data[i], out); - } - // fallthrough and finish off with plain-C - VP8LAddGreenToBlueAndRed_C(argb_data + i, num_pixels - i); -} - -//------------------------------------------------------------------------------ -// Color Transform - -static void TransformColorInverse(const VP8LMultipliers* const m, - uint32_t* argb_data, int num_pixels) { - // sign-extended multiplying constants, pre-shifted by 5. -#define CST(X) (((int16_t)(m->X << 8)) >> 5) // sign-extend - const __m128i mults_rb = _mm_set_epi16( - CST(green_to_red_), CST(green_to_blue_), - CST(green_to_red_), CST(green_to_blue_), - CST(green_to_red_), CST(green_to_blue_), - CST(green_to_red_), CST(green_to_blue_)); - const __m128i mults_b2 = _mm_set_epi16( - CST(red_to_blue_), 0, CST(red_to_blue_), 0, - CST(red_to_blue_), 0, CST(red_to_blue_), 0); -#undef CST - const __m128i mask_ag = _mm_set1_epi32(0xff00ff00); // alpha-green masks - int i; - for (i = 0; i + 4 <= num_pixels; i += 4) { - const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb - const __m128i A = _mm_and_si128(in, mask_ag); // a 0 g 0 - const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0)); - const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // g0g0 - const __m128i D = _mm_mulhi_epi16(C, mults_rb); // x dr x db1 - const __m128i E = _mm_add_epi8(in, D); // x r' x b' - const __m128i F = _mm_slli_epi16(E, 8); // r' 0 b' 0 - const __m128i G = _mm_mulhi_epi16(F, mults_b2); // x db2 0 0 - const __m128i H = _mm_srli_epi32(G, 8); // 0 x db2 0 - const __m128i I = _mm_add_epi8(H, F); // r' x b'' 0 - const __m128i J = _mm_srli_epi16(I, 8); // 0 r' 0 b'' - const __m128i out = _mm_or_si128(J, A); - _mm_storeu_si128((__m128i*)&argb_data[i], out); - } - // Fall-back to C-version for left-overs. - VP8LTransformColorInverse_C(m, argb_data + i, num_pixels - i); -} - -//------------------------------------------------------------------------------ -// Color-space conversion functions - -static void ConvertBGRAToRGBA(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const __m128i* in = (const __m128i*)src; - __m128i* out = (__m128i*)dst; - while (num_pixels >= 8) { - const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3 - const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7 - const __m128i v0l = _mm_unpacklo_epi8(bgra0, bgra4); // b0b4g0g4r0r4a0a4... - const __m128i v0h = _mm_unpackhi_epi8(bgra0, bgra4); // b2b6g2g6r2r6a2a6... - const __m128i v1l = _mm_unpacklo_epi8(v0l, v0h); // b0b2b4b6g0g2g4g6... - const __m128i v1h = _mm_unpackhi_epi8(v0l, v0h); // b1b3b5b7g1g3g5g7... - const __m128i v2l = _mm_unpacklo_epi8(v1l, v1h); // b0...b7 | g0...g7 - const __m128i v2h = _mm_unpackhi_epi8(v1l, v1h); // r0...r7 | a0...a7 - const __m128i ga0 = _mm_unpackhi_epi64(v2l, v2h); // g0...g7 | a0...a7 - const __m128i rb0 = _mm_unpacklo_epi64(v2h, v2l); // r0...r7 | b0...b7 - const __m128i rg0 = _mm_unpacklo_epi8(rb0, ga0); // r0g0r1g1 ... r6g6r7g7 - const __m128i ba0 = _mm_unpackhi_epi8(rb0, ga0); // b0a0b1a1 ... b6a6b7a7 - const __m128i rgba0 = _mm_unpacklo_epi16(rg0, ba0); // rgba0|rgba1... - const __m128i rgba4 = _mm_unpackhi_epi16(rg0, ba0); // rgba4|rgba5... - _mm_storeu_si128(out++, rgba0); - _mm_storeu_si128(out++, rgba4); - num_pixels -= 8; - } - // left-overs - VP8LConvertBGRAToRGBA_C((const uint32_t*)in, num_pixels, (uint8_t*)out); -} - -static void ConvertBGRAToRGBA4444(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const __m128i mask_0x0f = _mm_set1_epi8(0x0f); - const __m128i mask_0xf0 = _mm_set1_epi8(0xf0); - const __m128i* in = (const __m128i*)src; - __m128i* out = (__m128i*)dst; - while (num_pixels >= 8) { - const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3 - const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7 - const __m128i v0l = _mm_unpacklo_epi8(bgra0, bgra4); // b0b4g0g4r0r4a0a4... - const __m128i v0h = _mm_unpackhi_epi8(bgra0, bgra4); // b2b6g2g6r2r6a2a6... - const __m128i v1l = _mm_unpacklo_epi8(v0l, v0h); // b0b2b4b6g0g2g4g6... - const __m128i v1h = _mm_unpackhi_epi8(v0l, v0h); // b1b3b5b7g1g3g5g7... - const __m128i v2l = _mm_unpacklo_epi8(v1l, v1h); // b0...b7 | g0...g7 - const __m128i v2h = _mm_unpackhi_epi8(v1l, v1h); // r0...r7 | a0...a7 - const __m128i ga0 = _mm_unpackhi_epi64(v2l, v2h); // g0...g7 | a0...a7 - const __m128i rb0 = _mm_unpacklo_epi64(v2h, v2l); // r0...r7 | b0...b7 - const __m128i ga1 = _mm_srli_epi16(ga0, 4); // g0-|g1-|...|a6-|a7- - const __m128i rb1 = _mm_and_si128(rb0, mask_0xf0); // -r0|-r1|...|-b6|-a7 - const __m128i ga2 = _mm_and_si128(ga1, mask_0x0f); // g0-|g1-|...|a6-|a7- - const __m128i rgba0 = _mm_or_si128(ga2, rb1); // rg0..rg7 | ba0..ba7 - const __m128i rgba1 = _mm_srli_si128(rgba0, 8); // ba0..ba7 | 0 -#ifdef WEBP_SWAP_16BIT_CSP - const __m128i rgba = _mm_unpacklo_epi8(rgba1, rgba0); // barg0...barg7 -#else - const __m128i rgba = _mm_unpacklo_epi8(rgba0, rgba1); // rgba0...rgba7 -#endif - _mm_storeu_si128(out++, rgba); - num_pixels -= 8; - } - // left-overs - VP8LConvertBGRAToRGBA4444_C((const uint32_t*)in, num_pixels, (uint8_t*)out); -} - -static void ConvertBGRAToRGB565(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const __m128i mask_0xe0 = _mm_set1_epi8(0xe0); - const __m128i mask_0xf8 = _mm_set1_epi8(0xf8); - const __m128i mask_0x07 = _mm_set1_epi8(0x07); - const __m128i* in = (const __m128i*)src; - __m128i* out = (__m128i*)dst; - while (num_pixels >= 8) { - const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3 - const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7 - const __m128i v0l = _mm_unpacklo_epi8(bgra0, bgra4); // b0b4g0g4r0r4a0a4... - const __m128i v0h = _mm_unpackhi_epi8(bgra0, bgra4); // b2b6g2g6r2r6a2a6... - const __m128i v1l = _mm_unpacklo_epi8(v0l, v0h); // b0b2b4b6g0g2g4g6... - const __m128i v1h = _mm_unpackhi_epi8(v0l, v0h); // b1b3b5b7g1g3g5g7... - const __m128i v2l = _mm_unpacklo_epi8(v1l, v1h); // b0...b7 | g0...g7 - const __m128i v2h = _mm_unpackhi_epi8(v1l, v1h); // r0...r7 | a0...a7 - const __m128i ga0 = _mm_unpackhi_epi64(v2l, v2h); // g0...g7 | a0...a7 - const __m128i rb0 = _mm_unpacklo_epi64(v2h, v2l); // r0...r7 | b0...b7 - const __m128i rb1 = _mm_and_si128(rb0, mask_0xf8); // -r0..-r7|-b0..-b7 - const __m128i g_lo1 = _mm_srli_epi16(ga0, 5); - const __m128i g_lo2 = _mm_and_si128(g_lo1, mask_0x07); // g0-...g7-|xx (3b) - const __m128i g_hi1 = _mm_slli_epi16(ga0, 3); - const __m128i g_hi2 = _mm_and_si128(g_hi1, mask_0xe0); // -g0...-g7|xx (3b) - const __m128i b0 = _mm_srli_si128(rb1, 8); // -b0...-b7|0 - const __m128i rg1 = _mm_or_si128(rb1, g_lo2); // gr0...gr7|xx - const __m128i b1 = _mm_srli_epi16(b0, 3); - const __m128i gb1 = _mm_or_si128(b1, g_hi2); // bg0...bg7|xx -#ifdef WEBP_SWAP_16BIT_CSP - const __m128i rgba = _mm_unpacklo_epi8(gb1, rg1); // rggb0...rggb7 -#else - const __m128i rgba = _mm_unpacklo_epi8(rg1, gb1); // bgrb0...bgrb7 -#endif - _mm_storeu_si128(out++, rgba); - num_pixels -= 8; - } - // left-overs - VP8LConvertBGRAToRGB565_C((const uint32_t*)in, num_pixels, (uint8_t*)out); -} - -static void ConvertBGRAToBGR(const uint32_t* src, - int num_pixels, uint8_t* dst) { - const __m128i mask_l = _mm_set_epi32(0, 0x00ffffff, 0, 0x00ffffff); - const __m128i mask_h = _mm_set_epi32(0x00ffffff, 0, 0x00ffffff, 0); - const __m128i* in = (const __m128i*)src; - const uint8_t* const end = dst + num_pixels * 3; - // the last storel_epi64 below writes 8 bytes starting at offset 18 - while (dst + 26 <= end) { - const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3 - const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7 - const __m128i a0l = _mm_and_si128(bgra0, mask_l); // bgr0|0|bgr0|0 - const __m128i a4l = _mm_and_si128(bgra4, mask_l); // bgr0|0|bgr0|0 - const __m128i a0h = _mm_and_si128(bgra0, mask_h); // 0|bgr0|0|bgr0 - const __m128i a4h = _mm_and_si128(bgra4, mask_h); // 0|bgr0|0|bgr0 - const __m128i b0h = _mm_srli_epi64(a0h, 8); // 000b|gr00|000b|gr00 - const __m128i b4h = _mm_srli_epi64(a4h, 8); // 000b|gr00|000b|gr00 - const __m128i c0 = _mm_or_si128(a0l, b0h); // rgbrgb00|rgbrgb00 - const __m128i c4 = _mm_or_si128(a4l, b4h); // rgbrgb00|rgbrgb00 - const __m128i c2 = _mm_srli_si128(c0, 8); - const __m128i c6 = _mm_srli_si128(c4, 8); - _mm_storel_epi64((__m128i*)(dst + 0), c0); - _mm_storel_epi64((__m128i*)(dst + 6), c2); - _mm_storel_epi64((__m128i*)(dst + 12), c4); - _mm_storel_epi64((__m128i*)(dst + 18), c6); - dst += 24; - num_pixels -= 8; - } - // left-overs - VP8LConvertBGRAToBGR_C((const uint32_t*)in, num_pixels, dst); -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void VP8LDspInitSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitSSE2(void) { - VP8LPredictors[5] = Predictor5; - VP8LPredictors[6] = Predictor6; - VP8LPredictors[7] = Predictor7; - VP8LPredictors[8] = Predictor8; - VP8LPredictors[9] = Predictor9; - VP8LPredictors[10] = Predictor10; - VP8LPredictors[11] = Predictor11; - VP8LPredictors[12] = Predictor12; - VP8LPredictors[13] = Predictor13; - - VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed; - VP8LTransformColorInverse = TransformColorInverse; - - VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA; - VP8LConvertBGRAToRGBA4444 = ConvertBGRAToRGBA4444; - VP8LConvertBGRAToRGB565 = ConvertBGRAToRGB565; - VP8LConvertBGRAToBGR = ConvertBGRAToBGR; -} - -#else // !WEBP_USE_SSE2 - -WEBP_DSP_INIT_STUB(VP8LDspInitSSE2) - -#endif // WEBP_USE_SSE2 diff --git a/Example/Pods/libwebp/src/dsp/mips_macro.h b/Example/Pods/libwebp/src/dsp/mips_macro.h deleted file mode 100644 index 44aba9b7..00000000 --- a/Example/Pods/libwebp/src/dsp/mips_macro.h +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// MIPS common macros - -#ifndef WEBP_DSP_MIPS_MACRO_H_ -#define WEBP_DSP_MIPS_MACRO_H_ - -#if defined(__GNUC__) && defined(__ANDROID__) && LOCAL_GCC_VERSION == 0x409 -#define WORK_AROUND_GCC -#endif - -#define STR(s) #s -#define XSTR(s) STR(s) - -// O0[31..16 | 15..0] = I0[31..16 | 15..0] + I1[31..16 | 15..0] -// O1[31..16 | 15..0] = I0[31..16 | 15..0] - I1[31..16 | 15..0] -// O - output -// I - input (macro doesn't change it) -#define ADD_SUB_HALVES(O0, O1, \ - I0, I1) \ - "addq.ph %[" #O0 "], %[" #I0 "], %[" #I1 "] \n\t" \ - "subq.ph %[" #O1 "], %[" #I0 "], %[" #I1 "] \n\t" - -// O - output -// I - input (macro doesn't change it) -// I[0/1] - offset in bytes -#define LOAD_IN_X2(O0, O1, \ - I0, I1) \ - "lh %[" #O0 "], " #I0 "(%[in]) \n\t" \ - "lh %[" #O1 "], " #I1 "(%[in]) \n\t" - -// I0 - location -// I1..I9 - offsets in bytes -#define LOAD_WITH_OFFSET_X4(O0, O1, O2, O3, \ - I0, I1, I2, I3, I4, I5, I6, I7, I8, I9) \ - "ulw %[" #O0 "], " #I1 "+" XSTR(I9) "*" #I5 "(%[" #I0 "]) \n\t" \ - "ulw %[" #O1 "], " #I2 "+" XSTR(I9) "*" #I6 "(%[" #I0 "]) \n\t" \ - "ulw %[" #O2 "], " #I3 "+" XSTR(I9) "*" #I7 "(%[" #I0 "]) \n\t" \ - "ulw %[" #O3 "], " #I4 "+" XSTR(I9) "*" #I8 "(%[" #I0 "]) \n\t" - -// O - output -// IO - input/output -// I - input (macro doesn't change it) -#define MUL_SHIFT_SUM(O0, O1, O2, O3, O4, O5, O6, O7, \ - IO0, IO1, IO2, IO3, \ - I0, I1, I2, I3, I4, I5, I6, I7) \ - "mul %[" #O0 "], %[" #I0 "], %[kC2] \n\t" \ - "mul %[" #O1 "], %[" #I0 "], %[kC1] \n\t" \ - "mul %[" #O2 "], %[" #I1 "], %[kC2] \n\t" \ - "mul %[" #O3 "], %[" #I1 "], %[kC1] \n\t" \ - "mul %[" #O4 "], %[" #I2 "], %[kC2] \n\t" \ - "mul %[" #O5 "], %[" #I2 "], %[kC1] \n\t" \ - "mul %[" #O6 "], %[" #I3 "], %[kC2] \n\t" \ - "mul %[" #O7 "], %[" #I3 "], %[kC1] \n\t" \ - "sra %[" #O0 "], %[" #O0 "], 16 \n\t" \ - "sra %[" #O1 "], %[" #O1 "], 16 \n\t" \ - "sra %[" #O2 "], %[" #O2 "], 16 \n\t" \ - "sra %[" #O3 "], %[" #O3 "], 16 \n\t" \ - "sra %[" #O4 "], %[" #O4 "], 16 \n\t" \ - "sra %[" #O5 "], %[" #O5 "], 16 \n\t" \ - "sra %[" #O6 "], %[" #O6 "], 16 \n\t" \ - "sra %[" #O7 "], %[" #O7 "], 16 \n\t" \ - "addu %[" #IO0 "], %[" #IO0 "], %[" #I4 "] \n\t" \ - "addu %[" #IO1 "], %[" #IO1 "], %[" #I5 "] \n\t" \ - "subu %[" #IO2 "], %[" #IO2 "], %[" #I6 "] \n\t" \ - "subu %[" #IO3 "], %[" #IO3 "], %[" #I7 "] \n\t" - -// O - output -// I - input (macro doesn't change it) -#define INSERT_HALF_X2(O0, O1, \ - I0, I1) \ - "ins %[" #O0 "], %[" #I0 "], 16, 16 \n\t" \ - "ins %[" #O1 "], %[" #I1 "], 16, 16 \n\t" - -// O - output -// I - input (macro doesn't change it) -#define SRA_16(O0, O1, O2, O3, \ - I0, I1, I2, I3) \ - "sra %[" #O0 "], %[" #I0 "], 16 \n\t" \ - "sra %[" #O1 "], %[" #I1 "], 16 \n\t" \ - "sra %[" #O2 "], %[" #I2 "], 16 \n\t" \ - "sra %[" #O3 "], %[" #I3 "], 16 \n\t" - -// temp0[31..16 | 15..0] = temp8[31..16 | 15..0] + temp12[31..16 | 15..0] -// temp1[31..16 | 15..0] = temp8[31..16 | 15..0] - temp12[31..16 | 15..0] -// temp0[31..16 | 15..0] = temp0[31..16 >> 3 | 15..0 >> 3] -// temp1[31..16 | 15..0] = temp1[31..16 >> 3 | 15..0 >> 3] -// O - output -// I - input (macro doesn't change it) -#define SHIFT_R_SUM_X2(O0, O1, O2, O3, O4, O5, O6, O7, \ - I0, I1, I2, I3, I4, I5, I6, I7) \ - "addq.ph %[" #O0 "], %[" #I0 "], %[" #I4 "] \n\t" \ - "subq.ph %[" #O1 "], %[" #I0 "], %[" #I4 "] \n\t" \ - "addq.ph %[" #O2 "], %[" #I1 "], %[" #I5 "] \n\t" \ - "subq.ph %[" #O3 "], %[" #I1 "], %[" #I5 "] \n\t" \ - "addq.ph %[" #O4 "], %[" #I2 "], %[" #I6 "] \n\t" \ - "subq.ph %[" #O5 "], %[" #I2 "], %[" #I6 "] \n\t" \ - "addq.ph %[" #O6 "], %[" #I3 "], %[" #I7 "] \n\t" \ - "subq.ph %[" #O7 "], %[" #I3 "], %[" #I7 "] \n\t" \ - "shra.ph %[" #O0 "], %[" #O0 "], 3 \n\t" \ - "shra.ph %[" #O1 "], %[" #O1 "], 3 \n\t" \ - "shra.ph %[" #O2 "], %[" #O2 "], 3 \n\t" \ - "shra.ph %[" #O3 "], %[" #O3 "], 3 \n\t" \ - "shra.ph %[" #O4 "], %[" #O4 "], 3 \n\t" \ - "shra.ph %[" #O5 "], %[" #O5 "], 3 \n\t" \ - "shra.ph %[" #O6 "], %[" #O6 "], 3 \n\t" \ - "shra.ph %[" #O7 "], %[" #O7 "], 3 \n\t" - -// precrq.ph.w temp0, temp8, temp2 -// temp0 = temp8[31..16] | temp2[31..16] -// ins temp2, temp8, 16, 16 -// temp2 = temp8[31..16] | temp2[15..0] -// O - output -// IO - input/output -// I - input (macro doesn't change it) -#define PACK_2_HALVES_TO_WORD(O0, O1, O2, O3, \ - IO0, IO1, IO2, IO3, \ - I0, I1, I2, I3) \ - "precrq.ph.w %[" #O0 "], %[" #I0 "], %[" #IO0 "] \n\t" \ - "precrq.ph.w %[" #O1 "], %[" #I1 "], %[" #IO1 "] \n\t" \ - "ins %[" #IO0 "], %[" #I0 "], 16, 16 \n\t" \ - "ins %[" #IO1 "], %[" #I1 "], 16, 16 \n\t" \ - "precrq.ph.w %[" #O2 "], %[" #I2 "], %[" #IO2 "] \n\t" \ - "precrq.ph.w %[" #O3 "], %[" #I3 "], %[" #IO3 "] \n\t" \ - "ins %[" #IO2 "], %[" #I2 "], 16, 16 \n\t" \ - "ins %[" #IO3 "], %[" #I3 "], 16, 16 \n\t" - -// preceu.ph.qbr temp0, temp8 -// temp0 = 0 | 0 | temp8[23..16] | temp8[7..0] -// preceu.ph.qbl temp1, temp8 -// temp1 = temp8[23..16] | temp8[7..0] | 0 | 0 -// O - output -// I - input (macro doesn't change it) -#define CONVERT_2_BYTES_TO_HALF(O0, O1, O2, O3, O4, O5, O6, O7, \ - I0, I1, I2, I3) \ - "preceu.ph.qbr %[" #O0 "], %[" #I0 "] \n\t" \ - "preceu.ph.qbl %[" #O1 "], %[" #I0 "] \n\t" \ - "preceu.ph.qbr %[" #O2 "], %[" #I1 "] \n\t" \ - "preceu.ph.qbl %[" #O3 "], %[" #I1 "] \n\t" \ - "preceu.ph.qbr %[" #O4 "], %[" #I2 "] \n\t" \ - "preceu.ph.qbl %[" #O5 "], %[" #I2 "] \n\t" \ - "preceu.ph.qbr %[" #O6 "], %[" #I3 "] \n\t" \ - "preceu.ph.qbl %[" #O7 "], %[" #I3 "] \n\t" - -// temp0[31..16 | 15..0] = temp0[31..16 | 15..0] + temp8[31..16 | 15..0] -// temp0[31..16 | 15..0] = temp0[31..16 <<(s) 7 | 15..0 <<(s) 7] -// temp1..temp7 same as temp0 -// precrqu_s.qb.ph temp0, temp1, temp0: -// temp0 = temp1[31..24] | temp1[15..8] | temp0[31..24] | temp0[15..8] -// store temp0 to dst -// IO - input/output -// I - input (macro doesn't change it) -#define STORE_SAT_SUM_X2(IO0, IO1, IO2, IO3, IO4, IO5, IO6, IO7, \ - I0, I1, I2, I3, I4, I5, I6, I7, \ - I8, I9, I10, I11, I12, I13) \ - "addq.ph %[" #IO0 "], %[" #IO0 "], %[" #I0 "] \n\t" \ - "addq.ph %[" #IO1 "], %[" #IO1 "], %[" #I1 "] \n\t" \ - "addq.ph %[" #IO2 "], %[" #IO2 "], %[" #I2 "] \n\t" \ - "addq.ph %[" #IO3 "], %[" #IO3 "], %[" #I3 "] \n\t" \ - "addq.ph %[" #IO4 "], %[" #IO4 "], %[" #I4 "] \n\t" \ - "addq.ph %[" #IO5 "], %[" #IO5 "], %[" #I5 "] \n\t" \ - "addq.ph %[" #IO6 "], %[" #IO6 "], %[" #I6 "] \n\t" \ - "addq.ph %[" #IO7 "], %[" #IO7 "], %[" #I7 "] \n\t" \ - "shll_s.ph %[" #IO0 "], %[" #IO0 "], 7 \n\t" \ - "shll_s.ph %[" #IO1 "], %[" #IO1 "], 7 \n\t" \ - "shll_s.ph %[" #IO2 "], %[" #IO2 "], 7 \n\t" \ - "shll_s.ph %[" #IO3 "], %[" #IO3 "], 7 \n\t" \ - "shll_s.ph %[" #IO4 "], %[" #IO4 "], 7 \n\t" \ - "shll_s.ph %[" #IO5 "], %[" #IO5 "], 7 \n\t" \ - "shll_s.ph %[" #IO6 "], %[" #IO6 "], 7 \n\t" \ - "shll_s.ph %[" #IO7 "], %[" #IO7 "], 7 \n\t" \ - "precrqu_s.qb.ph %[" #IO0 "], %[" #IO1 "], %[" #IO0 "] \n\t" \ - "precrqu_s.qb.ph %[" #IO2 "], %[" #IO3 "], %[" #IO2 "] \n\t" \ - "precrqu_s.qb.ph %[" #IO4 "], %[" #IO5 "], %[" #IO4 "] \n\t" \ - "precrqu_s.qb.ph %[" #IO6 "], %[" #IO7 "], %[" #IO6 "] \n\t" \ - "usw %[" #IO0 "], " XSTR(I13) "*" #I9 "(%[" #I8 "]) \n\t" \ - "usw %[" #IO2 "], " XSTR(I13) "*" #I10 "(%[" #I8 "]) \n\t" \ - "usw %[" #IO4 "], " XSTR(I13) "*" #I11 "(%[" #I8 "]) \n\t" \ - "usw %[" #IO6 "], " XSTR(I13) "*" #I12 "(%[" #I8 "]) \n\t" - -#define OUTPUT_EARLY_CLOBBER_REGS_10() \ - : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), \ - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6), \ - [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), [temp9]"=&r"(temp9), \ - [temp10]"=&r"(temp10) - -#define OUTPUT_EARLY_CLOBBER_REGS_18() \ - OUTPUT_EARLY_CLOBBER_REGS_10(), \ - [temp11]"=&r"(temp11), [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), \ - [temp14]"=&r"(temp14), [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), \ - [temp17]"=&r"(temp17), [temp18]"=&r"(temp18) - -#endif // WEBP_DSP_MIPS_MACRO_H_ diff --git a/Example/Pods/libwebp/src/dsp/neon.h b/Example/Pods/libwebp/src/dsp/neon.h deleted file mode 100644 index 0a062668..00000000 --- a/Example/Pods/libwebp/src/dsp/neon.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// NEON common code. - -#ifndef WEBP_DSP_NEON_H_ -#define WEBP_DSP_NEON_H_ - -#include - -#include "./dsp.h" - -// Right now, some intrinsics functions seem slower, so we disable them -// everywhere except aarch64 where the inline assembly is incompatible. -#if defined(__aarch64__) -#define WEBP_USE_INTRINSICS // use intrinsics when possible -#endif - -#define INIT_VECTOR2(v, a, b) do { \ - v.val[0] = a; \ - v.val[1] = b; \ -} while (0) - -#define INIT_VECTOR3(v, a, b, c) do { \ - v.val[0] = a; \ - v.val[1] = b; \ - v.val[2] = c; \ -} while (0) - -#define INIT_VECTOR4(v, a, b, c, d) do { \ - v.val[0] = a; \ - v.val[1] = b; \ - v.val[2] = c; \ - v.val[3] = d; \ -} while (0) - -// if using intrinsics, this flag avoids some functions that make gcc-4.6.3 -// crash ("internal compiler error: in immed_double_const, at emit-rtl."). -// (probably similar to gcc.gnu.org/bugzilla/show_bug.cgi?id=48183) -#if !(LOCAL_GCC_PREREQ(4,8) || defined(__aarch64__)) -#define WORK_AROUND_GCC -#endif - -static WEBP_INLINE int32x4x4_t Transpose4x4(const int32x4x4_t rows) { - uint64x2x2_t row01, row23; - - row01.val[0] = vreinterpretq_u64_s32(rows.val[0]); - row01.val[1] = vreinterpretq_u64_s32(rows.val[1]); - row23.val[0] = vreinterpretq_u64_s32(rows.val[2]); - row23.val[1] = vreinterpretq_u64_s32(rows.val[3]); - // Transpose 64-bit values (there's no vswp equivalent) - { - const uint64x1_t row0h = vget_high_u64(row01.val[0]); - const uint64x1_t row2l = vget_low_u64(row23.val[0]); - const uint64x1_t row1h = vget_high_u64(row01.val[1]); - const uint64x1_t row3l = vget_low_u64(row23.val[1]); - row01.val[0] = vcombine_u64(vget_low_u64(row01.val[0]), row2l); - row23.val[0] = vcombine_u64(row0h, vget_high_u64(row23.val[0])); - row01.val[1] = vcombine_u64(vget_low_u64(row01.val[1]), row3l); - row23.val[1] = vcombine_u64(row1h, vget_high_u64(row23.val[1])); - } - { - const int32x4x2_t out01 = vtrnq_s32(vreinterpretq_s32_u64(row01.val[0]), - vreinterpretq_s32_u64(row01.val[1])); - const int32x4x2_t out23 = vtrnq_s32(vreinterpretq_s32_u64(row23.val[0]), - vreinterpretq_s32_u64(row23.val[1])); - int32x4x4_t out; - out.val[0] = out01.val[0]; - out.val[1] = out01.val[1]; - out.val[2] = out23.val[0]; - out.val[3] = out23.val[1]; - return out; - } -} - -#endif // WEBP_DSP_NEON_H_ diff --git a/Example/Pods/libwebp/src/dsp/rescaler.c b/Example/Pods/libwebp/src/dsp/rescaler.c deleted file mode 100644 index bc743d5d..00000000 --- a/Example/Pods/libwebp/src/dsp/rescaler.c +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Rescaling functions -// -// Author: Skal (pascal.massimino@gmail.com) - -#include - -#include "./dsp.h" -#include "../utils/rescaler.h" - -//------------------------------------------------------------------------------ -// Implementations of critical functions ImportRow / ExportRow - -#define ROUNDER (WEBP_RESCALER_ONE >> 1) -#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) - -//------------------------------------------------------------------------------ -// Row import - -void WebPRescalerImportRowExpandC(WebPRescaler* const wrk, const uint8_t* src) { - const int x_stride = wrk->num_channels; - const int x_out_max = wrk->dst_width * wrk->num_channels; - int channel; - assert(!WebPRescalerInputDone(wrk)); - assert(wrk->x_expand); - for (channel = 0; channel < x_stride; ++channel) { - int x_in = channel; - int x_out = channel; - // simple bilinear interpolation - int accum = wrk->x_add; - int left = src[x_in]; - int right = (wrk->src_width > 1) ? src[x_in + x_stride] : left; - x_in += x_stride; - while (1) { - wrk->frow[x_out] = right * wrk->x_add + (left - right) * accum; - x_out += x_stride; - if (x_out >= x_out_max) break; - accum -= wrk->x_sub; - if (accum < 0) { - left = right; - x_in += x_stride; - assert(x_in < wrk->src_width * x_stride); - right = src[x_in]; - accum += wrk->x_add; - } - } - assert(wrk->x_sub == 0 /* <- special case for src_width=1 */ || accum == 0); - } -} - -void WebPRescalerImportRowShrinkC(WebPRescaler* const wrk, const uint8_t* src) { - const int x_stride = wrk->num_channels; - const int x_out_max = wrk->dst_width * wrk->num_channels; - int channel; - assert(!WebPRescalerInputDone(wrk)); - assert(!wrk->x_expand); - for (channel = 0; channel < x_stride; ++channel) { - int x_in = channel; - int x_out = channel; - uint32_t sum = 0; - int accum = 0; - while (x_out < x_out_max) { - uint32_t base = 0; - accum += wrk->x_add; - while (accum > 0) { - accum -= wrk->x_sub; - assert(x_in < wrk->src_width * x_stride); - base = src[x_in]; - sum += base; - x_in += x_stride; - } - { // Emit next horizontal pixel. - const rescaler_t frac = base * (-accum); - wrk->frow[x_out] = sum * wrk->x_sub - frac; - // fresh fractional start for next pixel - sum = (int)MULT_FIX(frac, wrk->fx_scale); - } - x_out += x_stride; - } - assert(accum == 0); - } -} - -//------------------------------------------------------------------------------ -// Row export - -void WebPRescalerExportRowExpandC(WebPRescaler* const wrk) { - int x_out; - uint8_t* const dst = wrk->dst; - rescaler_t* const irow = wrk->irow; - const int x_out_max = wrk->dst_width * wrk->num_channels; - const rescaler_t* const frow = wrk->frow; - assert(!WebPRescalerOutputDone(wrk)); - assert(wrk->y_accum <= 0); - assert(wrk->y_expand); - assert(wrk->y_sub != 0); - if (wrk->y_accum == 0) { - for (x_out = 0; x_out < x_out_max; ++x_out) { - const uint32_t J = frow[x_out]; - const int v = (int)MULT_FIX(J, wrk->fy_scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - } - } else { - const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub); - const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); - for (x_out = 0; x_out < x_out_max; ++x_out) { - const uint64_t I = (uint64_t)A * frow[x_out] - + (uint64_t)B * irow[x_out]; - const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX); - const int v = (int)MULT_FIX(J, wrk->fy_scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - } - } -} - -void WebPRescalerExportRowShrinkC(WebPRescaler* const wrk) { - int x_out; - uint8_t* const dst = wrk->dst; - rescaler_t* const irow = wrk->irow; - const int x_out_max = wrk->dst_width * wrk->num_channels; - const rescaler_t* const frow = wrk->frow; - const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum); - assert(!WebPRescalerOutputDone(wrk)); - assert(wrk->y_accum <= 0); - assert(!wrk->y_expand); - if (yscale) { - for (x_out = 0; x_out < x_out_max; ++x_out) { - const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale); - const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - irow[x_out] = frac; // new fractional start - } - } else { - for (x_out = 0; x_out < x_out_max; ++x_out) { - const int v = (int)MULT_FIX(irow[x_out], wrk->fxy_scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - irow[x_out] = 0; - } - } -} - -#undef MULT_FIX -#undef ROUNDER - -//------------------------------------------------------------------------------ -// Main entry calls - -void WebPRescalerImportRow(WebPRescaler* const wrk, const uint8_t* src) { - assert(!WebPRescalerInputDone(wrk)); - if (!wrk->x_expand) { - WebPRescalerImportRowShrink(wrk, src); - } else { - WebPRescalerImportRowExpand(wrk, src); - } -} - -void WebPRescalerExportRow(WebPRescaler* const wrk) { - if (wrk->y_accum <= 0) { - assert(!WebPRescalerOutputDone(wrk)); - if (wrk->y_expand) { - WebPRescalerExportRowExpand(wrk); - } else if (wrk->fxy_scale) { - WebPRescalerExportRowShrink(wrk); - } else { // very special case for src = dst = 1x1 - int i; - assert(wrk->src_width == 1 && wrk->dst_width <= 2); - assert(wrk->src_height == 1 && wrk->dst_height == 1); - for (i = 0; i < wrk->num_channels * wrk->dst_width; ++i) { - wrk->dst[i] = wrk->irow[i]; - wrk->irow[i] = 0; - } - } - wrk->y_accum += wrk->y_add; - wrk->dst += wrk->dst_stride; - ++wrk->dst_y; - } -} - -//------------------------------------------------------------------------------ - -WebPRescalerImportRowFunc WebPRescalerImportRowExpand; -WebPRescalerImportRowFunc WebPRescalerImportRowShrink; - -WebPRescalerExportRowFunc WebPRescalerExportRowExpand; -WebPRescalerExportRowFunc WebPRescalerExportRowShrink; - -extern void WebPRescalerDspInitSSE2(void); -extern void WebPRescalerDspInitMIPS32(void); -extern void WebPRescalerDspInitMIPSdspR2(void); -extern void WebPRescalerDspInitNEON(void); - -static volatile VP8CPUInfo rescaler_last_cpuinfo_used = - (VP8CPUInfo)&rescaler_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInit(void) { - if (rescaler_last_cpuinfo_used == VP8GetCPUInfo) return; - - WebPRescalerImportRowExpand = WebPRescalerImportRowExpandC; - WebPRescalerImportRowShrink = WebPRescalerImportRowShrinkC; - WebPRescalerExportRowExpand = WebPRescalerExportRowExpandC; - WebPRescalerExportRowShrink = WebPRescalerExportRowShrinkC; - - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - WebPRescalerDspInitSSE2(); - } -#endif -#if defined(WEBP_USE_NEON) - if (VP8GetCPUInfo(kNEON)) { - WebPRescalerDspInitNEON(); - } -#endif -#if defined(WEBP_USE_MIPS32) - if (VP8GetCPUInfo(kMIPS32)) { - WebPRescalerDspInitMIPS32(); - } -#endif -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - WebPRescalerDspInitMIPSdspR2(); - } -#endif - } - rescaler_last_cpuinfo_used = VP8GetCPUInfo; -} diff --git a/Example/Pods/libwebp/src/dsp/rescaler_mips32.c b/Example/Pods/libwebp/src/dsp/rescaler_mips32.c deleted file mode 100644 index ddaa3913..00000000 --- a/Example/Pods/libwebp/src/dsp/rescaler_mips32.c +++ /dev/null @@ -1,291 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// MIPS version of rescaling functions -// -// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS32) - -#include -#include "../utils/rescaler.h" - -//------------------------------------------------------------------------------ -// Row import - -static void ImportRowShrink(WebPRescaler* const wrk, const uint8_t* src) { - const int x_stride = wrk->num_channels; - const int x_out_max = wrk->dst_width * wrk->num_channels; - const int fx_scale = wrk->fx_scale; - const int x_add = wrk->x_add; - const int x_sub = wrk->x_sub; - const int x_stride1 = x_stride << 2; - int channel; - assert(!wrk->x_expand); - assert(!WebPRescalerInputDone(wrk)); - - for (channel = 0; channel < x_stride; ++channel) { - const uint8_t* src1 = src + channel; - rescaler_t* frow = wrk->frow + channel; - int temp1, temp2, temp3; - int base, frac, sum; - int accum, accum1; - int loop_c = x_out_max - channel; - - __asm__ volatile ( - "li %[temp1], 0x8000 \n\t" - "li %[temp2], 0x10000 \n\t" - "li %[sum], 0 \n\t" - "li %[accum], 0 \n\t" - "1: \n\t" - "addu %[accum], %[accum], %[x_add] \n\t" - "li %[base], 0 \n\t" - "blez %[accum], 3f \n\t" - "2: \n\t" - "lbu %[base], 0(%[src1]) \n\t" - "subu %[accum], %[accum], %[x_sub] \n\t" - "addu %[src1], %[src1], %[x_stride] \n\t" - "addu %[sum], %[sum], %[base] \n\t" - "bgtz %[accum], 2b \n\t" - "3: \n\t" - "negu %[accum1], %[accum] \n\t" - "mul %[frac], %[base], %[accum1] \n\t" - "mul %[temp3], %[sum], %[x_sub] \n\t" - "subu %[loop_c], %[loop_c], %[x_stride] \n\t" - "mult %[temp1], %[temp2] \n\t" - "maddu %[frac], %[fx_scale] \n\t" - "mfhi %[sum] \n\t" - "subu %[temp3], %[temp3], %[frac] \n\t" - "sw %[temp3], 0(%[frow]) \n\t" - "addu %[frow], %[frow], %[x_stride1] \n\t" - "bgtz %[loop_c], 1b \n\t" - : [accum]"=&r"(accum), [src1]"+r"(src1), [temp3]"=&r"(temp3), - [sum]"=&r"(sum), [base]"=&r"(base), [frac]"=&r"(frac), - [frow]"+r"(frow), [accum1]"=&r"(accum1), - [temp2]"=&r"(temp2), [temp1]"=&r"(temp1) - : [x_stride]"r"(x_stride), [fx_scale]"r"(fx_scale), - [x_sub]"r"(x_sub), [x_add]"r"(x_add), - [loop_c]"r"(loop_c), [x_stride1]"r"(x_stride1) - : "memory", "hi", "lo" - ); - assert(accum == 0); - } -} - -static void ImportRowExpand(WebPRescaler* const wrk, const uint8_t* src) { - const int x_stride = wrk->num_channels; - const int x_out_max = wrk->dst_width * wrk->num_channels; - const int x_add = wrk->x_add; - const int x_sub = wrk->x_sub; - const int src_width = wrk->src_width; - const int x_stride1 = x_stride << 2; - int channel; - assert(wrk->x_expand); - assert(!WebPRescalerInputDone(wrk)); - - for (channel = 0; channel < x_stride; ++channel) { - const uint8_t* src1 = src + channel; - rescaler_t* frow = wrk->frow + channel; - int temp1, temp2, temp3, temp4; - int frac; - int accum; - int x_out = channel; - - __asm__ volatile ( - "addiu %[temp3], %[src_width], -1 \n\t" - "lbu %[temp2], 0(%[src1]) \n\t" - "addu %[src1], %[src1], %[x_stride] \n\t" - "bgtz %[temp3], 0f \n\t" - "addiu %[temp1], %[temp2], 0 \n\t" - "b 3f \n\t" - "0: \n\t" - "lbu %[temp1], 0(%[src1]) \n\t" - "3: \n\t" - "addiu %[accum], %[x_add], 0 \n\t" - "1: \n\t" - "subu %[temp3], %[temp2], %[temp1] \n\t" - "mul %[temp3], %[temp3], %[accum] \n\t" - "mul %[temp4], %[temp1], %[x_add] \n\t" - "addu %[temp3], %[temp4], %[temp3] \n\t" - "sw %[temp3], 0(%[frow]) \n\t" - "addu %[frow], %[frow], %[x_stride1] \n\t" - "addu %[x_out], %[x_out], %[x_stride] \n\t" - "subu %[temp3], %[x_out], %[x_out_max] \n\t" - "bgez %[temp3], 2f \n\t" - "subu %[accum], %[accum], %[x_sub] \n\t" - "bgez %[accum], 4f \n\t" - "addiu %[temp2], %[temp1], 0 \n\t" - "addu %[src1], %[src1], %[x_stride] \n\t" - "lbu %[temp1], 0(%[src1]) \n\t" - "addu %[accum], %[accum], %[x_add] \n\t" - "4: \n\t" - "b 1b \n\t" - "2: \n\t" - : [src1]"+r"(src1), [accum]"=&r"(accum), [temp1]"=&r"(temp1), - [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), - [x_out]"+r"(x_out), [frac]"=&r"(frac), [frow]"+r"(frow) - : [x_stride]"r"(x_stride), [x_add]"r"(x_add), [x_sub]"r"(x_sub), - [x_stride1]"r"(x_stride1), [src_width]"r"(src_width), - [x_out_max]"r"(x_out_max) - : "memory", "hi", "lo" - ); - assert(wrk->x_sub == 0 /* <- special case for src_width=1 */ || accum == 0); - } -} - -//------------------------------------------------------------------------------ -// Row export - -static void ExportRowExpand(WebPRescaler* const wrk) { - uint8_t* dst = wrk->dst; - rescaler_t* irow = wrk->irow; - const int x_out_max = wrk->dst_width * wrk->num_channels; - const rescaler_t* frow = wrk->frow; - int temp0, temp1, temp3, temp4, temp5, loop_end; - const int temp2 = (int)wrk->fy_scale; - const int temp6 = x_out_max << 2; - assert(!WebPRescalerOutputDone(wrk)); - assert(wrk->y_accum <= 0); - assert(wrk->y_expand); - assert(wrk->y_sub != 0); - if (wrk->y_accum == 0) { - __asm__ volatile ( - "li %[temp3], 0x10000 \n\t" - "li %[temp4], 0x8000 \n\t" - "addu %[loop_end], %[frow], %[temp6] \n\t" - "1: \n\t" - "lw %[temp0], 0(%[frow]) \n\t" - "addiu %[dst], %[dst], 1 \n\t" - "addiu %[frow], %[frow], 4 \n\t" - "mult %[temp3], %[temp4] \n\t" - "maddu %[temp0], %[temp2] \n\t" - "mfhi %[temp5] \n\t" - "sb %[temp5], -1(%[dst]) \n\t" - "bne %[frow], %[loop_end], 1b \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), - [dst]"+r"(dst), [loop_end]"=&r"(loop_end) - : [temp2]"r"(temp2), [temp6]"r"(temp6) - : "memory", "hi", "lo" - ); - } else { - const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub); - const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); - __asm__ volatile ( - "li %[temp3], 0x10000 \n\t" - "li %[temp4], 0x8000 \n\t" - "addu %[loop_end], %[frow], %[temp6] \n\t" - "1: \n\t" - "lw %[temp0], 0(%[frow]) \n\t" - "lw %[temp1], 0(%[irow]) \n\t" - "addiu %[dst], %[dst], 1 \n\t" - "mult %[temp3], %[temp4] \n\t" - "maddu %[A], %[temp0] \n\t" - "maddu %[B], %[temp1] \n\t" - "addiu %[frow], %[frow], 4 \n\t" - "addiu %[irow], %[irow], 4 \n\t" - "mfhi %[temp5] \n\t" - "mult %[temp3], %[temp4] \n\t" - "maddu %[temp5], %[temp2] \n\t" - "mfhi %[temp5] \n\t" - "sb %[temp5], -1(%[dst]) \n\t" - "bne %[frow], %[loop_end], 1b \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), - [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end) - : [temp2]"r"(temp2), [temp6]"r"(temp6), [A]"r"(A), [B]"r"(B) - : "memory", "hi", "lo" - ); - } -} - -static void ExportRowShrink(WebPRescaler* const wrk) { - const int x_out_max = wrk->dst_width * wrk->num_channels; - uint8_t* dst = wrk->dst; - rescaler_t* irow = wrk->irow; - const rescaler_t* frow = wrk->frow; - const int yscale = wrk->fy_scale * (-wrk->y_accum); - int temp0, temp1, temp3, temp4, temp5, loop_end; - const int temp2 = (int)wrk->fxy_scale; - const int temp6 = x_out_max << 2; - - assert(!WebPRescalerOutputDone(wrk)); - assert(wrk->y_accum <= 0); - assert(!wrk->y_expand); - assert(wrk->fxy_scale != 0); - if (yscale) { - __asm__ volatile ( - "li %[temp3], 0x10000 \n\t" - "li %[temp4], 0x8000 \n\t" - "addu %[loop_end], %[frow], %[temp6] \n\t" - "1: \n\t" - "lw %[temp0], 0(%[frow]) \n\t" - "mult %[temp3], %[temp4] \n\t" - "addiu %[frow], %[frow], 4 \n\t" - "maddu %[temp0], %[yscale] \n\t" - "mfhi %[temp1] \n\t" - "lw %[temp0], 0(%[irow]) \n\t" - "addiu %[dst], %[dst], 1 \n\t" - "addiu %[irow], %[irow], 4 \n\t" - "subu %[temp0], %[temp0], %[temp1] \n\t" - "mult %[temp3], %[temp4] \n\t" - "maddu %[temp0], %[temp2] \n\t" - "mfhi %[temp5] \n\t" - "sw %[temp1], -4(%[irow]) \n\t" - "sb %[temp5], -1(%[dst]) \n\t" - "bne %[frow], %[loop_end], 1b \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), - [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end) - : [temp2]"r"(temp2), [yscale]"r"(yscale), [temp6]"r"(temp6) - : "memory", "hi", "lo" - ); - } else { - __asm__ volatile ( - "li %[temp3], 0x10000 \n\t" - "li %[temp4], 0x8000 \n\t" - "addu %[loop_end], %[irow], %[temp6] \n\t" - "1: \n\t" - "lw %[temp0], 0(%[irow]) \n\t" - "addiu %[dst], %[dst], 1 \n\t" - "addiu %[irow], %[irow], 4 \n\t" - "mult %[temp3], %[temp4] \n\t" - "maddu %[temp0], %[temp2] \n\t" - "mfhi %[temp5] \n\t" - "sw $zero, -4(%[irow]) \n\t" - "sb %[temp5], -1(%[dst]) \n\t" - "bne %[irow], %[loop_end], 1b \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [irow]"+r"(irow), - [dst]"+r"(dst), [loop_end]"=&r"(loop_end) - : [temp2]"r"(temp2), [temp6]"r"(temp6) - : "memory", "hi", "lo" - ); - } -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void WebPRescalerDspInitMIPS32(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPS32(void) { - WebPRescalerImportRowExpand = ImportRowExpand; - WebPRescalerImportRowShrink = ImportRowShrink; - WebPRescalerExportRowExpand = ExportRowExpand; - WebPRescalerExportRowShrink = ExportRowShrink; -} - -#else // !WEBP_USE_MIPS32 - -WEBP_DSP_INIT_STUB(WebPRescalerDspInitMIPS32) - -#endif // WEBP_USE_MIPS32 diff --git a/Example/Pods/libwebp/src/dsp/rescaler_mips_dsp_r2.c b/Example/Pods/libwebp/src/dsp/rescaler_mips_dsp_r2.c deleted file mode 100644 index b457d0a3..00000000 --- a/Example/Pods/libwebp/src/dsp/rescaler_mips_dsp_r2.c +++ /dev/null @@ -1,314 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// MIPS version of rescaling functions -// -// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_MIPS_DSP_R2) - -#include -#include "../utils/rescaler.h" - -#define ROUNDER (WEBP_RESCALER_ONE >> 1) -#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) - -//------------------------------------------------------------------------------ -// Row export - -static void ExportRowShrink(WebPRescaler* const wrk) { - int i; - const int x_out_max = wrk->dst_width * wrk->num_channels; - uint8_t* dst = wrk->dst; - rescaler_t* irow = wrk->irow; - const rescaler_t* frow = wrk->frow; - const int yscale = wrk->fy_scale * (-wrk->y_accum); - int temp0, temp1, temp2, temp3, temp4, temp5, loop_end; - const int temp7 = (int)wrk->fxy_scale; - const int temp6 = (x_out_max & ~0x3) << 2; - assert(!WebPRescalerOutputDone(wrk)); - assert(wrk->y_accum <= 0); - assert(!wrk->y_expand); - assert(wrk->fxy_scale != 0); - if (yscale) { - if (x_out_max >= 4) { - int temp8, temp9, temp10, temp11; - __asm__ volatile ( - "li %[temp3], 0x10000 \n\t" - "li %[temp4], 0x8000 \n\t" - "addu %[loop_end], %[frow], %[temp6] \n\t" - "1: \n\t" - "lw %[temp0], 0(%[frow]) \n\t" - "lw %[temp1], 4(%[frow]) \n\t" - "lw %[temp2], 8(%[frow]) \n\t" - "lw %[temp5], 12(%[frow]) \n\t" - "mult $ac0, %[temp3], %[temp4] \n\t" - "maddu $ac0, %[temp0], %[yscale] \n\t" - "mult $ac1, %[temp3], %[temp4] \n\t" - "maddu $ac1, %[temp1], %[yscale] \n\t" - "mult $ac2, %[temp3], %[temp4] \n\t" - "maddu $ac2, %[temp2], %[yscale] \n\t" - "mult $ac3, %[temp3], %[temp4] \n\t" - "maddu $ac3, %[temp5], %[yscale] \n\t" - "addiu %[frow], %[frow], 16 \n\t" - "mfhi %[temp0], $ac0 \n\t" - "mfhi %[temp1], $ac1 \n\t" - "mfhi %[temp2], $ac2 \n\t" - "mfhi %[temp5], $ac3 \n\t" - "lw %[temp8], 0(%[irow]) \n\t" - "lw %[temp9], 4(%[irow]) \n\t" - "lw %[temp10], 8(%[irow]) \n\t" - "lw %[temp11], 12(%[irow]) \n\t" - "addiu %[dst], %[dst], 4 \n\t" - "addiu %[irow], %[irow], 16 \n\t" - "subu %[temp8], %[temp8], %[temp0] \n\t" - "subu %[temp9], %[temp9], %[temp1] \n\t" - "subu %[temp10], %[temp10], %[temp2] \n\t" - "subu %[temp11], %[temp11], %[temp5] \n\t" - "mult $ac0, %[temp3], %[temp4] \n\t" - "maddu $ac0, %[temp8], %[temp7] \n\t" - "mult $ac1, %[temp3], %[temp4] \n\t" - "maddu $ac1, %[temp9], %[temp7] \n\t" - "mult $ac2, %[temp3], %[temp4] \n\t" - "maddu $ac2, %[temp10], %[temp7] \n\t" - "mult $ac3, %[temp3], %[temp4] \n\t" - "maddu $ac3, %[temp11], %[temp7] \n\t" - "mfhi %[temp8], $ac0 \n\t" - "mfhi %[temp9], $ac1 \n\t" - "mfhi %[temp10], $ac2 \n\t" - "mfhi %[temp11], $ac3 \n\t" - "sw %[temp0], -16(%[irow]) \n\t" - "sw %[temp1], -12(%[irow]) \n\t" - "sw %[temp2], -8(%[irow]) \n\t" - "sw %[temp5], -4(%[irow]) \n\t" - "sb %[temp8], -4(%[dst]) \n\t" - "sb %[temp9], -3(%[dst]) \n\t" - "sb %[temp10], -2(%[dst]) \n\t" - "sb %[temp11], -1(%[dst]) \n\t" - "bne %[frow], %[loop_end], 1b \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), - [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end), - [temp8]"=&r"(temp8), [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), - [temp11]"=&r"(temp11), [temp2]"=&r"(temp2) - : [temp7]"r"(temp7), [yscale]"r"(yscale), [temp6]"r"(temp6) - : "memory", "hi", "lo", "$ac1hi", "$ac1lo", - "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo" - ); - } - for (i = 0; i < (x_out_max & 0x3); ++i) { - const uint32_t frac = (uint32_t)MULT_FIX(*frow++, yscale); - const int v = (int)MULT_FIX(*irow - frac, wrk->fxy_scale); - assert(v >= 0 && v <= 255); - *dst++ = v; - *irow++ = frac; // new fractional start - } - } else { - if (x_out_max >= 4) { - __asm__ volatile ( - "li %[temp3], 0x10000 \n\t" - "li %[temp4], 0x8000 \n\t" - "addu %[loop_end], %[irow], %[temp6] \n\t" - "1: \n\t" - "lw %[temp0], 0(%[irow]) \n\t" - "lw %[temp1], 4(%[irow]) \n\t" - "lw %[temp2], 8(%[irow]) \n\t" - "lw %[temp5], 12(%[irow]) \n\t" - "addiu %[dst], %[dst], 4 \n\t" - "addiu %[irow], %[irow], 16 \n\t" - "mult $ac0, %[temp3], %[temp4] \n\t" - "maddu $ac0, %[temp0], %[temp7] \n\t" - "mult $ac1, %[temp3], %[temp4] \n\t" - "maddu $ac1, %[temp1], %[temp7] \n\t" - "mult $ac2, %[temp3], %[temp4] \n\t" - "maddu $ac2, %[temp2], %[temp7] \n\t" - "mult $ac3, %[temp3], %[temp4] \n\t" - "maddu $ac3, %[temp5], %[temp7] \n\t" - "mfhi %[temp0], $ac0 \n\t" - "mfhi %[temp1], $ac1 \n\t" - "mfhi %[temp2], $ac2 \n\t" - "mfhi %[temp5], $ac3 \n\t" - "sw $zero, -16(%[irow]) \n\t" - "sw $zero, -12(%[irow]) \n\t" - "sw $zero, -8(%[irow]) \n\t" - "sw $zero, -4(%[irow]) \n\t" - "sb %[temp0], -4(%[dst]) \n\t" - "sb %[temp1], -3(%[dst]) \n\t" - "sb %[temp2], -2(%[dst]) \n\t" - "sb %[temp5], -1(%[dst]) \n\t" - "bne %[irow], %[loop_end], 1b \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [irow]"+r"(irow), - [dst]"+r"(dst), [loop_end]"=&r"(loop_end), [temp2]"=&r"(temp2) - : [temp7]"r"(temp7), [temp6]"r"(temp6) - : "memory", "hi", "lo", "$ac1hi", "$ac1lo", - "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo" - ); - } - for (i = 0; i < (x_out_max & 0x3); ++i) { - const int v = (int)MULT_FIX(*irow, wrk->fxy_scale); - assert(v >= 0 && v <= 255); - *dst++ = v; - *irow++ = 0; - } - } -} - -static void ExportRowExpand(WebPRescaler* const wrk) { - int i; - uint8_t* dst = wrk->dst; - rescaler_t* irow = wrk->irow; - const int x_out_max = wrk->dst_width * wrk->num_channels; - const rescaler_t* frow = wrk->frow; - int temp0, temp1, temp2, temp3, temp4, temp5, loop_end; - const int temp6 = (x_out_max & ~0x3) << 2; - const int temp7 = (int)wrk->fy_scale; - assert(!WebPRescalerOutputDone(wrk)); - assert(wrk->y_accum <= 0); - assert(wrk->y_expand); - assert(wrk->y_sub != 0); - if (wrk->y_accum == 0) { - if (x_out_max >= 4) { - __asm__ volatile ( - "li %[temp4], 0x10000 \n\t" - "li %[temp5], 0x8000 \n\t" - "addu %[loop_end], %[frow], %[temp6] \n\t" - "1: \n\t" - "lw %[temp0], 0(%[frow]) \n\t" - "lw %[temp1], 4(%[frow]) \n\t" - "lw %[temp2], 8(%[frow]) \n\t" - "lw %[temp3], 12(%[frow]) \n\t" - "addiu %[dst], %[dst], 4 \n\t" - "addiu %[frow], %[frow], 16 \n\t" - "mult $ac0, %[temp4], %[temp5] \n\t" - "maddu $ac0, %[temp0], %[temp7] \n\t" - "mult $ac1, %[temp4], %[temp5] \n\t" - "maddu $ac1, %[temp1], %[temp7] \n\t" - "mult $ac2, %[temp4], %[temp5] \n\t" - "maddu $ac2, %[temp2], %[temp7] \n\t" - "mult $ac3, %[temp4], %[temp5] \n\t" - "maddu $ac3, %[temp3], %[temp7] \n\t" - "mfhi %[temp0], $ac0 \n\t" - "mfhi %[temp1], $ac1 \n\t" - "mfhi %[temp2], $ac2 \n\t" - "mfhi %[temp3], $ac3 \n\t" - "sb %[temp0], -4(%[dst]) \n\t" - "sb %[temp1], -3(%[dst]) \n\t" - "sb %[temp2], -2(%[dst]) \n\t" - "sb %[temp3], -1(%[dst]) \n\t" - "bne %[frow], %[loop_end], 1b \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), - [dst]"+r"(dst), [loop_end]"=&r"(loop_end), [temp2]"=&r"(temp2) - : [temp7]"r"(temp7), [temp6]"r"(temp6) - : "memory", "hi", "lo", "$ac1hi", "$ac1lo", - "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo" - ); - } - for (i = 0; i < (x_out_max & 0x3); ++i) { - const uint32_t J = *frow++; - const int v = (int)MULT_FIX(J, wrk->fy_scale); - assert(v >= 0 && v <= 255); - *dst++ = v; - } - } else { - const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub); - const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); - if (x_out_max >= 4) { - int temp8, temp9, temp10, temp11; - __asm__ volatile ( - "li %[temp8], 0x10000 \n\t" - "li %[temp9], 0x8000 \n\t" - "addu %[loop_end], %[frow], %[temp6] \n\t" - "1: \n\t" - "lw %[temp0], 0(%[frow]) \n\t" - "lw %[temp1], 4(%[frow]) \n\t" - "lw %[temp2], 8(%[frow]) \n\t" - "lw %[temp3], 12(%[frow]) \n\t" - "lw %[temp4], 0(%[irow]) \n\t" - "lw %[temp5], 4(%[irow]) \n\t" - "lw %[temp10], 8(%[irow]) \n\t" - "lw %[temp11], 12(%[irow]) \n\t" - "addiu %[dst], %[dst], 4 \n\t" - "mult $ac0, %[temp8], %[temp9] \n\t" - "maddu $ac0, %[A], %[temp0] \n\t" - "maddu $ac0, %[B], %[temp4] \n\t" - "mult $ac1, %[temp8], %[temp9] \n\t" - "maddu $ac1, %[A], %[temp1] \n\t" - "maddu $ac1, %[B], %[temp5] \n\t" - "mult $ac2, %[temp8], %[temp9] \n\t" - "maddu $ac2, %[A], %[temp2] \n\t" - "maddu $ac2, %[B], %[temp10] \n\t" - "mult $ac3, %[temp8], %[temp9] \n\t" - "maddu $ac3, %[A], %[temp3] \n\t" - "maddu $ac3, %[B], %[temp11] \n\t" - "addiu %[frow], %[frow], 16 \n\t" - "addiu %[irow], %[irow], 16 \n\t" - "mfhi %[temp0], $ac0 \n\t" - "mfhi %[temp1], $ac1 \n\t" - "mfhi %[temp2], $ac2 \n\t" - "mfhi %[temp3], $ac3 \n\t" - "mult $ac0, %[temp8], %[temp9] \n\t" - "maddu $ac0, %[temp0], %[temp7] \n\t" - "mult $ac1, %[temp8], %[temp9] \n\t" - "maddu $ac1, %[temp1], %[temp7] \n\t" - "mult $ac2, %[temp8], %[temp9] \n\t" - "maddu $ac2, %[temp2], %[temp7] \n\t" - "mult $ac3, %[temp8], %[temp9] \n\t" - "maddu $ac3, %[temp3], %[temp7] \n\t" - "mfhi %[temp0], $ac0 \n\t" - "mfhi %[temp1], $ac1 \n\t" - "mfhi %[temp2], $ac2 \n\t" - "mfhi %[temp3], $ac3 \n\t" - "sb %[temp0], -4(%[dst]) \n\t" - "sb %[temp1], -3(%[dst]) \n\t" - "sb %[temp2], -2(%[dst]) \n\t" - "sb %[temp3], -1(%[dst]) \n\t" - "bne %[frow], %[loop_end], 1b \n\t" - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), - [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), - [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end), - [temp8]"=&r"(temp8), [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), - [temp11]"=&r"(temp11), [temp2]"=&r"(temp2) - : [temp7]"r"(temp7), [temp6]"r"(temp6), [A]"r"(A), [B]"r"(B) - : "memory", "hi", "lo", "$ac1hi", "$ac1lo", - "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo" - ); - } - for (i = 0; i < (x_out_max & 0x3); ++i) { - const uint64_t I = (uint64_t)A * *frow++ - + (uint64_t)B * *irow++; - const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX); - const int v = (int)MULT_FIX(J, wrk->fy_scale); - assert(v >= 0 && v <= 255); - *dst++ = v; - } - } -} - -#undef MULT_FIX -#undef ROUNDER - -//------------------------------------------------------------------------------ -// Entry point - -extern void WebPRescalerDspInitMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPSdspR2(void) { - WebPRescalerExportRowExpand = ExportRowExpand; - WebPRescalerExportRowShrink = ExportRowShrink; -} - -#else // !WEBP_USE_MIPS_DSP_R2 - -WEBP_DSP_INIT_STUB(WebPRescalerDspInitMIPSdspR2) - -#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/Example/Pods/libwebp/src/dsp/rescaler_neon.c b/Example/Pods/libwebp/src/dsp/rescaler_neon.c deleted file mode 100644 index 16fd450e..00000000 --- a/Example/Pods/libwebp/src/dsp/rescaler_neon.c +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// NEON version of rescaling functions -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_NEON) - -#include -#include -#include "./neon.h" -#include "../utils/rescaler.h" - -#define ROUNDER (WEBP_RESCALER_ONE >> 1) -#define MULT_FIX_C(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) - -#define LOAD_32x4(SRC, DST) const uint32x4_t DST = vld1q_u32((SRC)) -#define LOAD_32x8(SRC, DST0, DST1) \ - LOAD_32x4(SRC + 0, DST0); \ - LOAD_32x4(SRC + 4, DST1) - -#define STORE_32x8(SRC0, SRC1, DST) do { \ - vst1q_u32((DST) + 0, SRC0); \ - vst1q_u32((DST) + 4, SRC1); \ -} while (0); - -#if (WEBP_RESCALER_RFIX == 32) -#define MAKE_HALF_CST(C) vdupq_n_s32((int32_t)((C) >> 1)) -#define MULT_FIX(A, B) /* note: B is actualy scale>>1. See MAKE_HALF_CST */ \ - vreinterpretq_u32_s32(vqrdmulhq_s32(vreinterpretq_s32_u32((A)), (B))) -#else -#error "MULT_FIX/WEBP_RESCALER_RFIX need some more work" -#endif - -static uint32x4_t Interpolate(const rescaler_t* const frow, - const rescaler_t* const irow, - uint32_t A, uint32_t B) { - LOAD_32x4(frow, A0); - LOAD_32x4(irow, B0); - const uint64x2_t C0 = vmull_n_u32(vget_low_u32(A0), A); - const uint64x2_t C1 = vmull_n_u32(vget_high_u32(A0), A); - const uint64x2_t D0 = vmlal_n_u32(C0, vget_low_u32(B0), B); - const uint64x2_t D1 = vmlal_n_u32(C1, vget_high_u32(B0), B); - const uint32x4_t E = vcombine_u32( - vrshrn_n_u64(D0, WEBP_RESCALER_RFIX), - vrshrn_n_u64(D1, WEBP_RESCALER_RFIX)); - return E; -} - -static void RescalerExportRowExpand(WebPRescaler* const wrk) { - int x_out; - uint8_t* const dst = wrk->dst; - rescaler_t* const irow = wrk->irow; - const int x_out_max = wrk->dst_width * wrk->num_channels; - const int max_span = x_out_max & ~7; - const rescaler_t* const frow = wrk->frow; - const uint32_t fy_scale = wrk->fy_scale; - const int32x4_t fy_scale_half = MAKE_HALF_CST(fy_scale); - assert(!WebPRescalerOutputDone(wrk)); - assert(wrk->y_accum <= 0); - assert(wrk->y_expand); - assert(wrk->y_sub != 0); - if (wrk->y_accum == 0) { - for (x_out = 0; x_out < max_span; x_out += 8) { - LOAD_32x4(frow + x_out + 0, A0); - LOAD_32x4(frow + x_out + 4, A1); - const uint32x4_t B0 = MULT_FIX(A0, fy_scale_half); - const uint32x4_t B1 = MULT_FIX(A1, fy_scale_half); - const uint16x4_t C0 = vmovn_u32(B0); - const uint16x4_t C1 = vmovn_u32(B1); - const uint8x8_t D = vmovn_u16(vcombine_u16(C0, C1)); - vst1_u8(dst + x_out, D); - } - for (; x_out < x_out_max; ++x_out) { - const uint32_t J = frow[x_out]; - const int v = (int)MULT_FIX_C(J, fy_scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - } - } else { - const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub); - const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); - for (x_out = 0; x_out < max_span; x_out += 8) { - const uint32x4_t C0 = - Interpolate(frow + x_out + 0, irow + x_out + 0, A, B); - const uint32x4_t C1 = - Interpolate(frow + x_out + 4, irow + x_out + 4, A, B); - const uint32x4_t D0 = MULT_FIX(C0, fy_scale_half); - const uint32x4_t D1 = MULT_FIX(C1, fy_scale_half); - const uint16x4_t E0 = vmovn_u32(D0); - const uint16x4_t E1 = vmovn_u32(D1); - const uint8x8_t F = vmovn_u16(vcombine_u16(E0, E1)); - vst1_u8(dst + x_out, F); - } - for (; x_out < x_out_max; ++x_out) { - const uint64_t I = (uint64_t)A * frow[x_out] - + (uint64_t)B * irow[x_out]; - const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX); - const int v = (int)MULT_FIX_C(J, fy_scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - } - } -} - -static void RescalerExportRowShrink(WebPRescaler* const wrk) { - int x_out; - uint8_t* const dst = wrk->dst; - rescaler_t* const irow = wrk->irow; - const int x_out_max = wrk->dst_width * wrk->num_channels; - const int max_span = x_out_max & ~7; - const rescaler_t* const frow = wrk->frow; - const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum); - const uint32_t fxy_scale = wrk->fxy_scale; - const uint32x4_t zero = vdupq_n_u32(0); - const int32x4_t yscale_half = MAKE_HALF_CST(yscale); - const int32x4_t fxy_scale_half = MAKE_HALF_CST(fxy_scale); - assert(!WebPRescalerOutputDone(wrk)); - assert(wrk->y_accum <= 0); - assert(!wrk->y_expand); - if (yscale) { - for (x_out = 0; x_out < max_span; x_out += 8) { - LOAD_32x8(frow + x_out, in0, in1); - LOAD_32x8(irow + x_out, in2, in3); - const uint32x4_t A0 = MULT_FIX(in0, yscale_half); - const uint32x4_t A1 = MULT_FIX(in1, yscale_half); - const uint32x4_t B0 = vqsubq_u32(in2, A0); - const uint32x4_t B1 = vqsubq_u32(in3, A1); - const uint32x4_t C0 = MULT_FIX(B0, fxy_scale_half); - const uint32x4_t C1 = MULT_FIX(B1, fxy_scale_half); - const uint16x4_t D0 = vmovn_u32(C0); - const uint16x4_t D1 = vmovn_u32(C1); - const uint8x8_t E = vmovn_u16(vcombine_u16(D0, D1)); - vst1_u8(dst + x_out, E); - STORE_32x8(A0, A1, irow + x_out); - } - for (; x_out < x_out_max; ++x_out) { - const uint32_t frac = (uint32_t)MULT_FIX_C(frow[x_out], yscale); - const int v = (int)MULT_FIX_C(irow[x_out] - frac, wrk->fxy_scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - irow[x_out] = frac; // new fractional start - } - } else { - for (x_out = 0; x_out < max_span; x_out += 8) { - LOAD_32x8(irow + x_out, in0, in1); - const uint32x4_t A0 = MULT_FIX(in0, fxy_scale_half); - const uint32x4_t A1 = MULT_FIX(in1, fxy_scale_half); - const uint16x4_t B0 = vmovn_u32(A0); - const uint16x4_t B1 = vmovn_u32(A1); - const uint8x8_t C = vmovn_u16(vcombine_u16(B0, B1)); - vst1_u8(dst + x_out, C); - STORE_32x8(zero, zero, irow + x_out); - } - for (; x_out < x_out_max; ++x_out) { - const int v = (int)MULT_FIX_C(irow[x_out], fxy_scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - irow[x_out] = 0; - } - } -} - -//------------------------------------------------------------------------------ - -extern void WebPRescalerDspInitNEON(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitNEON(void) { - WebPRescalerExportRowExpand = RescalerExportRowExpand; - WebPRescalerExportRowShrink = RescalerExportRowShrink; -} - -#else // !WEBP_USE_NEON - -WEBP_DSP_INIT_STUB(WebPRescalerDspInitNEON) - -#endif // WEBP_USE_NEON diff --git a/Example/Pods/libwebp/src/dsp/rescaler_sse2.c b/Example/Pods/libwebp/src/dsp/rescaler_sse2.c deleted file mode 100644 index 5ea4ddb2..00000000 --- a/Example/Pods/libwebp/src/dsp/rescaler_sse2.c +++ /dev/null @@ -1,374 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// SSE2 Rescaling functions -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE2) -#include - -#include -#include "../utils/rescaler.h" - -//------------------------------------------------------------------------------ -// Implementations of critical functions ImportRow / ExportRow - -#define ROUNDER (WEBP_RESCALER_ONE >> 1) -#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) - -// input: 8 bytes ABCDEFGH -> output: A0E0B0F0C0G0D0H0 -static void LoadTwoPixels(const uint8_t* const src, __m128i* out) { - const __m128i zero = _mm_setzero_si128(); - const __m128i A = _mm_loadl_epi64((const __m128i*)(src)); // ABCDEFGH - const __m128i B = _mm_unpacklo_epi8(A, zero); // A0B0C0D0E0F0G0H0 - const __m128i C = _mm_srli_si128(B, 8); // E0F0G0H0 - *out = _mm_unpacklo_epi16(B, C); -} - -// input: 8 bytes ABCDEFGH -> output: A0B0C0D0E0F0G0H0 -static void LoadHeightPixels(const uint8_t* const src, __m128i* out) { - const __m128i zero = _mm_setzero_si128(); - const __m128i A = _mm_loadl_epi64((const __m128i*)(src)); // ABCDEFGH - *out = _mm_unpacklo_epi8(A, zero); -} - -static void RescalerImportRowExpandSSE2(WebPRescaler* const wrk, - const uint8_t* src) { - rescaler_t* frow = wrk->frow; - const rescaler_t* const frow_end = frow + wrk->dst_width * wrk->num_channels; - const int x_add = wrk->x_add; - int accum = x_add; - __m128i cur_pixels; - - assert(!WebPRescalerInputDone(wrk)); - assert(wrk->x_expand); - if (wrk->num_channels == 4) { - if (wrk->src_width < 2) { - WebPRescalerImportRowExpandC(wrk, src); - return; - } - LoadTwoPixels(src, &cur_pixels); - src += 4; - while (1) { - const __m128i mult = _mm_set1_epi32(((x_add - accum) << 16) | accum); - const __m128i out = _mm_madd_epi16(cur_pixels, mult); - _mm_storeu_si128((__m128i*)frow, out); - frow += 4; - if (frow >= frow_end) break; - accum -= wrk->x_sub; - if (accum < 0) { - LoadTwoPixels(src, &cur_pixels); - src += 4; - accum += x_add; - } - } - } else { - int left; - const uint8_t* const src_limit = src + wrk->src_width - 8; - if (wrk->src_width < 8) { - WebPRescalerImportRowExpandC(wrk, src); - return; - } - LoadHeightPixels(src, &cur_pixels); - src += 7; - left = 7; - while (1) { - const __m128i mult = _mm_cvtsi32_si128(((x_add - accum) << 16) | accum); - const __m128i out = _mm_madd_epi16(cur_pixels, mult); - assert(sizeof(*frow) == sizeof(uint32_t)); - WebPUint32ToMem((uint8_t*)frow, _mm_cvtsi128_si32(out)); - frow += 1; - if (frow >= frow_end) break; - accum -= wrk->x_sub; - if (accum < 0) { - if (--left) { - cur_pixels = _mm_srli_si128(cur_pixels, 2); - } else if (src <= src_limit) { - LoadHeightPixels(src, &cur_pixels); - src += 7; - left = 7; - } else { // tail - cur_pixels = _mm_srli_si128(cur_pixels, 2); - cur_pixels = _mm_insert_epi16(cur_pixels, src[1], 1); - src += 1; - left = 1; - } - accum += x_add; - } - } - } - assert(accum == 0); -} - -static void RescalerImportRowShrinkSSE2(WebPRescaler* const wrk, - const uint8_t* src) { - const int x_sub = wrk->x_sub; - int accum = 0; - const __m128i zero = _mm_setzero_si128(); - const __m128i mult0 = _mm_set1_epi16(x_sub); - const __m128i mult1 = _mm_set1_epi32(wrk->fx_scale); - const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER); - __m128i sum = zero; - rescaler_t* frow = wrk->frow; - const rescaler_t* const frow_end = wrk->frow + 4 * wrk->dst_width; - - if (wrk->num_channels != 4 || wrk->x_add > (x_sub << 7)) { - WebPRescalerImportRowShrinkC(wrk, src); - return; - } - assert(!WebPRescalerInputDone(wrk)); - assert(!wrk->x_expand); - - for (; frow < frow_end; frow += 4) { - __m128i base = zero; - accum += wrk->x_add; - while (accum > 0) { - const __m128i A = _mm_cvtsi32_si128(WebPMemToUint32(src)); - src += 4; - base = _mm_unpacklo_epi8(A, zero); - // To avoid overflow, we need: base * x_add / x_sub < 32768 - // => x_add < x_sub << 7. That's a 1/128 reduction ratio limit. - sum = _mm_add_epi16(sum, base); - accum -= x_sub; - } - { // Emit next horizontal pixel. - const __m128i mult = _mm_set1_epi16(-accum); - const __m128i frac0 = _mm_mullo_epi16(base, mult); // 16b x 16b -> 32b - const __m128i frac1 = _mm_mulhi_epu16(base, mult); - const __m128i frac = _mm_unpacklo_epi16(frac0, frac1); // frac is 32b - const __m128i A0 = _mm_mullo_epi16(sum, mult0); - const __m128i A1 = _mm_mulhi_epu16(sum, mult0); - const __m128i B0 = _mm_unpacklo_epi16(A0, A1); // sum * x_sub - const __m128i frow_out = _mm_sub_epi32(B0, frac); // sum * x_sub - frac - const __m128i D0 = _mm_srli_epi64(frac, 32); - const __m128i D1 = _mm_mul_epu32(frac, mult1); // 32b x 16b -> 64b - const __m128i D2 = _mm_mul_epu32(D0, mult1); - const __m128i E1 = _mm_add_epi64(D1, rounder); - const __m128i E2 = _mm_add_epi64(D2, rounder); - const __m128i F1 = _mm_shuffle_epi32(E1, 1 | (3 << 2)); - const __m128i F2 = _mm_shuffle_epi32(E2, 1 | (3 << 2)); - const __m128i G = _mm_unpacklo_epi32(F1, F2); - sum = _mm_packs_epi32(G, zero); - _mm_storeu_si128((__m128i*)frow, frow_out); - } - } - assert(accum == 0); -} - -//------------------------------------------------------------------------------ -// Row export - -// load *src as epi64, multiply by mult and store result in [out0 ... out3] -static WEBP_INLINE void LoadDispatchAndMult(const rescaler_t* const src, - const __m128i* const mult, - __m128i* const out0, - __m128i* const out1, - __m128i* const out2, - __m128i* const out3) { - const __m128i A0 = _mm_loadu_si128((const __m128i*)(src + 0)); - const __m128i A1 = _mm_loadu_si128((const __m128i*)(src + 4)); - const __m128i A2 = _mm_srli_epi64(A0, 32); - const __m128i A3 = _mm_srli_epi64(A1, 32); - if (mult != NULL) { - *out0 = _mm_mul_epu32(A0, *mult); - *out1 = _mm_mul_epu32(A1, *mult); - *out2 = _mm_mul_epu32(A2, *mult); - *out3 = _mm_mul_epu32(A3, *mult); - } else { - *out0 = A0; - *out1 = A1; - *out2 = A2; - *out3 = A3; - } -} - -static WEBP_INLINE void ProcessRow(const __m128i* const A0, - const __m128i* const A1, - const __m128i* const A2, - const __m128i* const A3, - const __m128i* const mult, - uint8_t* const dst) { - const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER); - const __m128i mask = _mm_set_epi32(0xffffffffu, 0, 0xffffffffu, 0); - const __m128i B0 = _mm_mul_epu32(*A0, *mult); - const __m128i B1 = _mm_mul_epu32(*A1, *mult); - const __m128i B2 = _mm_mul_epu32(*A2, *mult); - const __m128i B3 = _mm_mul_epu32(*A3, *mult); - const __m128i C0 = _mm_add_epi64(B0, rounder); - const __m128i C1 = _mm_add_epi64(B1, rounder); - const __m128i C2 = _mm_add_epi64(B2, rounder); - const __m128i C3 = _mm_add_epi64(B3, rounder); - const __m128i D0 = _mm_srli_epi64(C0, WEBP_RESCALER_RFIX); - const __m128i D1 = _mm_srli_epi64(C1, WEBP_RESCALER_RFIX); -#if (WEBP_RESCALER_FIX < 32) - const __m128i D2 = - _mm_and_si128(_mm_slli_epi64(C2, 32 - WEBP_RESCALER_RFIX), mask); - const __m128i D3 = - _mm_and_si128(_mm_slli_epi64(C3, 32 - WEBP_RESCALER_RFIX), mask); -#else - const __m128i D2 = _mm_and_si128(C2, mask); - const __m128i D3 = _mm_and_si128(C3, mask); -#endif - const __m128i E0 = _mm_or_si128(D0, D2); - const __m128i E1 = _mm_or_si128(D1, D3); - const __m128i F = _mm_packs_epi32(E0, E1); - const __m128i G = _mm_packus_epi16(F, F); - _mm_storel_epi64((__m128i*)dst, G); -} - -static void RescalerExportRowExpandSSE2(WebPRescaler* const wrk) { - int x_out; - uint8_t* const dst = wrk->dst; - rescaler_t* const irow = wrk->irow; - const int x_out_max = wrk->dst_width * wrk->num_channels; - const rescaler_t* const frow = wrk->frow; - const __m128i mult = _mm_set_epi32(0, wrk->fy_scale, 0, wrk->fy_scale); - - assert(!WebPRescalerOutputDone(wrk)); - assert(wrk->y_accum <= 0 && wrk->y_sub + wrk->y_accum >= 0); - assert(wrk->y_expand); - if (wrk->y_accum == 0) { - for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) { - __m128i A0, A1, A2, A3; - LoadDispatchAndMult(frow + x_out, NULL, &A0, &A1, &A2, &A3); - ProcessRow(&A0, &A1, &A2, &A3, &mult, dst + x_out); - } - for (; x_out < x_out_max; ++x_out) { - const uint32_t J = frow[x_out]; - const int v = (int)MULT_FIX(J, wrk->fy_scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - } - } else { - const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub); - const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); - const __m128i mA = _mm_set_epi32(0, A, 0, A); - const __m128i mB = _mm_set_epi32(0, B, 0, B); - const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER); - for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) { - __m128i A0, A1, A2, A3, B0, B1, B2, B3; - LoadDispatchAndMult(frow + x_out, &mA, &A0, &A1, &A2, &A3); - LoadDispatchAndMult(irow + x_out, &mB, &B0, &B1, &B2, &B3); - { - const __m128i C0 = _mm_add_epi64(A0, B0); - const __m128i C1 = _mm_add_epi64(A1, B1); - const __m128i C2 = _mm_add_epi64(A2, B2); - const __m128i C3 = _mm_add_epi64(A3, B3); - const __m128i D0 = _mm_add_epi64(C0, rounder); - const __m128i D1 = _mm_add_epi64(C1, rounder); - const __m128i D2 = _mm_add_epi64(C2, rounder); - const __m128i D3 = _mm_add_epi64(C3, rounder); - const __m128i E0 = _mm_srli_epi64(D0, WEBP_RESCALER_RFIX); - const __m128i E1 = _mm_srli_epi64(D1, WEBP_RESCALER_RFIX); - const __m128i E2 = _mm_srli_epi64(D2, WEBP_RESCALER_RFIX); - const __m128i E3 = _mm_srli_epi64(D3, WEBP_RESCALER_RFIX); - ProcessRow(&E0, &E1, &E2, &E3, &mult, dst + x_out); - } - } - for (; x_out < x_out_max; ++x_out) { - const uint64_t I = (uint64_t)A * frow[x_out] - + (uint64_t)B * irow[x_out]; - const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX); - const int v = (int)MULT_FIX(J, wrk->fy_scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - } - } -} - -static void RescalerExportRowShrinkSSE2(WebPRescaler* const wrk) { - int x_out; - uint8_t* const dst = wrk->dst; - rescaler_t* const irow = wrk->irow; - const int x_out_max = wrk->dst_width * wrk->num_channels; - const rescaler_t* const frow = wrk->frow; - const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum); - assert(!WebPRescalerOutputDone(wrk)); - assert(wrk->y_accum <= 0); - assert(!wrk->y_expand); - if (yscale) { - const int scale_xy = wrk->fxy_scale; - const __m128i mult_xy = _mm_set_epi32(0, scale_xy, 0, scale_xy); - const __m128i mult_y = _mm_set_epi32(0, yscale, 0, yscale); - const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER); - for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) { - __m128i A0, A1, A2, A3, B0, B1, B2, B3; - LoadDispatchAndMult(irow + x_out, NULL, &A0, &A1, &A2, &A3); - LoadDispatchAndMult(frow + x_out, &mult_y, &B0, &B1, &B2, &B3); - { - const __m128i C0 = _mm_add_epi64(B0, rounder); - const __m128i C1 = _mm_add_epi64(B1, rounder); - const __m128i C2 = _mm_add_epi64(B2, rounder); - const __m128i C3 = _mm_add_epi64(B3, rounder); - const __m128i D0 = _mm_srli_epi64(C0, WEBP_RESCALER_RFIX); // = frac - const __m128i D1 = _mm_srli_epi64(C1, WEBP_RESCALER_RFIX); - const __m128i D2 = _mm_srli_epi64(C2, WEBP_RESCALER_RFIX); - const __m128i D3 = _mm_srli_epi64(C3, WEBP_RESCALER_RFIX); - const __m128i E0 = _mm_sub_epi64(A0, D0); // irow[x] - frac - const __m128i E1 = _mm_sub_epi64(A1, D1); - const __m128i E2 = _mm_sub_epi64(A2, D2); - const __m128i E3 = _mm_sub_epi64(A3, D3); - const __m128i F2 = _mm_slli_epi64(D2, 32); - const __m128i F3 = _mm_slli_epi64(D3, 32); - const __m128i G0 = _mm_or_si128(D0, F2); - const __m128i G1 = _mm_or_si128(D1, F3); - _mm_storeu_si128((__m128i*)(irow + x_out + 0), G0); - _mm_storeu_si128((__m128i*)(irow + x_out + 4), G1); - ProcessRow(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out); - } - } - for (; x_out < x_out_max; ++x_out) { - const uint32_t frac = (int)MULT_FIX(frow[x_out], yscale); - const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - irow[x_out] = frac; // new fractional start - } - } else { - const uint32_t scale = wrk->fxy_scale; - const __m128i mult = _mm_set_epi32(0, scale, 0, scale); - const __m128i zero = _mm_setzero_si128(); - for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) { - __m128i A0, A1, A2, A3; - LoadDispatchAndMult(irow + x_out, NULL, &A0, &A1, &A2, &A3); - _mm_storeu_si128((__m128i*)(irow + x_out + 0), zero); - _mm_storeu_si128((__m128i*)(irow + x_out + 4), zero); - ProcessRow(&A0, &A1, &A2, &A3, &mult, dst + x_out); - } - for (; x_out < x_out_max; ++x_out) { - const int v = (int)MULT_FIX(irow[x_out], scale); - assert(v >= 0 && v <= 255); - dst[x_out] = v; - irow[x_out] = 0; - } - } -} - -#undef MULT_FIX -#undef ROUNDER - -//------------------------------------------------------------------------------ - -extern void WebPRescalerDspInitSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitSSE2(void) { - WebPRescalerImportRowExpand = RescalerImportRowExpandSSE2; - WebPRescalerImportRowShrink = RescalerImportRowShrinkSSE2; - WebPRescalerExportRowExpand = RescalerExportRowExpandSSE2; - WebPRescalerExportRowShrink = RescalerExportRowShrinkSSE2; -} - -#else // !WEBP_USE_SSE2 - -WEBP_DSP_INIT_STUB(WebPRescalerDspInitSSE2) - -#endif // WEBP_USE_SSE2 diff --git a/Example/Pods/libwebp/src/dsp/upsampling.c b/Example/Pods/libwebp/src/dsp/upsampling.c deleted file mode 100644 index 651274fc..00000000 --- a/Example/Pods/libwebp/src/dsp/upsampling.c +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// YUV to RGB upsampling functions. -// -// Author: somnath@google.com (Somnath Banerjee) - -#include "./dsp.h" -#include "./yuv.h" - -#include - -//------------------------------------------------------------------------------ -// Fancy upsampler - -#ifdef FANCY_UPSAMPLING - -// Fancy upsampling functions to convert YUV to RGB -WebPUpsampleLinePairFunc WebPUpsamplers[MODE_LAST]; - -// Given samples laid out in a square as: -// [a b] -// [c d] -// we interpolate u/v as: -// ([9*a + 3*b + 3*c + d 3*a + 9*b + 3*c + d] + [8 8]) / 16 -// ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16 - -// We process u and v together stashed into 32bit (16bit each). -#define LOAD_UV(u, v) ((u) | ((v) << 16)) - -#define UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ -static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ - const uint8_t* top_u, const uint8_t* top_v, \ - const uint8_t* cur_u, const uint8_t* cur_v, \ - uint8_t* top_dst, uint8_t* bottom_dst, int len) { \ - int x; \ - const int last_pixel_pair = (len - 1) >> 1; \ - uint32_t tl_uv = LOAD_UV(top_u[0], top_v[0]); /* top-left sample */ \ - uint32_t l_uv = LOAD_UV(cur_u[0], cur_v[0]); /* left-sample */ \ - assert(top_y != NULL); \ - { \ - const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ - FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \ - } \ - if (bottom_y != NULL) { \ - const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ - FUNC(bottom_y[0], uv0 & 0xff, (uv0 >> 16), bottom_dst); \ - } \ - for (x = 1; x <= last_pixel_pair; ++x) { \ - const uint32_t t_uv = LOAD_UV(top_u[x], top_v[x]); /* top sample */ \ - const uint32_t uv = LOAD_UV(cur_u[x], cur_v[x]); /* sample */ \ - /* precompute invariant values associated with first and second diagonals*/\ - const uint32_t avg = tl_uv + t_uv + l_uv + uv + 0x00080008u; \ - const uint32_t diag_12 = (avg + 2 * (t_uv + l_uv)) >> 3; \ - const uint32_t diag_03 = (avg + 2 * (tl_uv + uv)) >> 3; \ - { \ - const uint32_t uv0 = (diag_12 + tl_uv) >> 1; \ - const uint32_t uv1 = (diag_03 + t_uv) >> 1; \ - FUNC(top_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ - top_dst + (2 * x - 1) * XSTEP); \ - FUNC(top_y[2 * x - 0], uv1 & 0xff, (uv1 >> 16), \ - top_dst + (2 * x - 0) * XSTEP); \ - } \ - if (bottom_y != NULL) { \ - const uint32_t uv0 = (diag_03 + l_uv) >> 1; \ - const uint32_t uv1 = (diag_12 + uv) >> 1; \ - FUNC(bottom_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ - bottom_dst + (2 * x - 1) * XSTEP); \ - FUNC(bottom_y[2 * x + 0], uv1 & 0xff, (uv1 >> 16), \ - bottom_dst + (2 * x + 0) * XSTEP); \ - } \ - tl_uv = t_uv; \ - l_uv = uv; \ - } \ - if (!(len & 1)) { \ - { \ - const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ - FUNC(top_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ - top_dst + (len - 1) * XSTEP); \ - } \ - if (bottom_y != NULL) { \ - const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ - FUNC(bottom_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ - bottom_dst + (len - 1) * XSTEP); \ - } \ - } \ -} - -// All variants implemented. -UPSAMPLE_FUNC(UpsampleRgbLinePair, VP8YuvToRgb, 3) -UPSAMPLE_FUNC(UpsampleBgrLinePair, VP8YuvToBgr, 3) -UPSAMPLE_FUNC(UpsampleRgbaLinePair, VP8YuvToRgba, 4) -UPSAMPLE_FUNC(UpsampleBgraLinePair, VP8YuvToBgra, 4) -UPSAMPLE_FUNC(UpsampleArgbLinePair, VP8YuvToArgb, 4) -UPSAMPLE_FUNC(UpsampleRgba4444LinePair, VP8YuvToRgba4444, 2) -UPSAMPLE_FUNC(UpsampleRgb565LinePair, VP8YuvToRgb565, 2) - -#undef LOAD_UV -#undef UPSAMPLE_FUNC - -#endif // FANCY_UPSAMPLING - -//------------------------------------------------------------------------------ - -#if !defined(FANCY_UPSAMPLING) -#define DUAL_SAMPLE_FUNC(FUNC_NAME, FUNC) \ -static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bot_y, \ - const uint8_t* top_u, const uint8_t* top_v, \ - const uint8_t* bot_u, const uint8_t* bot_v, \ - uint8_t* top_dst, uint8_t* bot_dst, int len) { \ - const int half_len = len >> 1; \ - int x; \ - assert(top_dst != NULL); \ - { \ - for (x = 0; x < half_len; ++x) { \ - FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x + 0); \ - FUNC(top_y[2 * x + 1], top_u[x], top_v[x], top_dst + 8 * x + 4); \ - } \ - if (len & 1) FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x); \ - } \ - if (bot_dst != NULL) { \ - for (x = 0; x < half_len; ++x) { \ - FUNC(bot_y[2 * x + 0], bot_u[x], bot_v[x], bot_dst + 8 * x + 0); \ - FUNC(bot_y[2 * x + 1], bot_u[x], bot_v[x], bot_dst + 8 * x + 4); \ - } \ - if (len & 1) FUNC(bot_y[2 * x + 0], bot_u[x], bot_v[x], bot_dst + 8 * x); \ - } \ -} - -DUAL_SAMPLE_FUNC(DualLineSamplerBGRA, VP8YuvToBgra) -DUAL_SAMPLE_FUNC(DualLineSamplerARGB, VP8YuvToArgb) -#undef DUAL_SAMPLE_FUNC - -#endif // !FANCY_UPSAMPLING - -WebPUpsampleLinePairFunc WebPGetLinePairConverter(int alpha_is_last) { - WebPInitUpsamplers(); - VP8YUVInit(); -#ifdef FANCY_UPSAMPLING - return WebPUpsamplers[alpha_is_last ? MODE_BGRA : MODE_ARGB]; -#else - return (alpha_is_last ? DualLineSamplerBGRA : DualLineSamplerARGB); -#endif -} - -//------------------------------------------------------------------------------ -// YUV444 converter - -#define YUV444_FUNC(FUNC_NAME, FUNC, XSTEP) \ -extern void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ - uint8_t* dst, int len); \ -void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ - uint8_t* dst, int len) { \ - int i; \ - for (i = 0; i < len; ++i) FUNC(y[i], u[i], v[i], &dst[i * XSTEP]); \ -} - -YUV444_FUNC(WebPYuv444ToRgbC, VP8YuvToRgb, 3) -YUV444_FUNC(WebPYuv444ToBgrC, VP8YuvToBgr, 3) -YUV444_FUNC(WebPYuv444ToRgbaC, VP8YuvToRgba, 4) -YUV444_FUNC(WebPYuv444ToBgraC, VP8YuvToBgra, 4) -YUV444_FUNC(WebPYuv444ToArgbC, VP8YuvToArgb, 4) -YUV444_FUNC(WebPYuv444ToRgba4444C, VP8YuvToRgba4444, 2) -YUV444_FUNC(WebPYuv444ToRgb565C, VP8YuvToRgb565, 2) - -#undef YUV444_FUNC - -WebPYUV444Converter WebPYUV444Converters[MODE_LAST]; - -extern void WebPInitYUV444ConvertersMIPSdspR2(void); -extern void WebPInitYUV444ConvertersSSE2(void); - -static volatile VP8CPUInfo upsampling_last_cpuinfo_used1 = - (VP8CPUInfo)&upsampling_last_cpuinfo_used1; - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444Converters(void) { - if (upsampling_last_cpuinfo_used1 == VP8GetCPUInfo) return; - - WebPYUV444Converters[MODE_RGB] = WebPYuv444ToRgbC; - WebPYUV444Converters[MODE_RGBA] = WebPYuv444ToRgbaC; - WebPYUV444Converters[MODE_BGR] = WebPYuv444ToBgrC; - WebPYUV444Converters[MODE_BGRA] = WebPYuv444ToBgraC; - WebPYUV444Converters[MODE_ARGB] = WebPYuv444ToArgbC; - WebPYUV444Converters[MODE_RGBA_4444] = WebPYuv444ToRgba4444C; - WebPYUV444Converters[MODE_RGB_565] = WebPYuv444ToRgb565C; - WebPYUV444Converters[MODE_rgbA] = WebPYuv444ToRgbaC; - WebPYUV444Converters[MODE_bgrA] = WebPYuv444ToBgraC; - WebPYUV444Converters[MODE_Argb] = WebPYuv444ToArgbC; - WebPYUV444Converters[MODE_rgbA_4444] = WebPYuv444ToRgba4444C; - - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - WebPInitYUV444ConvertersSSE2(); - } -#endif -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - WebPInitYUV444ConvertersMIPSdspR2(); - } -#endif - } - upsampling_last_cpuinfo_used1 = VP8GetCPUInfo; -} - -//------------------------------------------------------------------------------ -// Main calls - -extern void WebPInitUpsamplersSSE2(void); -extern void WebPInitUpsamplersNEON(void); -extern void WebPInitUpsamplersMIPSdspR2(void); - -static volatile VP8CPUInfo upsampling_last_cpuinfo_used2 = - (VP8CPUInfo)&upsampling_last_cpuinfo_used2; - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplers(void) { - if (upsampling_last_cpuinfo_used2 == VP8GetCPUInfo) return; - -#ifdef FANCY_UPSAMPLING - WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; - WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; - WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair; - WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair; - WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair; - - // If defined, use CPUInfo() to overwrite some pointers with faster versions. - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - WebPInitUpsamplersSSE2(); - } -#endif -#if defined(WEBP_USE_NEON) - if (VP8GetCPUInfo(kNEON)) { - WebPInitUpsamplersNEON(); - } -#endif -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - WebPInitUpsamplersMIPSdspR2(); - } -#endif - } -#endif // FANCY_UPSAMPLING - upsampling_last_cpuinfo_used2 = VP8GetCPUInfo; -} - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/dsp/upsampling_mips_dsp_r2.c b/Example/Pods/libwebp/src/dsp/upsampling_mips_dsp_r2.c deleted file mode 100644 index d4ccbe0a..00000000 --- a/Example/Pods/libwebp/src/dsp/upsampling_mips_dsp_r2.c +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// YUV to RGB upsampling functions. -// -// Author(s): Branimir Vasic (branimir.vasic@imgtec.com) -// Djordje Pesut (djordje.pesut@imgtec.com) - -#include "./dsp.h" - -// Code is disabled for now, in favor of the plain-C version -// TODO(djordje.pesut): adapt the code to reflect the C-version. -#if 0 // defined(WEBP_USE_MIPS_DSP_R2) - -#include -#include "./yuv.h" - -#if !defined(WEBP_YUV_USE_TABLE) - -#define YUV_TO_RGB(Y, U, V, R, G, B) do { \ - const int t1 = kYScale * Y; \ - const int t2 = kVToG * V; \ - R = kVToR * V; \ - G = kUToG * U; \ - B = kUToB * U; \ - R = t1 + R; \ - G = t1 - G; \ - B = t1 + B; \ - R = R + kRCst; \ - G = G - t2 + kGCst; \ - B = B + kBCst; \ - __asm__ volatile ( \ - "shll_s.w %[" #R "], %[" #R "], 9 \n\t" \ - "shll_s.w %[" #G "], %[" #G "], 9 \n\t" \ - "shll_s.w %[" #B "], %[" #B "], 9 \n\t" \ - "precrqu_s.qb.ph %[" #R "], %[" #R "], $zero \n\t" \ - "precrqu_s.qb.ph %[" #G "], %[" #G "], $zero \n\t" \ - "precrqu_s.qb.ph %[" #B "], %[" #B "], $zero \n\t" \ - "srl %[" #R "], %[" #R "], 24 \n\t" \ - "srl %[" #G "], %[" #G "], 24 \n\t" \ - "srl %[" #B "], %[" #B "], 24 \n\t" \ - : [R]"+r"(R), [G]"+r"(G), [B]"+r"(B) \ - : \ - ); \ - } while (0) - -static WEBP_INLINE void YuvToRgb(int y, int u, int v, uint8_t* const rgb) { - int r, g, b; - YUV_TO_RGB(y, u, v, r, g, b); - rgb[0] = r; - rgb[1] = g; - rgb[2] = b; -} -static WEBP_INLINE void YuvToBgr(int y, int u, int v, uint8_t* const bgr) { - int r, g, b; - YUV_TO_RGB(y, u, v, r, g, b); - bgr[0] = b; - bgr[1] = g; - bgr[2] = r; -} -static WEBP_INLINE void YuvToRgb565(int y, int u, int v, uint8_t* const rgb) { - int r, g, b; - YUV_TO_RGB(y, u, v, r, g, b); - { - const int rg = (r & 0xf8) | (g >> 5); - const int gb = ((g << 3) & 0xe0) | (b >> 3); -#ifdef WEBP_SWAP_16BIT_CSP - rgb[0] = gb; - rgb[1] = rg; -#else - rgb[0] = rg; - rgb[1] = gb; -#endif - } -} -static WEBP_INLINE void YuvToRgba4444(int y, int u, int v, - uint8_t* const argb) { - int r, g, b; - YUV_TO_RGB(y, u, v, r, g, b); - { - const int rg = (r & 0xf0) | (g >> 4); - const int ba = (b & 0xf0) | 0x0f; // overwrite the lower 4 bits -#ifdef WEBP_SWAP_16BIT_CSP - argb[0] = ba; - argb[1] = rg; -#else - argb[0] = rg; - argb[1] = ba; -#endif - } -} -#endif // WEBP_YUV_USE_TABLE - -//----------------------------------------------------------------------------- -// Alpha handling variants - -static WEBP_INLINE void YuvToArgb(uint8_t y, uint8_t u, uint8_t v, - uint8_t* const argb) { - int r, g, b; - YUV_TO_RGB(y, u, v, r, g, b); - argb[0] = 0xff; - argb[1] = r; - argb[2] = g; - argb[3] = b; -} -static WEBP_INLINE void YuvToBgra(uint8_t y, uint8_t u, uint8_t v, - uint8_t* const bgra) { - int r, g, b; - YUV_TO_RGB(y, u, v, r, g, b); - bgra[0] = b; - bgra[1] = g; - bgra[2] = r; - bgra[3] = 0xff; -} -static WEBP_INLINE void YuvToRgba(uint8_t y, uint8_t u, uint8_t v, - uint8_t* const rgba) { - int r, g, b; - YUV_TO_RGB(y, u, v, r, g, b); - rgba[0] = r; - rgba[1] = g; - rgba[2] = b; - rgba[3] = 0xff; -} - -//------------------------------------------------------------------------------ -// Fancy upsampler - -#ifdef FANCY_UPSAMPLING - -// Given samples laid out in a square as: -// [a b] -// [c d] -// we interpolate u/v as: -// ([9*a + 3*b + 3*c + d 3*a + 9*b + 3*c + d] + [8 8]) / 16 -// ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16 - -// We process u and v together stashed into 32bit (16bit each). -#define LOAD_UV(u, v) ((u) | ((v) << 16)) - -#define UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ -static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ - const uint8_t* top_u, const uint8_t* top_v, \ - const uint8_t* cur_u, const uint8_t* cur_v, \ - uint8_t* top_dst, uint8_t* bottom_dst, int len) { \ - int x; \ - const int last_pixel_pair = (len - 1) >> 1; \ - uint32_t tl_uv = LOAD_UV(top_u[0], top_v[0]); /* top-left sample */ \ - uint32_t l_uv = LOAD_UV(cur_u[0], cur_v[0]); /* left-sample */ \ - assert(top_y != NULL); \ - { \ - const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ - FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \ - } \ - if (bottom_y != NULL) { \ - const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ - FUNC(bottom_y[0], uv0 & 0xff, (uv0 >> 16), bottom_dst); \ - } \ - for (x = 1; x <= last_pixel_pair; ++x) { \ - const uint32_t t_uv = LOAD_UV(top_u[x], top_v[x]); /* top sample */ \ - const uint32_t uv = LOAD_UV(cur_u[x], cur_v[x]); /* sample */ \ - /* precompute invariant values associated with first and second diagonals*/\ - const uint32_t avg = tl_uv + t_uv + l_uv + uv + 0x00080008u; \ - const uint32_t diag_12 = (avg + 2 * (t_uv + l_uv)) >> 3; \ - const uint32_t diag_03 = (avg + 2 * (tl_uv + uv)) >> 3; \ - { \ - const uint32_t uv0 = (diag_12 + tl_uv) >> 1; \ - const uint32_t uv1 = (diag_03 + t_uv) >> 1; \ - FUNC(top_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ - top_dst + (2 * x - 1) * XSTEP); \ - FUNC(top_y[2 * x - 0], uv1 & 0xff, (uv1 >> 16), \ - top_dst + (2 * x - 0) * XSTEP); \ - } \ - if (bottom_y != NULL) { \ - const uint32_t uv0 = (diag_03 + l_uv) >> 1; \ - const uint32_t uv1 = (diag_12 + uv) >> 1; \ - FUNC(bottom_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ - bottom_dst + (2 * x - 1) * XSTEP); \ - FUNC(bottom_y[2 * x + 0], uv1 & 0xff, (uv1 >> 16), \ - bottom_dst + (2 * x + 0) * XSTEP); \ - } \ - tl_uv = t_uv; \ - l_uv = uv; \ - } \ - if (!(len & 1)) { \ - { \ - const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ - FUNC(top_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ - top_dst + (len - 1) * XSTEP); \ - } \ - if (bottom_y != NULL) { \ - const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ - FUNC(bottom_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ - bottom_dst + (len - 1) * XSTEP); \ - } \ - } \ -} - -// All variants implemented. -UPSAMPLE_FUNC(UpsampleRgbLinePair, YuvToRgb, 3) -UPSAMPLE_FUNC(UpsampleBgrLinePair, YuvToBgr, 3) -UPSAMPLE_FUNC(UpsampleRgbaLinePair, YuvToRgba, 4) -UPSAMPLE_FUNC(UpsampleBgraLinePair, YuvToBgra, 4) -UPSAMPLE_FUNC(UpsampleArgbLinePair, YuvToArgb, 4) -UPSAMPLE_FUNC(UpsampleRgba4444LinePair, YuvToRgba4444, 2) -UPSAMPLE_FUNC(UpsampleRgb565LinePair, YuvToRgb565, 2) - -#undef LOAD_UV -#undef UPSAMPLE_FUNC - -//------------------------------------------------------------------------------ -// Entry point - -extern void WebPInitUpsamplersMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersMIPSdspR2(void) { - WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; - WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; - WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair; - WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair; - WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair; -} - -#endif // FANCY_UPSAMPLING - -//------------------------------------------------------------------------------ -// YUV444 converter - -#define YUV444_FUNC(FUNC_NAME, FUNC, XSTEP) \ -static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ - uint8_t* dst, int len) { \ - int i; \ - for (i = 0; i < len; ++i) FUNC(y[i], u[i], v[i], &dst[i * XSTEP]); \ -} - -YUV444_FUNC(Yuv444ToRgb, YuvToRgb, 3) -YUV444_FUNC(Yuv444ToBgr, YuvToBgr, 3) -YUV444_FUNC(Yuv444ToRgba, YuvToRgba, 4) -YUV444_FUNC(Yuv444ToBgra, YuvToBgra, 4) -YUV444_FUNC(Yuv444ToArgb, YuvToArgb, 4) -YUV444_FUNC(Yuv444ToRgba4444, YuvToRgba4444, 2) -YUV444_FUNC(Yuv444ToRgb565, YuvToRgb565, 2) - -#undef YUV444_FUNC - -//------------------------------------------------------------------------------ -// Entry point - -extern void WebPInitYUV444ConvertersMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444ConvertersMIPSdspR2(void) { - WebPYUV444Converters[MODE_RGB] = Yuv444ToRgb; - WebPYUV444Converters[MODE_RGBA] = Yuv444ToRgba; - WebPYUV444Converters[MODE_BGR] = Yuv444ToBgr; - WebPYUV444Converters[MODE_BGRA] = Yuv444ToBgra; - WebPYUV444Converters[MODE_ARGB] = Yuv444ToArgb; - WebPYUV444Converters[MODE_RGBA_4444] = Yuv444ToRgba4444; - WebPYUV444Converters[MODE_RGB_565] = Yuv444ToRgb565; - WebPYUV444Converters[MODE_rgbA] = Yuv444ToRgba; - WebPYUV444Converters[MODE_bgrA] = Yuv444ToBgra; - WebPYUV444Converters[MODE_Argb] = Yuv444ToArgb; - WebPYUV444Converters[MODE_rgbA_4444] = Yuv444ToRgba4444; -} - -#else // !WEBP_USE_MIPS_DSP_R2 - -WEBP_DSP_INIT_STUB(WebPInitYUV444ConvertersMIPSdspR2) - -#endif // WEBP_USE_MIPS_DSP_R2 - -#if 1 // !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_MIPS_DSP_R2)) -WEBP_DSP_INIT_STUB(WebPInitUpsamplersMIPSdspR2) -#endif diff --git a/Example/Pods/libwebp/src/dsp/upsampling_neon.c b/Example/Pods/libwebp/src/dsp/upsampling_neon.c deleted file mode 100644 index 2b0c99bd..00000000 --- a/Example/Pods/libwebp/src/dsp/upsampling_neon.c +++ /dev/null @@ -1,300 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// NEON version of YUV to RGB upsampling functions. -// -// Author: mans@mansr.com (Mans Rullgard) -// Based on SSE code by: somnath@google.com (Somnath Banerjee) - -#include "./dsp.h" - -#if defined(WEBP_USE_NEON) - -#include -#include -#include -#include "./neon.h" -#include "./yuv.h" - -#ifdef FANCY_UPSAMPLING - -//----------------------------------------------------------------------------- -// U/V upsampling - -// Loads 9 pixels each from rows r1 and r2 and generates 16 pixels. -#define UPSAMPLE_16PIXELS(r1, r2, out) { \ - uint8x8_t a = vld1_u8(r1); \ - uint8x8_t b = vld1_u8(r1 + 1); \ - uint8x8_t c = vld1_u8(r2); \ - uint8x8_t d = vld1_u8(r2 + 1); \ - \ - uint16x8_t al = vshll_n_u8(a, 1); \ - uint16x8_t bl = vshll_n_u8(b, 1); \ - uint16x8_t cl = vshll_n_u8(c, 1); \ - uint16x8_t dl = vshll_n_u8(d, 1); \ - \ - uint8x8_t diag1, diag2; \ - uint16x8_t sl; \ - \ - /* a + b + c + d */ \ - sl = vaddl_u8(a, b); \ - sl = vaddw_u8(sl, c); \ - sl = vaddw_u8(sl, d); \ - \ - al = vaddq_u16(sl, al); /* 3a + b + c + d */ \ - bl = vaddq_u16(sl, bl); /* a + 3b + c + d */ \ - \ - al = vaddq_u16(al, dl); /* 3a + b + c + 3d */ \ - bl = vaddq_u16(bl, cl); /* a + 3b + 3c + d */ \ - \ - diag2 = vshrn_n_u16(al, 3); \ - diag1 = vshrn_n_u16(bl, 3); \ - \ - a = vrhadd_u8(a, diag1); \ - b = vrhadd_u8(b, diag2); \ - c = vrhadd_u8(c, diag2); \ - d = vrhadd_u8(d, diag1); \ - \ - { \ - uint8x8x2_t a_b, c_d; \ - INIT_VECTOR2(a_b, a, b); \ - INIT_VECTOR2(c_d, c, d); \ - vst2_u8(out, a_b); \ - vst2_u8(out + 32, c_d); \ - } \ -} - -// Turn the macro into a function for reducing code-size when non-critical -static void Upsample16Pixels(const uint8_t *r1, const uint8_t *r2, - uint8_t *out) { - UPSAMPLE_16PIXELS(r1, r2, out); -} - -#define UPSAMPLE_LAST_BLOCK(tb, bb, num_pixels, out) { \ - uint8_t r1[9], r2[9]; \ - memcpy(r1, (tb), (num_pixels)); \ - memcpy(r2, (bb), (num_pixels)); \ - /* replicate last byte */ \ - memset(r1 + (num_pixels), r1[(num_pixels) - 1], 9 - (num_pixels)); \ - memset(r2 + (num_pixels), r2[(num_pixels) - 1], 9 - (num_pixels)); \ - Upsample16Pixels(r1, r2, out); \ -} - -//----------------------------------------------------------------------------- -// YUV->RGB conversion - -// note: we represent the 33050 large constant as 32768 + 282 -static const int16_t kCoeffs1[4] = { 19077, 26149, 6419, 13320 }; - -#define v255 vdup_n_u8(255) -#define v_0x0f vdup_n_u8(15) - -#define STORE_Rgb(out, r, g, b) do { \ - uint8x8x3_t r_g_b; \ - INIT_VECTOR3(r_g_b, r, g, b); \ - vst3_u8(out, r_g_b); \ -} while (0) - -#define STORE_Bgr(out, r, g, b) do { \ - uint8x8x3_t b_g_r; \ - INIT_VECTOR3(b_g_r, b, g, r); \ - vst3_u8(out, b_g_r); \ -} while (0) - -#define STORE_Rgba(out, r, g, b) do { \ - uint8x8x4_t r_g_b_v255; \ - INIT_VECTOR4(r_g_b_v255, r, g, b, v255); \ - vst4_u8(out, r_g_b_v255); \ -} while (0) - -#define STORE_Bgra(out, r, g, b) do { \ - uint8x8x4_t b_g_r_v255; \ - INIT_VECTOR4(b_g_r_v255, b, g, r, v255); \ - vst4_u8(out, b_g_r_v255); \ -} while (0) - -#define STORE_Argb(out, r, g, b) do { \ - uint8x8x4_t v255_r_g_b; \ - INIT_VECTOR4(v255_r_g_b, v255, r, g, b); \ - vst4_u8(out, v255_r_g_b); \ -} while (0) - -#if !defined(WEBP_SWAP_16BIT_CSP) -#define ZIP_U8(lo, hi) vzip_u8((lo), (hi)) -#else -#define ZIP_U8(lo, hi) vzip_u8((hi), (lo)) -#endif - -#define STORE_Rgba4444(out, r, g, b) do { \ - const uint8x8_t r1 = vshl_n_u8(vshr_n_u8(r, 4), 4); /* 4bits */ \ - const uint8x8_t g1 = vshr_n_u8(g, 4); \ - const uint8x8_t ba = vorr_u8(b, v_0x0f); \ - const uint8x8_t rg = vorr_u8(r1, g1); \ - const uint8x8x2_t rgba4444 = ZIP_U8(rg, ba); \ - vst1q_u8(out, vcombine_u8(rgba4444.val[0], rgba4444.val[1])); \ -} while (0) - -#define STORE_Rgb565(out, r, g, b) do { \ - const uint8x8_t r1 = vshl_n_u8(vshr_n_u8(r, 3), 3); /* 5bits */ \ - const uint8x8_t g1 = vshr_n_u8(g, 5); /* upper 3bits */\ - const uint8x8_t g2 = vshl_n_u8(vshr_n_u8(g, 2), 5); /* lower 3bits */\ - const uint8x8_t b1 = vshr_n_u8(b, 3); /* 5bits */ \ - const uint8x8_t rg = vorr_u8(r1, g1); \ - const uint8x8_t gb = vorr_u8(g2, b1); \ - const uint8x8x2_t rgb565 = ZIP_U8(rg, gb); \ - vst1q_u8(out, vcombine_u8(rgb565.val[0], rgb565.val[1])); \ -} while (0) - -#define CONVERT8(FMT, XSTEP, N, src_y, src_uv, out, cur_x) do { \ - int i; \ - for (i = 0; i < N; i += 8) { \ - const int off = ((cur_x) + i) * XSTEP; \ - const uint8x8_t y = vld1_u8((src_y) + (cur_x) + i); \ - const uint8x8_t u = vld1_u8((src_uv) + i + 0); \ - const uint8x8_t v = vld1_u8((src_uv) + i + 16); \ - const int16x8_t Y0 = vreinterpretq_s16_u16(vshll_n_u8(y, 7)); \ - const int16x8_t U0 = vreinterpretq_s16_u16(vshll_n_u8(u, 7)); \ - const int16x8_t V0 = vreinterpretq_s16_u16(vshll_n_u8(v, 7)); \ - const int16x8_t Y1 = vqdmulhq_lane_s16(Y0, coeff1, 0); \ - const int16x8_t R0 = vqdmulhq_lane_s16(V0, coeff1, 1); \ - const int16x8_t G0 = vqdmulhq_lane_s16(U0, coeff1, 2); \ - const int16x8_t G1 = vqdmulhq_lane_s16(V0, coeff1, 3); \ - const int16x8_t B0 = vqdmulhq_n_s16(U0, 282); \ - const int16x8_t R1 = vqaddq_s16(Y1, R_Rounder); \ - const int16x8_t G2 = vqaddq_s16(Y1, G_Rounder); \ - const int16x8_t B1 = vqaddq_s16(Y1, B_Rounder); \ - const int16x8_t R2 = vqaddq_s16(R0, R1); \ - const int16x8_t G3 = vqaddq_s16(G0, G1); \ - const int16x8_t B2 = vqaddq_s16(B0, B1); \ - const int16x8_t G4 = vqsubq_s16(G2, G3); \ - const int16x8_t B3 = vqaddq_s16(B2, U0); \ - const uint8x8_t R = vqshrun_n_s16(R2, YUV_FIX2); \ - const uint8x8_t G = vqshrun_n_s16(G4, YUV_FIX2); \ - const uint8x8_t B = vqshrun_n_s16(B3, YUV_FIX2); \ - STORE_ ## FMT(out + off, R, G, B); \ - } \ -} while (0) - -#define CONVERT1(FUNC, XSTEP, N, src_y, src_uv, rgb, cur_x) { \ - int i; \ - for (i = 0; i < N; i++) { \ - const int off = ((cur_x) + i) * XSTEP; \ - const int y = src_y[(cur_x) + i]; \ - const int u = (src_uv)[i]; \ - const int v = (src_uv)[i + 16]; \ - FUNC(y, u, v, rgb + off); \ - } \ -} - -#define CONVERT2RGB_8(FMT, XSTEP, top_y, bottom_y, uv, \ - top_dst, bottom_dst, cur_x, len) { \ - CONVERT8(FMT, XSTEP, len, top_y, uv, top_dst, cur_x); \ - if (bottom_y != NULL) { \ - CONVERT8(FMT, XSTEP, len, bottom_y, (uv) + 32, bottom_dst, cur_x); \ - } \ -} - -#define CONVERT2RGB_1(FUNC, XSTEP, top_y, bottom_y, uv, \ - top_dst, bottom_dst, cur_x, len) { \ - CONVERT1(FUNC, XSTEP, len, top_y, uv, top_dst, cur_x); \ - if (bottom_y != NULL) { \ - CONVERT1(FUNC, XSTEP, len, bottom_y, (uv) + 32, bottom_dst, cur_x); \ - } \ -} - -#define NEON_UPSAMPLE_FUNC(FUNC_NAME, FMT, XSTEP) \ -static void FUNC_NAME(const uint8_t *top_y, const uint8_t *bottom_y, \ - const uint8_t *top_u, const uint8_t *top_v, \ - const uint8_t *cur_u, const uint8_t *cur_v, \ - uint8_t *top_dst, uint8_t *bottom_dst, int len) { \ - int block; \ - /* 16 byte aligned array to cache reconstructed u and v */ \ - uint8_t uv_buf[2 * 32 + 15]; \ - uint8_t *const r_uv = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \ - const int uv_len = (len + 1) >> 1; \ - /* 9 pixels must be read-able for each block */ \ - const int num_blocks = (uv_len - 1) >> 3; \ - const int leftover = uv_len - num_blocks * 8; \ - const int last_pos = 1 + 16 * num_blocks; \ - \ - const int u_diag = ((top_u[0] + cur_u[0]) >> 1) + 1; \ - const int v_diag = ((top_v[0] + cur_v[0]) >> 1) + 1; \ - \ - const int16x4_t coeff1 = vld1_s16(kCoeffs1); \ - const int16x8_t R_Rounder = vdupq_n_s16(-14234); \ - const int16x8_t G_Rounder = vdupq_n_s16(8708); \ - const int16x8_t B_Rounder = vdupq_n_s16(-17685); \ - \ - /* Treat the first pixel in regular way */ \ - assert(top_y != NULL); \ - { \ - const int u0 = (top_u[0] + u_diag) >> 1; \ - const int v0 = (top_v[0] + v_diag) >> 1; \ - VP8YuvTo ## FMT(top_y[0], u0, v0, top_dst); \ - } \ - if (bottom_y != NULL) { \ - const int u0 = (cur_u[0] + u_diag) >> 1; \ - const int v0 = (cur_v[0] + v_diag) >> 1; \ - VP8YuvTo ## FMT(bottom_y[0], u0, v0, bottom_dst); \ - } \ - \ - for (block = 0; block < num_blocks; ++block) { \ - UPSAMPLE_16PIXELS(top_u, cur_u, r_uv); \ - UPSAMPLE_16PIXELS(top_v, cur_v, r_uv + 16); \ - CONVERT2RGB_8(FMT, XSTEP, top_y, bottom_y, r_uv, \ - top_dst, bottom_dst, 16 * block + 1, 16); \ - top_u += 8; \ - cur_u += 8; \ - top_v += 8; \ - cur_v += 8; \ - } \ - \ - UPSAMPLE_LAST_BLOCK(top_u, cur_u, leftover, r_uv); \ - UPSAMPLE_LAST_BLOCK(top_v, cur_v, leftover, r_uv + 16); \ - CONVERT2RGB_1(VP8YuvTo ## FMT, XSTEP, top_y, bottom_y, r_uv, \ - top_dst, bottom_dst, last_pos, len - last_pos); \ -} - -// NEON variants of the fancy upsampler. -NEON_UPSAMPLE_FUNC(UpsampleRgbLinePair, Rgb, 3) -NEON_UPSAMPLE_FUNC(UpsampleBgrLinePair, Bgr, 3) -NEON_UPSAMPLE_FUNC(UpsampleRgbaLinePair, Rgba, 4) -NEON_UPSAMPLE_FUNC(UpsampleBgraLinePair, Bgra, 4) -NEON_UPSAMPLE_FUNC(UpsampleArgbLinePair, Argb, 4) -NEON_UPSAMPLE_FUNC(UpsampleRgba4444LinePair, Rgba4444, 2) -NEON_UPSAMPLE_FUNC(UpsampleRgb565LinePair, Rgb565, 2) - -//------------------------------------------------------------------------------ -// Entry point - -extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; - -extern void WebPInitUpsamplersNEON(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersNEON(void) { - WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; - WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; - WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair; - WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair; - WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair; -} - -#endif // FANCY_UPSAMPLING - -#endif // WEBP_USE_NEON - -#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_NEON)) -WEBP_DSP_INIT_STUB(WebPInitUpsamplersNEON) -#endif diff --git a/Example/Pods/libwebp/src/dsp/upsampling_sse2.c b/Example/Pods/libwebp/src/dsp/upsampling_sse2.c deleted file mode 100644 index b5b66890..00000000 --- a/Example/Pods/libwebp/src/dsp/upsampling_sse2.c +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// SSE2 version of YUV to RGB upsampling functions. -// -// Author: somnath@google.com (Somnath Banerjee) - -#include "./dsp.h" - -#if defined(WEBP_USE_SSE2) - -#include -#include -#include -#include "./yuv.h" - -#ifdef FANCY_UPSAMPLING - -// We compute (9*a + 3*b + 3*c + d + 8) / 16 as follows -// u = (9*a + 3*b + 3*c + d + 8) / 16 -// = (a + (a + 3*b + 3*c + d) / 8 + 1) / 2 -// = (a + m + 1) / 2 -// where m = (a + 3*b + 3*c + d) / 8 -// = ((a + b + c + d) / 2 + b + c) / 4 -// -// Let's say k = (a + b + c + d) / 4. -// We can compute k as -// k = (s + t + 1) / 2 - ((a^d) | (b^c) | (s^t)) & 1 -// where s = (a + d + 1) / 2 and t = (b + c + 1) / 2 -// -// Then m can be written as -// m = (k + t + 1) / 2 - (((b^c) & (s^t)) | (k^t)) & 1 - -// Computes out = (k + in + 1) / 2 - ((ij & (s^t)) | (k^in)) & 1 -#define GET_M(ij, in, out) do { \ - const __m128i tmp0 = _mm_avg_epu8(k, (in)); /* (k + in + 1) / 2 */ \ - const __m128i tmp1 = _mm_and_si128((ij), st); /* (ij) & (s^t) */ \ - const __m128i tmp2 = _mm_xor_si128(k, (in)); /* (k^in) */ \ - const __m128i tmp3 = _mm_or_si128(tmp1, tmp2); /* ((ij) & (s^t)) | (k^in) */\ - const __m128i tmp4 = _mm_and_si128(tmp3, one); /* & 1 -> lsb_correction */ \ - (out) = _mm_sub_epi8(tmp0, tmp4); /* (k + in + 1) / 2 - lsb_correction */ \ -} while (0) - -// pack and store two alternating pixel rows -#define PACK_AND_STORE(a, b, da, db, out) do { \ - const __m128i t_a = _mm_avg_epu8(a, da); /* (9a + 3b + 3c + d + 8) / 16 */ \ - const __m128i t_b = _mm_avg_epu8(b, db); /* (3a + 9b + c + 3d + 8) / 16 */ \ - const __m128i t_1 = _mm_unpacklo_epi8(t_a, t_b); \ - const __m128i t_2 = _mm_unpackhi_epi8(t_a, t_b); \ - _mm_store_si128(((__m128i*)(out)) + 0, t_1); \ - _mm_store_si128(((__m128i*)(out)) + 1, t_2); \ -} while (0) - -// Loads 17 pixels each from rows r1 and r2 and generates 32 pixels. -#define UPSAMPLE_32PIXELS(r1, r2, out) { \ - const __m128i one = _mm_set1_epi8(1); \ - const __m128i a = _mm_loadu_si128((const __m128i*)&(r1)[0]); \ - const __m128i b = _mm_loadu_si128((const __m128i*)&(r1)[1]); \ - const __m128i c = _mm_loadu_si128((const __m128i*)&(r2)[0]); \ - const __m128i d = _mm_loadu_si128((const __m128i*)&(r2)[1]); \ - \ - const __m128i s = _mm_avg_epu8(a, d); /* s = (a + d + 1) / 2 */ \ - const __m128i t = _mm_avg_epu8(b, c); /* t = (b + c + 1) / 2 */ \ - const __m128i st = _mm_xor_si128(s, t); /* st = s^t */ \ - \ - const __m128i ad = _mm_xor_si128(a, d); /* ad = a^d */ \ - const __m128i bc = _mm_xor_si128(b, c); /* bc = b^c */ \ - \ - const __m128i t1 = _mm_or_si128(ad, bc); /* (a^d) | (b^c) */ \ - const __m128i t2 = _mm_or_si128(t1, st); /* (a^d) | (b^c) | (s^t) */ \ - const __m128i t3 = _mm_and_si128(t2, one); /* (a^d) | (b^c) | (s^t) & 1 */ \ - const __m128i t4 = _mm_avg_epu8(s, t); \ - const __m128i k = _mm_sub_epi8(t4, t3); /* k = (a + b + c + d) / 4 */ \ - __m128i diag1, diag2; \ - \ - GET_M(bc, t, diag1); /* diag1 = (a + 3b + 3c + d) / 8 */ \ - GET_M(ad, s, diag2); /* diag2 = (3a + b + c + 3d) / 8 */ \ - \ - /* pack the alternate pixels */ \ - PACK_AND_STORE(a, b, diag1, diag2, out + 0); /* store top */ \ - PACK_AND_STORE(c, d, diag2, diag1, out + 2 * 32); /* store bottom */ \ -} - -// Turn the macro into a function for reducing code-size when non-critical -static void Upsample32Pixels(const uint8_t r1[], const uint8_t r2[], - uint8_t* const out) { - UPSAMPLE_32PIXELS(r1, r2, out); -} - -#define UPSAMPLE_LAST_BLOCK(tb, bb, num_pixels, out) { \ - uint8_t r1[17], r2[17]; \ - memcpy(r1, (tb), (num_pixels)); \ - memcpy(r2, (bb), (num_pixels)); \ - /* replicate last byte */ \ - memset(r1 + (num_pixels), r1[(num_pixels) - 1], 17 - (num_pixels)); \ - memset(r2 + (num_pixels), r2[(num_pixels) - 1], 17 - (num_pixels)); \ - /* using the shared function instead of the macro saves ~3k code size */ \ - Upsample32Pixels(r1, r2, out); \ -} - -#define CONVERT2RGB(FUNC, XSTEP, top_y, bottom_y, \ - top_dst, bottom_dst, cur_x, num_pixels) { \ - int n; \ - for (n = 0; n < (num_pixels); ++n) { \ - FUNC(top_y[(cur_x) + n], r_u[n], r_v[n], \ - top_dst + ((cur_x) + n) * XSTEP); \ - } \ - if (bottom_y != NULL) { \ - for (n = 0; n < (num_pixels); ++n) { \ - FUNC(bottom_y[(cur_x) + n], r_u[64 + n], r_v[64 + n], \ - bottom_dst + ((cur_x) + n) * XSTEP); \ - } \ - } \ -} - -#define CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, \ - top_dst, bottom_dst, cur_x) do { \ - FUNC##32(top_y + (cur_x), r_u, r_v, top_dst + (cur_x) * XSTEP); \ - if (bottom_y != NULL) { \ - FUNC##32(bottom_y + (cur_x), r_u + 64, r_v + 64, \ - bottom_dst + (cur_x) * XSTEP); \ - } \ -} while (0) - -#define SSE2_UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ -static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ - const uint8_t* top_u, const uint8_t* top_v, \ - const uint8_t* cur_u, const uint8_t* cur_v, \ - uint8_t* top_dst, uint8_t* bottom_dst, int len) { \ - int uv_pos, pos; \ - /* 16byte-aligned array to cache reconstructed u and v */ \ - uint8_t uv_buf[4 * 32 + 15]; \ - uint8_t* const r_u = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \ - uint8_t* const r_v = r_u + 32; \ - \ - assert(top_y != NULL); \ - { /* Treat the first pixel in regular way */ \ - const int u_diag = ((top_u[0] + cur_u[0]) >> 1) + 1; \ - const int v_diag = ((top_v[0] + cur_v[0]) >> 1) + 1; \ - const int u0_t = (top_u[0] + u_diag) >> 1; \ - const int v0_t = (top_v[0] + v_diag) >> 1; \ - FUNC(top_y[0], u0_t, v0_t, top_dst); \ - if (bottom_y != NULL) { \ - const int u0_b = (cur_u[0] + u_diag) >> 1; \ - const int v0_b = (cur_v[0] + v_diag) >> 1; \ - FUNC(bottom_y[0], u0_b, v0_b, bottom_dst); \ - } \ - } \ - /* For UPSAMPLE_32PIXELS, 17 u/v values must be read-able for each block */ \ - for (pos = 1, uv_pos = 0; pos + 32 + 1 <= len; pos += 32, uv_pos += 16) { \ - UPSAMPLE_32PIXELS(top_u + uv_pos, cur_u + uv_pos, r_u); \ - UPSAMPLE_32PIXELS(top_v + uv_pos, cur_v + uv_pos, r_v); \ - CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, top_dst, bottom_dst, pos); \ - } \ - if (len > 1) { \ - const int left_over = ((len + 1) >> 1) - (pos >> 1); \ - assert(left_over > 0); \ - UPSAMPLE_LAST_BLOCK(top_u + uv_pos, cur_u + uv_pos, left_over, r_u); \ - UPSAMPLE_LAST_BLOCK(top_v + uv_pos, cur_v + uv_pos, left_over, r_v); \ - CONVERT2RGB(FUNC, XSTEP, top_y, bottom_y, top_dst, bottom_dst, \ - pos, len - pos); \ - } \ -} - -// SSE2 variants of the fancy upsampler. -SSE2_UPSAMPLE_FUNC(UpsampleRgbLinePair, VP8YuvToRgb, 3) -SSE2_UPSAMPLE_FUNC(UpsampleBgrLinePair, VP8YuvToBgr, 3) -SSE2_UPSAMPLE_FUNC(UpsampleRgbaLinePair, VP8YuvToRgba, 4) -SSE2_UPSAMPLE_FUNC(UpsampleBgraLinePair, VP8YuvToBgra, 4) -SSE2_UPSAMPLE_FUNC(UpsampleArgbLinePair, VP8YuvToArgb, 4) -SSE2_UPSAMPLE_FUNC(UpsampleRgba4444LinePair, VP8YuvToRgba4444, 2) -SSE2_UPSAMPLE_FUNC(UpsampleRgb565LinePair, VP8YuvToRgb565, 2) - -#undef GET_M -#undef PACK_AND_STORE -#undef UPSAMPLE_32PIXELS -#undef UPSAMPLE_LAST_BLOCK -#undef CONVERT2RGB -#undef CONVERT2RGB_32 -#undef SSE2_UPSAMPLE_FUNC - -//------------------------------------------------------------------------------ -// Entry point - -extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; - -extern void WebPInitUpsamplersSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersSSE2(void) { - WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; - WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; - WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair; - WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair; - WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair; -} - -#endif // FANCY_UPSAMPLING - -//------------------------------------------------------------------------------ - -extern WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */]; -extern void WebPInitYUV444ConvertersSSE2(void); - -#define YUV444_FUNC(FUNC_NAME, CALL, XSTEP) \ -extern void WebP##FUNC_NAME##C(const uint8_t* y, const uint8_t* u, \ - const uint8_t* v, uint8_t* dst, int len); \ -static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ - uint8_t* dst, int len) { \ - int i; \ - const int max_len = len & ~31; \ - for (i = 0; i < max_len; i += 32) CALL(y + i, u + i, v + i, dst + i * XSTEP);\ - if (i < len) { /* C-fallback */ \ - WebP##FUNC_NAME##C(y + i, u + i, v + i, dst + i * XSTEP, len - i); \ - } \ -} - -YUV444_FUNC(Yuv444ToRgba, VP8YuvToRgba32, 4); -YUV444_FUNC(Yuv444ToBgra, VP8YuvToBgra32, 4); -YUV444_FUNC(Yuv444ToRgb, VP8YuvToRgb32, 3); -YUV444_FUNC(Yuv444ToBgr, VP8YuvToBgr32, 3); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444ConvertersSSE2(void) { - WebPYUV444Converters[MODE_RGBA] = Yuv444ToRgba; - WebPYUV444Converters[MODE_BGRA] = Yuv444ToBgra; - WebPYUV444Converters[MODE_RGB] = Yuv444ToRgb; - WebPYUV444Converters[MODE_BGR] = Yuv444ToBgr; -} - -#else - -WEBP_DSP_INIT_STUB(WebPInitYUV444ConvertersSSE2) - -#endif // WEBP_USE_SSE2 - -#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_SSE2)) -WEBP_DSP_INIT_STUB(WebPInitUpsamplersSSE2) -#endif diff --git a/Example/Pods/libwebp/src/dsp/yuv.c b/Example/Pods/libwebp/src/dsp/yuv.c deleted file mode 100644 index f50a2531..00000000 --- a/Example/Pods/libwebp/src/dsp/yuv.c +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// YUV->RGB conversion functions -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./yuv.h" - -#if defined(WEBP_YUV_USE_TABLE) - -static int done = 0; - -static WEBP_INLINE uint8_t clip(int v, int max_value) { - return v < 0 ? 0 : v > max_value ? max_value : v; -} - -int16_t VP8kVToR[256], VP8kUToB[256]; -int32_t VP8kVToG[256], VP8kUToG[256]; -uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN]; -uint8_t VP8kClip4Bits[YUV_RANGE_MAX - YUV_RANGE_MIN]; - -WEBP_TSAN_IGNORE_FUNCTION void VP8YUVInit(void) { - int i; - if (done) { - return; - } -#ifndef USE_YUVj - for (i = 0; i < 256; ++i) { - VP8kVToR[i] = (89858 * (i - 128) + YUV_HALF) >> YUV_FIX; - VP8kUToG[i] = -22014 * (i - 128) + YUV_HALF; - VP8kVToG[i] = -45773 * (i - 128); - VP8kUToB[i] = (113618 * (i - 128) + YUV_HALF) >> YUV_FIX; - } - for (i = YUV_RANGE_MIN; i < YUV_RANGE_MAX; ++i) { - const int k = ((i - 16) * 76283 + YUV_HALF) >> YUV_FIX; - VP8kClip[i - YUV_RANGE_MIN] = clip(k, 255); - VP8kClip4Bits[i - YUV_RANGE_MIN] = clip((k + 8) >> 4, 15); - } -#else - for (i = 0; i < 256; ++i) { - VP8kVToR[i] = (91881 * (i - 128) + YUV_HALF) >> YUV_FIX; - VP8kUToG[i] = -22554 * (i - 128) + YUV_HALF; - VP8kVToG[i] = -46802 * (i - 128); - VP8kUToB[i] = (116130 * (i - 128) + YUV_HALF) >> YUV_FIX; - } - for (i = YUV_RANGE_MIN; i < YUV_RANGE_MAX; ++i) { - const int k = i; - VP8kClip[i - YUV_RANGE_MIN] = clip(k, 255); - VP8kClip4Bits[i - YUV_RANGE_MIN] = clip((k + 8) >> 4, 15); - } -#endif - - done = 1; -} - -#else - -WEBP_TSAN_IGNORE_FUNCTION void VP8YUVInit(void) {} - -#endif // WEBP_YUV_USE_TABLE - -//----------------------------------------------------------------------------- -// Plain-C version - -#define ROW_FUNC(FUNC_NAME, FUNC, XSTEP) \ -static void FUNC_NAME(const uint8_t* y, \ - const uint8_t* u, const uint8_t* v, \ - uint8_t* dst, int len) { \ - const uint8_t* const end = dst + (len & ~1) * XSTEP; \ - while (dst != end) { \ - FUNC(y[0], u[0], v[0], dst); \ - FUNC(y[1], u[0], v[0], dst + XSTEP); \ - y += 2; \ - ++u; \ - ++v; \ - dst += 2 * XSTEP; \ - } \ - if (len & 1) { \ - FUNC(y[0], u[0], v[0], dst); \ - } \ -} \ - -// All variants implemented. -ROW_FUNC(YuvToRgbRow, VP8YuvToRgb, 3) -ROW_FUNC(YuvToBgrRow, VP8YuvToBgr, 3) -ROW_FUNC(YuvToRgbaRow, VP8YuvToRgba, 4) -ROW_FUNC(YuvToBgraRow, VP8YuvToBgra, 4) -ROW_FUNC(YuvToArgbRow, VP8YuvToArgb, 4) -ROW_FUNC(YuvToRgba4444Row, VP8YuvToRgba4444, 2) -ROW_FUNC(YuvToRgb565Row, VP8YuvToRgb565, 2) - -#undef ROW_FUNC - -// Main call for processing a plane with a WebPSamplerRowFunc function: -void WebPSamplerProcessPlane(const uint8_t* y, int y_stride, - const uint8_t* u, const uint8_t* v, int uv_stride, - uint8_t* dst, int dst_stride, - int width, int height, WebPSamplerRowFunc func) { - int j; - for (j = 0; j < height; ++j) { - func(y, u, v, dst, width); - y += y_stride; - if (j & 1) { - u += uv_stride; - v += uv_stride; - } - dst += dst_stride; - } -} - -//----------------------------------------------------------------------------- -// Main call - -WebPSamplerRowFunc WebPSamplers[MODE_LAST]; - -extern void WebPInitSamplersSSE2(void); -extern void WebPInitSamplersMIPS32(void); -extern void WebPInitSamplersMIPSdspR2(void); - -static volatile VP8CPUInfo yuv_last_cpuinfo_used = - (VP8CPUInfo)&yuv_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplers(void) { - if (yuv_last_cpuinfo_used == VP8GetCPUInfo) return; - - WebPSamplers[MODE_RGB] = YuvToRgbRow; - WebPSamplers[MODE_RGBA] = YuvToRgbaRow; - WebPSamplers[MODE_BGR] = YuvToBgrRow; - WebPSamplers[MODE_BGRA] = YuvToBgraRow; - WebPSamplers[MODE_ARGB] = YuvToArgbRow; - WebPSamplers[MODE_RGBA_4444] = YuvToRgba4444Row; - WebPSamplers[MODE_RGB_565] = YuvToRgb565Row; - WebPSamplers[MODE_rgbA] = YuvToRgbaRow; - WebPSamplers[MODE_bgrA] = YuvToBgraRow; - WebPSamplers[MODE_Argb] = YuvToArgbRow; - WebPSamplers[MODE_rgbA_4444] = YuvToRgba4444Row; - - // If defined, use CPUInfo() to overwrite some pointers with faster versions. - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - WebPInitSamplersSSE2(); - } -#endif // WEBP_USE_SSE2 -#if defined(WEBP_USE_MIPS32) - if (VP8GetCPUInfo(kMIPS32)) { - WebPInitSamplersMIPS32(); - } -#endif // WEBP_USE_MIPS32 -#if defined(WEBP_USE_MIPS_DSP_R2) - if (VP8GetCPUInfo(kMIPSdspR2)) { - WebPInitSamplersMIPSdspR2(); - } -#endif // WEBP_USE_MIPS_DSP_R2 - } - yuv_last_cpuinfo_used = VP8GetCPUInfo; -} - -//----------------------------------------------------------------------------- -// ARGB -> YUV converters - -static void ConvertARGBToY(const uint32_t* argb, uint8_t* y, int width) { - int i; - for (i = 0; i < width; ++i) { - const uint32_t p = argb[i]; - y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff, - YUV_HALF); - } -} - -void WebPConvertARGBToUV_C(const uint32_t* argb, uint8_t* u, uint8_t* v, - int src_width, int do_store) { - // No rounding. Last pixel is dealt with separately. - const int uv_width = src_width >> 1; - int i; - for (i = 0; i < uv_width; ++i) { - const uint32_t v0 = argb[2 * i + 0]; - const uint32_t v1 = argb[2 * i + 1]; - // VP8RGBToU/V expects four accumulated pixels. Hence we need to - // scale r/g/b value by a factor 2. We just shift v0/v1 one bit less. - const int r = ((v0 >> 15) & 0x1fe) + ((v1 >> 15) & 0x1fe); - const int g = ((v0 >> 7) & 0x1fe) + ((v1 >> 7) & 0x1fe); - const int b = ((v0 << 1) & 0x1fe) + ((v1 << 1) & 0x1fe); - const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2); - const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2); - if (do_store) { - u[i] = tmp_u; - v[i] = tmp_v; - } else { - // Approximated average-of-four. But it's an acceptable diff. - u[i] = (u[i] + tmp_u + 1) >> 1; - v[i] = (v[i] + tmp_v + 1) >> 1; - } - } - if (src_width & 1) { // last pixel - const uint32_t v0 = argb[2 * i + 0]; - const int r = (v0 >> 14) & 0x3fc; - const int g = (v0 >> 6) & 0x3fc; - const int b = (v0 << 2) & 0x3fc; - const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2); - const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2); - if (do_store) { - u[i] = tmp_u; - v[i] = tmp_v; - } else { - u[i] = (u[i] + tmp_u + 1) >> 1; - v[i] = (v[i] + tmp_v + 1) >> 1; - } - } -} - -//----------------------------------------------------------------------------- - -static void ConvertRGB24ToY(const uint8_t* rgb, uint8_t* y, int width) { - int i; - for (i = 0; i < width; ++i, rgb += 3) { - y[i] = VP8RGBToY(rgb[0], rgb[1], rgb[2], YUV_HALF); - } -} - -static void ConvertBGR24ToY(const uint8_t* bgr, uint8_t* y, int width) { - int i; - for (i = 0; i < width; ++i, bgr += 3) { - y[i] = VP8RGBToY(bgr[2], bgr[1], bgr[0], YUV_HALF); - } -} - -void WebPConvertRGBA32ToUV_C(const uint16_t* rgb, - uint8_t* u, uint8_t* v, int width) { - int i; - for (i = 0; i < width; i += 1, rgb += 4) { - const int r = rgb[0], g = rgb[1], b = rgb[2]; - u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2); - v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2); - } -} - -//----------------------------------------------------------------------------- - -void (*WebPConvertRGB24ToY)(const uint8_t* rgb, uint8_t* y, int width); -void (*WebPConvertBGR24ToY)(const uint8_t* bgr, uint8_t* y, int width); -void (*WebPConvertRGBA32ToUV)(const uint16_t* rgb, - uint8_t* u, uint8_t* v, int width); - -void (*WebPConvertARGBToY)(const uint32_t* argb, uint8_t* y, int width); -void (*WebPConvertARGBToUV)(const uint32_t* argb, uint8_t* u, uint8_t* v, - int src_width, int do_store); - -static volatile VP8CPUInfo rgba_to_yuv_last_cpuinfo_used = - (VP8CPUInfo)&rgba_to_yuv_last_cpuinfo_used; - -extern void WebPInitConvertARGBToYUVSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUV(void) { - if (rgba_to_yuv_last_cpuinfo_used == VP8GetCPUInfo) return; - - WebPConvertARGBToY = ConvertARGBToY; - WebPConvertARGBToUV = WebPConvertARGBToUV_C; - - WebPConvertRGB24ToY = ConvertRGB24ToY; - WebPConvertBGR24ToY = ConvertBGR24ToY; - - WebPConvertRGBA32ToUV = WebPConvertRGBA32ToUV_C; - - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - WebPInitConvertARGBToYUVSSE2(); - } -#endif // WEBP_USE_SSE2 - } - rgba_to_yuv_last_cpuinfo_used = VP8GetCPUInfo; -} diff --git a/Example/Pods/libwebp/src/dsp/yuv.h b/Example/Pods/libwebp/src/dsp/yuv.h deleted file mode 100644 index 01c40fcb..00000000 --- a/Example/Pods/libwebp/src/dsp/yuv.h +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// inline YUV<->RGB conversion function -// -// The exact naming is Y'CbCr, following the ITU-R BT.601 standard. -// More information at: http://en.wikipedia.org/wiki/YCbCr -// Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16 -// U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128 -// V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128 -// We use 16bit fixed point operations for RGB->YUV conversion (YUV_FIX). -// -// For the Y'CbCr to RGB conversion, the BT.601 specification reads: -// R = 1.164 * (Y-16) + 1.596 * (V-128) -// G = 1.164 * (Y-16) - 0.813 * (V-128) - 0.391 * (U-128) -// B = 1.164 * (Y-16) + 2.018 * (U-128) -// where Y is in the [16,235] range, and U/V in the [16,240] range. -// -// The fixed-point implementation used here is: -// R = (19077 . y + 26149 . v - 14234) >> 6 -// G = (19077 . y - 6419 . u - 13320 . v + 8708) >> 6 -// B = (19077 . y + 33050 . u - 17685) >> 6 -// where the '.' operator is the mulhi_epu16 variant: -// a . b = ((a << 8) * b) >> 16 -// that preserves 8 bits of fractional precision before final descaling. - -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_DSP_YUV_H_ -#define WEBP_DSP_YUV_H_ - -#include "./dsp.h" -#include "../dec/decode_vp8.h" - -#if defined(WEBP_EXPERIMENTAL_FEATURES) -// Do NOT activate this feature for real compression. This is only experimental! -// This flag is for comparison purpose against JPEG's "YUVj" natural colorspace. -// This colorspace is close to Rec.601's Y'CbCr model with the notable -// difference of allowing larger range for luma/chroma. -// See http://en.wikipedia.org/wiki/YCbCr#JPEG_conversion paragraph, and its -// difference with http://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion -// #define USE_YUVj -#endif - -//------------------------------------------------------------------------------ -// YUV -> RGB conversion - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - YUV_FIX = 16, // fixed-point precision for RGB->YUV - YUV_HALF = 1 << (YUV_FIX - 1), - YUV_MASK = (256 << YUV_FIX) - 1, - YUV_RANGE_MIN = -227, // min value of r/g/b output - YUV_RANGE_MAX = 256 + 226, // max value of r/g/b output - - YUV_FIX2 = 6, // fixed-point precision for YUV->RGB - YUV_HALF2 = 1 << YUV_FIX2 >> 1, - YUV_MASK2 = (256 << YUV_FIX2) - 1 -}; - -//------------------------------------------------------------------------------ -// slower on x86 by ~7-8%, but bit-exact with the SSE2/NEON version - -static WEBP_INLINE int MultHi(int v, int coeff) { // _mm_mulhi_epu16 emulation - return (v * coeff) >> 8; -} - -static WEBP_INLINE int VP8Clip8(int v) { - return ((v & ~YUV_MASK2) == 0) ? (v >> YUV_FIX2) : (v < 0) ? 0 : 255; -} - -static WEBP_INLINE int VP8YUVToR(int y, int v) { - return VP8Clip8(MultHi(y, 19077) + MultHi(v, 26149) - 14234); -} - -static WEBP_INLINE int VP8YUVToG(int y, int u, int v) { - return VP8Clip8(MultHi(y, 19077) - MultHi(u, 6419) - MultHi(v, 13320) + 8708); -} - -static WEBP_INLINE int VP8YUVToB(int y, int u) { - return VP8Clip8(MultHi(y, 19077) + MultHi(u, 33050) - 17685); -} - -static WEBP_INLINE void VP8YuvToRgb(int y, int u, int v, - uint8_t* const rgb) { - rgb[0] = VP8YUVToR(y, v); - rgb[1] = VP8YUVToG(y, u, v); - rgb[2] = VP8YUVToB(y, u); -} - -static WEBP_INLINE void VP8YuvToBgr(int y, int u, int v, - uint8_t* const bgr) { - bgr[0] = VP8YUVToB(y, u); - bgr[1] = VP8YUVToG(y, u, v); - bgr[2] = VP8YUVToR(y, v); -} - -static WEBP_INLINE void VP8YuvToRgb565(int y, int u, int v, - uint8_t* const rgb) { - const int r = VP8YUVToR(y, v); // 5 usable bits - const int g = VP8YUVToG(y, u, v); // 6 usable bits - const int b = VP8YUVToB(y, u); // 5 usable bits - const int rg = (r & 0xf8) | (g >> 5); - const int gb = ((g << 3) & 0xe0) | (b >> 3); -#ifdef WEBP_SWAP_16BIT_CSP - rgb[0] = gb; - rgb[1] = rg; -#else - rgb[0] = rg; - rgb[1] = gb; -#endif -} - -static WEBP_INLINE void VP8YuvToRgba4444(int y, int u, int v, - uint8_t* const argb) { - const int r = VP8YUVToR(y, v); // 4 usable bits - const int g = VP8YUVToG(y, u, v); // 4 usable bits - const int b = VP8YUVToB(y, u); // 4 usable bits - const int rg = (r & 0xf0) | (g >> 4); - const int ba = (b & 0xf0) | 0x0f; // overwrite the lower 4 bits -#ifdef WEBP_SWAP_16BIT_CSP - argb[0] = ba; - argb[1] = rg; -#else - argb[0] = rg; - argb[1] = ba; -#endif -} - -//----------------------------------------------------------------------------- -// Alpha handling variants - -static WEBP_INLINE void VP8YuvToArgb(uint8_t y, uint8_t u, uint8_t v, - uint8_t* const argb) { - argb[0] = 0xff; - VP8YuvToRgb(y, u, v, argb + 1); -} - -static WEBP_INLINE void VP8YuvToBgra(uint8_t y, uint8_t u, uint8_t v, - uint8_t* const bgra) { - VP8YuvToBgr(y, u, v, bgra); - bgra[3] = 0xff; -} - -static WEBP_INLINE void VP8YuvToRgba(uint8_t y, uint8_t u, uint8_t v, - uint8_t* const rgba) { - VP8YuvToRgb(y, u, v, rgba); - rgba[3] = 0xff; -} - -// Must be called before everything, to initialize the tables. -void VP8YUVInit(void); - -//----------------------------------------------------------------------------- -// SSE2 extra functions (mostly for upsampling_sse2.c) - -#if defined(WEBP_USE_SSE2) - -// Process 32 pixels and store the result (16b, 24b or 32b per pixel) in *dst. -void VP8YuvToRgba32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst); -void VP8YuvToRgb32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst); -void VP8YuvToBgra32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst); -void VP8YuvToBgr32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst); -void VP8YuvToArgb32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst); -void VP8YuvToRgba444432(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst); -void VP8YuvToRgb56532(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst); - -#endif // WEBP_USE_SSE2 - -//------------------------------------------------------------------------------ -// RGB -> YUV conversion - -// Stub functions that can be called with various rounding values: -static WEBP_INLINE int VP8ClipUV(int uv, int rounding) { - uv = (uv + rounding + (128 << (YUV_FIX + 2))) >> (YUV_FIX + 2); - return ((uv & ~0xff) == 0) ? uv : (uv < 0) ? 0 : 255; -} - -#ifndef USE_YUVj - -static WEBP_INLINE int VP8RGBToY(int r, int g, int b, int rounding) { - const int luma = 16839 * r + 33059 * g + 6420 * b; - return (luma + rounding + (16 << YUV_FIX)) >> YUV_FIX; // no need to clip -} - -static WEBP_INLINE int VP8RGBToU(int r, int g, int b, int rounding) { - const int u = -9719 * r - 19081 * g + 28800 * b; - return VP8ClipUV(u, rounding); -} - -static WEBP_INLINE int VP8RGBToV(int r, int g, int b, int rounding) { - const int v = +28800 * r - 24116 * g - 4684 * b; - return VP8ClipUV(v, rounding); -} - -#else - -// This JPEG-YUV colorspace, only for comparison! -// These are also 16bit precision coefficients from Rec.601, but with full -// [0..255] output range. -static WEBP_INLINE int VP8RGBToY(int r, int g, int b, int rounding) { - const int luma = 19595 * r + 38470 * g + 7471 * b; - return (luma + rounding) >> YUV_FIX; // no need to clip -} - -static WEBP_INLINE int VP8RGBToU(int r, int g, int b, int rounding) { - const int u = -11058 * r - 21710 * g + 32768 * b; - return VP8ClipUV(u, rounding); -} - -static WEBP_INLINE int VP8RGBToV(int r, int g, int b, int rounding) { - const int v = 32768 * r - 27439 * g - 5329 * b; - return VP8ClipUV(v, rounding); -} - -#endif // USE_YUVj - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_DSP_YUV_H_ */ diff --git a/Example/Pods/libwebp/src/dsp/yuv_mips32.c b/Example/Pods/libwebp/src/dsp/yuv_mips32.c deleted file mode 100644 index b8fe512f..00000000 --- a/Example/Pods/libwebp/src/dsp/yuv_mips32.c +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// MIPS version of YUV to RGB upsampling functions. -// -// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) -// Jovan Zelincevic (jovan.zelincevic@imgtec.com) - -#include "./dsp.h" - -// Code is disabled for now, in favor of the plain-C version -#if 0 // defined(WEBP_USE_MIPS32) - -#include "./yuv.h" - -//------------------------------------------------------------------------------ -// simple point-sampling - -#define ROW_FUNC(FUNC_NAME, XSTEP, R, G, B, A) \ -static void FUNC_NAME(const uint8_t* y, \ - const uint8_t* u, const uint8_t* v, \ - uint8_t* dst, int len) { \ - int i, r, g, b; \ - int temp0, temp1, temp2, temp3, temp4; \ - for (i = 0; i < (len >> 1); i++) { \ - temp1 = kVToR * v[0]; \ - temp3 = kVToG * v[0]; \ - temp2 = kUToG * u[0]; \ - temp4 = kUToB * u[0]; \ - temp0 = kYScale * y[0]; \ - temp1 += kRCst; \ - temp3 -= kGCst; \ - temp2 += temp3; \ - temp4 += kBCst; \ - r = VP8Clip8(temp0 + temp1); \ - g = VP8Clip8(temp0 - temp2); \ - b = VP8Clip8(temp0 + temp4); \ - temp0 = kYScale * y[1]; \ - dst[R] = r; \ - dst[G] = g; \ - dst[B] = b; \ - if (A) dst[A] = 0xff; \ - r = VP8Clip8(temp0 + temp1); \ - g = VP8Clip8(temp0 - temp2); \ - b = VP8Clip8(temp0 + temp4); \ - dst[R + XSTEP] = r; \ - dst[G + XSTEP] = g; \ - dst[B + XSTEP] = b; \ - if (A) dst[A + XSTEP] = 0xff; \ - y += 2; \ - ++u; \ - ++v; \ - dst += 2 * XSTEP; \ - } \ - if (len & 1) { \ - temp1 = kVToR * v[0]; \ - temp3 = kVToG * v[0]; \ - temp2 = kUToG * u[0]; \ - temp4 = kUToB * u[0]; \ - temp0 = kYScale * y[0]; \ - temp1 += kRCst; \ - temp3 -= kGCst; \ - temp2 += temp3; \ - temp4 += kBCst; \ - r = VP8Clip8(temp0 + temp1); \ - g = VP8Clip8(temp0 - temp2); \ - b = VP8Clip8(temp0 + temp4); \ - dst[R] = r; \ - dst[G] = g; \ - dst[B] = b; \ - if (A) dst[A] = 0xff; \ - } \ -} - -ROW_FUNC(YuvToRgbRow, 3, 0, 1, 2, 0) -ROW_FUNC(YuvToRgbaRow, 4, 0, 1, 2, 3) -ROW_FUNC(YuvToBgrRow, 3, 2, 1, 0, 0) -ROW_FUNC(YuvToBgraRow, 4, 2, 1, 0, 3) - -#undef ROW_FUNC - -//------------------------------------------------------------------------------ -// Entry point - -extern void WebPInitSamplersMIPS32(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersMIPS32(void) { - WebPSamplers[MODE_RGB] = YuvToRgbRow; - WebPSamplers[MODE_RGBA] = YuvToRgbaRow; - WebPSamplers[MODE_BGR] = YuvToBgrRow; - WebPSamplers[MODE_BGRA] = YuvToBgraRow; -} - -#else // !WEBP_USE_MIPS32 - -WEBP_DSP_INIT_STUB(WebPInitSamplersMIPS32) - -#endif // WEBP_USE_MIPS32 diff --git a/Example/Pods/libwebp/src/dsp/yuv_mips_dsp_r2.c b/Example/Pods/libwebp/src/dsp/yuv_mips_dsp_r2.c deleted file mode 100644 index dea0fdb8..00000000 --- a/Example/Pods/libwebp/src/dsp/yuv_mips_dsp_r2.c +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// MIPS DSPr2 version of YUV to RGB upsampling functions. -// -// Author(s): Branimir Vasic (branimir.vasic@imgtec.com) -// Djordje Pesut (djordje.pesut@imgtec.com) - -#include "./dsp.h" - -// Code is disabled for now, in favor of the plain-C version -#if 0 // defined(WEBP_USE_MIPS_DSP_R2) - -#include "./yuv.h" - -//------------------------------------------------------------------------------ -// simple point-sampling - -#define ROW_FUNC_PART_1() \ - "lbu %[temp3], 0(%[v]) \n\t" \ - "lbu %[temp4], 0(%[u]) \n\t" \ - "lbu %[temp0], 0(%[y]) \n\t" \ - "mul %[temp1], %[t_con_1], %[temp3] \n\t" \ - "mul %[temp3], %[t_con_2], %[temp3] \n\t" \ - "mul %[temp2], %[t_con_3], %[temp4] \n\t" \ - "mul %[temp4], %[t_con_4], %[temp4] \n\t" \ - "mul %[temp0], %[t_con_5], %[temp0] \n\t" \ - "addu %[temp1], %[temp1], %[t_con_6] \n\t" \ - "subu %[temp3], %[temp3], %[t_con_7] \n\t" \ - "addu %[temp2], %[temp2], %[temp3] \n\t" \ - "addu %[temp4], %[temp4], %[t_con_8] \n\t" \ - -#define ROW_FUNC_PART_2(R, G, B, K) \ - "addu %[temp5], %[temp0], %[temp1] \n\t" \ - "subu %[temp6], %[temp0], %[temp2] \n\t" \ - "addu %[temp7], %[temp0], %[temp4] \n\t" \ -".if " #K " \n\t" \ - "lbu %[temp0], 1(%[y]) \n\t" \ -".endif \n\t" \ - "shll_s.w %[temp5], %[temp5], 9 \n\t" \ - "shll_s.w %[temp6], %[temp6], 9 \n\t" \ -".if " #K " \n\t" \ - "mul %[temp0], %[t_con_5], %[temp0] \n\t" \ -".endif \n\t" \ - "shll_s.w %[temp7], %[temp7], 9 \n\t" \ - "precrqu_s.qb.ph %[temp5], %[temp5], $zero \n\t" \ - "precrqu_s.qb.ph %[temp6], %[temp6], $zero \n\t" \ - "precrqu_s.qb.ph %[temp7], %[temp7], $zero \n\t" \ - "srl %[temp5], %[temp5], 24 \n\t" \ - "srl %[temp6], %[temp6], 24 \n\t" \ - "srl %[temp7], %[temp7], 24 \n\t" \ - "sb %[temp5], " #R "(%[dst]) \n\t" \ - "sb %[temp6], " #G "(%[dst]) \n\t" \ - "sb %[temp7], " #B "(%[dst]) \n\t" \ - -#define ASM_CLOBBER_LIST() \ - : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \ - [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \ - [temp6]"=&r"(temp6), [temp7]"=&r"(temp7) \ - : [t_con_1]"r"(t_con_1), [t_con_2]"r"(t_con_2), [t_con_3]"r"(t_con_3), \ - [t_con_4]"r"(t_con_4), [t_con_5]"r"(t_con_5), [t_con_6]"r"(t_con_6), \ - [u]"r"(u), [v]"r"(v), [y]"r"(y), [dst]"r"(dst), \ - [t_con_7]"r"(t_con_7), [t_con_8]"r"(t_con_8) \ - : "memory", "hi", "lo" \ - -#define ROW_FUNC(FUNC_NAME, XSTEP, R, G, B, A) \ -static void FUNC_NAME(const uint8_t* y, \ - const uint8_t* u, const uint8_t* v, \ - uint8_t* dst, int len) { \ - int i; \ - uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; \ - const int t_con_1 = kVToR; \ - const int t_con_2 = kVToG; \ - const int t_con_3 = kUToG; \ - const int t_con_4 = kUToB; \ - const int t_con_5 = kYScale; \ - const int t_con_6 = kRCst; \ - const int t_con_7 = kGCst; \ - const int t_con_8 = kBCst; \ - for (i = 0; i < (len >> 1); i++) { \ - __asm__ volatile ( \ - ROW_FUNC_PART_1() \ - ROW_FUNC_PART_2(R, G, B, 1) \ - ROW_FUNC_PART_2(R + XSTEP, G + XSTEP, B + XSTEP, 0) \ - ASM_CLOBBER_LIST() \ - ); \ - if (A) dst[A] = dst[A + XSTEP] = 0xff; \ - y += 2; \ - ++u; \ - ++v; \ - dst += 2 * XSTEP; \ - } \ - if (len & 1) { \ - __asm__ volatile ( \ - ROW_FUNC_PART_1() \ - ROW_FUNC_PART_2(R, G, B, 0) \ - ASM_CLOBBER_LIST() \ - ); \ - if (A) dst[A] = 0xff; \ - } \ -} - -ROW_FUNC(YuvToRgbRow, 3, 0, 1, 2, 0) -ROW_FUNC(YuvToRgbaRow, 4, 0, 1, 2, 3) -ROW_FUNC(YuvToBgrRow, 3, 2, 1, 0, 0) -ROW_FUNC(YuvToBgraRow, 4, 2, 1, 0, 3) - -#undef ROW_FUNC -#undef ASM_CLOBBER_LIST -#undef ROW_FUNC_PART_2 -#undef ROW_FUNC_PART_1 - -//------------------------------------------------------------------------------ -// Entry point - -extern void WebPInitSamplersMIPSdspR2(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersMIPSdspR2(void) { - WebPSamplers[MODE_RGB] = YuvToRgbRow; - WebPSamplers[MODE_RGBA] = YuvToRgbaRow; - WebPSamplers[MODE_BGR] = YuvToBgrRow; - WebPSamplers[MODE_BGRA] = YuvToBgraRow; -} - -#else // !WEBP_USE_MIPS_DSP_R2 - -WEBP_DSP_INIT_STUB(WebPInitSamplersMIPSdspR2) - -#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/Example/Pods/libwebp/src/dsp/yuv_sse2.c b/Example/Pods/libwebp/src/dsp/yuv_sse2.c deleted file mode 100644 index f72fe324..00000000 --- a/Example/Pods/libwebp/src/dsp/yuv_sse2.c +++ /dev/null @@ -1,774 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// YUV->RGB conversion functions -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./yuv.h" - -#if defined(WEBP_USE_SSE2) - -#include - -//----------------------------------------------------------------------------- -// Convert spans of 32 pixels to various RGB formats for the fancy upsampler. - -// These constants are 14b fixed-point version of ITU-R BT.601 constants. -// R = (19077 * y + 26149 * v - 14234) >> 6 -// G = (19077 * y - 6419 * u - 13320 * v + 8708) >> 6 -// B = (19077 * y + 33050 * u - 17685) >> 6 -static void ConvertYUV444ToRGB(const __m128i* const Y0, - const __m128i* const U0, - const __m128i* const V0, - __m128i* const R, - __m128i* const G, - __m128i* const B) { - const __m128i k19077 = _mm_set1_epi16(19077); - const __m128i k26149 = _mm_set1_epi16(26149); - const __m128i k14234 = _mm_set1_epi16(14234); - const __m128i k33050 = _mm_set1_epi16(33050); - const __m128i k17685 = _mm_set1_epi16(17685); - const __m128i k6419 = _mm_set1_epi16(6419); - const __m128i k13320 = _mm_set1_epi16(13320); - const __m128i k8708 = _mm_set1_epi16(8708); - - const __m128i Y1 = _mm_mulhi_epu16(*Y0, k19077); - - const __m128i R0 = _mm_mulhi_epu16(*V0, k26149); - const __m128i R1 = _mm_sub_epi16(Y1, k14234); - const __m128i R2 = _mm_add_epi16(R1, R0); - - const __m128i G0 = _mm_mulhi_epu16(*U0, k6419); - const __m128i G1 = _mm_mulhi_epu16(*V0, k13320); - const __m128i G2 = _mm_add_epi16(Y1, k8708); - const __m128i G3 = _mm_add_epi16(G0, G1); - const __m128i G4 = _mm_sub_epi16(G2, G3); - - // be careful with the saturated *unsigned* arithmetic here! - const __m128i B0 = _mm_mulhi_epu16(*U0, k33050); - const __m128i B1 = _mm_adds_epu16(B0, Y1); - const __m128i B2 = _mm_subs_epu16(B1, k17685); - - // use logical shift for B2, which can be larger than 32767 - *R = _mm_srai_epi16(R2, 6); // range: [-14234, 30815] - *G = _mm_srai_epi16(G4, 6); // range: [-10953, 27710] - *B = _mm_srli_epi16(B2, 6); // range: [0, 34238] -} - -// Load the bytes into the *upper* part of 16b words. That's "<< 8", basically. -static WEBP_INLINE __m128i Load_HI_16(const uint8_t* src) { - const __m128i zero = _mm_setzero_si128(); - return _mm_unpacklo_epi8(zero, _mm_loadl_epi64((const __m128i*)src)); -} - -// Load and replicate the U/V samples -static WEBP_INLINE __m128i Load_UV_HI_8(const uint8_t* src) { - const __m128i zero = _mm_setzero_si128(); - const __m128i tmp0 = _mm_cvtsi32_si128(*(const uint32_t*)src); - const __m128i tmp1 = _mm_unpacklo_epi8(zero, tmp0); - return _mm_unpacklo_epi16(tmp1, tmp1); // replicate samples -} - -// Convert 32 samples of YUV444 to R/G/B -static void YUV444ToRGB(const uint8_t* const y, - const uint8_t* const u, - const uint8_t* const v, - __m128i* const R, __m128i* const G, __m128i* const B) { - const __m128i Y0 = Load_HI_16(y), U0 = Load_HI_16(u), V0 = Load_HI_16(v); - ConvertYUV444ToRGB(&Y0, &U0, &V0, R, G, B); -} - -// Convert 32 samples of YUV420 to R/G/B -static void YUV420ToRGB(const uint8_t* const y, - const uint8_t* const u, - const uint8_t* const v, - __m128i* const R, __m128i* const G, __m128i* const B) { - const __m128i Y0 = Load_HI_16(y), U0 = Load_UV_HI_8(u), V0 = Load_UV_HI_8(v); - ConvertYUV444ToRGB(&Y0, &U0, &V0, R, G, B); -} - -// Pack R/G/B/A results into 32b output. -static WEBP_INLINE void PackAndStore4(const __m128i* const R, - const __m128i* const G, - const __m128i* const B, - const __m128i* const A, - uint8_t* const dst) { - const __m128i rb = _mm_packus_epi16(*R, *B); - const __m128i ga = _mm_packus_epi16(*G, *A); - const __m128i rg = _mm_unpacklo_epi8(rb, ga); - const __m128i ba = _mm_unpackhi_epi8(rb, ga); - const __m128i RGBA_lo = _mm_unpacklo_epi16(rg, ba); - const __m128i RGBA_hi = _mm_unpackhi_epi16(rg, ba); - _mm_storeu_si128((__m128i*)(dst + 0), RGBA_lo); - _mm_storeu_si128((__m128i*)(dst + 16), RGBA_hi); -} - -// Pack R/G/B/A results into 16b output. -static WEBP_INLINE void PackAndStore4444(const __m128i* const R, - const __m128i* const G, - const __m128i* const B, - const __m128i* const A, - uint8_t* const dst) { -#if !defined(WEBP_SWAP_16BIT_CSP) - const __m128i rg0 = _mm_packus_epi16(*R, *G); - const __m128i ba0 = _mm_packus_epi16(*B, *A); -#else - const __m128i rg0 = _mm_packus_epi16(*B, *A); - const __m128i ba0 = _mm_packus_epi16(*R, *G); -#endif - const __m128i mask_0xf0 = _mm_set1_epi8(0xf0); - const __m128i rb1 = _mm_unpacklo_epi8(rg0, ba0); // rbrbrbrbrb... - const __m128i ga1 = _mm_unpackhi_epi8(rg0, ba0); // gagagagaga... - const __m128i rb2 = _mm_and_si128(rb1, mask_0xf0); - const __m128i ga2 = _mm_srli_epi16(_mm_and_si128(ga1, mask_0xf0), 4); - const __m128i rgba4444 = _mm_or_si128(rb2, ga2); - _mm_storeu_si128((__m128i*)dst, rgba4444); -} - -// Pack R/G/B results into 16b output. -static WEBP_INLINE void PackAndStore565(const __m128i* const R, - const __m128i* const G, - const __m128i* const B, - uint8_t* const dst) { - const __m128i r0 = _mm_packus_epi16(*R, *R); - const __m128i g0 = _mm_packus_epi16(*G, *G); - const __m128i b0 = _mm_packus_epi16(*B, *B); - const __m128i r1 = _mm_and_si128(r0, _mm_set1_epi8(0xf8)); - const __m128i b1 = _mm_and_si128(_mm_srli_epi16(b0, 3), _mm_set1_epi8(0x1f)); - const __m128i g1 = _mm_srli_epi16(_mm_and_si128(g0, _mm_set1_epi8(0xe0)), 5); - const __m128i g2 = _mm_slli_epi16(_mm_and_si128(g0, _mm_set1_epi8(0x1c)), 3); - const __m128i rg = _mm_or_si128(r1, g1); - const __m128i gb = _mm_or_si128(g2, b1); -#if !defined(WEBP_SWAP_16BIT_CSP) - const __m128i rgb565 = _mm_unpacklo_epi8(rg, gb); -#else - const __m128i rgb565 = _mm_unpacklo_epi8(gb, rg); -#endif - _mm_storeu_si128((__m128i*)dst, rgb565); -} - -// Function used several times in PlanarTo24b. -// It samples the in buffer as follows: one every two unsigned char is stored -// at the beginning of the buffer, while the other half is stored at the end. -static WEBP_INLINE void PlanarTo24bHelper(const __m128i* const in /*in[6]*/, - __m128i* const out /*out[6]*/) { - const __m128i v_mask = _mm_set1_epi16(0x00ff); - - // Take one every two upper 8b values. - out[0] = _mm_packus_epi16(_mm_and_si128(in[0], v_mask), - _mm_and_si128(in[1], v_mask)); - out[1] = _mm_packus_epi16(_mm_and_si128(in[2], v_mask), - _mm_and_si128(in[3], v_mask)); - out[2] = _mm_packus_epi16(_mm_and_si128(in[4], v_mask), - _mm_and_si128(in[5], v_mask)); - // Take one every two lower 8b values. - out[3] = _mm_packus_epi16(_mm_srli_epi16(in[0], 8), _mm_srli_epi16(in[1], 8)); - out[4] = _mm_packus_epi16(_mm_srli_epi16(in[2], 8), _mm_srli_epi16(in[3], 8)); - out[5] = _mm_packus_epi16(_mm_srli_epi16(in[4], 8), _mm_srli_epi16(in[5], 8)); -} - -// Pack the planar buffers -// rrrr... rrrr... gggg... gggg... bbbb... bbbb.... -// triplet by triplet in the output buffer rgb as rgbrgbrgbrgb ... -static WEBP_INLINE void PlanarTo24b(__m128i* const in /*in[6]*/, uint8_t* rgb) { - // The input is 6 registers of sixteen 8b but for the sake of explanation, - // let's take 6 registers of four 8b values. - // To pack, we will keep taking one every two 8b integer and move it - // around as follows: - // Input: - // r0r1r2r3 | r4r5r6r7 | g0g1g2g3 | g4g5g6g7 | b0b1b2b3 | b4b5b6b7 - // Split the 6 registers in two sets of 3 registers: the first set as the even - // 8b bytes, the second the odd ones: - // r0r2r4r6 | g0g2g4g6 | b0b2b4b6 | r1r3r5r7 | g1g3g5g7 | b1b3b5b7 - // Repeat the same permutations twice more: - // r0r4g0g4 | b0b4r1r5 | g1g5b1b5 | r2r6g2g6 | b2b6r3r7 | g3g7b3b7 - // r0g0b0r1 | g1b1r2g2 | b2r3g3b3 | r4g4b4r5 | g5b5r6g6 | b6r7g7b7 - __m128i tmp[6]; - PlanarTo24bHelper(in, tmp); - PlanarTo24bHelper(tmp, in); - PlanarTo24bHelper(in, tmp); - // We need to do it two more times than the example as we have sixteen bytes. - PlanarTo24bHelper(tmp, in); - PlanarTo24bHelper(in, tmp); - - _mm_storeu_si128((__m128i*)(rgb + 0), tmp[0]); - _mm_storeu_si128((__m128i*)(rgb + 16), tmp[1]); - _mm_storeu_si128((__m128i*)(rgb + 32), tmp[2]); - _mm_storeu_si128((__m128i*)(rgb + 48), tmp[3]); - _mm_storeu_si128((__m128i*)(rgb + 64), tmp[4]); - _mm_storeu_si128((__m128i*)(rgb + 80), tmp[5]); -} -#undef MK_UINT32 - -void VP8YuvToRgba32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst) { - const __m128i kAlpha = _mm_set1_epi16(255); - int n; - for (n = 0; n < 32; n += 8, dst += 32) { - __m128i R, G, B; - YUV444ToRGB(y + n, u + n, v + n, &R, &G, &B); - PackAndStore4(&R, &G, &B, &kAlpha, dst); - } -} - -void VP8YuvToBgra32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst) { - const __m128i kAlpha = _mm_set1_epi16(255); - int n; - for (n = 0; n < 32; n += 8, dst += 32) { - __m128i R, G, B; - YUV444ToRGB(y + n, u + n, v + n, &R, &G, &B); - PackAndStore4(&B, &G, &R, &kAlpha, dst); - } -} - -void VP8YuvToArgb32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst) { - const __m128i kAlpha = _mm_set1_epi16(255); - int n; - for (n = 0; n < 32; n += 8, dst += 32) { - __m128i R, G, B; - YUV444ToRGB(y + n, u + n, v + n, &R, &G, &B); - PackAndStore4(&kAlpha, &R, &G, &B, dst); - } -} - -void VP8YuvToRgba444432(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst) { - const __m128i kAlpha = _mm_set1_epi16(255); - int n; - for (n = 0; n < 32; n += 8, dst += 16) { - __m128i R, G, B; - YUV444ToRGB(y + n, u + n, v + n, &R, &G, &B); - PackAndStore4444(&R, &G, &B, &kAlpha, dst); - } -} - -void VP8YuvToRgb56532(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst) { - int n; - for (n = 0; n < 32; n += 8, dst += 16) { - __m128i R, G, B; - YUV444ToRGB(y + n, u + n, v + n, &R, &G, &B); - PackAndStore565(&R, &G, &B, dst); - } -} - -void VP8YuvToRgb32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst) { - __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; - __m128i rgb[6]; - - YUV444ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0); - YUV444ToRGB(y + 8, u + 8, v + 8, &R1, &G1, &B1); - YUV444ToRGB(y + 16, u + 16, v + 16, &R2, &G2, &B2); - YUV444ToRGB(y + 24, u + 24, v + 24, &R3, &G3, &B3); - - // Cast to 8b and store as RRRRGGGGBBBB. - rgb[0] = _mm_packus_epi16(R0, R1); - rgb[1] = _mm_packus_epi16(R2, R3); - rgb[2] = _mm_packus_epi16(G0, G1); - rgb[3] = _mm_packus_epi16(G2, G3); - rgb[4] = _mm_packus_epi16(B0, B1); - rgb[5] = _mm_packus_epi16(B2, B3); - - // Pack as RGBRGBRGBRGB. - PlanarTo24b(rgb, dst); -} - -void VP8YuvToBgr32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst) { - __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; - __m128i bgr[6]; - - YUV444ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0); - YUV444ToRGB(y + 8, u + 8, v + 8, &R1, &G1, &B1); - YUV444ToRGB(y + 16, u + 16, v + 16, &R2, &G2, &B2); - YUV444ToRGB(y + 24, u + 24, v + 24, &R3, &G3, &B3); - - // Cast to 8b and store as BBBBGGGGRRRR. - bgr[0] = _mm_packus_epi16(B0, B1); - bgr[1] = _mm_packus_epi16(B2, B3); - bgr[2] = _mm_packus_epi16(G0, G1); - bgr[3] = _mm_packus_epi16(G2, G3); - bgr[4] = _mm_packus_epi16(R0, R1); - bgr[5] = _mm_packus_epi16(R2, R3); - - // Pack as BGRBGRBGRBGR. - PlanarTo24b(bgr, dst); -} - -//----------------------------------------------------------------------------- -// Arbitrary-length row conversion functions - -static void YuvToRgbaRow(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst, int len) { - const __m128i kAlpha = _mm_set1_epi16(255); - int n; - for (n = 0; n + 8 <= len; n += 8, dst += 32) { - __m128i R, G, B; - YUV420ToRGB(y, u, v, &R, &G, &B); - PackAndStore4(&R, &G, &B, &kAlpha, dst); - y += 8; - u += 4; - v += 4; - } - for (; n < len; ++n) { // Finish off - VP8YuvToRgba(y[0], u[0], v[0], dst); - dst += 4; - y += 1; - u += (n & 1); - v += (n & 1); - } -} - -static void YuvToBgraRow(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst, int len) { - const __m128i kAlpha = _mm_set1_epi16(255); - int n; - for (n = 0; n + 8 <= len; n += 8, dst += 32) { - __m128i R, G, B; - YUV420ToRGB(y, u, v, &R, &G, &B); - PackAndStore4(&B, &G, &R, &kAlpha, dst); - y += 8; - u += 4; - v += 4; - } - for (; n < len; ++n) { // Finish off - VP8YuvToBgra(y[0], u[0], v[0], dst); - dst += 4; - y += 1; - u += (n & 1); - v += (n & 1); - } -} - -static void YuvToArgbRow(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst, int len) { - const __m128i kAlpha = _mm_set1_epi16(255); - int n; - for (n = 0; n + 8 <= len; n += 8, dst += 32) { - __m128i R, G, B; - YUV420ToRGB(y, u, v, &R, &G, &B); - PackAndStore4(&kAlpha, &R, &G, &B, dst); - y += 8; - u += 4; - v += 4; - } - for (; n < len; ++n) { // Finish off - VP8YuvToArgb(y[0], u[0], v[0], dst); - dst += 4; - y += 1; - u += (n & 1); - v += (n & 1); - } -} - -static void YuvToRgbRow(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst, int len) { - int n; - for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) { - __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; - __m128i rgb[6]; - - YUV420ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0); - YUV420ToRGB(y + 8, u + 4, v + 4, &R1, &G1, &B1); - YUV420ToRGB(y + 16, u + 8, v + 8, &R2, &G2, &B2); - YUV420ToRGB(y + 24, u + 12, v + 12, &R3, &G3, &B3); - - // Cast to 8b and store as RRRRGGGGBBBB. - rgb[0] = _mm_packus_epi16(R0, R1); - rgb[1] = _mm_packus_epi16(R2, R3); - rgb[2] = _mm_packus_epi16(G0, G1); - rgb[3] = _mm_packus_epi16(G2, G3); - rgb[4] = _mm_packus_epi16(B0, B1); - rgb[5] = _mm_packus_epi16(B2, B3); - - // Pack as RGBRGBRGBRGB. - PlanarTo24b(rgb, dst); - - y += 32; - u += 16; - v += 16; - } - for (; n < len; ++n) { // Finish off - VP8YuvToRgb(y[0], u[0], v[0], dst); - dst += 3; - y += 1; - u += (n & 1); - v += (n & 1); - } -} - -static void YuvToBgrRow(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst, int len) { - int n; - for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) { - __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; - __m128i bgr[6]; - - YUV420ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0); - YUV420ToRGB(y + 8, u + 4, v + 4, &R1, &G1, &B1); - YUV420ToRGB(y + 16, u + 8, v + 8, &R2, &G2, &B2); - YUV420ToRGB(y + 24, u + 12, v + 12, &R3, &G3, &B3); - - // Cast to 8b and store as BBBBGGGGRRRR. - bgr[0] = _mm_packus_epi16(B0, B1); - bgr[1] = _mm_packus_epi16(B2, B3); - bgr[2] = _mm_packus_epi16(G0, G1); - bgr[3] = _mm_packus_epi16(G2, G3); - bgr[4] = _mm_packus_epi16(R0, R1); - bgr[5] = _mm_packus_epi16(R2, R3); - - // Pack as BGRBGRBGRBGR. - PlanarTo24b(bgr, dst); - - y += 32; - u += 16; - v += 16; - } - for (; n < len; ++n) { // Finish off - VP8YuvToBgr(y[0], u[0], v[0], dst); - dst += 3; - y += 1; - u += (n & 1); - v += (n & 1); - } -} - -//------------------------------------------------------------------------------ -// Entry point - -extern void WebPInitSamplersSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersSSE2(void) { - WebPSamplers[MODE_RGB] = YuvToRgbRow; - WebPSamplers[MODE_RGBA] = YuvToRgbaRow; - WebPSamplers[MODE_BGR] = YuvToBgrRow; - WebPSamplers[MODE_BGRA] = YuvToBgraRow; - WebPSamplers[MODE_ARGB] = YuvToArgbRow; -} - -//------------------------------------------------------------------------------ -// RGB24/32 -> YUV converters - -// Load eight 16b-words from *src. -#define LOAD_16(src) _mm_loadu_si128((const __m128i*)(src)) -// Store either 16b-words into *dst -#define STORE_16(V, dst) _mm_storeu_si128((__m128i*)(dst), (V)) - -// Function that inserts a value of the second half of the in buffer in between -// every two char of the first half. -static WEBP_INLINE void RGB24PackedToPlanarHelper( - const __m128i* const in /*in[6]*/, __m128i* const out /*out[6]*/) { - out[0] = _mm_unpacklo_epi8(in[0], in[3]); - out[1] = _mm_unpackhi_epi8(in[0], in[3]); - out[2] = _mm_unpacklo_epi8(in[1], in[4]); - out[3] = _mm_unpackhi_epi8(in[1], in[4]); - out[4] = _mm_unpacklo_epi8(in[2], in[5]); - out[5] = _mm_unpackhi_epi8(in[2], in[5]); -} - -// Unpack the 8b input rgbrgbrgbrgb ... as contiguous registers: -// rrrr... rrrr... gggg... gggg... bbbb... bbbb.... -// Similar to PlanarTo24bHelper(), but in reverse order. -static WEBP_INLINE void RGB24PackedToPlanar(const uint8_t* const rgb, - __m128i* const out /*out[6]*/) { - __m128i tmp[6]; - tmp[0] = _mm_loadu_si128((const __m128i*)(rgb + 0)); - tmp[1] = _mm_loadu_si128((const __m128i*)(rgb + 16)); - tmp[2] = _mm_loadu_si128((const __m128i*)(rgb + 32)); - tmp[3] = _mm_loadu_si128((const __m128i*)(rgb + 48)); - tmp[4] = _mm_loadu_si128((const __m128i*)(rgb + 64)); - tmp[5] = _mm_loadu_si128((const __m128i*)(rgb + 80)); - - RGB24PackedToPlanarHelper(tmp, out); - RGB24PackedToPlanarHelper(out, tmp); - RGB24PackedToPlanarHelper(tmp, out); - RGB24PackedToPlanarHelper(out, tmp); - RGB24PackedToPlanarHelper(tmp, out); -} - -// Convert 8 packed ARGB to r[], g[], b[] -static WEBP_INLINE void RGB32PackedToPlanar(const uint32_t* const argb, - __m128i* const r, - __m128i* const g, - __m128i* const b) { - const __m128i zero = _mm_setzero_si128(); - const __m128i in0 = LOAD_16(argb + 0); // argb3 | argb2 | argb1 | argb0 - const __m128i in1 = LOAD_16(argb + 4); // argb7 | argb6 | argb5 | argb4 - // column-wise transpose - const __m128i A0 = _mm_unpacklo_epi8(in0, in1); - const __m128i A1 = _mm_unpackhi_epi8(in0, in1); - const __m128i B0 = _mm_unpacklo_epi8(A0, A1); - const __m128i B1 = _mm_unpackhi_epi8(A0, A1); - // C0 = g7 g6 ... g1 g0 | b7 b6 ... b1 b0 - // C1 = a7 a6 ... a1 a0 | r7 r6 ... r1 r0 - const __m128i C0 = _mm_unpacklo_epi8(B0, B1); - const __m128i C1 = _mm_unpackhi_epi8(B0, B1); - // store 16b - *r = _mm_unpacklo_epi8(C1, zero); - *g = _mm_unpackhi_epi8(C0, zero); - *b = _mm_unpacklo_epi8(C0, zero); -} - -// This macro computes (RG * MULT_RG + GB * MULT_GB + ROUNDER) >> DESCALE_FIX -// It's a macro and not a function because we need to use immediate values with -// srai_epi32, e.g. -#define TRANSFORM(RG_LO, RG_HI, GB_LO, GB_HI, MULT_RG, MULT_GB, \ - ROUNDER, DESCALE_FIX, OUT) do { \ - const __m128i V0_lo = _mm_madd_epi16(RG_LO, MULT_RG); \ - const __m128i V0_hi = _mm_madd_epi16(RG_HI, MULT_RG); \ - const __m128i V1_lo = _mm_madd_epi16(GB_LO, MULT_GB); \ - const __m128i V1_hi = _mm_madd_epi16(GB_HI, MULT_GB); \ - const __m128i V2_lo = _mm_add_epi32(V0_lo, V1_lo); \ - const __m128i V2_hi = _mm_add_epi32(V0_hi, V1_hi); \ - const __m128i V3_lo = _mm_add_epi32(V2_lo, ROUNDER); \ - const __m128i V3_hi = _mm_add_epi32(V2_hi, ROUNDER); \ - const __m128i V5_lo = _mm_srai_epi32(V3_lo, DESCALE_FIX); \ - const __m128i V5_hi = _mm_srai_epi32(V3_hi, DESCALE_FIX); \ - (OUT) = _mm_packs_epi32(V5_lo, V5_hi); \ -} while (0) - -#define MK_CST_16(A, B) _mm_set_epi16((B), (A), (B), (A), (B), (A), (B), (A)) -static WEBP_INLINE void ConvertRGBToY(const __m128i* const R, - const __m128i* const G, - const __m128i* const B, - __m128i* const Y) { - const __m128i kRG_y = MK_CST_16(16839, 33059 - 16384); - const __m128i kGB_y = MK_CST_16(16384, 6420); - const __m128i kHALF_Y = _mm_set1_epi32((16 << YUV_FIX) + YUV_HALF); - - const __m128i RG_lo = _mm_unpacklo_epi16(*R, *G); - const __m128i RG_hi = _mm_unpackhi_epi16(*R, *G); - const __m128i GB_lo = _mm_unpacklo_epi16(*G, *B); - const __m128i GB_hi = _mm_unpackhi_epi16(*G, *B); - TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_y, kGB_y, kHALF_Y, YUV_FIX, *Y); -} - -static WEBP_INLINE void ConvertRGBToUV(const __m128i* const R, - const __m128i* const G, - const __m128i* const B, - __m128i* const U, __m128i* const V) { - const __m128i kRG_u = MK_CST_16(-9719, -19081); - const __m128i kGB_u = MK_CST_16(0, 28800); - const __m128i kRG_v = MK_CST_16(28800, 0); - const __m128i kGB_v = MK_CST_16(-24116, -4684); - const __m128i kHALF_UV = _mm_set1_epi32(((128 << YUV_FIX) + YUV_HALF) << 2); - - const __m128i RG_lo = _mm_unpacklo_epi16(*R, *G); - const __m128i RG_hi = _mm_unpackhi_epi16(*R, *G); - const __m128i GB_lo = _mm_unpacklo_epi16(*G, *B); - const __m128i GB_hi = _mm_unpackhi_epi16(*G, *B); - TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_u, kGB_u, - kHALF_UV, YUV_FIX + 2, *U); - TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_v, kGB_v, - kHALF_UV, YUV_FIX + 2, *V); -} - -#undef MK_CST_16 -#undef TRANSFORM - -static void ConvertRGB24ToY(const uint8_t* rgb, uint8_t* y, int width) { - const int max_width = width & ~31; - int i; - for (i = 0; i < max_width; rgb += 3 * 16 * 2) { - __m128i rgb_plane[6]; - int j; - - RGB24PackedToPlanar(rgb, rgb_plane); - - for (j = 0; j < 2; ++j, i += 16) { - const __m128i zero = _mm_setzero_si128(); - __m128i r, g, b, Y0, Y1; - - // Convert to 16-bit Y. - r = _mm_unpacklo_epi8(rgb_plane[0 + j], zero); - g = _mm_unpacklo_epi8(rgb_plane[2 + j], zero); - b = _mm_unpacklo_epi8(rgb_plane[4 + j], zero); - ConvertRGBToY(&r, &g, &b, &Y0); - - // Convert to 16-bit Y. - r = _mm_unpackhi_epi8(rgb_plane[0 + j], zero); - g = _mm_unpackhi_epi8(rgb_plane[2 + j], zero); - b = _mm_unpackhi_epi8(rgb_plane[4 + j], zero); - ConvertRGBToY(&r, &g, &b, &Y1); - - // Cast to 8-bit and store. - STORE_16(_mm_packus_epi16(Y0, Y1), y + i); - } - } - for (; i < width; ++i, rgb += 3) { // left-over - y[i] = VP8RGBToY(rgb[0], rgb[1], rgb[2], YUV_HALF); - } -} - -static void ConvertBGR24ToY(const uint8_t* bgr, uint8_t* y, int width) { - const int max_width = width & ~31; - int i; - for (i = 0; i < max_width; bgr += 3 * 16 * 2) { - __m128i bgr_plane[6]; - int j; - - RGB24PackedToPlanar(bgr, bgr_plane); - - for (j = 0; j < 2; ++j, i += 16) { - const __m128i zero = _mm_setzero_si128(); - __m128i r, g, b, Y0, Y1; - - // Convert to 16-bit Y. - b = _mm_unpacklo_epi8(bgr_plane[0 + j], zero); - g = _mm_unpacklo_epi8(bgr_plane[2 + j], zero); - r = _mm_unpacklo_epi8(bgr_plane[4 + j], zero); - ConvertRGBToY(&r, &g, &b, &Y0); - - // Convert to 16-bit Y. - b = _mm_unpackhi_epi8(bgr_plane[0 + j], zero); - g = _mm_unpackhi_epi8(bgr_plane[2 + j], zero); - r = _mm_unpackhi_epi8(bgr_plane[4 + j], zero); - ConvertRGBToY(&r, &g, &b, &Y1); - - // Cast to 8-bit and store. - STORE_16(_mm_packus_epi16(Y0, Y1), y + i); - } - } - for (; i < width; ++i, bgr += 3) { // left-over - y[i] = VP8RGBToY(bgr[2], bgr[1], bgr[0], YUV_HALF); - } -} - -static void ConvertARGBToY(const uint32_t* argb, uint8_t* y, int width) { - const int max_width = width & ~15; - int i; - for (i = 0; i < max_width; i += 16) { - __m128i r, g, b, Y0, Y1; - RGB32PackedToPlanar(&argb[i + 0], &r, &g, &b); - ConvertRGBToY(&r, &g, &b, &Y0); - RGB32PackedToPlanar(&argb[i + 8], &r, &g, &b); - ConvertRGBToY(&r, &g, &b, &Y1); - STORE_16(_mm_packus_epi16(Y0, Y1), y + i); - } - for (; i < width; ++i) { // left-over - const uint32_t p = argb[i]; - y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff, - YUV_HALF); - } -} - -// Horizontal add (doubled) of two 16b values, result is 16b. -// in: A | B | C | D | ... -> out: 2*(A+B) | 2*(C+D) | ... -static void HorizontalAddPack(const __m128i* const A, const __m128i* const B, - __m128i* const out) { - const __m128i k2 = _mm_set1_epi16(2); - const __m128i C = _mm_madd_epi16(*A, k2); - const __m128i D = _mm_madd_epi16(*B, k2); - *out = _mm_packs_epi32(C, D); -} - -static void ConvertARGBToUV(const uint32_t* argb, uint8_t* u, uint8_t* v, - int src_width, int do_store) { - const int max_width = src_width & ~31; - int i; - for (i = 0; i < max_width; i += 32, u += 16, v += 16) { - __m128i r0, g0, b0, r1, g1, b1, U0, V0, U1, V1; - RGB32PackedToPlanar(&argb[i + 0], &r0, &g0, &b0); - RGB32PackedToPlanar(&argb[i + 8], &r1, &g1, &b1); - HorizontalAddPack(&r0, &r1, &r0); - HorizontalAddPack(&g0, &g1, &g0); - HorizontalAddPack(&b0, &b1, &b0); - ConvertRGBToUV(&r0, &g0, &b0, &U0, &V0); - - RGB32PackedToPlanar(&argb[i + 16], &r0, &g0, &b0); - RGB32PackedToPlanar(&argb[i + 24], &r1, &g1, &b1); - HorizontalAddPack(&r0, &r1, &r0); - HorizontalAddPack(&g0, &g1, &g0); - HorizontalAddPack(&b0, &b1, &b0); - ConvertRGBToUV(&r0, &g0, &b0, &U1, &V1); - - U0 = _mm_packus_epi16(U0, U1); - V0 = _mm_packus_epi16(V0, V1); - if (!do_store) { - const __m128i prev_u = LOAD_16(u); - const __m128i prev_v = LOAD_16(v); - U0 = _mm_avg_epu8(U0, prev_u); - V0 = _mm_avg_epu8(V0, prev_v); - } - STORE_16(U0, u); - STORE_16(V0, v); - } - if (i < src_width) { // left-over - WebPConvertARGBToUV_C(argb + i, u, v, src_width - i, do_store); - } -} - -// Convert 16 packed ARGB 16b-values to r[], g[], b[] -static WEBP_INLINE void RGBA32PackedToPlanar_16b(const uint16_t* const rgbx, - __m128i* const r, - __m128i* const g, - __m128i* const b) { - const __m128i in0 = LOAD_16(rgbx + 0); // r0 | g0 | b0 |x| r1 | g1 | b1 |x - const __m128i in1 = LOAD_16(rgbx + 8); // r2 | g2 | b2 |x| r3 | g3 | b3 |x - const __m128i in2 = LOAD_16(rgbx + 16); // r4 | ... - const __m128i in3 = LOAD_16(rgbx + 24); // r6 | ... - // column-wise transpose - const __m128i A0 = _mm_unpacklo_epi16(in0, in1); - const __m128i A1 = _mm_unpackhi_epi16(in0, in1); - const __m128i A2 = _mm_unpacklo_epi16(in2, in3); - const __m128i A3 = _mm_unpackhi_epi16(in2, in3); - const __m128i B0 = _mm_unpacklo_epi16(A0, A1); // r0 r1 r2 r3 | g0 g1 .. - const __m128i B1 = _mm_unpackhi_epi16(A0, A1); // b0 b1 b2 b3 | x x x x - const __m128i B2 = _mm_unpacklo_epi16(A2, A3); // r4 r5 r6 r7 | g4 g5 .. - const __m128i B3 = _mm_unpackhi_epi16(A2, A3); // b4 b5 b6 b7 | x x x x - *r = _mm_unpacklo_epi64(B0, B2); - *g = _mm_unpackhi_epi64(B0, B2); - *b = _mm_unpacklo_epi64(B1, B3); -} - -static void ConvertRGBA32ToUV(const uint16_t* rgb, - uint8_t* u, uint8_t* v, int width) { - const int max_width = width & ~15; - const uint16_t* const last_rgb = rgb + 4 * max_width; - while (rgb < last_rgb) { - __m128i r, g, b, U0, V0, U1, V1; - RGBA32PackedToPlanar_16b(rgb + 0, &r, &g, &b); - ConvertRGBToUV(&r, &g, &b, &U0, &V0); - RGBA32PackedToPlanar_16b(rgb + 32, &r, &g, &b); - ConvertRGBToUV(&r, &g, &b, &U1, &V1); - STORE_16(_mm_packus_epi16(U0, U1), u); - STORE_16(_mm_packus_epi16(V0, V1), v); - u += 16; - v += 16; - rgb += 2 * 32; - } - if (max_width < width) { // left-over - WebPConvertRGBA32ToUV_C(rgb, u, v, width - max_width); - } -} - -//------------------------------------------------------------------------------ - -extern void WebPInitConvertARGBToYUVSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUVSSE2(void) { - WebPConvertARGBToY = ConvertARGBToY; - WebPConvertARGBToUV = ConvertARGBToUV; - - WebPConvertRGB24ToY = ConvertRGB24ToY; - WebPConvertBGR24ToY = ConvertBGR24ToY; - - WebPConvertRGBA32ToUV = ConvertRGBA32ToUV; -} - -#else // !WEBP_USE_SSE2 - -WEBP_DSP_INIT_STUB(WebPInitSamplersSSE2) -WEBP_DSP_INIT_STUB(WebPInitConvertARGBToYUVSSE2) - -#endif // WEBP_USE_SSE2 diff --git a/Example/Pods/libwebp/src/enc/alpha.c b/Example/Pods/libwebp/src/enc/alpha.c deleted file mode 100644 index 3c970b00..00000000 --- a/Example/Pods/libwebp/src/enc/alpha.c +++ /dev/null @@ -1,430 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Alpha-plane compression. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include - -#include "./vp8enci.h" -#include "../dsp/dsp.h" -#include "../utils/filters.h" -#include "../utils/quant_levels.h" -#include "../utils/utils.h" -#include "../webp/format_constants.h" - -// ----------------------------------------------------------------------------- -// Encodes the given alpha data via specified compression method 'method'. -// The pre-processing (quantization) is performed if 'quality' is less than 100. -// For such cases, the encoding is lossy. The valid range is [0, 100] for -// 'quality' and [0, 1] for 'method': -// 'method = 0' - No compression; -// 'method = 1' - Use lossless coder on the alpha plane only -// 'filter' values [0, 4] correspond to prediction modes none, horizontal, -// vertical & gradient filters. The prediction mode 4 will try all the -// prediction modes 0 to 3 and pick the best one. -// 'effort_level': specifies how much effort must be spent to try and reduce -// the compressed output size. In range 0 (quick) to 6 (slow). -// -// 'output' corresponds to the buffer containing compressed alpha data. -// This buffer is allocated by this method and caller should call -// WebPSafeFree(*output) when done. -// 'output_size' corresponds to size of this compressed alpha buffer. -// -// Returns 1 on successfully encoding the alpha and -// 0 if either: -// invalid quality or method, or -// memory allocation for the compressed data fails. - -#include "../enc/vp8li.h" - -static int EncodeLossless(const uint8_t* const data, int width, int height, - int effort_level, // in [0..6] range - VP8LBitWriter* const bw, - WebPAuxStats* const stats) { - int ok = 0; - WebPConfig config; - WebPPicture picture; - - WebPPictureInit(&picture); - picture.width = width; - picture.height = height; - picture.use_argb = 1; - picture.stats = stats; - if (!WebPPictureAlloc(&picture)) return 0; - - // Transfer the alpha values to the green channel. - WebPDispatchAlphaToGreen(data, width, picture.width, picture.height, - picture.argb, picture.argb_stride); - - WebPConfigInit(&config); - config.lossless = 1; - // Enable exact, or it would alter RGB values of transparent alpha, which is - // normally OK but not here since we are not encoding the input image but an - // internal encoding-related image containing necessary exact information in - // RGB channels. - config.exact = 1; - config.method = effort_level; // impact is very small - // Set a low default quality for encoding alpha. Ensure that Alpha quality at - // lower methods (3 and below) is less than the threshold for triggering - // costly 'BackwardReferencesTraceBackwards'. - config.quality = 8.f * effort_level; - assert(config.quality >= 0 && config.quality <= 100.f); - - ok = (VP8LEncodeStream(&config, &picture, bw) == VP8_ENC_OK); - WebPPictureFree(&picture); - ok = ok && !bw->error_; - if (!ok) { - VP8LBitWriterWipeOut(bw); - return 0; - } - return 1; -} - -// ----------------------------------------------------------------------------- - -// Small struct to hold the result of a filter mode compression attempt. -typedef struct { - size_t score; - VP8BitWriter bw; - WebPAuxStats stats; -} FilterTrial; - -// This function always returns an initialized 'bw' object, even upon error. -static int EncodeAlphaInternal(const uint8_t* const data, int width, int height, - int method, int filter, int reduce_levels, - int effort_level, // in [0..6] range - uint8_t* const tmp_alpha, - FilterTrial* result) { - int ok = 0; - const uint8_t* alpha_src; - WebPFilterFunc filter_func; - uint8_t header; - const size_t data_size = width * height; - const uint8_t* output = NULL; - size_t output_size = 0; - VP8LBitWriter tmp_bw; - - assert((uint64_t)data_size == (uint64_t)width * height); // as per spec - assert(filter >= 0 && filter < WEBP_FILTER_LAST); - assert(method >= ALPHA_NO_COMPRESSION); - assert(method <= ALPHA_LOSSLESS_COMPRESSION); - assert(sizeof(header) == ALPHA_HEADER_LEN); - // TODO(skal): have a common function and #define's to validate alpha params. - - filter_func = WebPFilters[filter]; - if (filter_func != NULL) { - filter_func(data, width, height, width, tmp_alpha); - alpha_src = tmp_alpha; - } else { - alpha_src = data; - } - - if (method != ALPHA_NO_COMPRESSION) { - ok = VP8LBitWriterInit(&tmp_bw, data_size >> 3); - ok = ok && EncodeLossless(alpha_src, width, height, effort_level, - &tmp_bw, &result->stats); - if (ok) { - output = VP8LBitWriterFinish(&tmp_bw); - output_size = VP8LBitWriterNumBytes(&tmp_bw); - if (output_size > data_size) { - // compressed size is larger than source! Revert to uncompressed mode. - method = ALPHA_NO_COMPRESSION; - VP8LBitWriterWipeOut(&tmp_bw); - } - } else { - VP8LBitWriterWipeOut(&tmp_bw); - return 0; - } - } - - if (method == ALPHA_NO_COMPRESSION) { - output = alpha_src; - output_size = data_size; - ok = 1; - } - - // Emit final result. - header = method | (filter << 2); - if (reduce_levels) header |= ALPHA_PREPROCESSED_LEVELS << 4; - - VP8BitWriterInit(&result->bw, ALPHA_HEADER_LEN + output_size); - ok = ok && VP8BitWriterAppend(&result->bw, &header, ALPHA_HEADER_LEN); - ok = ok && VP8BitWriterAppend(&result->bw, output, output_size); - - if (method != ALPHA_NO_COMPRESSION) { - VP8LBitWriterWipeOut(&tmp_bw); - } - ok = ok && !result->bw.error_; - result->score = VP8BitWriterSize(&result->bw); - return ok; -} - -// ----------------------------------------------------------------------------- - -static int GetNumColors(const uint8_t* data, int width, int height, - int stride) { - int j; - int colors = 0; - uint8_t color[256] = { 0 }; - - for (j = 0; j < height; ++j) { - int i; - const uint8_t* const p = data + j * stride; - for (i = 0; i < width; ++i) { - color[p[i]] = 1; - } - } - for (j = 0; j < 256; ++j) { - if (color[j] > 0) ++colors; - } - return colors; -} - -#define FILTER_TRY_NONE (1 << WEBP_FILTER_NONE) -#define FILTER_TRY_ALL ((1 << WEBP_FILTER_LAST) - 1) - -// Given the input 'filter' option, return an OR'd bit-set of filters to try. -static uint32_t GetFilterMap(const uint8_t* alpha, int width, int height, - int filter, int effort_level) { - uint32_t bit_map = 0U; - if (filter == WEBP_FILTER_FAST) { - // Quick estimate of the best candidate. - int try_filter_none = (effort_level > 3); - const int kMinColorsForFilterNone = 16; - const int kMaxColorsForFilterNone = 192; - const int num_colors = GetNumColors(alpha, width, height, width); - // For low number of colors, NONE yields better compression. - filter = (num_colors <= kMinColorsForFilterNone) - ? WEBP_FILTER_NONE - : WebPEstimateBestFilter(alpha, width, height, width); - bit_map |= 1 << filter; - // For large number of colors, try FILTER_NONE in addition to the best - // filter as well. - if (try_filter_none || num_colors > kMaxColorsForFilterNone) { - bit_map |= FILTER_TRY_NONE; - } - } else if (filter == WEBP_FILTER_NONE) { - bit_map = FILTER_TRY_NONE; - } else { // WEBP_FILTER_BEST -> try all - bit_map = FILTER_TRY_ALL; - } - return bit_map; -} - -static void InitFilterTrial(FilterTrial* const score) { - score->score = (size_t)~0U; - VP8BitWriterInit(&score->bw, 0); -} - -static int ApplyFiltersAndEncode(const uint8_t* alpha, int width, int height, - size_t data_size, int method, int filter, - int reduce_levels, int effort_level, - uint8_t** const output, - size_t* const output_size, - WebPAuxStats* const stats) { - int ok = 1; - FilterTrial best; - uint32_t try_map = - GetFilterMap(alpha, width, height, filter, effort_level); - InitFilterTrial(&best); - - if (try_map != FILTER_TRY_NONE) { - uint8_t* filtered_alpha = (uint8_t*)WebPSafeMalloc(1ULL, data_size); - if (filtered_alpha == NULL) return 0; - - for (filter = WEBP_FILTER_NONE; ok && try_map; ++filter, try_map >>= 1) { - if (try_map & 1) { - FilterTrial trial; - ok = EncodeAlphaInternal(alpha, width, height, method, filter, - reduce_levels, effort_level, filtered_alpha, - &trial); - if (ok && trial.score < best.score) { - VP8BitWriterWipeOut(&best.bw); - best = trial; - } else { - VP8BitWriterWipeOut(&trial.bw); - } - } - } - WebPSafeFree(filtered_alpha); - } else { - ok = EncodeAlphaInternal(alpha, width, height, method, WEBP_FILTER_NONE, - reduce_levels, effort_level, NULL, &best); - } - if (ok) { - if (stats != NULL) { - stats->lossless_features = best.stats.lossless_features; - stats->histogram_bits = best.stats.histogram_bits; - stats->transform_bits = best.stats.transform_bits; - stats->cache_bits = best.stats.cache_bits; - stats->palette_size = best.stats.palette_size; - stats->lossless_size = best.stats.lossless_size; - stats->lossless_hdr_size = best.stats.lossless_hdr_size; - stats->lossless_data_size = best.stats.lossless_data_size; - } - *output_size = VP8BitWriterSize(&best.bw); - *output = VP8BitWriterBuf(&best.bw); - } else { - VP8BitWriterWipeOut(&best.bw); - } - return ok; -} - -static int EncodeAlpha(VP8Encoder* const enc, - int quality, int method, int filter, - int effort_level, - uint8_t** const output, size_t* const output_size) { - const WebPPicture* const pic = enc->pic_; - const int width = pic->width; - const int height = pic->height; - - uint8_t* quant_alpha = NULL; - const size_t data_size = width * height; - uint64_t sse = 0; - int ok = 1; - const int reduce_levels = (quality < 100); - - // quick sanity checks - assert((uint64_t)data_size == (uint64_t)width * height); // as per spec - assert(enc != NULL && pic != NULL && pic->a != NULL); - assert(output != NULL && output_size != NULL); - assert(width > 0 && height > 0); - assert(pic->a_stride >= width); - assert(filter >= WEBP_FILTER_NONE && filter <= WEBP_FILTER_FAST); - - if (quality < 0 || quality > 100) { - return 0; - } - - if (method < ALPHA_NO_COMPRESSION || method > ALPHA_LOSSLESS_COMPRESSION) { - return 0; - } - - if (method == ALPHA_NO_COMPRESSION) { - // Don't filter, as filtering will make no impact on compressed size. - filter = WEBP_FILTER_NONE; - } - - quant_alpha = (uint8_t*)WebPSafeMalloc(1ULL, data_size); - if (quant_alpha == NULL) { - return 0; - } - - // Extract alpha data (width x height) from raw_data (stride x height). - WebPCopyPlane(pic->a, pic->a_stride, quant_alpha, width, width, height); - - if (reduce_levels) { // No Quantization required for 'quality = 100'. - // 16 alpha levels gives quite a low MSE w.r.t original alpha plane hence - // mapped to moderate quality 70. Hence Quality:[0, 70] -> Levels:[2, 16] - // and Quality:]70, 100] -> Levels:]16, 256]. - const int alpha_levels = (quality <= 70) ? (2 + quality / 5) - : (16 + (quality - 70) * 8); - ok = QuantizeLevels(quant_alpha, width, height, alpha_levels, &sse); - } - - if (ok) { - VP8FiltersInit(); - ok = ApplyFiltersAndEncode(quant_alpha, width, height, data_size, method, - filter, reduce_levels, effort_level, output, - output_size, pic->stats); - if (pic->stats != NULL) { // need stats? - pic->stats->coded_size += (int)(*output_size); - enc->sse_[3] = sse; - } - } - - WebPSafeFree(quant_alpha); - return ok; -} - -//------------------------------------------------------------------------------ -// Main calls - -static int CompressAlphaJob(VP8Encoder* const enc, void* dummy) { - const WebPConfig* config = enc->config_; - uint8_t* alpha_data = NULL; - size_t alpha_size = 0; - const int effort_level = config->method; // maps to [0..6] - const WEBP_FILTER_TYPE filter = - (config->alpha_filtering == 0) ? WEBP_FILTER_NONE : - (config->alpha_filtering == 1) ? WEBP_FILTER_FAST : - WEBP_FILTER_BEST; - if (!EncodeAlpha(enc, config->alpha_quality, config->alpha_compression, - filter, effort_level, &alpha_data, &alpha_size)) { - return 0; - } - if (alpha_size != (uint32_t)alpha_size) { // Sanity check. - WebPSafeFree(alpha_data); - return 0; - } - enc->alpha_data_size_ = (uint32_t)alpha_size; - enc->alpha_data_ = alpha_data; - (void)dummy; - return 1; -} - -void VP8EncInitAlpha(VP8Encoder* const enc) { - WebPInitAlphaProcessing(); - enc->has_alpha_ = WebPPictureHasTransparency(enc->pic_); - enc->alpha_data_ = NULL; - enc->alpha_data_size_ = 0; - if (enc->thread_level_ > 0) { - WebPWorker* const worker = &enc->alpha_worker_; - WebPGetWorkerInterface()->Init(worker); - worker->data1 = enc; - worker->data2 = NULL; - worker->hook = (WebPWorkerHook)CompressAlphaJob; - } -} - -int VP8EncStartAlpha(VP8Encoder* const enc) { - if (enc->has_alpha_) { - if (enc->thread_level_ > 0) { - WebPWorker* const worker = &enc->alpha_worker_; - // Makes sure worker is good to go. - if (!WebPGetWorkerInterface()->Reset(worker)) { - return 0; - } - WebPGetWorkerInterface()->Launch(worker); - return 1; - } else { - return CompressAlphaJob(enc, NULL); // just do the job right away - } - } - return 1; -} - -int VP8EncFinishAlpha(VP8Encoder* const enc) { - if (enc->has_alpha_) { - if (enc->thread_level_ > 0) { - WebPWorker* const worker = &enc->alpha_worker_; - if (!WebPGetWorkerInterface()->Sync(worker)) return 0; // error - } - } - return WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_); -} - -int VP8EncDeleteAlpha(VP8Encoder* const enc) { - int ok = 1; - if (enc->thread_level_ > 0) { - WebPWorker* const worker = &enc->alpha_worker_; - // finish anything left in flight - ok = WebPGetWorkerInterface()->Sync(worker); - // still need to end the worker, even if !ok - WebPGetWorkerInterface()->End(worker); - } - WebPSafeFree(enc->alpha_data_); - enc->alpha_data_ = NULL; - enc->alpha_data_size_ = 0; - enc->has_alpha_ = 0; - return ok; -} diff --git a/Example/Pods/libwebp/src/enc/analysis.c b/Example/Pods/libwebp/src/enc/analysis.c deleted file mode 100644 index b55128fd..00000000 --- a/Example/Pods/libwebp/src/enc/analysis.c +++ /dev/null @@ -1,501 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Macroblock analysis -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include -#include - -#include "./vp8enci.h" -#include "./cost.h" -#include "../utils/utils.h" - -#define MAX_ITERS_K_MEANS 6 - -//------------------------------------------------------------------------------ -// Smooth the segment map by replacing isolated block by the majority of its -// neighbours. - -static void SmoothSegmentMap(VP8Encoder* const enc) { - int n, x, y; - const int w = enc->mb_w_; - const int h = enc->mb_h_; - const int majority_cnt_3_x_3_grid = 5; - uint8_t* const tmp = (uint8_t*)WebPSafeMalloc(w * h, sizeof(*tmp)); - assert((uint64_t)(w * h) == (uint64_t)w * h); // no overflow, as per spec - - if (tmp == NULL) return; - for (y = 1; y < h - 1; ++y) { - for (x = 1; x < w - 1; ++x) { - int cnt[NUM_MB_SEGMENTS] = { 0 }; - const VP8MBInfo* const mb = &enc->mb_info_[x + w * y]; - int majority_seg = mb->segment_; - // Check the 8 neighbouring segment values. - cnt[mb[-w - 1].segment_]++; // top-left - cnt[mb[-w + 0].segment_]++; // top - cnt[mb[-w + 1].segment_]++; // top-right - cnt[mb[ - 1].segment_]++; // left - cnt[mb[ + 1].segment_]++; // right - cnt[mb[ w - 1].segment_]++; // bottom-left - cnt[mb[ w + 0].segment_]++; // bottom - cnt[mb[ w + 1].segment_]++; // bottom-right - for (n = 0; n < NUM_MB_SEGMENTS; ++n) { - if (cnt[n] >= majority_cnt_3_x_3_grid) { - majority_seg = n; - break; - } - } - tmp[x + y * w] = majority_seg; - } - } - for (y = 1; y < h - 1; ++y) { - for (x = 1; x < w - 1; ++x) { - VP8MBInfo* const mb = &enc->mb_info_[x + w * y]; - mb->segment_ = tmp[x + y * w]; - } - } - WebPSafeFree(tmp); -} - -//------------------------------------------------------------------------------ -// set segment susceptibility alpha_ / beta_ - -static WEBP_INLINE int clip(int v, int m, int M) { - return (v < m) ? m : (v > M) ? M : v; -} - -static void SetSegmentAlphas(VP8Encoder* const enc, - const int centers[NUM_MB_SEGMENTS], - int mid) { - const int nb = enc->segment_hdr_.num_segments_; - int min = centers[0], max = centers[0]; - int n; - - if (nb > 1) { - for (n = 0; n < nb; ++n) { - if (min > centers[n]) min = centers[n]; - if (max < centers[n]) max = centers[n]; - } - } - if (max == min) max = min + 1; - assert(mid <= max && mid >= min); - for (n = 0; n < nb; ++n) { - const int alpha = 255 * (centers[n] - mid) / (max - min); - const int beta = 255 * (centers[n] - min) / (max - min); - enc->dqm_[n].alpha_ = clip(alpha, -127, 127); - enc->dqm_[n].beta_ = clip(beta, 0, 255); - } -} - -//------------------------------------------------------------------------------ -// Compute susceptibility based on DCT-coeff histograms: -// the higher, the "easier" the macroblock is to compress. - -#define MAX_ALPHA 255 // 8b of precision for susceptibilities. -#define ALPHA_SCALE (2 * MAX_ALPHA) // scaling factor for alpha. -#define DEFAULT_ALPHA (-1) -#define IS_BETTER_ALPHA(alpha, best_alpha) ((alpha) > (best_alpha)) - -static int FinalAlphaValue(int alpha) { - alpha = MAX_ALPHA - alpha; - return clip(alpha, 0, MAX_ALPHA); -} - -static int GetAlpha(const VP8Histogram* const histo) { - // 'alpha' will later be clipped to [0..MAX_ALPHA] range, clamping outer - // values which happen to be mostly noise. This leaves the maximum precision - // for handling the useful small values which contribute most. - const int max_value = histo->max_value; - const int last_non_zero = histo->last_non_zero; - const int alpha = - (max_value > 1) ? ALPHA_SCALE * last_non_zero / max_value : 0; - return alpha; -} - -static void InitHistogram(VP8Histogram* const histo) { - histo->max_value = 0; - histo->last_non_zero = 1; -} - -static void MergeHistograms(const VP8Histogram* const in, - VP8Histogram* const out) { - if (in->max_value > out->max_value) { - out->max_value = in->max_value; - } - if (in->last_non_zero > out->last_non_zero) { - out->last_non_zero = in->last_non_zero; - } -} - -//------------------------------------------------------------------------------ -// Simplified k-Means, to assign Nb segments based on alpha-histogram - -static void AssignSegments(VP8Encoder* const enc, - const int alphas[MAX_ALPHA + 1]) { - // 'num_segments_' is previously validated and <= NUM_MB_SEGMENTS, but an - // explicit check is needed to avoid spurious warning about 'n + 1' exceeding - // array bounds of 'centers' with some compilers (noticed with gcc-4.9). - const int nb = (enc->segment_hdr_.num_segments_ < NUM_MB_SEGMENTS) ? - enc->segment_hdr_.num_segments_ : NUM_MB_SEGMENTS; - int centers[NUM_MB_SEGMENTS]; - int weighted_average = 0; - int map[MAX_ALPHA + 1]; - int a, n, k; - int min_a = 0, max_a = MAX_ALPHA, range_a; - // 'int' type is ok for histo, and won't overflow - int accum[NUM_MB_SEGMENTS], dist_accum[NUM_MB_SEGMENTS]; - - assert(nb >= 1); - assert(nb <= NUM_MB_SEGMENTS); - - // bracket the input - for (n = 0; n <= MAX_ALPHA && alphas[n] == 0; ++n) {} - min_a = n; - for (n = MAX_ALPHA; n > min_a && alphas[n] == 0; --n) {} - max_a = n; - range_a = max_a - min_a; - - // Spread initial centers evenly - for (k = 0, n = 1; k < nb; ++k, n += 2) { - assert(n < 2 * nb); - centers[k] = min_a + (n * range_a) / (2 * nb); - } - - for (k = 0; k < MAX_ITERS_K_MEANS; ++k) { // few iters are enough - int total_weight; - int displaced; - // Reset stats - for (n = 0; n < nb; ++n) { - accum[n] = 0; - dist_accum[n] = 0; - } - // Assign nearest center for each 'a' - n = 0; // track the nearest center for current 'a' - for (a = min_a; a <= max_a; ++a) { - if (alphas[a]) { - while (n + 1 < nb && abs(a - centers[n + 1]) < abs(a - centers[n])) { - n++; - } - map[a] = n; - // accumulate contribution into best centroid - dist_accum[n] += a * alphas[a]; - accum[n] += alphas[a]; - } - } - // All point are classified. Move the centroids to the - // center of their respective cloud. - displaced = 0; - weighted_average = 0; - total_weight = 0; - for (n = 0; n < nb; ++n) { - if (accum[n]) { - const int new_center = (dist_accum[n] + accum[n] / 2) / accum[n]; - displaced += abs(centers[n] - new_center); - centers[n] = new_center; - weighted_average += new_center * accum[n]; - total_weight += accum[n]; - } - } - weighted_average = (weighted_average + total_weight / 2) / total_weight; - if (displaced < 5) break; // no need to keep on looping... - } - - // Map each original value to the closest centroid - for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { - VP8MBInfo* const mb = &enc->mb_info_[n]; - const int alpha = mb->alpha_; - mb->segment_ = map[alpha]; - mb->alpha_ = centers[map[alpha]]; // for the record. - } - - if (nb > 1) { - const int smooth = (enc->config_->preprocessing & 1); - if (smooth) SmoothSegmentMap(enc); - } - - SetSegmentAlphas(enc, centers, weighted_average); // pick some alphas. -} - -//------------------------------------------------------------------------------ -// Macroblock analysis: collect histogram for each mode, deduce the maximal -// susceptibility and set best modes for this macroblock. -// Segment assignment is done later. - -// Number of modes to inspect for alpha_ evaluation. We don't need to test all -// the possible modes during the analysis phase: we risk falling into a local -// optimum, or be subject to boundary effect -#define MAX_INTRA16_MODE 2 -#define MAX_INTRA4_MODE 2 -#define MAX_UV_MODE 2 - -static int MBAnalyzeBestIntra16Mode(VP8EncIterator* const it) { - const int max_mode = MAX_INTRA16_MODE; - int mode; - int best_alpha = DEFAULT_ALPHA; - int best_mode = 0; - - VP8MakeLuma16Preds(it); - for (mode = 0; mode < max_mode; ++mode) { - VP8Histogram histo; - int alpha; - - InitHistogram(&histo); - VP8CollectHistogram(it->yuv_in_ + Y_OFF_ENC, - it->yuv_p_ + VP8I16ModeOffsets[mode], - 0, 16, &histo); - alpha = GetAlpha(&histo); - if (IS_BETTER_ALPHA(alpha, best_alpha)) { - best_alpha = alpha; - best_mode = mode; - } - } - VP8SetIntra16Mode(it, best_mode); - return best_alpha; -} - -static int MBAnalyzeBestIntra4Mode(VP8EncIterator* const it, - int best_alpha) { - uint8_t modes[16]; - const int max_mode = MAX_INTRA4_MODE; - int i4_alpha; - VP8Histogram total_histo; - int cur_histo = 0; - InitHistogram(&total_histo); - - VP8IteratorStartI4(it); - do { - int mode; - int best_mode_alpha = DEFAULT_ALPHA; - VP8Histogram histos[2]; - const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_]; - - VP8MakeIntra4Preds(it); - for (mode = 0; mode < max_mode; ++mode) { - int alpha; - - InitHistogram(&histos[cur_histo]); - VP8CollectHistogram(src, it->yuv_p_ + VP8I4ModeOffsets[mode], - 0, 1, &histos[cur_histo]); - alpha = GetAlpha(&histos[cur_histo]); - if (IS_BETTER_ALPHA(alpha, best_mode_alpha)) { - best_mode_alpha = alpha; - modes[it->i4_] = mode; - cur_histo ^= 1; // keep track of best histo so far. - } - } - // accumulate best histogram - MergeHistograms(&histos[cur_histo ^ 1], &total_histo); - // Note: we reuse the original samples for predictors - } while (VP8IteratorRotateI4(it, it->yuv_in_ + Y_OFF_ENC)); - - i4_alpha = GetAlpha(&total_histo); - if (IS_BETTER_ALPHA(i4_alpha, best_alpha)) { - VP8SetIntra4Mode(it, modes); - best_alpha = i4_alpha; - } - return best_alpha; -} - -static int MBAnalyzeBestUVMode(VP8EncIterator* const it) { - int best_alpha = DEFAULT_ALPHA; - int best_mode = 0; - const int max_mode = MAX_UV_MODE; - int mode; - - VP8MakeChroma8Preds(it); - for (mode = 0; mode < max_mode; ++mode) { - VP8Histogram histo; - int alpha; - InitHistogram(&histo); - VP8CollectHistogram(it->yuv_in_ + U_OFF_ENC, - it->yuv_p_ + VP8UVModeOffsets[mode], - 16, 16 + 4 + 4, &histo); - alpha = GetAlpha(&histo); - if (IS_BETTER_ALPHA(alpha, best_alpha)) { - best_alpha = alpha; - best_mode = mode; - } - } - VP8SetIntraUVMode(it, best_mode); - return best_alpha; -} - -static void MBAnalyze(VP8EncIterator* const it, - int alphas[MAX_ALPHA + 1], - int* const alpha, int* const uv_alpha) { - const VP8Encoder* const enc = it->enc_; - int best_alpha, best_uv_alpha; - - VP8SetIntra16Mode(it, 0); // default: Intra16, DC_PRED - VP8SetSkip(it, 0); // not skipped - VP8SetSegment(it, 0); // default segment, spec-wise. - - best_alpha = MBAnalyzeBestIntra16Mode(it); - if (enc->method_ >= 5) { - // We go and make a fast decision for intra4/intra16. - // It's usually not a good and definitive pick, but helps seeding the stats - // about level bit-cost. - // TODO(skal): improve criterion. - best_alpha = MBAnalyzeBestIntra4Mode(it, best_alpha); - } - best_uv_alpha = MBAnalyzeBestUVMode(it); - - // Final susceptibility mix - best_alpha = (3 * best_alpha + best_uv_alpha + 2) >> 2; - best_alpha = FinalAlphaValue(best_alpha); - alphas[best_alpha]++; - it->mb_->alpha_ = best_alpha; // for later remapping. - - // Accumulate for later complexity analysis. - *alpha += best_alpha; // mixed susceptibility (not just luma) - *uv_alpha += best_uv_alpha; -} - -static void DefaultMBInfo(VP8MBInfo* const mb) { - mb->type_ = 1; // I16x16 - mb->uv_mode_ = 0; - mb->skip_ = 0; // not skipped - mb->segment_ = 0; // default segment - mb->alpha_ = 0; -} - -//------------------------------------------------------------------------------ -// Main analysis loop: -// Collect all susceptibilities for each macroblock and record their -// distribution in alphas[]. Segments is assigned a-posteriori, based on -// this histogram. -// We also pick an intra16 prediction mode, which shouldn't be considered -// final except for fast-encode settings. We can also pick some intra4 modes -// and decide intra4/intra16, but that's usually almost always a bad choice at -// this stage. - -static void ResetAllMBInfo(VP8Encoder* const enc) { - int n; - for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { - DefaultMBInfo(&enc->mb_info_[n]); - } - // Default susceptibilities. - enc->dqm_[0].alpha_ = 0; - enc->dqm_[0].beta_ = 0; - // Note: we can't compute this alpha_ / uv_alpha_ -> set to default value. - enc->alpha_ = 0; - enc->uv_alpha_ = 0; - WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_); -} - -// struct used to collect job result -typedef struct { - WebPWorker worker; - int alphas[MAX_ALPHA + 1]; - int alpha, uv_alpha; - VP8EncIterator it; - int delta_progress; -} SegmentJob; - -// main work call -static int DoSegmentsJob(SegmentJob* const job, VP8EncIterator* const it) { - int ok = 1; - if (!VP8IteratorIsDone(it)) { - uint8_t tmp[32 + WEBP_ALIGN_CST]; - uint8_t* const scratch = (uint8_t*)WEBP_ALIGN(tmp); - do { - // Let's pretend we have perfect lossless reconstruction. - VP8IteratorImport(it, scratch); - MBAnalyze(it, job->alphas, &job->alpha, &job->uv_alpha); - ok = VP8IteratorProgress(it, job->delta_progress); - } while (ok && VP8IteratorNext(it)); - } - return ok; -} - -static void MergeJobs(const SegmentJob* const src, SegmentJob* const dst) { - int i; - for (i = 0; i <= MAX_ALPHA; ++i) dst->alphas[i] += src->alphas[i]; - dst->alpha += src->alpha; - dst->uv_alpha += src->uv_alpha; -} - -// initialize the job struct with some TODOs -static void InitSegmentJob(VP8Encoder* const enc, SegmentJob* const job, - int start_row, int end_row) { - WebPGetWorkerInterface()->Init(&job->worker); - job->worker.data1 = job; - job->worker.data2 = &job->it; - job->worker.hook = (WebPWorkerHook)DoSegmentsJob; - VP8IteratorInit(enc, &job->it); - VP8IteratorSetRow(&job->it, start_row); - VP8IteratorSetCountDown(&job->it, (end_row - start_row) * enc->mb_w_); - memset(job->alphas, 0, sizeof(job->alphas)); - job->alpha = 0; - job->uv_alpha = 0; - // only one of both jobs can record the progress, since we don't - // expect the user's hook to be multi-thread safe - job->delta_progress = (start_row == 0) ? 20 : 0; -} - -// main entry point -int VP8EncAnalyze(VP8Encoder* const enc) { - int ok = 1; - const int do_segments = - enc->config_->emulate_jpeg_size || // We need the complexity evaluation. - (enc->segment_hdr_.num_segments_ > 1) || - (enc->method_ == 0); // for method 0, we need preds_[] to be filled. - if (do_segments) { - const int last_row = enc->mb_h_; - // We give a little more than a half work to the main thread. - const int split_row = (9 * last_row + 15) >> 4; - const int total_mb = last_row * enc->mb_w_; -#ifdef WEBP_USE_THREAD - const int kMinSplitRow = 2; // minimal rows needed for mt to be worth it - const int do_mt = (enc->thread_level_ > 0) && (split_row >= kMinSplitRow); -#else - const int do_mt = 0; -#endif - const WebPWorkerInterface* const worker_interface = - WebPGetWorkerInterface(); - SegmentJob main_job; - if (do_mt) { - SegmentJob side_job; - // Note the use of '&' instead of '&&' because we must call the functions - // no matter what. - InitSegmentJob(enc, &main_job, 0, split_row); - InitSegmentJob(enc, &side_job, split_row, last_row); - // we don't need to call Reset() on main_job.worker, since we're calling - // WebPWorkerExecute() on it - ok &= worker_interface->Reset(&side_job.worker); - // launch the two jobs in parallel - if (ok) { - worker_interface->Launch(&side_job.worker); - worker_interface->Execute(&main_job.worker); - ok &= worker_interface->Sync(&side_job.worker); - ok &= worker_interface->Sync(&main_job.worker); - } - worker_interface->End(&side_job.worker); - if (ok) MergeJobs(&side_job, &main_job); // merge results together - } else { - // Even for single-thread case, we use the generic Worker tools. - InitSegmentJob(enc, &main_job, 0, last_row); - worker_interface->Execute(&main_job.worker); - ok &= worker_interface->Sync(&main_job.worker); - } - worker_interface->End(&main_job.worker); - if (ok) { - enc->alpha_ = main_job.alpha / total_mb; - enc->uv_alpha_ = main_job.uv_alpha / total_mb; - AssignSegments(enc, main_job.alphas); - } - } else { // Use only one default segment. - ResetAllMBInfo(enc); - } - return ok; -} - diff --git a/Example/Pods/libwebp/src/enc/backward_references.c b/Example/Pods/libwebp/src/enc/backward_references.c deleted file mode 100644 index c39437dd..00000000 --- a/Example/Pods/libwebp/src/enc/backward_references.c +++ /dev/null @@ -1,1093 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Jyrki Alakuijala (jyrki@google.com) -// - -#include -#include - -#include "./backward_references.h" -#include "./histogram.h" -#include "../dsp/lossless.h" -#include "../dsp/dsp.h" -#include "../utils/color_cache.h" -#include "../utils/utils.h" - -#define VALUES_IN_BYTE 256 - -#define MIN_BLOCK_SIZE 256 // minimum block size for backward references - -#define MAX_ENTROPY (1e30f) - -// 1M window (4M bytes) minus 120 special codes for short distances. -#define WINDOW_SIZE ((1 << 20) - 120) - -// Bounds for the match length. -#define MIN_LENGTH 2 -#define MAX_LENGTH 4096 - -// ----------------------------------------------------------------------------- - -static const uint8_t plane_to_code_lut[128] = { - 96, 73, 55, 39, 23, 13, 5, 1, 255, 255, 255, 255, 255, 255, 255, 255, - 101, 78, 58, 42, 26, 16, 8, 2, 0, 3, 9, 17, 27, 43, 59, 79, - 102, 86, 62, 46, 32, 20, 10, 6, 4, 7, 11, 21, 33, 47, 63, 87, - 105, 90, 70, 52, 37, 28, 18, 14, 12, 15, 19, 29, 38, 53, 71, 91, - 110, 99, 82, 66, 48, 35, 30, 24, 22, 25, 31, 36, 49, 67, 83, 100, - 115, 108, 94, 76, 64, 50, 44, 40, 34, 41, 45, 51, 65, 77, 95, 109, - 118, 113, 103, 92, 80, 68, 60, 56, 54, 57, 61, 69, 81, 93, 104, 114, - 119, 116, 111, 106, 97, 88, 84, 74, 72, 75, 85, 89, 98, 107, 112, 117 -}; - -static int DistanceToPlaneCode(int xsize, int dist) { - const int yoffset = dist / xsize; - const int xoffset = dist - yoffset * xsize; - if (xoffset <= 8 && yoffset < 8) { - return plane_to_code_lut[yoffset * 16 + 8 - xoffset] + 1; - } else if (xoffset > xsize - 8 && yoffset < 7) { - return plane_to_code_lut[(yoffset + 1) * 16 + 8 + (xsize - xoffset)] + 1; - } - return dist + 120; -} - -// Returns the exact index where array1 and array2 are different if this -// index is strictly superior to best_len_match. Otherwise, it returns 0. -// If no two elements are the same, it returns max_limit. -static WEBP_INLINE int FindMatchLength(const uint32_t* const array1, - const uint32_t* const array2, - int best_len_match, - int max_limit) { - int match_len; - - // Before 'expensive' linear match, check if the two arrays match at the - // current best length index. - if (array1[best_len_match] != array2[best_len_match]) return 0; - -#if defined(WEBP_USE_SSE2) - // Check if anything is different up to best_len_match excluded. - // memcmp seems to be slower on ARM so it is disabled for now. - if (memcmp(array1, array2, best_len_match * sizeof(*array1))) return 0; - match_len = best_len_match + 1; -#else - match_len = 0; -#endif - - while (match_len < max_limit && array1[match_len] == array2[match_len]) { - ++match_len; - } - return match_len; -} - -// ----------------------------------------------------------------------------- -// VP8LBackwardRefs - -struct PixOrCopyBlock { - PixOrCopyBlock* next_; // next block (or NULL) - PixOrCopy* start_; // data start - int size_; // currently used size -}; - -static void ClearBackwardRefs(VP8LBackwardRefs* const refs) { - assert(refs != NULL); - if (refs->tail_ != NULL) { - *refs->tail_ = refs->free_blocks_; // recycle all blocks at once - } - refs->free_blocks_ = refs->refs_; - refs->tail_ = &refs->refs_; - refs->last_block_ = NULL; - refs->refs_ = NULL; -} - -void VP8LBackwardRefsClear(VP8LBackwardRefs* const refs) { - assert(refs != NULL); - ClearBackwardRefs(refs); - while (refs->free_blocks_ != NULL) { - PixOrCopyBlock* const next = refs->free_blocks_->next_; - WebPSafeFree(refs->free_blocks_); - refs->free_blocks_ = next; - } -} - -void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size) { - assert(refs != NULL); - memset(refs, 0, sizeof(*refs)); - refs->tail_ = &refs->refs_; - refs->block_size_ = - (block_size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : block_size; -} - -VP8LRefsCursor VP8LRefsCursorInit(const VP8LBackwardRefs* const refs) { - VP8LRefsCursor c; - c.cur_block_ = refs->refs_; - if (refs->refs_ != NULL) { - c.cur_pos = c.cur_block_->start_; - c.last_pos_ = c.cur_pos + c.cur_block_->size_; - } else { - c.cur_pos = NULL; - c.last_pos_ = NULL; - } - return c; -} - -void VP8LRefsCursorNextBlock(VP8LRefsCursor* const c) { - PixOrCopyBlock* const b = c->cur_block_->next_; - c->cur_pos = (b == NULL) ? NULL : b->start_; - c->last_pos_ = (b == NULL) ? NULL : b->start_ + b->size_; - c->cur_block_ = b; -} - -// Create a new block, either from the free list or allocated -static PixOrCopyBlock* BackwardRefsNewBlock(VP8LBackwardRefs* const refs) { - PixOrCopyBlock* b = refs->free_blocks_; - if (b == NULL) { // allocate new memory chunk - const size_t total_size = - sizeof(*b) + refs->block_size_ * sizeof(*b->start_); - b = (PixOrCopyBlock*)WebPSafeMalloc(1ULL, total_size); - if (b == NULL) { - refs->error_ |= 1; - return NULL; - } - b->start_ = (PixOrCopy*)((uint8_t*)b + sizeof(*b)); // not always aligned - } else { // recycle from free-list - refs->free_blocks_ = b->next_; - } - *refs->tail_ = b; - refs->tail_ = &b->next_; - refs->last_block_ = b; - b->next_ = NULL; - b->size_ = 0; - return b; -} - -static WEBP_INLINE void BackwardRefsCursorAdd(VP8LBackwardRefs* const refs, - const PixOrCopy v) { - PixOrCopyBlock* b = refs->last_block_; - if (b == NULL || b->size_ == refs->block_size_) { - b = BackwardRefsNewBlock(refs); - if (b == NULL) return; // refs->error_ is set - } - b->start_[b->size_++] = v; -} - -int VP8LBackwardRefsCopy(const VP8LBackwardRefs* const src, - VP8LBackwardRefs* const dst) { - const PixOrCopyBlock* b = src->refs_; - ClearBackwardRefs(dst); - assert(src->block_size_ == dst->block_size_); - while (b != NULL) { - PixOrCopyBlock* const new_b = BackwardRefsNewBlock(dst); - if (new_b == NULL) return 0; // dst->error_ is set - memcpy(new_b->start_, b->start_, b->size_ * sizeof(*b->start_)); - new_b->size_ = b->size_; - b = b->next_; - } - return 1; -} - -// ----------------------------------------------------------------------------- -// Hash chains - -// initialize as empty -static void HashChainReset(VP8LHashChain* const p) { - assert(p != NULL); - // Set the int32_t arrays to -1. - memset(p->chain_, 0xff, p->size_ * sizeof(*p->chain_)); - memset(p->hash_to_first_index_, 0xff, - HASH_SIZE * sizeof(*p->hash_to_first_index_)); -} - -int VP8LHashChainInit(VP8LHashChain* const p, int size) { - assert(p->size_ == 0); - assert(p->chain_ == NULL); - assert(size > 0); - p->chain_ = (int*)WebPSafeMalloc(size, sizeof(*p->chain_)); - if (p->chain_ == NULL) return 0; - p->size_ = size; - HashChainReset(p); - return 1; -} - -void VP8LHashChainClear(VP8LHashChain* const p) { - assert(p != NULL); - WebPSafeFree(p->chain_); - p->size_ = 0; - p->chain_ = NULL; -} - -// ----------------------------------------------------------------------------- - -#define HASH_MULTIPLIER_HI (0xc6a4a793U) -#define HASH_MULTIPLIER_LO (0x5bd1e996U) - -static WEBP_INLINE uint32_t GetPixPairHash64(const uint32_t* const argb) { - uint32_t key; - key = argb[1] * HASH_MULTIPLIER_HI; - key += argb[0] * HASH_MULTIPLIER_LO; - key = key >> (32 - HASH_BITS); - return key; -} - -// Insertion of two pixels at a time. -static void HashChainInsert(VP8LHashChain* const p, - const uint32_t* const argb, int pos) { - const uint32_t hash_code = GetPixPairHash64(argb); - p->chain_[pos] = p->hash_to_first_index_[hash_code]; - p->hash_to_first_index_[hash_code] = pos; -} - -// Returns the maximum number of hash chain lookups to do for a -// given compression quality. Return value in range [6, 86]. -static int GetMaxItersForQuality(int quality, int low_effort) { - return (low_effort ? 6 : 8) + (quality * quality) / 128; -} - -static int GetWindowSizeForHashChain(int quality, int xsize) { - const int max_window_size = (quality > 75) ? WINDOW_SIZE - : (quality > 50) ? (xsize << 8) - : (quality > 25) ? (xsize << 6) - : (xsize << 4); - assert(xsize > 0); - return (max_window_size > WINDOW_SIZE) ? WINDOW_SIZE : max_window_size; -} - -static WEBP_INLINE int MaxFindCopyLength(int len) { - return (len < MAX_LENGTH) ? len : MAX_LENGTH; -} - -static void HashChainFindOffset(const VP8LHashChain* const p, int base_position, - const uint32_t* const argb, int len, - int window_size, int* const distance_ptr) { - const uint32_t* const argb_start = argb + base_position; - const int min_pos = - (base_position > window_size) ? base_position - window_size : 0; - int pos; - assert(len <= MAX_LENGTH); - for (pos = p->hash_to_first_index_[GetPixPairHash64(argb_start)]; - pos >= min_pos; - pos = p->chain_[pos]) { - const int curr_length = - FindMatchLength(argb + pos, argb_start, len - 1, len); - if (curr_length == len) break; - } - *distance_ptr = base_position - pos; -} - -static int HashChainFindCopy(const VP8LHashChain* const p, - int base_position, - const uint32_t* const argb, int max_len, - int window_size, int iter_max, - int* const distance_ptr, - int* const length_ptr) { - const uint32_t* const argb_start = argb + base_position; - int iter = iter_max; - int best_length = 0; - int best_distance = 0; - const int min_pos = - (base_position > window_size) ? base_position - window_size : 0; - int pos; - int length_max = 256; - if (max_len < length_max) { - length_max = max_len; - } - for (pos = p->hash_to_first_index_[GetPixPairHash64(argb_start)]; - pos >= min_pos; - pos = p->chain_[pos]) { - int curr_length; - int distance; - if (--iter < 0) { - break; - } - - curr_length = FindMatchLength(argb + pos, argb_start, best_length, max_len); - if (best_length < curr_length) { - distance = base_position - pos; - best_length = curr_length; - best_distance = distance; - if (curr_length >= length_max) { - break; - } - } - } - *distance_ptr = best_distance; - *length_ptr = best_length; - return (best_length >= MIN_LENGTH); -} - -static WEBP_INLINE void AddSingleLiteral(uint32_t pixel, int use_color_cache, - VP8LColorCache* const hashers, - VP8LBackwardRefs* const refs) { - PixOrCopy v; - if (use_color_cache) { - const uint32_t key = VP8LColorCacheGetIndex(hashers, pixel); - if (VP8LColorCacheLookup(hashers, key) == pixel) { - v = PixOrCopyCreateCacheIdx(key); - } else { - v = PixOrCopyCreateLiteral(pixel); - VP8LColorCacheSet(hashers, key, pixel); - } - } else { - v = PixOrCopyCreateLiteral(pixel); - } - BackwardRefsCursorAdd(refs, v); -} - -static int BackwardReferencesRle(int xsize, int ysize, - const uint32_t* const argb, - int cache_bits, VP8LBackwardRefs* const refs) { - const int pix_count = xsize * ysize; - int i, k; - const int use_color_cache = (cache_bits > 0); - VP8LColorCache hashers; - - if (use_color_cache && !VP8LColorCacheInit(&hashers, cache_bits)) { - return 0; - } - ClearBackwardRefs(refs); - // Add first pixel as literal. - AddSingleLiteral(argb[0], use_color_cache, &hashers, refs); - i = 1; - while (i < pix_count) { - const int max_len = MaxFindCopyLength(pix_count - i); - const int kMinLength = 4; - const int rle_len = FindMatchLength(argb + i, argb + i - 1, 0, max_len); - const int prev_row_len = (i < xsize) ? 0 : - FindMatchLength(argb + i, argb + i - xsize, 0, max_len); - if (rle_len >= prev_row_len && rle_len >= kMinLength) { - BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(1, rle_len)); - // We don't need to update the color cache here since it is always the - // same pixel being copied, and that does not change the color cache - // state. - i += rle_len; - } else if (prev_row_len >= kMinLength) { - BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(xsize, prev_row_len)); - if (use_color_cache) { - for (k = 0; k < prev_row_len; ++k) { - VP8LColorCacheInsert(&hashers, argb[i + k]); - } - } - i += prev_row_len; - } else { - AddSingleLiteral(argb[i], use_color_cache, &hashers, refs); - i++; - } - } - if (use_color_cache) VP8LColorCacheClear(&hashers); - return !refs->error_; -} - -static int BackwardReferencesLz77(int xsize, int ysize, - const uint32_t* const argb, int cache_bits, - int quality, int low_effort, - VP8LHashChain* const hash_chain, - VP8LBackwardRefs* const refs) { - int i; - int ok = 0; - int cc_init = 0; - const int use_color_cache = (cache_bits > 0); - const int pix_count = xsize * ysize; - VP8LColorCache hashers; - int iter_max = GetMaxItersForQuality(quality, low_effort); - const int window_size = GetWindowSizeForHashChain(quality, xsize); - int min_matches = 32; - - if (use_color_cache) { - cc_init = VP8LColorCacheInit(&hashers, cache_bits); - if (!cc_init) goto Error; - } - ClearBackwardRefs(refs); - HashChainReset(hash_chain); - for (i = 0; i < pix_count - 2; ) { - // Alternative#1: Code the pixels starting at 'i' using backward reference. - int offset = 0; - int len = 0; - const int max_len = MaxFindCopyLength(pix_count - i); - HashChainFindCopy(hash_chain, i, argb, max_len, window_size, - iter_max, &offset, &len); - if (len > MIN_LENGTH || (len == MIN_LENGTH && offset <= 512)) { - int offset2 = 0; - int len2 = 0; - int k; - min_matches = 8; - HashChainInsert(hash_chain, &argb[i], i); - if ((len < (max_len >> 2)) && !low_effort) { - // Evaluate Alternative#2: Insert the pixel at 'i' as literal, and code - // the pixels starting at 'i + 1' using backward reference. - HashChainFindCopy(hash_chain, i + 1, argb, max_len - 1, - window_size, iter_max, &offset2, - &len2); - if (len2 > len + 1) { - AddSingleLiteral(argb[i], use_color_cache, &hashers, refs); - i++; // Backward reference to be done for next pixel. - len = len2; - offset = offset2; - } - } - BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len)); - if (use_color_cache) { - for (k = 0; k < len; ++k) { - VP8LColorCacheInsert(&hashers, argb[i + k]); - } - } - // Add to the hash_chain (but cannot add the last pixel). - if (offset >= 3 && offset != xsize) { - const int last = (len < pix_count - 1 - i) ? len : pix_count - 1 - i; - for (k = 2; k < last - 8; k += 2) { - HashChainInsert(hash_chain, &argb[i + k], i + k); - } - for (; k < last; ++k) { - HashChainInsert(hash_chain, &argb[i + k], i + k); - } - } - i += len; - } else { - AddSingleLiteral(argb[i], use_color_cache, &hashers, refs); - HashChainInsert(hash_chain, &argb[i], i); - ++i; - --min_matches; - if (min_matches <= 0) { - AddSingleLiteral(argb[i], use_color_cache, &hashers, refs); - HashChainInsert(hash_chain, &argb[i], i); - ++i; - } - } - } - while (i < pix_count) { - // Handle the last pixel(s). - AddSingleLiteral(argb[i], use_color_cache, &hashers, refs); - ++i; - } - - ok = !refs->error_; - Error: - if (cc_init) VP8LColorCacheClear(&hashers); - return ok; -} - -// ----------------------------------------------------------------------------- - -typedef struct { - double alpha_[VALUES_IN_BYTE]; - double red_[VALUES_IN_BYTE]; - double blue_[VALUES_IN_BYTE]; - double distance_[NUM_DISTANCE_CODES]; - double* literal_; -} CostModel; - -static int BackwardReferencesTraceBackwards( - int xsize, int ysize, const uint32_t* const argb, int quality, - int cache_bits, VP8LHashChain* const hash_chain, - VP8LBackwardRefs* const refs); - -static void ConvertPopulationCountTableToBitEstimates( - int num_symbols, const uint32_t population_counts[], double output[]) { - uint32_t sum = 0; - int nonzeros = 0; - int i; - for (i = 0; i < num_symbols; ++i) { - sum += population_counts[i]; - if (population_counts[i] > 0) { - ++nonzeros; - } - } - if (nonzeros <= 1) { - memset(output, 0, num_symbols * sizeof(*output)); - } else { - const double logsum = VP8LFastLog2(sum); - for (i = 0; i < num_symbols; ++i) { - output[i] = logsum - VP8LFastLog2(population_counts[i]); - } - } -} - -static int CostModelBuild(CostModel* const m, int cache_bits, - VP8LBackwardRefs* const refs) { - int ok = 0; - VP8LHistogram* const histo = VP8LAllocateHistogram(cache_bits); - if (histo == NULL) goto Error; - - VP8LHistogramCreate(histo, refs, cache_bits); - - ConvertPopulationCountTableToBitEstimates( - VP8LHistogramNumCodes(histo->palette_code_bits_), - histo->literal_, m->literal_); - ConvertPopulationCountTableToBitEstimates( - VALUES_IN_BYTE, histo->red_, m->red_); - ConvertPopulationCountTableToBitEstimates( - VALUES_IN_BYTE, histo->blue_, m->blue_); - ConvertPopulationCountTableToBitEstimates( - VALUES_IN_BYTE, histo->alpha_, m->alpha_); - ConvertPopulationCountTableToBitEstimates( - NUM_DISTANCE_CODES, histo->distance_, m->distance_); - ok = 1; - - Error: - VP8LFreeHistogram(histo); - return ok; -} - -static WEBP_INLINE double GetLiteralCost(const CostModel* const m, uint32_t v) { - return m->alpha_[v >> 24] + - m->red_[(v >> 16) & 0xff] + - m->literal_[(v >> 8) & 0xff] + - m->blue_[v & 0xff]; -} - -static WEBP_INLINE double GetCacheCost(const CostModel* const m, uint32_t idx) { - const int literal_idx = VALUES_IN_BYTE + NUM_LENGTH_CODES + idx; - return m->literal_[literal_idx]; -} - -static WEBP_INLINE double GetLengthCost(const CostModel* const m, - uint32_t length) { - int code, extra_bits; - VP8LPrefixEncodeBits(length, &code, &extra_bits); - return m->literal_[VALUES_IN_BYTE + code] + extra_bits; -} - -static WEBP_INLINE double GetDistanceCost(const CostModel* const m, - uint32_t distance) { - int code, extra_bits; - VP8LPrefixEncodeBits(distance, &code, &extra_bits); - return m->distance_[code] + extra_bits; -} - -static void AddSingleLiteralWithCostModel( - const uint32_t* const argb, VP8LHashChain* const hash_chain, - VP8LColorCache* const hashers, const CostModel* const cost_model, int idx, - int is_last, int use_color_cache, double prev_cost, float* const cost, - uint16_t* const dist_array) { - double cost_val = prev_cost; - const uint32_t color = argb[0]; - if (!is_last) { - HashChainInsert(hash_chain, argb, idx); - } - if (use_color_cache && VP8LColorCacheContains(hashers, color)) { - const double mul0 = 0.68; - const int ix = VP8LColorCacheGetIndex(hashers, color); - cost_val += GetCacheCost(cost_model, ix) * mul0; - } else { - const double mul1 = 0.82; - if (use_color_cache) VP8LColorCacheInsert(hashers, color); - cost_val += GetLiteralCost(cost_model, color) * mul1; - } - if (cost[idx] > cost_val) { - cost[idx] = (float)cost_val; - dist_array[idx] = 1; // only one is inserted. - } -} - -static int BackwardReferencesHashChainDistanceOnly( - int xsize, int ysize, const uint32_t* const argb, - int quality, int cache_bits, VP8LHashChain* const hash_chain, - VP8LBackwardRefs* const refs, uint16_t* const dist_array) { - int i; - int ok = 0; - int cc_init = 0; - const int pix_count = xsize * ysize; - const int use_color_cache = (cache_bits > 0); - float* const cost = - (float*)WebPSafeMalloc(pix_count, sizeof(*cost)); - const size_t literal_array_size = sizeof(double) * - (NUM_LITERAL_CODES + NUM_LENGTH_CODES + - ((cache_bits > 0) ? (1 << cache_bits) : 0)); - const size_t cost_model_size = sizeof(CostModel) + literal_array_size; - CostModel* const cost_model = - (CostModel*)WebPSafeMalloc(1ULL, cost_model_size); - VP8LColorCache hashers; - const int skip_length = 32 + quality; - const int skip_min_distance_code = 2; - int iter_max = GetMaxItersForQuality(quality, 0); - const int window_size = GetWindowSizeForHashChain(quality, xsize); - - if (cost == NULL || cost_model == NULL) goto Error; - - cost_model->literal_ = (double*)(cost_model + 1); - if (use_color_cache) { - cc_init = VP8LColorCacheInit(&hashers, cache_bits); - if (!cc_init) goto Error; - } - - if (!CostModelBuild(cost_model, cache_bits, refs)) { - goto Error; - } - - for (i = 0; i < pix_count; ++i) cost[i] = 1e38f; - - // We loop one pixel at a time, but store all currently best points to - // non-processed locations from this point. - dist_array[0] = 0; - HashChainReset(hash_chain); - // Add first pixel as literal. - AddSingleLiteralWithCostModel(argb + 0, hash_chain, &hashers, cost_model, 0, - 0, use_color_cache, 0.0, cost, dist_array); - for (i = 1; i < pix_count - 1; ++i) { - int offset = 0; - int len = 0; - double prev_cost = cost[i - 1]; - const int max_len = MaxFindCopyLength(pix_count - i); - HashChainFindCopy(hash_chain, i, argb, max_len, window_size, - iter_max, &offset, &len); - if (len >= MIN_LENGTH) { - const int code = DistanceToPlaneCode(xsize, offset); - const double distance_cost = - prev_cost + GetDistanceCost(cost_model, code); - int k; - for (k = 1; k < len; ++k) { - const double cost_val = distance_cost + GetLengthCost(cost_model, k); - if (cost[i + k] > cost_val) { - cost[i + k] = (float)cost_val; - dist_array[i + k] = k + 1; - } - } - // This if is for speedup only. It roughly doubles the speed, and - // makes compression worse by .1 %. - if (len >= skip_length && code <= skip_min_distance_code) { - // Long copy for short distances, let's skip the middle - // lookups for better copies. - // 1) insert the hashes. - if (use_color_cache) { - for (k = 0; k < len; ++k) { - VP8LColorCacheInsert(&hashers, argb[i + k]); - } - } - // 2) Add to the hash_chain (but cannot add the last pixel) - { - const int last = (len + i < pix_count - 1) ? len + i - : pix_count - 1; - for (k = i; k < last; ++k) { - HashChainInsert(hash_chain, &argb[k], k); - } - } - // 3) jump. - i += len - 1; // for loop does ++i, thus -1 here. - goto next_symbol; - } - if (len != MIN_LENGTH) { - int code_min_length; - double cost_total; - HashChainFindOffset(hash_chain, i, argb, MIN_LENGTH, window_size, - &offset); - code_min_length = DistanceToPlaneCode(xsize, offset); - cost_total = prev_cost + - GetDistanceCost(cost_model, code_min_length) + - GetLengthCost(cost_model, 1); - if (cost[i + 1] > cost_total) { - cost[i + 1] = (float)cost_total; - dist_array[i + 1] = 2; - } - } - } - AddSingleLiteralWithCostModel(argb + i, hash_chain, &hashers, cost_model, i, - 0, use_color_cache, prev_cost, cost, - dist_array); - next_symbol: ; - } - // Handle the last pixel. - if (i == (pix_count - 1)) { - AddSingleLiteralWithCostModel(argb + i, hash_chain, &hashers, cost_model, i, - 1, use_color_cache, cost[pix_count - 2], cost, - dist_array); - } - ok = !refs->error_; - Error: - if (cc_init) VP8LColorCacheClear(&hashers); - WebPSafeFree(cost_model); - WebPSafeFree(cost); - return ok; -} - -// We pack the path at the end of *dist_array and return -// a pointer to this part of the array. Example: -// dist_array = [1x2xx3x2] => packed [1x2x1232], chosen_path = [1232] -static void TraceBackwards(uint16_t* const dist_array, - int dist_array_size, - uint16_t** const chosen_path, - int* const chosen_path_size) { - uint16_t* path = dist_array + dist_array_size; - uint16_t* cur = dist_array + dist_array_size - 1; - while (cur >= dist_array) { - const int k = *cur; - --path; - *path = k; - cur -= k; - } - *chosen_path = path; - *chosen_path_size = (int)(dist_array + dist_array_size - path); -} - -static int BackwardReferencesHashChainFollowChosenPath( - int xsize, int ysize, const uint32_t* const argb, - int quality, int cache_bits, - const uint16_t* const chosen_path, int chosen_path_size, - VP8LHashChain* const hash_chain, - VP8LBackwardRefs* const refs) { - const int pix_count = xsize * ysize; - const int use_color_cache = (cache_bits > 0); - int ix; - int i = 0; - int ok = 0; - int cc_init = 0; - const int window_size = GetWindowSizeForHashChain(quality, xsize); - VP8LColorCache hashers; - - if (use_color_cache) { - cc_init = VP8LColorCacheInit(&hashers, cache_bits); - if (!cc_init) goto Error; - } - - ClearBackwardRefs(refs); - HashChainReset(hash_chain); - for (ix = 0; ix < chosen_path_size; ++ix) { - int offset = 0; - const int len = chosen_path[ix]; - if (len != 1) { - int k; - HashChainFindOffset(hash_chain, i, argb, len, window_size, &offset); - BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len)); - if (use_color_cache) { - for (k = 0; k < len; ++k) { - VP8LColorCacheInsert(&hashers, argb[i + k]); - } - } - { - const int last = (len < pix_count - 1 - i) ? len : pix_count - 1 - i; - for (k = 0; k < last; ++k) { - HashChainInsert(hash_chain, &argb[i + k], i + k); - } - } - i += len; - } else { - PixOrCopy v; - if (use_color_cache && VP8LColorCacheContains(&hashers, argb[i])) { - // push pixel as a color cache index - const int idx = VP8LColorCacheGetIndex(&hashers, argb[i]); - v = PixOrCopyCreateCacheIdx(idx); - } else { - if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]); - v = PixOrCopyCreateLiteral(argb[i]); - } - BackwardRefsCursorAdd(refs, v); - if (i + 1 < pix_count) { - HashChainInsert(hash_chain, &argb[i], i); - } - ++i; - } - } - ok = !refs->error_; - Error: - if (cc_init) VP8LColorCacheClear(&hashers); - return ok; -} - -// Returns 1 on success. -static int BackwardReferencesTraceBackwards(int xsize, int ysize, - const uint32_t* const argb, - int quality, int cache_bits, - VP8LHashChain* const hash_chain, - VP8LBackwardRefs* const refs) { - int ok = 0; - const int dist_array_size = xsize * ysize; - uint16_t* chosen_path = NULL; - int chosen_path_size = 0; - uint16_t* dist_array = - (uint16_t*)WebPSafeMalloc(dist_array_size, sizeof(*dist_array)); - - if (dist_array == NULL) goto Error; - - if (!BackwardReferencesHashChainDistanceOnly( - xsize, ysize, argb, quality, cache_bits, hash_chain, - refs, dist_array)) { - goto Error; - } - TraceBackwards(dist_array, dist_array_size, &chosen_path, &chosen_path_size); - if (!BackwardReferencesHashChainFollowChosenPath( - xsize, ysize, argb, quality, cache_bits, chosen_path, chosen_path_size, - hash_chain, refs)) { - goto Error; - } - ok = 1; - Error: - WebPSafeFree(dist_array); - return ok; -} - -static void BackwardReferences2DLocality(int xsize, - const VP8LBackwardRefs* const refs) { - VP8LRefsCursor c = VP8LRefsCursorInit(refs); - while (VP8LRefsCursorOk(&c)) { - if (PixOrCopyIsCopy(c.cur_pos)) { - const int dist = c.cur_pos->argb_or_distance; - const int transformed_dist = DistanceToPlaneCode(xsize, dist); - c.cur_pos->argb_or_distance = transformed_dist; - } - VP8LRefsCursorNext(&c); - } -} - -// Returns entropy for the given cache bits. -static double ComputeCacheEntropy(const uint32_t* argb, - const VP8LBackwardRefs* const refs, - int cache_bits) { - const int use_color_cache = (cache_bits > 0); - int cc_init = 0; - double entropy = MAX_ENTROPY; - const double kSmallPenaltyForLargeCache = 4.0; - VP8LColorCache hashers; - VP8LRefsCursor c = VP8LRefsCursorInit(refs); - VP8LHistogram* histo = VP8LAllocateHistogram(cache_bits); - if (histo == NULL) goto Error; - - if (use_color_cache) { - cc_init = VP8LColorCacheInit(&hashers, cache_bits); - if (!cc_init) goto Error; - } - if (!use_color_cache) { - while (VP8LRefsCursorOk(&c)) { - VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos); - VP8LRefsCursorNext(&c); - } - } else { - while (VP8LRefsCursorOk(&c)) { - const PixOrCopy* const v = c.cur_pos; - if (PixOrCopyIsLiteral(v)) { - const uint32_t pix = *argb++; - const uint32_t key = VP8LColorCacheGetIndex(&hashers, pix); - if (VP8LColorCacheLookup(&hashers, key) == pix) { - ++histo->literal_[NUM_LITERAL_CODES + NUM_LENGTH_CODES + key]; - } else { - VP8LColorCacheSet(&hashers, key, pix); - ++histo->blue_[pix & 0xff]; - ++histo->literal_[(pix >> 8) & 0xff]; - ++histo->red_[(pix >> 16) & 0xff]; - ++histo->alpha_[pix >> 24]; - } - } else { - int len = PixOrCopyLength(v); - int code, extra_bits; - VP8LPrefixEncodeBits(len, &code, &extra_bits); - ++histo->literal_[NUM_LITERAL_CODES + code]; - VP8LPrefixEncodeBits(PixOrCopyDistance(v), &code, &extra_bits); - ++histo->distance_[code]; - do { - VP8LColorCacheInsert(&hashers, *argb++); - } while(--len != 0); - } - VP8LRefsCursorNext(&c); - } - } - entropy = VP8LHistogramEstimateBits(histo) + - kSmallPenaltyForLargeCache * cache_bits; - Error: - if (cc_init) VP8LColorCacheClear(&hashers); - VP8LFreeHistogram(histo); - return entropy; -} - -// Evaluate optimal cache bits for the local color cache. -// The input *best_cache_bits sets the maximum cache bits to use (passing 0 -// implies disabling the local color cache). The local color cache is also -// disabled for the lower (<= 25) quality. -// Returns 0 in case of memory error. -static int CalculateBestCacheSize(const uint32_t* const argb, - int xsize, int ysize, int quality, - VP8LHashChain* const hash_chain, - VP8LBackwardRefs* const refs, - int* const lz77_computed, - int* const best_cache_bits) { - int eval_low = 1; - int eval_high = 1; - double entropy_low = MAX_ENTROPY; - double entropy_high = MAX_ENTROPY; - const double cost_mul = 5e-4; - int cache_bits_low = 0; - int cache_bits_high = (quality <= 25) ? 0 : *best_cache_bits; - - assert(cache_bits_high <= MAX_COLOR_CACHE_BITS); - - *lz77_computed = 0; - if (cache_bits_high == 0) { - *best_cache_bits = 0; - // Local color cache is disabled. - return 1; - } - if (!BackwardReferencesLz77(xsize, ysize, argb, cache_bits_low, quality, 0, - hash_chain, refs)) { - return 0; - } - // Do a binary search to find the optimal entropy for cache_bits. - while (eval_low || eval_high) { - if (eval_low) { - entropy_low = ComputeCacheEntropy(argb, refs, cache_bits_low); - entropy_low += entropy_low * cache_bits_low * cost_mul; - eval_low = 0; - } - if (eval_high) { - entropy_high = ComputeCacheEntropy(argb, refs, cache_bits_high); - entropy_high += entropy_high * cache_bits_high * cost_mul; - eval_high = 0; - } - if (entropy_high < entropy_low) { - const int prev_cache_bits_low = cache_bits_low; - *best_cache_bits = cache_bits_high; - cache_bits_low = (cache_bits_low + cache_bits_high) / 2; - if (cache_bits_low != prev_cache_bits_low) eval_low = 1; - } else { - *best_cache_bits = cache_bits_low; - cache_bits_high = (cache_bits_low + cache_bits_high) / 2; - if (cache_bits_high != cache_bits_low) eval_high = 1; - } - } - *lz77_computed = 1; - return 1; -} - -// Update (in-place) backward references for specified cache_bits. -static int BackwardRefsWithLocalCache(const uint32_t* const argb, - int cache_bits, - VP8LBackwardRefs* const refs) { - int pixel_index = 0; - VP8LColorCache hashers; - VP8LRefsCursor c = VP8LRefsCursorInit(refs); - if (!VP8LColorCacheInit(&hashers, cache_bits)) return 0; - - while (VP8LRefsCursorOk(&c)) { - PixOrCopy* const v = c.cur_pos; - if (PixOrCopyIsLiteral(v)) { - const uint32_t argb_literal = v->argb_or_distance; - if (VP8LColorCacheContains(&hashers, argb_literal)) { - const int ix = VP8LColorCacheGetIndex(&hashers, argb_literal); - *v = PixOrCopyCreateCacheIdx(ix); - } else { - VP8LColorCacheInsert(&hashers, argb_literal); - } - ++pixel_index; - } else { - // refs was created without local cache, so it can not have cache indexes. - int k; - assert(PixOrCopyIsCopy(v)); - for (k = 0; k < v->len; ++k) { - VP8LColorCacheInsert(&hashers, argb[pixel_index++]); - } - } - VP8LRefsCursorNext(&c); - } - VP8LColorCacheClear(&hashers); - return 1; -} - -static VP8LBackwardRefs* GetBackwardReferencesLowEffort( - int width, int height, const uint32_t* const argb, int quality, - int* const cache_bits, VP8LHashChain* const hash_chain, - VP8LBackwardRefs refs_array[2]) { - VP8LBackwardRefs* refs_lz77 = &refs_array[0]; - *cache_bits = 0; - if (!BackwardReferencesLz77(width, height, argb, 0, quality, - 1 /* Low effort. */, hash_chain, refs_lz77)) { - return NULL; - } - BackwardReferences2DLocality(width, refs_lz77); - return refs_lz77; -} - -static VP8LBackwardRefs* GetBackwardReferences( - int width, int height, const uint32_t* const argb, int quality, - int* const cache_bits, VP8LHashChain* const hash_chain, - VP8LBackwardRefs refs_array[2]) { - int lz77_is_useful; - int lz77_computed; - double bit_cost_lz77, bit_cost_rle; - VP8LBackwardRefs* best = NULL; - VP8LBackwardRefs* refs_lz77 = &refs_array[0]; - VP8LBackwardRefs* refs_rle = &refs_array[1]; - VP8LHistogram* histo = NULL; - - if (!CalculateBestCacheSize(argb, width, height, quality, hash_chain, - refs_lz77, &lz77_computed, cache_bits)) { - goto Error; - } - - if (lz77_computed) { - // Transform refs_lz77 for the optimized cache_bits. - if (*cache_bits > 0) { - if (!BackwardRefsWithLocalCache(argb, *cache_bits, refs_lz77)) { - goto Error; - } - } - } else { - if (!BackwardReferencesLz77(width, height, argb, *cache_bits, quality, - 0 /* Low effort. */, hash_chain, refs_lz77)) { - goto Error; - } - } - - if (!BackwardReferencesRle(width, height, argb, *cache_bits, refs_rle)) { - goto Error; - } - - histo = VP8LAllocateHistogram(*cache_bits); - if (histo == NULL) goto Error; - - { - // Evaluate LZ77 coding. - VP8LHistogramCreate(histo, refs_lz77, *cache_bits); - bit_cost_lz77 = VP8LHistogramEstimateBits(histo); - // Evaluate RLE coding. - VP8LHistogramCreate(histo, refs_rle, *cache_bits); - bit_cost_rle = VP8LHistogramEstimateBits(histo); - // Decide if LZ77 is useful. - lz77_is_useful = (bit_cost_lz77 < bit_cost_rle); - } - - // Choose appropriate backward reference. - if (lz77_is_useful) { - // TraceBackwards is costly. Don't execute it at lower quality. - const int try_lz77_trace_backwards = (quality >= 25); - best = refs_lz77; // default guess: lz77 is better - if (try_lz77_trace_backwards) { - VP8LBackwardRefs* const refs_trace = refs_rle; - if (!VP8LBackwardRefsCopy(refs_lz77, refs_trace)) { - best = NULL; - goto Error; - } - if (BackwardReferencesTraceBackwards(width, height, argb, quality, - *cache_bits, hash_chain, - refs_trace)) { - double bit_cost_trace; - // Evaluate LZ77 coding. - VP8LHistogramCreate(histo, refs_trace, *cache_bits); - bit_cost_trace = VP8LHistogramEstimateBits(histo); - if (bit_cost_trace < bit_cost_lz77) { - best = refs_trace; - } - } - } - } else { - best = refs_rle; - } - - BackwardReferences2DLocality(width, best); - - Error: - VP8LFreeHistogram(histo); - return best; -} - -VP8LBackwardRefs* VP8LGetBackwardReferences( - int width, int height, const uint32_t* const argb, int quality, - int low_effort, int* const cache_bits, VP8LHashChain* const hash_chain, - VP8LBackwardRefs refs_array[2]) { - if (low_effort) { - return GetBackwardReferencesLowEffort(width, height, argb, quality, - cache_bits, hash_chain, refs_array); - } else { - return GetBackwardReferences(width, height, argb, quality, cache_bits, - hash_chain, refs_array); - } -} diff --git a/Example/Pods/libwebp/src/enc/backward_references.h b/Example/Pods/libwebp/src/enc/backward_references.h deleted file mode 100644 index daa084d8..00000000 --- a/Example/Pods/libwebp/src/enc/backward_references.h +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Jyrki Alakuijala (jyrki@google.com) -// - -#ifndef WEBP_ENC_BACKWARD_REFERENCES_H_ -#define WEBP_ENC_BACKWARD_REFERENCES_H_ - -#include -#include -#include "../webp/types.h" -#include "../webp/format_constants.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// The maximum allowed limit is 11. -#define MAX_COLOR_CACHE_BITS 10 - -// ----------------------------------------------------------------------------- -// PixOrCopy - -enum Mode { - kLiteral, - kCacheIdx, - kCopy, - kNone -}; - -typedef struct { - // mode as uint8_t to make the memory layout to be exactly 8 bytes. - uint8_t mode; - uint16_t len; - uint32_t argb_or_distance; -} PixOrCopy; - -static WEBP_INLINE PixOrCopy PixOrCopyCreateCopy(uint32_t distance, - uint16_t len) { - PixOrCopy retval; - retval.mode = kCopy; - retval.argb_or_distance = distance; - retval.len = len; - return retval; -} - -static WEBP_INLINE PixOrCopy PixOrCopyCreateCacheIdx(int idx) { - PixOrCopy retval; - assert(idx >= 0); - assert(idx < (1 << MAX_COLOR_CACHE_BITS)); - retval.mode = kCacheIdx; - retval.argb_or_distance = idx; - retval.len = 1; - return retval; -} - -static WEBP_INLINE PixOrCopy PixOrCopyCreateLiteral(uint32_t argb) { - PixOrCopy retval; - retval.mode = kLiteral; - retval.argb_or_distance = argb; - retval.len = 1; - return retval; -} - -static WEBP_INLINE int PixOrCopyIsLiteral(const PixOrCopy* const p) { - return (p->mode == kLiteral); -} - -static WEBP_INLINE int PixOrCopyIsCacheIdx(const PixOrCopy* const p) { - return (p->mode == kCacheIdx); -} - -static WEBP_INLINE int PixOrCopyIsCopy(const PixOrCopy* const p) { - return (p->mode == kCopy); -} - -static WEBP_INLINE uint32_t PixOrCopyLiteral(const PixOrCopy* const p, - int component) { - assert(p->mode == kLiteral); - return (p->argb_or_distance >> (component * 8)) & 0xff; -} - -static WEBP_INLINE uint32_t PixOrCopyLength(const PixOrCopy* const p) { - return p->len; -} - -static WEBP_INLINE uint32_t PixOrCopyArgb(const PixOrCopy* const p) { - assert(p->mode == kLiteral); - return p->argb_or_distance; -} - -static WEBP_INLINE uint32_t PixOrCopyCacheIdx(const PixOrCopy* const p) { - assert(p->mode == kCacheIdx); - assert(p->argb_or_distance < (1U << MAX_COLOR_CACHE_BITS)); - return p->argb_or_distance; -} - -static WEBP_INLINE uint32_t PixOrCopyDistance(const PixOrCopy* const p) { - assert(p->mode == kCopy); - return p->argb_or_distance; -} - -// ----------------------------------------------------------------------------- -// VP8LHashChain - -#define HASH_BITS 18 -#define HASH_SIZE (1 << HASH_BITS) - -typedef struct VP8LHashChain VP8LHashChain; -struct VP8LHashChain { - // Stores the most recently added position with the given hash value. - int32_t hash_to_first_index_[HASH_SIZE]; - // chain_[pos] stores the previous position with the same hash value - // for every pixel in the image. - int32_t* chain_; - // This is the maximum size of the hash_chain that can be constructed. - // Typically this is the pixel count (width x height) for a given image. - int size_; -}; - -// Must be called first, to set size. -int VP8LHashChainInit(VP8LHashChain* const p, int size); -void VP8LHashChainClear(VP8LHashChain* const p); // release memory - -// ----------------------------------------------------------------------------- -// VP8LBackwardRefs (block-based backward-references storage) - -// maximum number of reference blocks the image will be segmented into -#define MAX_REFS_BLOCK_PER_IMAGE 16 - -typedef struct PixOrCopyBlock PixOrCopyBlock; // forward declaration -typedef struct VP8LBackwardRefs VP8LBackwardRefs; - -// Container for blocks chain -struct VP8LBackwardRefs { - int block_size_; // common block-size - int error_; // set to true if some memory error occurred - PixOrCopyBlock* refs_; // list of currently used blocks - PixOrCopyBlock** tail_; // for list recycling - PixOrCopyBlock* free_blocks_; // free-list - PixOrCopyBlock* last_block_; // used for adding new refs (internal) -}; - -// Initialize the object. 'block_size' is the common block size to store -// references (typically, width * height / MAX_REFS_BLOCK_PER_IMAGE). -void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size); -// Release memory for backward references. -void VP8LBackwardRefsClear(VP8LBackwardRefs* const refs); -// Copies the 'src' backward refs to the 'dst'. Returns 0 in case of error. -int VP8LBackwardRefsCopy(const VP8LBackwardRefs* const src, - VP8LBackwardRefs* const dst); - -// Cursor for iterating on references content -typedef struct { - // public: - PixOrCopy* cur_pos; // current position - // private: - PixOrCopyBlock* cur_block_; // current block in the refs list - const PixOrCopy* last_pos_; // sentinel for switching to next block -} VP8LRefsCursor; - -// Returns a cursor positioned at the beginning of the references list. -VP8LRefsCursor VP8LRefsCursorInit(const VP8LBackwardRefs* const refs); -// Returns true if cursor is pointing at a valid position. -static WEBP_INLINE int VP8LRefsCursorOk(const VP8LRefsCursor* const c) { - return (c->cur_pos != NULL); -} -// Move to next block of references. Internal, not to be called directly. -void VP8LRefsCursorNextBlock(VP8LRefsCursor* const c); -// Move to next position, or NULL. Should not be called if !VP8LRefsCursorOk(). -static WEBP_INLINE void VP8LRefsCursorNext(VP8LRefsCursor* const c) { - assert(c != NULL); - assert(VP8LRefsCursorOk(c)); - if (++c->cur_pos == c->last_pos_) VP8LRefsCursorNextBlock(c); -} - -// ----------------------------------------------------------------------------- -// Main entry points - -// Evaluates best possible backward references for specified quality. -// The input cache_bits to 'VP8LGetBackwardReferences' sets the maximum cache -// bits to use (passing 0 implies disabling the local color cache). -// The optimal cache bits is evaluated and set for the *cache_bits parameter. -// The return value is the pointer to the best of the two backward refs viz, -// refs[0] or refs[1]. -VP8LBackwardRefs* VP8LGetBackwardReferences( - int width, int height, const uint32_t* const argb, int quality, - int low_effort, int* const cache_bits, VP8LHashChain* const hash_chain, - VP8LBackwardRefs refs[2]); - -#ifdef __cplusplus -} -#endif - -#endif // WEBP_ENC_BACKWARD_REFERENCES_H_ diff --git a/Example/Pods/libwebp/src/enc/config.c b/Example/Pods/libwebp/src/enc/config.c deleted file mode 100644 index f9f7961d..00000000 --- a/Example/Pods/libwebp/src/enc/config.c +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Coding tools configuration -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "../webp/encode.h" - -//------------------------------------------------------------------------------ -// WebPConfig -//------------------------------------------------------------------------------ - -int WebPConfigInitInternal(WebPConfig* config, - WebPPreset preset, float quality, int version) { - if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_ENCODER_ABI_VERSION)) { - return 0; // caller/system version mismatch! - } - if (config == NULL) return 0; - - config->quality = quality; - config->target_size = 0; - config->target_PSNR = 0.; - config->method = 4; - config->sns_strength = 50; - config->filter_strength = 60; // mid-filtering - config->filter_sharpness = 0; - config->filter_type = 1; // default: strong (so U/V is filtered too) - config->partitions = 0; - config->segments = 4; - config->pass = 1; - config->show_compressed = 0; - config->preprocessing = 0; - config->autofilter = 0; - config->partition_limit = 0; - config->alpha_compression = 1; - config->alpha_filtering = 1; - config->alpha_quality = 100; - config->lossless = 0; - config->exact = 0; - config->image_hint = WEBP_HINT_DEFAULT; - config->emulate_jpeg_size = 0; - config->thread_level = 0; - config->low_memory = 0; - config->near_lossless = 100; -#ifdef WEBP_EXPERIMENTAL_FEATURES - config->delta_palettization = 0; -#endif // WEBP_EXPERIMENTAL_FEATURES - - // TODO(skal): tune. - switch (preset) { - case WEBP_PRESET_PICTURE: - config->sns_strength = 80; - config->filter_sharpness = 4; - config->filter_strength = 35; - config->preprocessing &= ~2; // no dithering - break; - case WEBP_PRESET_PHOTO: - config->sns_strength = 80; - config->filter_sharpness = 3; - config->filter_strength = 30; - config->preprocessing |= 2; - break; - case WEBP_PRESET_DRAWING: - config->sns_strength = 25; - config->filter_sharpness = 6; - config->filter_strength = 10; - break; - case WEBP_PRESET_ICON: - config->sns_strength = 0; - config->filter_strength = 0; // disable filtering to retain sharpness - config->preprocessing &= ~2; // no dithering - break; - case WEBP_PRESET_TEXT: - config->sns_strength = 0; - config->filter_strength = 0; // disable filtering to retain sharpness - config->preprocessing &= ~2; // no dithering - config->segments = 2; - break; - case WEBP_PRESET_DEFAULT: - default: - break; - } - return WebPValidateConfig(config); -} - -int WebPValidateConfig(const WebPConfig* config) { - if (config == NULL) return 0; - if (config->quality < 0 || config->quality > 100) - return 0; - if (config->target_size < 0) - return 0; - if (config->target_PSNR < 0) - return 0; - if (config->method < 0 || config->method > 6) - return 0; - if (config->segments < 1 || config->segments > 4) - return 0; - if (config->sns_strength < 0 || config->sns_strength > 100) - return 0; - if (config->filter_strength < 0 || config->filter_strength > 100) - return 0; - if (config->filter_sharpness < 0 || config->filter_sharpness > 7) - return 0; - if (config->filter_type < 0 || config->filter_type > 1) - return 0; - if (config->autofilter < 0 || config->autofilter > 1) - return 0; - if (config->pass < 1 || config->pass > 10) - return 0; - if (config->show_compressed < 0 || config->show_compressed > 1) - return 0; - if (config->preprocessing < 0 || config->preprocessing > 7) - return 0; - if (config->partitions < 0 || config->partitions > 3) - return 0; - if (config->partition_limit < 0 || config->partition_limit > 100) - return 0; - if (config->alpha_compression < 0) - return 0; - if (config->alpha_filtering < 0) - return 0; - if (config->alpha_quality < 0 || config->alpha_quality > 100) - return 0; - if (config->lossless < 0 || config->lossless > 1) - return 0; - if (config->near_lossless < 0 || config->near_lossless > 100) - return 0; - if (config->image_hint >= WEBP_HINT_LAST) - return 0; - if (config->emulate_jpeg_size < 0 || config->emulate_jpeg_size > 1) - return 0; - if (config->thread_level < 0 || config->thread_level > 1) - return 0; - if (config->low_memory < 0 || config->low_memory > 1) - return 0; - if (config->exact < 0 || config->exact > 1) - return 0; -#ifdef WEBP_EXPERIMENTAL_FEATURES - if (config->delta_palettization < 0 || config->delta_palettization > 1) - return 0; -#endif // WEBP_EXPERIMENTAL_FEATURES - return 1; -} - -//------------------------------------------------------------------------------ - -#define MAX_LEVEL 9 - -// Mapping between -z level and -m / -q parameter settings. -static const struct { - uint8_t method_; - uint8_t quality_; -} kLosslessPresets[MAX_LEVEL + 1] = { - { 0, 0 }, { 1, 20 }, { 2, 25 }, { 3, 30 }, { 3, 50 }, - { 4, 50 }, { 4, 75 }, { 4, 90 }, { 5, 90 }, { 6, 100 } -}; - -int WebPConfigLosslessPreset(WebPConfig* config, int level) { - if (config == NULL || level < 0 || level > MAX_LEVEL) return 0; - config->lossless = 1; - config->method = kLosslessPresets[level].method_; - config->quality = kLosslessPresets[level].quality_; - return 1; -} - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/enc/cost.c b/Example/Pods/libwebp/src/enc/cost.c deleted file mode 100644 index ae7fe013..00000000 --- a/Example/Pods/libwebp/src/enc/cost.c +++ /dev/null @@ -1,354 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Cost tables for level and modes -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./cost.h" - -//------------------------------------------------------------------------------ -// Level cost tables - -// For each given level, the following table gives the pattern of contexts to -// use for coding it (in [][0]) as well as the bit value to use for each -// context (in [][1]). -const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2] = { - {0x001, 0x000}, {0x007, 0x001}, {0x00f, 0x005}, - {0x00f, 0x00d}, {0x033, 0x003}, {0x033, 0x003}, {0x033, 0x023}, - {0x033, 0x023}, {0x033, 0x023}, {0x033, 0x023}, {0x0d3, 0x013}, - {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x013}, - {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x093}, - {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, - {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, - {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, - {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x153, 0x053}, - {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, - {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, - {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, - {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, - {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, - {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, - {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, - {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x153} -}; - -static int VariableLevelCost(int level, const uint8_t probas[NUM_PROBAS]) { - int pattern = VP8LevelCodes[level - 1][0]; - int bits = VP8LevelCodes[level - 1][1]; - int cost = 0; - int i; - for (i = 2; pattern; ++i) { - if (pattern & 1) { - cost += VP8BitCost(bits & 1, probas[i]); - } - bits >>= 1; - pattern >>= 1; - } - return cost; -} - -//------------------------------------------------------------------------------ -// Pre-calc level costs once for all - -void VP8CalculateLevelCosts(VP8EncProba* const proba) { - int ctype, band, ctx; - - if (!proba->dirty_) return; // nothing to do. - - for (ctype = 0; ctype < NUM_TYPES; ++ctype) { - int n; - for (band = 0; band < NUM_BANDS; ++band) { - for (ctx = 0; ctx < NUM_CTX; ++ctx) { - const uint8_t* const p = proba->coeffs_[ctype][band][ctx]; - uint16_t* const table = proba->level_cost_[ctype][band][ctx]; - const int cost0 = (ctx > 0) ? VP8BitCost(1, p[0]) : 0; - const int cost_base = VP8BitCost(1, p[1]) + cost0; - int v; - table[0] = VP8BitCost(0, p[1]) + cost0; - for (v = 1; v <= MAX_VARIABLE_LEVEL; ++v) { - table[v] = cost_base + VariableLevelCost(v, p); - } - // Starting at level 67 and up, the variable part of the cost is - // actually constant. - } - } - for (n = 0; n < 16; ++n) { // replicate bands. We don't need to sentinel. - for (ctx = 0; ctx < NUM_CTX; ++ctx) { - proba->remapped_costs_[ctype][n][ctx] = - proba->level_cost_[ctype][VP8EncBands[n]][ctx]; - } - } - } - proba->dirty_ = 0; -} - -//------------------------------------------------------------------------------ -// Mode cost tables. - -// These are the fixed probabilities (in the coding trees) turned into bit-cost -// by calling VP8BitCost(). -const uint16_t VP8FixedCostsUV[4] = { 302, 984, 439, 642 }; -// note: these values include the fixed VP8BitCost(1, 145) mode selection cost. -const uint16_t VP8FixedCostsI16[4] = { 663, 919, 872, 919 }; -const uint16_t VP8FixedCostsI4[NUM_BMODES][NUM_BMODES][NUM_BMODES] = { - { { 40, 1151, 1723, 1874, 2103, 2019, 1628, 1777, 2226, 2137 }, - { 192, 469, 1296, 1308, 1849, 1794, 1781, 1703, 1713, 1522 }, - { 142, 910, 762, 1684, 1849, 1576, 1460, 1305, 1801, 1657 }, - { 559, 641, 1370, 421, 1182, 1569, 1612, 1725, 863, 1007 }, - { 299, 1059, 1256, 1108, 636, 1068, 1581, 1883, 869, 1142 }, - { 277, 1111, 707, 1362, 1089, 672, 1603, 1541, 1545, 1291 }, - { 214, 781, 1609, 1303, 1632, 2229, 726, 1560, 1713, 918 }, - { 152, 1037, 1046, 1759, 1983, 2174, 1358, 742, 1740, 1390 }, - { 512, 1046, 1420, 753, 752, 1297, 1486, 1613, 460, 1207 }, - { 424, 827, 1362, 719, 1462, 1202, 1199, 1476, 1199, 538 } }, - { { 240, 402, 1134, 1491, 1659, 1505, 1517, 1555, 1979, 2099 }, - { 467, 242, 960, 1232, 1714, 1620, 1834, 1570, 1676, 1391 }, - { 500, 455, 463, 1507, 1699, 1282, 1564, 982, 2114, 2114 }, - { 672, 643, 1372, 331, 1589, 1667, 1453, 1938, 996, 876 }, - { 458, 783, 1037, 911, 738, 968, 1165, 1518, 859, 1033 }, - { 504, 815, 504, 1139, 1219, 719, 1506, 1085, 1268, 1268 }, - { 333, 630, 1445, 1239, 1883, 3672, 799, 1548, 1865, 598 }, - { 399, 644, 746, 1342, 1856, 1350, 1493, 613, 1855, 1015 }, - { 622, 749, 1205, 608, 1066, 1408, 1290, 1406, 546, 971 }, - { 500, 753, 1041, 668, 1230, 1617, 1297, 1425, 1383, 523 } }, - { { 394, 553, 523, 1502, 1536, 981, 1608, 1142, 1666, 2181 }, - { 655, 430, 375, 1411, 1861, 1220, 1677, 1135, 1978, 1553 }, - { 690, 640, 245, 1954, 2070, 1194, 1528, 982, 1972, 2232 }, - { 559, 834, 741, 867, 1131, 980, 1225, 852, 1092, 784 }, - { 690, 875, 516, 959, 673, 894, 1056, 1190, 1528, 1126 }, - { 740, 951, 384, 1277, 1177, 492, 1579, 1155, 1846, 1513 }, - { 323, 775, 1062, 1776, 3062, 1274, 813, 1188, 1372, 655 }, - { 488, 971, 484, 1767, 1515, 1775, 1115, 503, 1539, 1461 }, - { 740, 1006, 998, 709, 851, 1230, 1337, 788, 741, 721 }, - { 522, 1073, 573, 1045, 1346, 887, 1046, 1146, 1203, 697 } }, - { { 105, 864, 1442, 1009, 1934, 1840, 1519, 1920, 1673, 1579 }, - { 534, 305, 1193, 683, 1388, 2164, 1802, 1894, 1264, 1170 }, - { 305, 518, 877, 1108, 1426, 3215, 1425, 1064, 1320, 1242 }, - { 683, 732, 1927, 257, 1493, 2048, 1858, 1552, 1055, 947 }, - { 394, 814, 1024, 660, 959, 1556, 1282, 1289, 893, 1047 }, - { 528, 615, 996, 940, 1201, 635, 1094, 2515, 803, 1358 }, - { 347, 614, 1609, 1187, 3133, 1345, 1007, 1339, 1017, 667 }, - { 218, 740, 878, 1605, 3650, 3650, 1345, 758, 1357, 1617 }, - { 672, 750, 1541, 558, 1257, 1599, 1870, 2135, 402, 1087 }, - { 592, 684, 1161, 430, 1092, 1497, 1475, 1489, 1095, 822 } }, - { { 228, 1056, 1059, 1368, 752, 982, 1512, 1518, 987, 1782 }, - { 494, 514, 818, 942, 965, 892, 1610, 1356, 1048, 1363 }, - { 512, 648, 591, 1042, 761, 991, 1196, 1454, 1309, 1463 }, - { 683, 749, 1043, 676, 841, 1396, 1133, 1138, 654, 939 }, - { 622, 1101, 1126, 994, 361, 1077, 1203, 1318, 877, 1219 }, - { 631, 1068, 857, 1650, 651, 477, 1650, 1419, 828, 1170 }, - { 555, 727, 1068, 1335, 3127, 1339, 820, 1331, 1077, 429 }, - { 504, 879, 624, 1398, 889, 889, 1392, 808, 891, 1406 }, - { 683, 1602, 1289, 977, 578, 983, 1280, 1708, 406, 1122 }, - { 399, 865, 1433, 1070, 1072, 764, 968, 1477, 1223, 678 } }, - { { 333, 760, 935, 1638, 1010, 529, 1646, 1410, 1472, 2219 }, - { 512, 494, 750, 1160, 1215, 610, 1870, 1868, 1628, 1169 }, - { 572, 646, 492, 1934, 1208, 603, 1580, 1099, 1398, 1995 }, - { 786, 789, 942, 581, 1018, 951, 1599, 1207, 731, 768 }, - { 690, 1015, 672, 1078, 582, 504, 1693, 1438, 1108, 2897 }, - { 768, 1267, 571, 2005, 1243, 244, 2881, 1380, 1786, 1453 }, - { 452, 899, 1293, 903, 1311, 3100, 465, 1311, 1319, 813 }, - { 394, 927, 942, 1103, 1358, 1104, 946, 593, 1363, 1109 }, - { 559, 1005, 1007, 1016, 658, 1173, 1021, 1164, 623, 1028 }, - { 564, 796, 632, 1005, 1014, 863, 2316, 1268, 938, 764 } }, - { { 266, 606, 1098, 1228, 1497, 1243, 948, 1030, 1734, 1461 }, - { 366, 585, 901, 1060, 1407, 1247, 876, 1134, 1620, 1054 }, - { 452, 565, 542, 1729, 1479, 1479, 1016, 886, 2938, 1150 }, - { 555, 1088, 1533, 950, 1354, 895, 834, 1019, 1021, 496 }, - { 704, 815, 1193, 971, 973, 640, 1217, 2214, 832, 578 }, - { 672, 1245, 579, 871, 875, 774, 872, 1273, 1027, 949 }, - { 296, 1134, 2050, 1784, 1636, 3425, 442, 1550, 2076, 722 }, - { 342, 982, 1259, 1846, 1848, 1848, 622, 568, 1847, 1052 }, - { 555, 1064, 1304, 828, 746, 1343, 1075, 1329, 1078, 494 }, - { 288, 1167, 1285, 1174, 1639, 1639, 833, 2254, 1304, 509 } }, - { { 342, 719, 767, 1866, 1757, 1270, 1246, 550, 1746, 2151 }, - { 483, 653, 694, 1509, 1459, 1410, 1218, 507, 1914, 1266 }, - { 488, 757, 447, 2979, 1813, 1268, 1654, 539, 1849, 2109 }, - { 522, 1097, 1085, 851, 1365, 1111, 851, 901, 961, 605 }, - { 709, 716, 841, 728, 736, 945, 941, 862, 2845, 1057 }, - { 512, 1323, 500, 1336, 1083, 681, 1342, 717, 1604, 1350 }, - { 452, 1155, 1372, 1900, 1501, 3290, 311, 944, 1919, 922 }, - { 403, 1520, 977, 2132, 1733, 3522, 1076, 276, 3335, 1547 }, - { 559, 1374, 1101, 615, 673, 2462, 974, 795, 984, 984 }, - { 547, 1122, 1062, 812, 1410, 951, 1140, 622, 1268, 651 } }, - { { 165, 982, 1235, 938, 1334, 1366, 1659, 1578, 964, 1612 }, - { 592, 422, 925, 847, 1139, 1112, 1387, 2036, 861, 1041 }, - { 403, 837, 732, 770, 941, 1658, 1250, 809, 1407, 1407 }, - { 896, 874, 1071, 381, 1568, 1722, 1437, 2192, 480, 1035 }, - { 640, 1098, 1012, 1032, 684, 1382, 1581, 2106, 416, 865 }, - { 559, 1005, 819, 914, 710, 770, 1418, 920, 838, 1435 }, - { 415, 1258, 1245, 870, 1278, 3067, 770, 1021, 1287, 522 }, - { 406, 990, 601, 1009, 1265, 1265, 1267, 759, 1017, 1277 }, - { 968, 1182, 1329, 788, 1032, 1292, 1705, 1714, 203, 1403 }, - { 732, 877, 1279, 471, 901, 1161, 1545, 1294, 755, 755 } }, - { { 111, 931, 1378, 1185, 1933, 1648, 1148, 1714, 1873, 1307 }, - { 406, 414, 1030, 1023, 1910, 1404, 1313, 1647, 1509, 793 }, - { 342, 640, 575, 1088, 1241, 1349, 1161, 1350, 1756, 1502 }, - { 559, 766, 1185, 357, 1682, 1428, 1329, 1897, 1219, 802 }, - { 473, 909, 1164, 771, 719, 2508, 1427, 1432, 722, 782 }, - { 342, 892, 785, 1145, 1150, 794, 1296, 1550, 973, 1057 }, - { 208, 1036, 1326, 1343, 1606, 3395, 815, 1455, 1618, 712 }, - { 228, 928, 890, 1046, 3499, 1711, 994, 829, 1720, 1318 }, - { 768, 724, 1058, 636, 991, 1075, 1319, 1324, 616, 825 }, - { 305, 1167, 1358, 899, 1587, 1587, 987, 1988, 1332, 501 } } -}; - -//------------------------------------------------------------------------------ -// helper functions for residuals struct VP8Residual. - -void VP8InitResidual(int first, int coeff_type, - VP8Encoder* const enc, VP8Residual* const res) { - res->coeff_type = coeff_type; - res->prob = enc->proba_.coeffs_[coeff_type]; - res->stats = enc->proba_.stats_[coeff_type]; - res->costs = enc->proba_.remapped_costs_[coeff_type]; - res->first = first; -} - -//------------------------------------------------------------------------------ -// Mode costs - -int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]) { - const int x = (it->i4_ & 3), y = (it->i4_ >> 2); - VP8Residual res; - VP8Encoder* const enc = it->enc_; - int R = 0; - int ctx; - - VP8InitResidual(0, 3, enc, &res); - ctx = it->top_nz_[x] + it->left_nz_[y]; - VP8SetResidualCoeffs(levels, &res); - R += VP8GetResidualCost(ctx, &res); - return R; -} - -int VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd) { - VP8Residual res; - VP8Encoder* const enc = it->enc_; - int x, y; - int R = 0; - - VP8IteratorNzToBytes(it); // re-import the non-zero context - - // DC - VP8InitResidual(0, 1, enc, &res); - VP8SetResidualCoeffs(rd->y_dc_levels, &res); - R += VP8GetResidualCost(it->top_nz_[8] + it->left_nz_[8], &res); - - // AC - VP8InitResidual(1, 0, enc, &res); - for (y = 0; y < 4; ++y) { - for (x = 0; x < 4; ++x) { - const int ctx = it->top_nz_[x] + it->left_nz_[y]; - VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); - R += VP8GetResidualCost(ctx, &res); - it->top_nz_[x] = it->left_nz_[y] = (res.last >= 0); - } - } - return R; -} - -int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd) { - VP8Residual res; - VP8Encoder* const enc = it->enc_; - int ch, x, y; - int R = 0; - - VP8IteratorNzToBytes(it); // re-import the non-zero context - - VP8InitResidual(0, 2, enc, &res); - for (ch = 0; ch <= 2; ch += 2) { - for (y = 0; y < 2; ++y) { - for (x = 0; x < 2; ++x) { - const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; - VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); - R += VP8GetResidualCost(ctx, &res); - it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = (res.last >= 0); - } - } - } - return R; -} - - -//------------------------------------------------------------------------------ -// Recording of token probabilities. - -// Record proba context used -static int Record(int bit, proba_t* const stats) { - proba_t p = *stats; - if (p >= 0xffff0000u) { // an overflow is inbound. - p = ((p + 1u) >> 1) & 0x7fff7fffu; // -> divide the stats by 2. - } - // record bit count (lower 16 bits) and increment total count (upper 16 bits). - p += 0x00010000u + bit; - *stats = p; - return bit; -} - -// We keep the table-free variant around for reference, in case. -#define USE_LEVEL_CODE_TABLE - -// Simulate block coding, but only record statistics. -// Note: no need to record the fixed probas. -int VP8RecordCoeffs(int ctx, const VP8Residual* const res) { - int n = res->first; - // should be stats[VP8EncBands[n]], but it's equivalent for n=0 or 1 - proba_t* s = res->stats[n][ctx]; - if (res->last < 0) { - Record(0, s + 0); - return 0; - } - while (n <= res->last) { - int v; - Record(1, s + 0); // order of record doesn't matter - while ((v = res->coeffs[n++]) == 0) { - Record(0, s + 1); - s = res->stats[VP8EncBands[n]][0]; - } - Record(1, s + 1); - if (!Record(2u < (unsigned int)(v + 1), s + 2)) { // v = -1 or 1 - s = res->stats[VP8EncBands[n]][1]; - } else { - v = abs(v); -#if !defined(USE_LEVEL_CODE_TABLE) - if (!Record(v > 4, s + 3)) { - if (Record(v != 2, s + 4)) - Record(v == 4, s + 5); - } else if (!Record(v > 10, s + 6)) { - Record(v > 6, s + 7); - } else if (!Record((v >= 3 + (8 << 2)), s + 8)) { - Record((v >= 3 + (8 << 1)), s + 9); - } else { - Record((v >= 3 + (8 << 3)), s + 10); - } -#else - if (v > MAX_VARIABLE_LEVEL) { - v = MAX_VARIABLE_LEVEL; - } - - { - const int bits = VP8LevelCodes[v - 1][1]; - int pattern = VP8LevelCodes[v - 1][0]; - int i; - for (i = 0; (pattern >>= 1) != 0; ++i) { - const int mask = 2 << i; - if (pattern & 1) Record(!!(bits & mask), s + 3 + i); - } - } -#endif - s = res->stats[VP8EncBands[n]][2]; - } - } - if (n < 16) Record(0, s + 0); - return 1; -} - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/enc/cost.h b/Example/Pods/libwebp/src/enc/cost.h deleted file mode 100644 index 20960d6d..00000000 --- a/Example/Pods/libwebp/src/enc/cost.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Cost tables for level and modes. -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_ENC_COST_H_ -#define WEBP_ENC_COST_H_ - -#include -#include -#include "./vp8enci.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// On-the-fly info about the current set of residuals. Handy to avoid -// passing zillions of params. -typedef struct VP8Residual VP8Residual; -struct VP8Residual { - int first; - int last; - const int16_t* coeffs; - - int coeff_type; - ProbaArray* prob; - StatsArray* stats; - CostArrayPtr costs; -}; - -void VP8InitResidual(int first, int coeff_type, - VP8Encoder* const enc, VP8Residual* const res); - -int VP8RecordCoeffs(int ctx, const VP8Residual* const res); - -// Cost of coding one event with probability 'proba'. -static WEBP_INLINE int VP8BitCost(int bit, uint8_t proba) { - return !bit ? VP8EntropyCost[proba] : VP8EntropyCost[255 - proba]; -} - -// Level cost calculations -extern const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2]; -void VP8CalculateLevelCosts(VP8EncProba* const proba); -static WEBP_INLINE int VP8LevelCost(const uint16_t* const table, int level) { - return VP8LevelFixedCosts[level] - + table[(level > MAX_VARIABLE_LEVEL) ? MAX_VARIABLE_LEVEL : level]; -} - -// Mode costs -extern const uint16_t VP8FixedCostsUV[4]; -extern const uint16_t VP8FixedCostsI16[4]; -extern const uint16_t VP8FixedCostsI4[NUM_BMODES][NUM_BMODES][NUM_BMODES]; - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_ENC_COST_H_ */ diff --git a/Example/Pods/libwebp/src/enc/delta_palettization.c b/Example/Pods/libwebp/src/enc/delta_palettization.c deleted file mode 100644 index 062e588d..00000000 --- a/Example/Pods/libwebp/src/enc/delta_palettization.c +++ /dev/null @@ -1,455 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Mislav Bradac (mislavm@google.com) -// - -#include "./delta_palettization.h" - -#ifdef WEBP_EXPERIMENTAL_FEATURES -#include "../webp/types.h" -#include "../dsp/lossless.h" - -#define MK_COL(r, g, b) (((r) << 16) + ((g) << 8) + (b)) - -// Format allows palette up to 256 entries, but more palette entries produce -// bigger entropy. In the future it will probably be useful to add more entries -// that are far from the origin of the palette or choose remaining entries -// dynamically. -#define DELTA_PALETTE_SIZE 226 - -// Palette used for delta_palettization. Entries are roughly sorted by distance -// of their signed equivalents from the origin. -static const uint32_t kDeltaPalette[DELTA_PALETTE_SIZE] = { - MK_COL(0u, 0u, 0u), - MK_COL(255u, 255u, 255u), - MK_COL(1u, 1u, 1u), - MK_COL(254u, 254u, 254u), - MK_COL(2u, 2u, 2u), - MK_COL(4u, 4u, 4u), - MK_COL(252u, 252u, 252u), - MK_COL(250u, 0u, 0u), - MK_COL(0u, 250u, 0u), - MK_COL(0u, 0u, 250u), - MK_COL(6u, 0u, 0u), - MK_COL(0u, 6u, 0u), - MK_COL(0u, 0u, 6u), - MK_COL(0u, 0u, 248u), - MK_COL(0u, 0u, 8u), - MK_COL(0u, 248u, 0u), - MK_COL(0u, 248u, 248u), - MK_COL(0u, 248u, 8u), - MK_COL(0u, 8u, 0u), - MK_COL(0u, 8u, 248u), - MK_COL(0u, 8u, 8u), - MK_COL(8u, 8u, 8u), - MK_COL(248u, 0u, 0u), - MK_COL(248u, 0u, 248u), - MK_COL(248u, 0u, 8u), - MK_COL(248u, 248u, 0u), - MK_COL(248u, 8u, 0u), - MK_COL(8u, 0u, 0u), - MK_COL(8u, 0u, 248u), - MK_COL(8u, 0u, 8u), - MK_COL(8u, 248u, 0u), - MK_COL(8u, 8u, 0u), - MK_COL(23u, 23u, 23u), - MK_COL(13u, 13u, 13u), - MK_COL(232u, 232u, 232u), - MK_COL(244u, 244u, 244u), - MK_COL(245u, 245u, 250u), - MK_COL(50u, 50u, 50u), - MK_COL(204u, 204u, 204u), - MK_COL(236u, 236u, 236u), - MK_COL(16u, 16u, 16u), - MK_COL(240u, 16u, 16u), - MK_COL(16u, 240u, 16u), - MK_COL(240u, 240u, 16u), - MK_COL(16u, 16u, 240u), - MK_COL(240u, 16u, 240u), - MK_COL(16u, 240u, 240u), - MK_COL(240u, 240u, 240u), - MK_COL(0u, 0u, 232u), - MK_COL(0u, 232u, 0u), - MK_COL(232u, 0u, 0u), - MK_COL(0u, 0u, 24u), - MK_COL(0u, 24u, 0u), - MK_COL(24u, 0u, 0u), - MK_COL(32u, 32u, 32u), - MK_COL(224u, 32u, 32u), - MK_COL(32u, 224u, 32u), - MK_COL(224u, 224u, 32u), - MK_COL(32u, 32u, 224u), - MK_COL(224u, 32u, 224u), - MK_COL(32u, 224u, 224u), - MK_COL(224u, 224u, 224u), - MK_COL(0u, 0u, 176u), - MK_COL(0u, 0u, 80u), - MK_COL(0u, 176u, 0u), - MK_COL(0u, 176u, 176u), - MK_COL(0u, 176u, 80u), - MK_COL(0u, 80u, 0u), - MK_COL(0u, 80u, 176u), - MK_COL(0u, 80u, 80u), - MK_COL(176u, 0u, 0u), - MK_COL(176u, 0u, 176u), - MK_COL(176u, 0u, 80u), - MK_COL(176u, 176u, 0u), - MK_COL(176u, 80u, 0u), - MK_COL(80u, 0u, 0u), - MK_COL(80u, 0u, 176u), - MK_COL(80u, 0u, 80u), - MK_COL(80u, 176u, 0u), - MK_COL(80u, 80u, 0u), - MK_COL(0u, 0u, 152u), - MK_COL(0u, 0u, 104u), - MK_COL(0u, 152u, 0u), - MK_COL(0u, 152u, 152u), - MK_COL(0u, 152u, 104u), - MK_COL(0u, 104u, 0u), - MK_COL(0u, 104u, 152u), - MK_COL(0u, 104u, 104u), - MK_COL(152u, 0u, 0u), - MK_COL(152u, 0u, 152u), - MK_COL(152u, 0u, 104u), - MK_COL(152u, 152u, 0u), - MK_COL(152u, 104u, 0u), - MK_COL(104u, 0u, 0u), - MK_COL(104u, 0u, 152u), - MK_COL(104u, 0u, 104u), - MK_COL(104u, 152u, 0u), - MK_COL(104u, 104u, 0u), - MK_COL(216u, 216u, 216u), - MK_COL(216u, 216u, 40u), - MK_COL(216u, 216u, 176u), - MK_COL(216u, 216u, 80u), - MK_COL(216u, 40u, 216u), - MK_COL(216u, 40u, 40u), - MK_COL(216u, 40u, 176u), - MK_COL(216u, 40u, 80u), - MK_COL(216u, 176u, 216u), - MK_COL(216u, 176u, 40u), - MK_COL(216u, 176u, 176u), - MK_COL(216u, 176u, 80u), - MK_COL(216u, 80u, 216u), - MK_COL(216u, 80u, 40u), - MK_COL(216u, 80u, 176u), - MK_COL(216u, 80u, 80u), - MK_COL(40u, 216u, 216u), - MK_COL(40u, 216u, 40u), - MK_COL(40u, 216u, 176u), - MK_COL(40u, 216u, 80u), - MK_COL(40u, 40u, 216u), - MK_COL(40u, 40u, 40u), - MK_COL(40u, 40u, 176u), - MK_COL(40u, 40u, 80u), - MK_COL(40u, 176u, 216u), - MK_COL(40u, 176u, 40u), - MK_COL(40u, 176u, 176u), - MK_COL(40u, 176u, 80u), - MK_COL(40u, 80u, 216u), - MK_COL(40u, 80u, 40u), - MK_COL(40u, 80u, 176u), - MK_COL(40u, 80u, 80u), - MK_COL(80u, 216u, 216u), - MK_COL(80u, 216u, 40u), - MK_COL(80u, 216u, 176u), - MK_COL(80u, 216u, 80u), - MK_COL(80u, 40u, 216u), - MK_COL(80u, 40u, 40u), - MK_COL(80u, 40u, 176u), - MK_COL(80u, 40u, 80u), - MK_COL(80u, 176u, 216u), - MK_COL(80u, 176u, 40u), - MK_COL(80u, 176u, 176u), - MK_COL(80u, 176u, 80u), - MK_COL(80u, 80u, 216u), - MK_COL(80u, 80u, 40u), - MK_COL(80u, 80u, 176u), - MK_COL(80u, 80u, 80u), - MK_COL(0u, 0u, 192u), - MK_COL(0u, 0u, 64u), - MK_COL(0u, 0u, 128u), - MK_COL(0u, 192u, 0u), - MK_COL(0u, 192u, 192u), - MK_COL(0u, 192u, 64u), - MK_COL(0u, 192u, 128u), - MK_COL(0u, 64u, 0u), - MK_COL(0u, 64u, 192u), - MK_COL(0u, 64u, 64u), - MK_COL(0u, 64u, 128u), - MK_COL(0u, 128u, 0u), - MK_COL(0u, 128u, 192u), - MK_COL(0u, 128u, 64u), - MK_COL(0u, 128u, 128u), - MK_COL(176u, 216u, 216u), - MK_COL(176u, 216u, 40u), - MK_COL(176u, 216u, 176u), - MK_COL(176u, 216u, 80u), - MK_COL(176u, 40u, 216u), - MK_COL(176u, 40u, 40u), - MK_COL(176u, 40u, 176u), - MK_COL(176u, 40u, 80u), - MK_COL(176u, 176u, 216u), - MK_COL(176u, 176u, 40u), - MK_COL(176u, 176u, 176u), - MK_COL(176u, 176u, 80u), - MK_COL(176u, 80u, 216u), - MK_COL(176u, 80u, 40u), - MK_COL(176u, 80u, 176u), - MK_COL(176u, 80u, 80u), - MK_COL(192u, 0u, 0u), - MK_COL(192u, 0u, 192u), - MK_COL(192u, 0u, 64u), - MK_COL(192u, 0u, 128u), - MK_COL(192u, 192u, 0u), - MK_COL(192u, 192u, 192u), - MK_COL(192u, 192u, 64u), - MK_COL(192u, 192u, 128u), - MK_COL(192u, 64u, 0u), - MK_COL(192u, 64u, 192u), - MK_COL(192u, 64u, 64u), - MK_COL(192u, 64u, 128u), - MK_COL(192u, 128u, 0u), - MK_COL(192u, 128u, 192u), - MK_COL(192u, 128u, 64u), - MK_COL(192u, 128u, 128u), - MK_COL(64u, 0u, 0u), - MK_COL(64u, 0u, 192u), - MK_COL(64u, 0u, 64u), - MK_COL(64u, 0u, 128u), - MK_COL(64u, 192u, 0u), - MK_COL(64u, 192u, 192u), - MK_COL(64u, 192u, 64u), - MK_COL(64u, 192u, 128u), - MK_COL(64u, 64u, 0u), - MK_COL(64u, 64u, 192u), - MK_COL(64u, 64u, 64u), - MK_COL(64u, 64u, 128u), - MK_COL(64u, 128u, 0u), - MK_COL(64u, 128u, 192u), - MK_COL(64u, 128u, 64u), - MK_COL(64u, 128u, 128u), - MK_COL(128u, 0u, 0u), - MK_COL(128u, 0u, 192u), - MK_COL(128u, 0u, 64u), - MK_COL(128u, 0u, 128u), - MK_COL(128u, 192u, 0u), - MK_COL(128u, 192u, 192u), - MK_COL(128u, 192u, 64u), - MK_COL(128u, 192u, 128u), - MK_COL(128u, 64u, 0u), - MK_COL(128u, 64u, 192u), - MK_COL(128u, 64u, 64u), - MK_COL(128u, 64u, 128u), - MK_COL(128u, 128u, 0u), - MK_COL(128u, 128u, 192u), - MK_COL(128u, 128u, 64u), - MK_COL(128u, 128u, 128u), -}; - -#undef MK_COL - -//------------------------------------------------------------------------------ -// TODO(skal): move the functions to dsp/lossless.c when the correct -// granularity is found. For now, we'll just copy-paste some useful bits -// here instead. - -// In-place sum of each component with mod 256. -static WEBP_INLINE void AddPixelsEq(uint32_t* a, uint32_t b) { - const uint32_t alpha_and_green = (*a & 0xff00ff00u) + (b & 0xff00ff00u); - const uint32_t red_and_blue = (*a & 0x00ff00ffu) + (b & 0x00ff00ffu); - *a = (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu); -} - -static WEBP_INLINE uint32_t Clip255(uint32_t a) { - if (a < 256) { - return a; - } - // return 0, when a is a negative integer. - // return 255, when a is positive. - return ~a >> 24; -} - -// Delta palettization functions. -static WEBP_INLINE int Square(int x) { - return x * x; -} - -static WEBP_INLINE uint32_t Intensity(uint32_t a) { - return - 30 * ((a >> 16) & 0xff) + - 59 * ((a >> 8) & 0xff) + - 11 * ((a >> 0) & 0xff); -} - -static uint32_t CalcDist(uint32_t predicted_value, uint32_t actual_value, - uint32_t palette_entry) { - int i; - uint32_t distance = 0; - AddPixelsEq(&predicted_value, palette_entry); - for (i = 0; i < 32; i += 8) { - const int32_t av = (actual_value >> i) & 0xff; - const int32_t pv = (predicted_value >> i) & 0xff; - distance += Square(pv - av); - } - // We sum square of intensity difference with factor 10, but because Intensity - // returns 100 times real intensity we need to multiply differences of colors - // by 1000. - distance *= 1000u; - distance += Square(Intensity(predicted_value) - - Intensity(actual_value)); - return distance; -} - -static uint32_t Predict(int x, int y, uint32_t* image) { - const uint32_t t = (y == 0) ? ARGB_BLACK : image[x]; - const uint32_t l = (x == 0) ? ARGB_BLACK : image[x - 1]; - const uint32_t p = - (((((t >> 24) & 0xff) + ((l >> 24) & 0xff)) / 2) << 24) + - (((((t >> 16) & 0xff) + ((l >> 16) & 0xff)) / 2) << 16) + - (((((t >> 8) & 0xff) + ((l >> 8) & 0xff)) / 2) << 8) + - (((((t >> 0) & 0xff) + ((l >> 0) & 0xff)) / 2) << 0); - if (x == 0 && y == 0) return ARGB_BLACK; - if (x == 0) return t; - if (y == 0) return l; - return p; -} - -static WEBP_INLINE int AddSubtractComponentFullWithCoefficient( - int a, int b, int c) { - return Clip255(a + ((b - c) >> 2)); -} - -static WEBP_INLINE uint32_t ClampedAddSubtractFullWithCoefficient( - uint32_t c0, uint32_t c1, uint32_t c2) { - const int a = AddSubtractComponentFullWithCoefficient( - c0 >> 24, c1 >> 24, c2 >> 24); - const int r = AddSubtractComponentFullWithCoefficient((c0 >> 16) & 0xff, - (c1 >> 16) & 0xff, - (c2 >> 16) & 0xff); - const int g = AddSubtractComponentFullWithCoefficient((c0 >> 8) & 0xff, - (c1 >> 8) & 0xff, - (c2 >> 8) & 0xff); - const int b = AddSubtractComponentFullWithCoefficient( - c0 & 0xff, c1 & 0xff, c2 & 0xff); - return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b; -} - -//------------------------------------------------------------------------------ - -// Find palette entry with minimum error from difference of actual pixel value -// and predicted pixel value. Propagate error of pixel to its top and left pixel -// in src array. Write predicted_value + palette_entry to new_image. Return -// index of best palette entry. -static int FindBestPaletteEntry(uint32_t src, uint32_t predicted_value, - const uint32_t palette[], int palette_size) { - int i; - int idx = 0; - uint32_t best_distance = CalcDist(predicted_value, src, palette[0]); - for (i = 1; i < palette_size; ++i) { - const uint32_t distance = CalcDist(predicted_value, src, palette[i]); - if (distance < best_distance) { - best_distance = distance; - idx = i; - } - } - return idx; -} - -static void ApplyBestPaletteEntry(int x, int y, - uint32_t new_value, uint32_t palette_value, - uint32_t* src, int src_stride, - uint32_t* new_image) { - AddPixelsEq(&new_value, palette_value); - if (x > 0) { - src[x - 1] = ClampedAddSubtractFullWithCoefficient(src[x - 1], - new_value, src[x]); - } - if (y > 0) { - src[x - src_stride] = - ClampedAddSubtractFullWithCoefficient(src[x - src_stride], - new_value, src[x]); - } - new_image[x] = new_value; -} - -//------------------------------------------------------------------------------ -// Main entry point - -static WebPEncodingError ApplyDeltaPalette(uint32_t* src, uint32_t* dst, - uint32_t src_stride, - uint32_t dst_stride, - const uint32_t* palette, - int palette_size, - int width, int height, - int num_passes) { - int x, y; - WebPEncodingError err = VP8_ENC_OK; - uint32_t* new_image = (uint32_t*)WebPSafeMalloc(width, sizeof(*new_image)); - uint8_t* const tmp_row = (uint8_t*)WebPSafeMalloc(width, sizeof(*tmp_row)); - if (new_image == NULL || tmp_row == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - while (num_passes--) { - uint32_t* cur_src = src; - uint32_t* cur_dst = dst; - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - const uint32_t predicted_value = Predict(x, y, new_image); - tmp_row[x] = FindBestPaletteEntry(cur_src[x], predicted_value, - palette, palette_size); - ApplyBestPaletteEntry(x, y, predicted_value, palette[tmp_row[x]], - cur_src, src_stride, new_image); - } - for (x = 0; x < width; ++x) { - cur_dst[x] = palette[tmp_row[x]]; - } - cur_src += src_stride; - cur_dst += dst_stride; - } - } - Error: - WebPSafeFree(new_image); - WebPSafeFree(tmp_row); - return err; -} - -// replaces enc->argb_ by a palettizable approximation of it, -// and generates optimal enc->palette_[] -WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc) { - const WebPPicture* const pic = enc->pic_; - uint32_t* src = pic->argb; - uint32_t* dst = enc->argb_; - const int width = pic->width; - const int height = pic->height; - - WebPEncodingError err = VP8_ENC_OK; - memcpy(enc->palette_, kDeltaPalette, sizeof(kDeltaPalette)); - enc->palette_[DELTA_PALETTE_SIZE - 1] = src[0] - 0xff000000u; - enc->palette_size_ = DELTA_PALETTE_SIZE; - err = ApplyDeltaPalette(src, dst, pic->argb_stride, enc->current_width_, - enc->palette_, enc->palette_size_, - width, height, 2); - if (err != VP8_ENC_OK) goto Error; - - Error: - return err; -} - -#else // !WEBP_EXPERIMENTAL_FEATURES - -WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc) { - (void)enc; - return VP8_ENC_ERROR_INVALID_CONFIGURATION; -} - -#endif // WEBP_EXPERIMENTAL_FEATURES diff --git a/Example/Pods/libwebp/src/enc/delta_palettization.h b/Example/Pods/libwebp/src/enc/delta_palettization.h deleted file mode 100644 index e41c0c5a..00000000 --- a/Example/Pods/libwebp/src/enc/delta_palettization.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Mislav Bradac (mislavm@google.com) -// - -#ifndef WEBP_ENC_DELTA_PALETTIZATION_H_ -#define WEBP_ENC_DELTA_PALETTIZATION_H_ - -#include "../webp/encode.h" -#include "../enc/vp8li.h" - -// Replaces enc->argb_[] input by a palettizable approximation of it, -// and generates optimal enc->palette_[]. -// This function can revert enc->use_palette_ / enc->use_predict_ flag -// if delta-palettization is not producing expected saving. -WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc); - -#endif // WEBP_ENC_DELTA_PALETTIZATION_H_ diff --git a/Example/Pods/libwebp/src/enc/filter.c b/Example/Pods/libwebp/src/enc/filter.c deleted file mode 100644 index 41813cff..00000000 --- a/Example/Pods/libwebp/src/enc/filter.c +++ /dev/null @@ -1,299 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Selecting filter level -// -// Author: somnath@google.com (Somnath Banerjee) - -#include -#include "./vp8enci.h" -#include "../dsp/dsp.h" - -// This table gives, for a given sharpness, the filtering strength to be -// used (at least) in order to filter a given edge step delta. -// This is constructed by brute force inspection: for all delta, we iterate -// over all possible filtering strength / thresh until needs_filter() returns -// true. -#define MAX_DELTA_SIZE 64 -static const uint8_t kLevelsFromDelta[8][MAX_DELTA_SIZE] = { - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 }, - { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 17, 18, - 20, 21, 23, 24, 26, 27, 29, 30, 32, 33, 35, 36, 38, 39, 41, 42, - 44, 45, 47, 48, 50, 51, 53, 54, 56, 57, 59, 60, 62, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, - { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 14, 16, 17, 19, - 20, 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, 37, 38, 40, 41, 43, - 44, 46, 47, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, - { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 18, 19, - 21, 22, 24, 25, 27, 28, 30, 31, 33, 34, 36, 37, 39, 40, 42, 43, - 45, 46, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, - { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 14, 15, 17, 18, 20, - 21, 23, 24, 26, 27, 29, 30, 32, 33, 35, 36, 38, 39, 41, 42, 44, - 45, 47, 48, 50, 51, 53, 54, 56, 57, 59, 60, 62, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, - { 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 17, 19, 20, - 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, 37, 38, 40, 41, 43, 44, - 46, 47, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, - { 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 18, 19, 21, - 22, 24, 25, 27, 28, 30, 31, 33, 34, 36, 37, 39, 40, 42, 43, 45, - 46, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, - { 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 14, 15, 17, 18, 20, 21, - 23, 24, 26, 27, 29, 30, 32, 33, 35, 36, 38, 39, 41, 42, 44, 45, - 47, 48, 50, 51, 53, 54, 56, 57, 59, 60, 62, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 } -}; - -int VP8FilterStrengthFromDelta(int sharpness, int delta) { - const int pos = (delta < MAX_DELTA_SIZE) ? delta : MAX_DELTA_SIZE - 1; - assert(sharpness >= 0 && sharpness <= 7); - return kLevelsFromDelta[sharpness][pos]; -} - -//------------------------------------------------------------------------------ -// Paragraph 15.4: compute the inner-edge filtering strength - -static int GetILevel(int sharpness, int level) { - if (sharpness > 0) { - if (sharpness > 4) { - level >>= 2; - } else { - level >>= 1; - } - if (level > 9 - sharpness) { - level = 9 - sharpness; - } - } - if (level < 1) level = 1; - return level; -} - -static void DoFilter(const VP8EncIterator* const it, int level) { - const VP8Encoder* const enc = it->enc_; - const int ilevel = GetILevel(enc->config_->filter_sharpness, level); - const int limit = 2 * level + ilevel; - - uint8_t* const y_dst = it->yuv_out2_ + Y_OFF_ENC; - uint8_t* const u_dst = it->yuv_out2_ + U_OFF_ENC; - uint8_t* const v_dst = it->yuv_out2_ + V_OFF_ENC; - - // copy current block to yuv_out2_ - memcpy(y_dst, it->yuv_out_, YUV_SIZE_ENC * sizeof(uint8_t)); - - if (enc->filter_hdr_.simple_ == 1) { // simple - VP8SimpleHFilter16i(y_dst, BPS, limit); - VP8SimpleVFilter16i(y_dst, BPS, limit); - } else { // complex - const int hev_thresh = (level >= 40) ? 2 : (level >= 15) ? 1 : 0; - VP8HFilter16i(y_dst, BPS, limit, ilevel, hev_thresh); - VP8HFilter8i(u_dst, v_dst, BPS, limit, ilevel, hev_thresh); - VP8VFilter16i(y_dst, BPS, limit, ilevel, hev_thresh); - VP8VFilter8i(u_dst, v_dst, BPS, limit, ilevel, hev_thresh); - } -} - -//------------------------------------------------------------------------------ -// SSIM metric - -enum { KERNEL = 3 }; -static const double kMinValue = 1.e-10; // minimal threshold - -void VP8SSIMAddStats(const DistoStats* const src, DistoStats* const dst) { - dst->w += src->w; - dst->xm += src->xm; - dst->ym += src->ym; - dst->xxm += src->xxm; - dst->xym += src->xym; - dst->yym += src->yym; -} - -static void VP8SSIMAccumulate(const uint8_t* src1, int stride1, - const uint8_t* src2, int stride2, - int xo, int yo, int W, int H, - DistoStats* const stats) { - const int ymin = (yo - KERNEL < 0) ? 0 : yo - KERNEL; - const int ymax = (yo + KERNEL > H - 1) ? H - 1 : yo + KERNEL; - const int xmin = (xo - KERNEL < 0) ? 0 : xo - KERNEL; - const int xmax = (xo + KERNEL > W - 1) ? W - 1 : xo + KERNEL; - int x, y; - src1 += ymin * stride1; - src2 += ymin * stride2; - for (y = ymin; y <= ymax; ++y, src1 += stride1, src2 += stride2) { - for (x = xmin; x <= xmax; ++x) { - const int s1 = src1[x]; - const int s2 = src2[x]; - stats->w += 1; - stats->xm += s1; - stats->ym += s2; - stats->xxm += s1 * s1; - stats->xym += s1 * s2; - stats->yym += s2 * s2; - } - } -} - -double VP8SSIMGet(const DistoStats* const stats) { - const double xmxm = stats->xm * stats->xm; - const double ymym = stats->ym * stats->ym; - const double xmym = stats->xm * stats->ym; - const double w2 = stats->w * stats->w; - double sxx = stats->xxm * stats->w - xmxm; - double syy = stats->yym * stats->w - ymym; - double sxy = stats->xym * stats->w - xmym; - double C1, C2; - double fnum; - double fden; - // small errors are possible, due to rounding. Clamp to zero. - if (sxx < 0.) sxx = 0.; - if (syy < 0.) syy = 0.; - C1 = 6.5025 * w2; - C2 = 58.5225 * w2; - fnum = (2 * xmym + C1) * (2 * sxy + C2); - fden = (xmxm + ymym + C1) * (sxx + syy + C2); - return (fden != 0.) ? fnum / fden : kMinValue; -} - -double VP8SSIMGetSquaredError(const DistoStats* const s) { - if (s->w > 0.) { - const double iw2 = 1. / (s->w * s->w); - const double sxx = s->xxm * s->w - s->xm * s->xm; - const double syy = s->yym * s->w - s->ym * s->ym; - const double sxy = s->xym * s->w - s->xm * s->ym; - const double SSE = iw2 * (sxx + syy - 2. * sxy); - if (SSE > kMinValue) return SSE; - } - return kMinValue; -} - -void VP8SSIMAccumulatePlane(const uint8_t* src1, int stride1, - const uint8_t* src2, int stride2, - int W, int H, DistoStats* const stats) { - int x, y; - for (y = 0; y < H; ++y) { - for (x = 0; x < W; ++x) { - VP8SSIMAccumulate(src1, stride1, src2, stride2, x, y, W, H, stats); - } - } -} - -static double GetMBSSIM(const uint8_t* yuv1, const uint8_t* yuv2) { - int x, y; - DistoStats s = { .0, .0, .0, .0, .0, .0 }; - - // compute SSIM in a 10 x 10 window - for (x = 3; x < 13; x++) { - for (y = 3; y < 13; y++) { - VP8SSIMAccumulate(yuv1 + Y_OFF_ENC, BPS, yuv2 + Y_OFF_ENC, BPS, - x, y, 16, 16, &s); - } - } - for (x = 1; x < 7; x++) { - for (y = 1; y < 7; y++) { - VP8SSIMAccumulate(yuv1 + U_OFF_ENC, BPS, yuv2 + U_OFF_ENC, BPS, - x, y, 8, 8, &s); - VP8SSIMAccumulate(yuv1 + V_OFF_ENC, BPS, yuv2 + V_OFF_ENC, BPS, - x, y, 8, 8, &s); - } - } - return VP8SSIMGet(&s); -} - -//------------------------------------------------------------------------------ -// Exposed APIs: Encoder should call the following 3 functions to adjust -// loop filter strength - -void VP8InitFilter(VP8EncIterator* const it) { - if (it->lf_stats_ != NULL) { - int s, i; - for (s = 0; s < NUM_MB_SEGMENTS; s++) { - for (i = 0; i < MAX_LF_LEVELS; i++) { - (*it->lf_stats_)[s][i] = 0; - } - } - } -} - -void VP8StoreFilterStats(VP8EncIterator* const it) { - int d; - VP8Encoder* const enc = it->enc_; - const int s = it->mb_->segment_; - const int level0 = enc->dqm_[s].fstrength_; - - // explore +/-quant range of values around level0 - const int delta_min = -enc->dqm_[s].quant_; - const int delta_max = enc->dqm_[s].quant_; - const int step_size = (delta_max - delta_min >= 4) ? 4 : 1; - - if (it->lf_stats_ == NULL) return; - - // NOTE: Currently we are applying filter only across the sublock edges - // There are two reasons for that. - // 1. Applying filter on macro block edges will change the pixels in - // the left and top macro blocks. That will be hard to restore - // 2. Macro Blocks on the bottom and right are not yet compressed. So we - // cannot apply filter on the right and bottom macro block edges. - if (it->mb_->type_ == 1 && it->mb_->skip_) return; - - // Always try filter level zero - (*it->lf_stats_)[s][0] += GetMBSSIM(it->yuv_in_, it->yuv_out_); - - for (d = delta_min; d <= delta_max; d += step_size) { - const int level = level0 + d; - if (level <= 0 || level >= MAX_LF_LEVELS) { - continue; - } - DoFilter(it, level); - (*it->lf_stats_)[s][level] += GetMBSSIM(it->yuv_in_, it->yuv_out2_); - } -} - -void VP8AdjustFilterStrength(VP8EncIterator* const it) { - VP8Encoder* const enc = it->enc_; - if (it->lf_stats_ != NULL) { - int s; - for (s = 0; s < NUM_MB_SEGMENTS; s++) { - int i, best_level = 0; - // Improvement over filter level 0 should be at least 1e-5 (relatively) - double best_v = 1.00001 * (*it->lf_stats_)[s][0]; - for (i = 1; i < MAX_LF_LEVELS; i++) { - const double v = (*it->lf_stats_)[s][i]; - if (v > best_v) { - best_v = v; - best_level = i; - } - } - enc->dqm_[s].fstrength_ = best_level; - } - } else if (enc->config_->filter_strength > 0) { - int max_level = 0; - int s; - for (s = 0; s < NUM_MB_SEGMENTS; s++) { - VP8SegmentInfo* const dqm = &enc->dqm_[s]; - // this '>> 3' accounts for some inverse WHT scaling - const int delta = (dqm->max_edge_ * dqm->y2_.q_[1]) >> 3; - const int level = - VP8FilterStrengthFromDelta(enc->filter_hdr_.sharpness_, delta); - if (level > dqm->fstrength_) { - dqm->fstrength_ = level; - } - if (max_level < dqm->fstrength_) { - max_level = dqm->fstrength_; - } - } - enc->filter_hdr_.level_ = max_level; - } -} - -// ----------------------------------------------------------------------------- diff --git a/Example/Pods/libwebp/src/enc/frame.c b/Example/Pods/libwebp/src/enc/frame.c deleted file mode 100644 index 5b7a40b9..00000000 --- a/Example/Pods/libwebp/src/enc/frame.c +++ /dev/null @@ -1,850 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// frame coding and analysis -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include - -#include "./cost.h" -#include "./vp8enci.h" -#include "../dsp/dsp.h" -#include "../webp/format_constants.h" // RIFF constants - -#define SEGMENT_VISU 0 -#define DEBUG_SEARCH 0 // useful to track search convergence - -//------------------------------------------------------------------------------ -// multi-pass convergence - -#define HEADER_SIZE_ESTIMATE (RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + \ - VP8_FRAME_HEADER_SIZE) -#define DQ_LIMIT 0.4 // convergence is considered reached if dq < DQ_LIMIT -// we allow 2k of extra head-room in PARTITION0 limit. -#define PARTITION0_SIZE_LIMIT ((VP8_MAX_PARTITION0_SIZE - 2048ULL) << 11) - -typedef struct { // struct for organizing convergence in either size or PSNR - int is_first; - float dq; - float q, last_q; - double value, last_value; // PSNR or size - double target; - int do_size_search; -} PassStats; - -static int InitPassStats(const VP8Encoder* const enc, PassStats* const s) { - const uint64_t target_size = (uint64_t)enc->config_->target_size; - const int do_size_search = (target_size != 0); - const float target_PSNR = enc->config_->target_PSNR; - - s->is_first = 1; - s->dq = 10.f; - s->q = s->last_q = enc->config_->quality; - s->target = do_size_search ? (double)target_size - : (target_PSNR > 0.) ? target_PSNR - : 40.; // default, just in case - s->value = s->last_value = 0.; - s->do_size_search = do_size_search; - return do_size_search; -} - -static float Clamp(float v, float min, float max) { - return (v < min) ? min : (v > max) ? max : v; -} - -static float ComputeNextQ(PassStats* const s) { - float dq; - if (s->is_first) { - dq = (s->value > s->target) ? -s->dq : s->dq; - s->is_first = 0; - } else if (s->value != s->last_value) { - const double slope = (s->target - s->value) / (s->last_value - s->value); - dq = (float)(slope * (s->last_q - s->q)); - } else { - dq = 0.; // we're done?! - } - // Limit variable to avoid large swings. - s->dq = Clamp(dq, -30.f, 30.f); - s->last_q = s->q; - s->last_value = s->value; - s->q = Clamp(s->q + s->dq, 0.f, 100.f); - return s->q; -} - -//------------------------------------------------------------------------------ -// Tables for level coding - -const uint8_t VP8Cat3[] = { 173, 148, 140 }; -const uint8_t VP8Cat4[] = { 176, 155, 140, 135 }; -const uint8_t VP8Cat5[] = { 180, 157, 141, 134, 130 }; -const uint8_t VP8Cat6[] = - { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129 }; - -//------------------------------------------------------------------------------ -// Reset the statistics about: number of skips, token proba, level cost,... - -static void ResetStats(VP8Encoder* const enc) { - VP8EncProba* const proba = &enc->proba_; - VP8CalculateLevelCosts(proba); - proba->nb_skip_ = 0; -} - -//------------------------------------------------------------------------------ -// Skip decision probability - -#define SKIP_PROBA_THRESHOLD 250 // value below which using skip_proba is OK. - -static int CalcSkipProba(uint64_t nb, uint64_t total) { - return (int)(total ? (total - nb) * 255 / total : 255); -} - -// Returns the bit-cost for coding the skip probability. -static int FinalizeSkipProba(VP8Encoder* const enc) { - VP8EncProba* const proba = &enc->proba_; - const int nb_mbs = enc->mb_w_ * enc->mb_h_; - const int nb_events = proba->nb_skip_; - int size; - proba->skip_proba_ = CalcSkipProba(nb_events, nb_mbs); - proba->use_skip_proba_ = (proba->skip_proba_ < SKIP_PROBA_THRESHOLD); - size = 256; // 'use_skip_proba' bit - if (proba->use_skip_proba_) { - size += nb_events * VP8BitCost(1, proba->skip_proba_) - + (nb_mbs - nb_events) * VP8BitCost(0, proba->skip_proba_); - size += 8 * 256; // cost of signaling the skip_proba_ itself. - } - return size; -} - -// Collect statistics and deduce probabilities for next coding pass. -// Return the total bit-cost for coding the probability updates. -static int CalcTokenProba(int nb, int total) { - assert(nb <= total); - return nb ? (255 - nb * 255 / total) : 255; -} - -// Cost of coding 'nb' 1's and 'total-nb' 0's using 'proba' probability. -static int BranchCost(int nb, int total, int proba) { - return nb * VP8BitCost(1, proba) + (total - nb) * VP8BitCost(0, proba); -} - -static void ResetTokenStats(VP8Encoder* const enc) { - VP8EncProba* const proba = &enc->proba_; - memset(proba->stats_, 0, sizeof(proba->stats_)); -} - -static int FinalizeTokenProbas(VP8EncProba* const proba) { - int has_changed = 0; - int size = 0; - int t, b, c, p; - for (t = 0; t < NUM_TYPES; ++t) { - for (b = 0; b < NUM_BANDS; ++b) { - for (c = 0; c < NUM_CTX; ++c) { - for (p = 0; p < NUM_PROBAS; ++p) { - const proba_t stats = proba->stats_[t][b][c][p]; - const int nb = (stats >> 0) & 0xffff; - const int total = (stats >> 16) & 0xffff; - const int update_proba = VP8CoeffsUpdateProba[t][b][c][p]; - const int old_p = VP8CoeffsProba0[t][b][c][p]; - const int new_p = CalcTokenProba(nb, total); - const int old_cost = BranchCost(nb, total, old_p) - + VP8BitCost(0, update_proba); - const int new_cost = BranchCost(nb, total, new_p) - + VP8BitCost(1, update_proba) - + 8 * 256; - const int use_new_p = (old_cost > new_cost); - size += VP8BitCost(use_new_p, update_proba); - if (use_new_p) { // only use proba that seem meaningful enough. - proba->coeffs_[t][b][c][p] = new_p; - has_changed |= (new_p != old_p); - size += 8 * 256; - } else { - proba->coeffs_[t][b][c][p] = old_p; - } - } - } - } - } - proba->dirty_ = has_changed; - return size; -} - -//------------------------------------------------------------------------------ -// Finalize Segment probability based on the coding tree - -static int GetProba(int a, int b) { - const int total = a + b; - return (total == 0) ? 255 // that's the default probability. - : (255 * a + total / 2) / total; // rounded proba -} - -static void SetSegmentProbas(VP8Encoder* const enc) { - int p[NUM_MB_SEGMENTS] = { 0 }; - int n; - - for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { - const VP8MBInfo* const mb = &enc->mb_info_[n]; - p[mb->segment_]++; - } - if (enc->pic_->stats != NULL) { - for (n = 0; n < NUM_MB_SEGMENTS; ++n) { - enc->pic_->stats->segment_size[n] = p[n]; - } - } - if (enc->segment_hdr_.num_segments_ > 1) { - uint8_t* const probas = enc->proba_.segments_; - probas[0] = GetProba(p[0] + p[1], p[2] + p[3]); - probas[1] = GetProba(p[0], p[1]); - probas[2] = GetProba(p[2], p[3]); - - enc->segment_hdr_.update_map_ = - (probas[0] != 255) || (probas[1] != 255) || (probas[2] != 255); - enc->segment_hdr_.size_ = - p[0] * (VP8BitCost(0, probas[0]) + VP8BitCost(0, probas[1])) + - p[1] * (VP8BitCost(0, probas[0]) + VP8BitCost(1, probas[1])) + - p[2] * (VP8BitCost(1, probas[0]) + VP8BitCost(0, probas[2])) + - p[3] * (VP8BitCost(1, probas[0]) + VP8BitCost(1, probas[2])); - } else { - enc->segment_hdr_.update_map_ = 0; - enc->segment_hdr_.size_ = 0; - } -} - -//------------------------------------------------------------------------------ -// Coefficient coding - -static int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) { - int n = res->first; - // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 - const uint8_t* p = res->prob[n][ctx]; - if (!VP8PutBit(bw, res->last >= 0, p[0])) { - return 0; - } - - while (n < 16) { - const int c = res->coeffs[n++]; - const int sign = c < 0; - int v = sign ? -c : c; - if (!VP8PutBit(bw, v != 0, p[1])) { - p = res->prob[VP8EncBands[n]][0]; - continue; - } - if (!VP8PutBit(bw, v > 1, p[2])) { - p = res->prob[VP8EncBands[n]][1]; - } else { - if (!VP8PutBit(bw, v > 4, p[3])) { - if (VP8PutBit(bw, v != 2, p[4])) - VP8PutBit(bw, v == 4, p[5]); - } else if (!VP8PutBit(bw, v > 10, p[6])) { - if (!VP8PutBit(bw, v > 6, p[7])) { - VP8PutBit(bw, v == 6, 159); - } else { - VP8PutBit(bw, v >= 9, 165); - VP8PutBit(bw, !(v & 1), 145); - } - } else { - int mask; - const uint8_t* tab; - if (v < 3 + (8 << 1)) { // VP8Cat3 (3b) - VP8PutBit(bw, 0, p[8]); - VP8PutBit(bw, 0, p[9]); - v -= 3 + (8 << 0); - mask = 1 << 2; - tab = VP8Cat3; - } else if (v < 3 + (8 << 2)) { // VP8Cat4 (4b) - VP8PutBit(bw, 0, p[8]); - VP8PutBit(bw, 1, p[9]); - v -= 3 + (8 << 1); - mask = 1 << 3; - tab = VP8Cat4; - } else if (v < 3 + (8 << 3)) { // VP8Cat5 (5b) - VP8PutBit(bw, 1, p[8]); - VP8PutBit(bw, 0, p[10]); - v -= 3 + (8 << 2); - mask = 1 << 4; - tab = VP8Cat5; - } else { // VP8Cat6 (11b) - VP8PutBit(bw, 1, p[8]); - VP8PutBit(bw, 1, p[10]); - v -= 3 + (8 << 3); - mask = 1 << 10; - tab = VP8Cat6; - } - while (mask) { - VP8PutBit(bw, !!(v & mask), *tab++); - mask >>= 1; - } - } - p = res->prob[VP8EncBands[n]][2]; - } - VP8PutBitUniform(bw, sign); - if (n == 16 || !VP8PutBit(bw, n <= res->last, p[0])) { - return 1; // EOB - } - } - return 1; -} - -static void CodeResiduals(VP8BitWriter* const bw, VP8EncIterator* const it, - const VP8ModeScore* const rd) { - int x, y, ch; - VP8Residual res; - uint64_t pos1, pos2, pos3; - const int i16 = (it->mb_->type_ == 1); - const int segment = it->mb_->segment_; - VP8Encoder* const enc = it->enc_; - - VP8IteratorNzToBytes(it); - - pos1 = VP8BitWriterPos(bw); - if (i16) { - VP8InitResidual(0, 1, enc, &res); - VP8SetResidualCoeffs(rd->y_dc_levels, &res); - it->top_nz_[8] = it->left_nz_[8] = - PutCoeffs(bw, it->top_nz_[8] + it->left_nz_[8], &res); - VP8InitResidual(1, 0, enc, &res); - } else { - VP8InitResidual(0, 3, enc, &res); - } - - // luma-AC - for (y = 0; y < 4; ++y) { - for (x = 0; x < 4; ++x) { - const int ctx = it->top_nz_[x] + it->left_nz_[y]; - VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); - it->top_nz_[x] = it->left_nz_[y] = PutCoeffs(bw, ctx, &res); - } - } - pos2 = VP8BitWriterPos(bw); - - // U/V - VP8InitResidual(0, 2, enc, &res); - for (ch = 0; ch <= 2; ch += 2) { - for (y = 0; y < 2; ++y) { - for (x = 0; x < 2; ++x) { - const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; - VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); - it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = - PutCoeffs(bw, ctx, &res); - } - } - } - pos3 = VP8BitWriterPos(bw); - it->luma_bits_ = pos2 - pos1; - it->uv_bits_ = pos3 - pos2; - it->bit_count_[segment][i16] += it->luma_bits_; - it->bit_count_[segment][2] += it->uv_bits_; - VP8IteratorBytesToNz(it); -} - -// Same as CodeResiduals, but doesn't actually write anything. -// Instead, it just records the event distribution. -static void RecordResiduals(VP8EncIterator* const it, - const VP8ModeScore* const rd) { - int x, y, ch; - VP8Residual res; - VP8Encoder* const enc = it->enc_; - - VP8IteratorNzToBytes(it); - - if (it->mb_->type_ == 1) { // i16x16 - VP8InitResidual(0, 1, enc, &res); - VP8SetResidualCoeffs(rd->y_dc_levels, &res); - it->top_nz_[8] = it->left_nz_[8] = - VP8RecordCoeffs(it->top_nz_[8] + it->left_nz_[8], &res); - VP8InitResidual(1, 0, enc, &res); - } else { - VP8InitResidual(0, 3, enc, &res); - } - - // luma-AC - for (y = 0; y < 4; ++y) { - for (x = 0; x < 4; ++x) { - const int ctx = it->top_nz_[x] + it->left_nz_[y]; - VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); - it->top_nz_[x] = it->left_nz_[y] = VP8RecordCoeffs(ctx, &res); - } - } - - // U/V - VP8InitResidual(0, 2, enc, &res); - for (ch = 0; ch <= 2; ch += 2) { - for (y = 0; y < 2; ++y) { - for (x = 0; x < 2; ++x) { - const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; - VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); - it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = - VP8RecordCoeffs(ctx, &res); - } - } - } - - VP8IteratorBytesToNz(it); -} - -//------------------------------------------------------------------------------ -// Token buffer - -#if !defined(DISABLE_TOKEN_BUFFER) - -static int RecordTokens(VP8EncIterator* const it, const VP8ModeScore* const rd, - VP8TBuffer* const tokens) { - int x, y, ch; - VP8Residual res; - VP8Encoder* const enc = it->enc_; - - VP8IteratorNzToBytes(it); - if (it->mb_->type_ == 1) { // i16x16 - const int ctx = it->top_nz_[8] + it->left_nz_[8]; - VP8InitResidual(0, 1, enc, &res); - VP8SetResidualCoeffs(rd->y_dc_levels, &res); - it->top_nz_[8] = it->left_nz_[8] = - VP8RecordCoeffTokens(ctx, 1, - res.first, res.last, res.coeffs, tokens); - VP8RecordCoeffs(ctx, &res); - VP8InitResidual(1, 0, enc, &res); - } else { - VP8InitResidual(0, 3, enc, &res); - } - - // luma-AC - for (y = 0; y < 4; ++y) { - for (x = 0; x < 4; ++x) { - const int ctx = it->top_nz_[x] + it->left_nz_[y]; - VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); - it->top_nz_[x] = it->left_nz_[y] = - VP8RecordCoeffTokens(ctx, res.coeff_type, - res.first, res.last, res.coeffs, tokens); - VP8RecordCoeffs(ctx, &res); - } - } - - // U/V - VP8InitResidual(0, 2, enc, &res); - for (ch = 0; ch <= 2; ch += 2) { - for (y = 0; y < 2; ++y) { - for (x = 0; x < 2; ++x) { - const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; - VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); - it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = - VP8RecordCoeffTokens(ctx, 2, - res.first, res.last, res.coeffs, tokens); - VP8RecordCoeffs(ctx, &res); - } - } - } - VP8IteratorBytesToNz(it); - return !tokens->error_; -} - -#endif // !DISABLE_TOKEN_BUFFER - -//------------------------------------------------------------------------------ -// ExtraInfo map / Debug function - -#if SEGMENT_VISU -static void SetBlock(uint8_t* p, int value, int size) { - int y; - for (y = 0; y < size; ++y) { - memset(p, value, size); - p += BPS; - } -} -#endif - -static void ResetSSE(VP8Encoder* const enc) { - enc->sse_[0] = 0; - enc->sse_[1] = 0; - enc->sse_[2] = 0; - // Note: enc->sse_[3] is managed by alpha.c - enc->sse_count_ = 0; -} - -static void StoreSSE(const VP8EncIterator* const it) { - VP8Encoder* const enc = it->enc_; - const uint8_t* const in = it->yuv_in_; - const uint8_t* const out = it->yuv_out_; - // Note: not totally accurate at boundary. And doesn't include in-loop filter. - enc->sse_[0] += VP8SSE16x16(in + Y_OFF_ENC, out + Y_OFF_ENC); - enc->sse_[1] += VP8SSE8x8(in + U_OFF_ENC, out + U_OFF_ENC); - enc->sse_[2] += VP8SSE8x8(in + V_OFF_ENC, out + V_OFF_ENC); - enc->sse_count_ += 16 * 16; -} - -static void StoreSideInfo(const VP8EncIterator* const it) { - VP8Encoder* const enc = it->enc_; - const VP8MBInfo* const mb = it->mb_; - WebPPicture* const pic = enc->pic_; - - if (pic->stats != NULL) { - StoreSSE(it); - enc->block_count_[0] += (mb->type_ == 0); - enc->block_count_[1] += (mb->type_ == 1); - enc->block_count_[2] += (mb->skip_ != 0); - } - - if (pic->extra_info != NULL) { - uint8_t* const info = &pic->extra_info[it->x_ + it->y_ * enc->mb_w_]; - switch (pic->extra_info_type) { - case 1: *info = mb->type_; break; - case 2: *info = mb->segment_; break; - case 3: *info = enc->dqm_[mb->segment_].quant_; break; - case 4: *info = (mb->type_ == 1) ? it->preds_[0] : 0xff; break; - case 5: *info = mb->uv_mode_; break; - case 6: { - const int b = (int)((it->luma_bits_ + it->uv_bits_ + 7) >> 3); - *info = (b > 255) ? 255 : b; break; - } - case 7: *info = mb->alpha_; break; - default: *info = 0; break; - } - } -#if SEGMENT_VISU // visualize segments and prediction modes - SetBlock(it->yuv_out_ + Y_OFF_ENC, mb->segment_ * 64, 16); - SetBlock(it->yuv_out_ + U_OFF_ENC, it->preds_[0] * 64, 8); - SetBlock(it->yuv_out_ + V_OFF_ENC, mb->uv_mode_ * 64, 8); -#endif -} - -static double GetPSNR(uint64_t mse, uint64_t size) { - return (mse > 0 && size > 0) ? 10. * log10(255. * 255. * size / mse) : 99; -} - -//------------------------------------------------------------------------------ -// StatLoop(): only collect statistics (number of skips, token usage, ...). -// This is used for deciding optimal probabilities. It also modifies the -// quantizer value if some target (size, PSNR) was specified. - -static void SetLoopParams(VP8Encoder* const enc, float q) { - // Make sure the quality parameter is inside valid bounds - q = Clamp(q, 0.f, 100.f); - - VP8SetSegmentParams(enc, q); // setup segment quantizations and filters - SetSegmentProbas(enc); // compute segment probabilities - - ResetStats(enc); - ResetSSE(enc); -} - -static uint64_t OneStatPass(VP8Encoder* const enc, VP8RDLevel rd_opt, - int nb_mbs, int percent_delta, - PassStats* const s) { - VP8EncIterator it; - uint64_t size = 0; - uint64_t size_p0 = 0; - uint64_t distortion = 0; - const uint64_t pixel_count = nb_mbs * 384; - - VP8IteratorInit(enc, &it); - SetLoopParams(enc, s->q); - do { - VP8ModeScore info; - VP8IteratorImport(&it, NULL); - if (VP8Decimate(&it, &info, rd_opt)) { - // Just record the number of skips and act like skip_proba is not used. - enc->proba_.nb_skip_++; - } - RecordResiduals(&it, &info); - size += info.R + info.H; - size_p0 += info.H; - distortion += info.D; - if (percent_delta && !VP8IteratorProgress(&it, percent_delta)) - return 0; - VP8IteratorSaveBoundary(&it); - } while (VP8IteratorNext(&it) && --nb_mbs > 0); - - size_p0 += enc->segment_hdr_.size_; - if (s->do_size_search) { - size += FinalizeSkipProba(enc); - size += FinalizeTokenProbas(&enc->proba_); - size = ((size + size_p0 + 1024) >> 11) + HEADER_SIZE_ESTIMATE; - s->value = (double)size; - } else { - s->value = GetPSNR(distortion, pixel_count); - } - return size_p0; -} - -static int StatLoop(VP8Encoder* const enc) { - const int method = enc->method_; - const int do_search = enc->do_search_; - const int fast_probe = ((method == 0 || method == 3) && !do_search); - int num_pass_left = enc->config_->pass; - const int task_percent = 20; - const int percent_per_pass = - (task_percent + num_pass_left / 2) / num_pass_left; - const int final_percent = enc->percent_ + task_percent; - const VP8RDLevel rd_opt = - (method >= 3 || do_search) ? RD_OPT_BASIC : RD_OPT_NONE; - int nb_mbs = enc->mb_w_ * enc->mb_h_; - PassStats stats; - - InitPassStats(enc, &stats); - ResetTokenStats(enc); - - // Fast mode: quick analysis pass over few mbs. Better than nothing. - if (fast_probe) { - if (method == 3) { // we need more stats for method 3 to be reliable. - nb_mbs = (nb_mbs > 200) ? nb_mbs >> 1 : 100; - } else { - nb_mbs = (nb_mbs > 200) ? nb_mbs >> 2 : 50; - } - } - - while (num_pass_left-- > 0) { - const int is_last_pass = (fabs(stats.dq) <= DQ_LIMIT) || - (num_pass_left == 0) || - (enc->max_i4_header_bits_ == 0); - const uint64_t size_p0 = - OneStatPass(enc, rd_opt, nb_mbs, percent_per_pass, &stats); - if (size_p0 == 0) return 0; -#if (DEBUG_SEARCH > 0) - printf("#%d value:%.1lf -> %.1lf q:%.2f -> %.2f\n", - num_pass_left, stats.last_value, stats.value, stats.last_q, stats.q); -#endif - if (enc->max_i4_header_bits_ > 0 && size_p0 > PARTITION0_SIZE_LIMIT) { - ++num_pass_left; - enc->max_i4_header_bits_ >>= 1; // strengthen header bit limitation... - continue; // ...and start over - } - if (is_last_pass) { - break; - } - // If no target size: just do several pass without changing 'q' - if (do_search) { - ComputeNextQ(&stats); - if (fabs(stats.dq) <= DQ_LIMIT) break; - } - } - if (!do_search || !stats.do_size_search) { - // Need to finalize probas now, since it wasn't done during the search. - FinalizeSkipProba(enc); - FinalizeTokenProbas(&enc->proba_); - } - VP8CalculateLevelCosts(&enc->proba_); // finalize costs - return WebPReportProgress(enc->pic_, final_percent, &enc->percent_); -} - -//------------------------------------------------------------------------------ -// Main loops -// - -static const int kAverageBytesPerMB[8] = { 50, 24, 16, 9, 7, 5, 3, 2 }; - -static int PreLoopInitialize(VP8Encoder* const enc) { - int p; - int ok = 1; - const int average_bytes_per_MB = kAverageBytesPerMB[enc->base_quant_ >> 4]; - const int bytes_per_parts = - enc->mb_w_ * enc->mb_h_ * average_bytes_per_MB / enc->num_parts_; - // Initialize the bit-writers - for (p = 0; ok && p < enc->num_parts_; ++p) { - ok = VP8BitWriterInit(enc->parts_ + p, bytes_per_parts); - } - if (!ok) { - VP8EncFreeBitWriters(enc); // malloc error occurred - WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); - } - return ok; -} - -static int PostLoopFinalize(VP8EncIterator* const it, int ok) { - VP8Encoder* const enc = it->enc_; - if (ok) { // Finalize the partitions, check for extra errors. - int p; - for (p = 0; p < enc->num_parts_; ++p) { - VP8BitWriterFinish(enc->parts_ + p); - ok &= !enc->parts_[p].error_; - } - } - - if (ok) { // All good. Finish up. - if (enc->pic_->stats != NULL) { // finalize byte counters... - int i, s; - for (i = 0; i <= 2; ++i) { - for (s = 0; s < NUM_MB_SEGMENTS; ++s) { - enc->residual_bytes_[i][s] = (int)((it->bit_count_[s][i] + 7) >> 3); - } - } - } - VP8AdjustFilterStrength(it); // ...and store filter stats. - } else { - // Something bad happened -> need to do some memory cleanup. - VP8EncFreeBitWriters(enc); - } - return ok; -} - -//------------------------------------------------------------------------------ -// VP8EncLoop(): does the final bitstream coding. - -static void ResetAfterSkip(VP8EncIterator* const it) { - if (it->mb_->type_ == 1) { - *it->nz_ = 0; // reset all predictors - it->left_nz_[8] = 0; - } else { - *it->nz_ &= (1 << 24); // preserve the dc_nz bit - } -} - -int VP8EncLoop(VP8Encoder* const enc) { - VP8EncIterator it; - int ok = PreLoopInitialize(enc); - if (!ok) return 0; - - StatLoop(enc); // stats-collection loop - - VP8IteratorInit(enc, &it); - VP8InitFilter(&it); - do { - VP8ModeScore info; - const int dont_use_skip = !enc->proba_.use_skip_proba_; - const VP8RDLevel rd_opt = enc->rd_opt_level_; - - VP8IteratorImport(&it, NULL); - // Warning! order is important: first call VP8Decimate() and - // *then* decide how to code the skip decision if there's one. - if (!VP8Decimate(&it, &info, rd_opt) || dont_use_skip) { - CodeResiduals(it.bw_, &it, &info); - } else { // reset predictors after a skip - ResetAfterSkip(&it); - } - StoreSideInfo(&it); - VP8StoreFilterStats(&it); - VP8IteratorExport(&it); - ok = VP8IteratorProgress(&it, 20); - VP8IteratorSaveBoundary(&it); - } while (ok && VP8IteratorNext(&it)); - - return PostLoopFinalize(&it, ok); -} - -//------------------------------------------------------------------------------ -// Single pass using Token Buffer. - -#if !defined(DISABLE_TOKEN_BUFFER) - -#define MIN_COUNT 96 // minimum number of macroblocks before updating stats - -int VP8EncTokenLoop(VP8Encoder* const enc) { - // Roughly refresh the proba eight times per pass - int max_count = (enc->mb_w_ * enc->mb_h_) >> 3; - int num_pass_left = enc->config_->pass; - const int do_search = enc->do_search_; - VP8EncIterator it; - VP8EncProba* const proba = &enc->proba_; - const VP8RDLevel rd_opt = enc->rd_opt_level_; - const uint64_t pixel_count = enc->mb_w_ * enc->mb_h_ * 384; - PassStats stats; - int ok; - - InitPassStats(enc, &stats); - ok = PreLoopInitialize(enc); - if (!ok) return 0; - - if (max_count < MIN_COUNT) max_count = MIN_COUNT; - - assert(enc->num_parts_ == 1); - assert(enc->use_tokens_); - assert(proba->use_skip_proba_ == 0); - assert(rd_opt >= RD_OPT_BASIC); // otherwise, token-buffer won't be useful - assert(num_pass_left > 0); - - while (ok && num_pass_left-- > 0) { - const int is_last_pass = (fabs(stats.dq) <= DQ_LIMIT) || - (num_pass_left == 0) || - (enc->max_i4_header_bits_ == 0); - uint64_t size_p0 = 0; - uint64_t distortion = 0; - int cnt = max_count; - VP8IteratorInit(enc, &it); - SetLoopParams(enc, stats.q); - if (is_last_pass) { - ResetTokenStats(enc); - VP8InitFilter(&it); // don't collect stats until last pass (too costly) - } - VP8TBufferClear(&enc->tokens_); - do { - VP8ModeScore info; - VP8IteratorImport(&it, NULL); - if (--cnt < 0) { - FinalizeTokenProbas(proba); - VP8CalculateLevelCosts(proba); // refresh cost tables for rd-opt - cnt = max_count; - } - VP8Decimate(&it, &info, rd_opt); - ok = RecordTokens(&it, &info, &enc->tokens_); - if (!ok) { - WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); - break; - } - size_p0 += info.H; - distortion += info.D; - if (is_last_pass) { - StoreSideInfo(&it); - VP8StoreFilterStats(&it); - VP8IteratorExport(&it); - ok = VP8IteratorProgress(&it, 20); - } - VP8IteratorSaveBoundary(&it); - } while (ok && VP8IteratorNext(&it)); - if (!ok) break; - - size_p0 += enc->segment_hdr_.size_; - if (stats.do_size_search) { - uint64_t size = FinalizeTokenProbas(&enc->proba_); - size += VP8EstimateTokenSize(&enc->tokens_, - (const uint8_t*)proba->coeffs_); - size = (size + size_p0 + 1024) >> 11; // -> size in bytes - size += HEADER_SIZE_ESTIMATE; - stats.value = (double)size; - } else { // compute and store PSNR - stats.value = GetPSNR(distortion, pixel_count); - } - -#if (DEBUG_SEARCH > 0) - printf("#%2d metric:%.1lf -> %.1lf last_q=%.2lf q=%.2lf dq=%.2lf\n", - num_pass_left, stats.last_value, stats.value, - stats.last_q, stats.q, stats.dq); -#endif - if (size_p0 > PARTITION0_SIZE_LIMIT) { - ++num_pass_left; - enc->max_i4_header_bits_ >>= 1; // strengthen header bit limitation... - continue; // ...and start over - } - if (is_last_pass) { - break; // done - } - if (do_search) { - ComputeNextQ(&stats); // Adjust q - } - } - if (ok) { - if (!stats.do_size_search) { - FinalizeTokenProbas(&enc->proba_); - } - ok = VP8EmitTokens(&enc->tokens_, enc->parts_ + 0, - (const uint8_t*)proba->coeffs_, 1); - } - ok = ok && WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_); - return PostLoopFinalize(&it, ok); -} - -#else - -int VP8EncTokenLoop(VP8Encoder* const enc) { - (void)enc; - return 0; // we shouldn't be here. -} - -#endif // DISABLE_TOKEN_BUFFER - -//------------------------------------------------------------------------------ - diff --git a/Example/Pods/libwebp/src/enc/histogram.c b/Example/Pods/libwebp/src/enc/histogram.c deleted file mode 100644 index 869882de..00000000 --- a/Example/Pods/libwebp/src/enc/histogram.c +++ /dev/null @@ -1,942 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Jyrki Alakuijala (jyrki@google.com) -// -#ifdef HAVE_CONFIG_H -#include "../webp/config.h" -#endif - -#include - -#include "./backward_references.h" -#include "./histogram.h" -#include "../dsp/lossless.h" -#include "../utils/utils.h" - -#define MAX_COST 1.e38 - -// Number of partitions for the three dominant (literal, red and blue) symbol -// costs. -#define NUM_PARTITIONS 4 -// The size of the bin-hash corresponding to the three dominant costs. -#define BIN_SIZE (NUM_PARTITIONS * NUM_PARTITIONS * NUM_PARTITIONS) -// Maximum number of histograms allowed in greedy combining algorithm. -#define MAX_HISTO_GREEDY 100 - -static void HistogramClear(VP8LHistogram* const p) { - uint32_t* const literal = p->literal_; - const int cache_bits = p->palette_code_bits_; - const int histo_size = VP8LGetHistogramSize(cache_bits); - memset(p, 0, histo_size); - p->palette_code_bits_ = cache_bits; - p->literal_ = literal; -} - -// Swap two histogram pointers. -static void HistogramSwap(VP8LHistogram** const A, VP8LHistogram** const B) { - VP8LHistogram* const tmp = *A; - *A = *B; - *B = tmp; -} - -static void HistogramCopy(const VP8LHistogram* const src, - VP8LHistogram* const dst) { - uint32_t* const dst_literal = dst->literal_; - const int dst_cache_bits = dst->palette_code_bits_; - const int histo_size = VP8LGetHistogramSize(dst_cache_bits); - assert(src->palette_code_bits_ == dst_cache_bits); - memcpy(dst, src, histo_size); - dst->literal_ = dst_literal; -} - -int VP8LGetHistogramSize(int cache_bits) { - const int literal_size = VP8LHistogramNumCodes(cache_bits); - const size_t total_size = sizeof(VP8LHistogram) + sizeof(int) * literal_size; - assert(total_size <= (size_t)0x7fffffff); - return (int)total_size; -} - -void VP8LFreeHistogram(VP8LHistogram* const histo) { - WebPSafeFree(histo); -} - -void VP8LFreeHistogramSet(VP8LHistogramSet* const histo) { - WebPSafeFree(histo); -} - -void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs, - VP8LHistogram* const histo) { - VP8LRefsCursor c = VP8LRefsCursorInit(refs); - while (VP8LRefsCursorOk(&c)) { - VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos); - VP8LRefsCursorNext(&c); - } -} - -void VP8LHistogramCreate(VP8LHistogram* const p, - const VP8LBackwardRefs* const refs, - int palette_code_bits) { - if (palette_code_bits >= 0) { - p->palette_code_bits_ = palette_code_bits; - } - HistogramClear(p); - VP8LHistogramStoreRefs(refs, p); -} - -void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits) { - p->palette_code_bits_ = palette_code_bits; - HistogramClear(p); -} - -VP8LHistogram* VP8LAllocateHistogram(int cache_bits) { - VP8LHistogram* histo = NULL; - const int total_size = VP8LGetHistogramSize(cache_bits); - uint8_t* const memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory)); - if (memory == NULL) return NULL; - histo = (VP8LHistogram*)memory; - // literal_ won't necessary be aligned. - histo->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram)); - VP8LHistogramInit(histo, cache_bits); - return histo; -} - -VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits) { - int i; - VP8LHistogramSet* set; - const int histo_size = VP8LGetHistogramSize(cache_bits); - const size_t total_size = - sizeof(*set) + size * (sizeof(*set->histograms) + - histo_size + WEBP_ALIGN_CST); - uint8_t* memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory)); - if (memory == NULL) return NULL; - - set = (VP8LHistogramSet*)memory; - memory += sizeof(*set); - set->histograms = (VP8LHistogram**)memory; - memory += size * sizeof(*set->histograms); - set->max_size = size; - set->size = size; - for (i = 0; i < size; ++i) { - memory = (uint8_t*)WEBP_ALIGN(memory); - set->histograms[i] = (VP8LHistogram*)memory; - // literal_ won't necessary be aligned. - set->histograms[i]->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram)); - VP8LHistogramInit(set->histograms[i], cache_bits); - memory += histo_size; - } - return set; -} - -// ----------------------------------------------------------------------------- - -void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo, - const PixOrCopy* const v) { - if (PixOrCopyIsLiteral(v)) { - ++histo->alpha_[PixOrCopyLiteral(v, 3)]; - ++histo->red_[PixOrCopyLiteral(v, 2)]; - ++histo->literal_[PixOrCopyLiteral(v, 1)]; - ++histo->blue_[PixOrCopyLiteral(v, 0)]; - } else if (PixOrCopyIsCacheIdx(v)) { - const int literal_ix = - NUM_LITERAL_CODES + NUM_LENGTH_CODES + PixOrCopyCacheIdx(v); - ++histo->literal_[literal_ix]; - } else { - int code, extra_bits; - VP8LPrefixEncodeBits(PixOrCopyLength(v), &code, &extra_bits); - ++histo->literal_[NUM_LITERAL_CODES + code]; - VP8LPrefixEncodeBits(PixOrCopyDistance(v), &code, &extra_bits); - ++histo->distance_[code]; - } -} - -// ----------------------------------------------------------------------------- -// Entropy-related functions. - -static WEBP_INLINE double BitsEntropyRefine(const VP8LBitEntropy* entropy) { - double mix; - if (entropy->nonzeros < 5) { - if (entropy->nonzeros <= 1) { - return 0; - } - // Two symbols, they will be 0 and 1 in a Huffman code. - // Let's mix in a bit of entropy to favor good clustering when - // distributions of these are combined. - if (entropy->nonzeros == 2) { - return 0.99 * entropy->sum + 0.01 * entropy->entropy; - } - // No matter what the entropy says, we cannot be better than min_limit - // with Huffman coding. I am mixing a bit of entropy into the - // min_limit since it produces much better (~0.5 %) compression results - // perhaps because of better entropy clustering. - if (entropy->nonzeros == 3) { - mix = 0.95; - } else { - mix = 0.7; // nonzeros == 4. - } - } else { - mix = 0.627; - } - - { - double min_limit = 2 * entropy->sum - entropy->max_val; - min_limit = mix * min_limit + (1.0 - mix) * entropy->entropy; - return (entropy->entropy < min_limit) ? min_limit : entropy->entropy; - } -} - -double VP8LBitsEntropy(const uint32_t* const array, int n, - uint32_t* const trivial_symbol) { - VP8LBitEntropy entropy; - VP8LBitsEntropyUnrefined(array, n, &entropy); - if (trivial_symbol != NULL) { - *trivial_symbol = - (entropy.nonzeros == 1) ? entropy.nonzero_code : VP8L_NON_TRIVIAL_SYM; - } - - return BitsEntropyRefine(&entropy); -} - -static double InitialHuffmanCost(void) { - // Small bias because Huffman code length is typically not stored in - // full length. - static const int kHuffmanCodeOfHuffmanCodeSize = CODE_LENGTH_CODES * 3; - static const double kSmallBias = 9.1; - return kHuffmanCodeOfHuffmanCodeSize - kSmallBias; -} - -// Finalize the Huffman cost based on streak numbers and length type (<3 or >=3) -static double FinalHuffmanCost(const VP8LStreaks* const stats) { - double retval = InitialHuffmanCost(); - retval += stats->counts[0] * 1.5625 + 0.234375 * stats->streaks[0][1]; - retval += stats->counts[1] * 2.578125 + 0.703125 * stats->streaks[1][1]; - retval += 1.796875 * stats->streaks[0][0]; - retval += 3.28125 * stats->streaks[1][0]; - return retval; -} - -// Get the symbol entropy for the distribution 'population'. -// Set 'trivial_sym', if there's only one symbol present in the distribution. -static double PopulationCost(const uint32_t* const population, int length, - uint32_t* const trivial_sym) { - VP8LBitEntropy bit_entropy; - VP8LStreaks stats; - VP8LGetEntropyUnrefined(population, length, &bit_entropy, &stats); - if (trivial_sym != NULL) { - *trivial_sym = (bit_entropy.nonzeros == 1) ? bit_entropy.nonzero_code - : VP8L_NON_TRIVIAL_SYM; - } - - return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats); -} - -static WEBP_INLINE double GetCombinedEntropy(const uint32_t* const X, - const uint32_t* const Y, - int length) { - VP8LBitEntropy bit_entropy; - VP8LStreaks stats; - VP8LGetCombinedEntropyUnrefined(X, Y, length, &bit_entropy, &stats); - - return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats); -} - -// Estimates the Entropy + Huffman + other block overhead size cost. -double VP8LHistogramEstimateBits(const VP8LHistogram* const p) { - return - PopulationCost( - p->literal_, VP8LHistogramNumCodes(p->palette_code_bits_), NULL) - + PopulationCost(p->red_, NUM_LITERAL_CODES, NULL) - + PopulationCost(p->blue_, NUM_LITERAL_CODES, NULL) - + PopulationCost(p->alpha_, NUM_LITERAL_CODES, NULL) - + PopulationCost(p->distance_, NUM_DISTANCE_CODES, NULL) - + VP8LExtraCost(p->literal_ + NUM_LITERAL_CODES, NUM_LENGTH_CODES) - + VP8LExtraCost(p->distance_, NUM_DISTANCE_CODES); -} - -// ----------------------------------------------------------------------------- -// Various histogram combine/cost-eval functions - -static int GetCombinedHistogramEntropy(const VP8LHistogram* const a, - const VP8LHistogram* const b, - double cost_threshold, - double* cost) { - const int palette_code_bits = a->palette_code_bits_; - assert(a->palette_code_bits_ == b->palette_code_bits_); - *cost += GetCombinedEntropy(a->literal_, b->literal_, - VP8LHistogramNumCodes(palette_code_bits)); - *cost += VP8LExtraCostCombined(a->literal_ + NUM_LITERAL_CODES, - b->literal_ + NUM_LITERAL_CODES, - NUM_LENGTH_CODES); - if (*cost > cost_threshold) return 0; - - *cost += GetCombinedEntropy(a->red_, b->red_, NUM_LITERAL_CODES); - if (*cost > cost_threshold) return 0; - - *cost += GetCombinedEntropy(a->blue_, b->blue_, NUM_LITERAL_CODES); - if (*cost > cost_threshold) return 0; - - *cost += GetCombinedEntropy(a->alpha_, b->alpha_, NUM_LITERAL_CODES); - if (*cost > cost_threshold) return 0; - - *cost += GetCombinedEntropy(a->distance_, b->distance_, NUM_DISTANCE_CODES); - *cost += - VP8LExtraCostCombined(a->distance_, b->distance_, NUM_DISTANCE_CODES); - if (*cost > cost_threshold) return 0; - - return 1; -} - -// Performs out = a + b, computing the cost C(a+b) - C(a) - C(b) while comparing -// to the threshold value 'cost_threshold'. The score returned is -// Score = C(a+b) - C(a) - C(b), where C(a) + C(b) is known and fixed. -// Since the previous score passed is 'cost_threshold', we only need to compare -// the partial cost against 'cost_threshold + C(a) + C(b)' to possibly bail-out -// early. -static double HistogramAddEval(const VP8LHistogram* const a, - const VP8LHistogram* const b, - VP8LHistogram* const out, - double cost_threshold) { - double cost = 0; - const double sum_cost = a->bit_cost_ + b->bit_cost_; - cost_threshold += sum_cost; - - if (GetCombinedHistogramEntropy(a, b, cost_threshold, &cost)) { - VP8LHistogramAdd(a, b, out); - out->bit_cost_ = cost; - out->palette_code_bits_ = a->palette_code_bits_; - out->trivial_symbol_ = (a->trivial_symbol_ == b->trivial_symbol_) ? - a->trivial_symbol_ : VP8L_NON_TRIVIAL_SYM; - } - - return cost - sum_cost; -} - -// Same as HistogramAddEval(), except that the resulting histogram -// is not stored. Only the cost C(a+b) - C(a) is evaluated. We omit -// the term C(b) which is constant over all the evaluations. -static double HistogramAddThresh(const VP8LHistogram* const a, - const VP8LHistogram* const b, - double cost_threshold) { - double cost = -a->bit_cost_; - GetCombinedHistogramEntropy(a, b, cost_threshold, &cost); - return cost; -} - -// ----------------------------------------------------------------------------- - -// The structure to keep track of cost range for the three dominant entropy -// symbols. -// TODO(skal): Evaluate if float can be used here instead of double for -// representing the entropy costs. -typedef struct { - double literal_max_; - double literal_min_; - double red_max_; - double red_min_; - double blue_max_; - double blue_min_; -} DominantCostRange; - -static void DominantCostRangeInit(DominantCostRange* const c) { - c->literal_max_ = 0.; - c->literal_min_ = MAX_COST; - c->red_max_ = 0.; - c->red_min_ = MAX_COST; - c->blue_max_ = 0.; - c->blue_min_ = MAX_COST; -} - -static void UpdateDominantCostRange( - const VP8LHistogram* const h, DominantCostRange* const c) { - if (c->literal_max_ < h->literal_cost_) c->literal_max_ = h->literal_cost_; - if (c->literal_min_ > h->literal_cost_) c->literal_min_ = h->literal_cost_; - if (c->red_max_ < h->red_cost_) c->red_max_ = h->red_cost_; - if (c->red_min_ > h->red_cost_) c->red_min_ = h->red_cost_; - if (c->blue_max_ < h->blue_cost_) c->blue_max_ = h->blue_cost_; - if (c->blue_min_ > h->blue_cost_) c->blue_min_ = h->blue_cost_; -} - -static void UpdateHistogramCost(VP8LHistogram* const h) { - uint32_t alpha_sym, red_sym, blue_sym; - const double alpha_cost = - PopulationCost(h->alpha_, NUM_LITERAL_CODES, &alpha_sym); - const double distance_cost = - PopulationCost(h->distance_, NUM_DISTANCE_CODES, NULL) + - VP8LExtraCost(h->distance_, NUM_DISTANCE_CODES); - const int num_codes = VP8LHistogramNumCodes(h->palette_code_bits_); - h->literal_cost_ = PopulationCost(h->literal_, num_codes, NULL) + - VP8LExtraCost(h->literal_ + NUM_LITERAL_CODES, - NUM_LENGTH_CODES); - h->red_cost_ = PopulationCost(h->red_, NUM_LITERAL_CODES, &red_sym); - h->blue_cost_ = PopulationCost(h->blue_, NUM_LITERAL_CODES, &blue_sym); - h->bit_cost_ = h->literal_cost_ + h->red_cost_ + h->blue_cost_ + - alpha_cost + distance_cost; - if ((alpha_sym | red_sym | blue_sym) == VP8L_NON_TRIVIAL_SYM) { - h->trivial_symbol_ = VP8L_NON_TRIVIAL_SYM; - } else { - h->trivial_symbol_ = - ((uint32_t)alpha_sym << 24) | (red_sym << 16) | (blue_sym << 0); - } -} - -static int GetBinIdForEntropy(double min, double max, double val) { - const double range = max - min + 1e-6; - const double delta = val - min; - return (int)(NUM_PARTITIONS * delta / range); -} - -static int GetHistoBinIndexLowEffort( - const VP8LHistogram* const h, const DominantCostRange* const c) { - const int bin_id = GetBinIdForEntropy(c->literal_min_, c->literal_max_, - h->literal_cost_); - assert(bin_id < NUM_PARTITIONS); - return bin_id; -} - -static int GetHistoBinIndex( - const VP8LHistogram* const h, const DominantCostRange* const c) { - const int bin_id = - GetBinIdForEntropy(c->blue_min_, c->blue_max_, h->blue_cost_) + - NUM_PARTITIONS * GetBinIdForEntropy(c->red_min_, c->red_max_, - h->red_cost_) + - NUM_PARTITIONS * NUM_PARTITIONS * GetBinIdForEntropy(c->literal_min_, - c->literal_max_, - h->literal_cost_); - assert(bin_id < BIN_SIZE); - return bin_id; -} - -// Construct the histograms from backward references. -static void HistogramBuild( - int xsize, int histo_bits, const VP8LBackwardRefs* const backward_refs, - VP8LHistogramSet* const image_histo) { - int x = 0, y = 0; - const int histo_xsize = VP8LSubSampleSize(xsize, histo_bits); - VP8LHistogram** const histograms = image_histo->histograms; - VP8LRefsCursor c = VP8LRefsCursorInit(backward_refs); - assert(histo_bits > 0); - while (VP8LRefsCursorOk(&c)) { - const PixOrCopy* const v = c.cur_pos; - const int ix = (y >> histo_bits) * histo_xsize + (x >> histo_bits); - VP8LHistogramAddSinglePixOrCopy(histograms[ix], v); - x += PixOrCopyLength(v); - while (x >= xsize) { - x -= xsize; - ++y; - } - VP8LRefsCursorNext(&c); - } -} - -// Copies the histograms and computes its bit_cost. -static void HistogramCopyAndAnalyze( - VP8LHistogramSet* const orig_histo, VP8LHistogramSet* const image_histo) { - int i; - const int histo_size = orig_histo->size; - VP8LHistogram** const orig_histograms = orig_histo->histograms; - VP8LHistogram** const histograms = image_histo->histograms; - for (i = 0; i < histo_size; ++i) { - VP8LHistogram* const histo = orig_histograms[i]; - UpdateHistogramCost(histo); - // Copy histograms from orig_histo[] to image_histo[]. - HistogramCopy(histo, histograms[i]); - } -} - -// Partition histograms to different entropy bins for three dominant (literal, -// red and blue) symbol costs and compute the histogram aggregate bit_cost. -static void HistogramAnalyzeEntropyBin(VP8LHistogramSet* const image_histo, - int16_t* const bin_map, int low_effort) { - int i; - VP8LHistogram** const histograms = image_histo->histograms; - const int histo_size = image_histo->size; - const int bin_depth = histo_size + 1; - DominantCostRange cost_range; - DominantCostRangeInit(&cost_range); - - // Analyze the dominant (literal, red and blue) entropy costs. - for (i = 0; i < histo_size; ++i) { - VP8LHistogram* const histo = histograms[i]; - UpdateDominantCostRange(histo, &cost_range); - } - - // bin-hash histograms on three of the dominant (literal, red and blue) - // symbol costs. - for (i = 0; i < histo_size; ++i) { - int num_histos; - VP8LHistogram* const histo = histograms[i]; - const int16_t bin_id = low_effort ? - (int16_t)GetHistoBinIndexLowEffort(histo, &cost_range) : - (int16_t)GetHistoBinIndex(histo, &cost_range); - const int bin_offset = bin_id * bin_depth; - // bin_map[n][0] for every bin 'n' maintains the counter for the number of - // histograms in that bin. - // Get and increment the num_histos in that bin. - num_histos = ++bin_map[bin_offset]; - assert(bin_offset + num_histos < bin_depth * BIN_SIZE); - // Add histogram i'th index at num_histos (last) position in the bin_map. - bin_map[bin_offset + num_histos] = i; - } -} - -// Compact the histogram set by removing unused entries. -static void HistogramCompactBins(VP8LHistogramSet* const image_histo) { - VP8LHistogram** const histograms = image_histo->histograms; - int i, j; - - for (i = 0, j = 0; i < image_histo->size; ++i) { - if (histograms[i] != NULL && histograms[i]->bit_cost_ != 0.) { - if (j < i) { - histograms[j] = histograms[i]; - histograms[i] = NULL; - } - ++j; - } - } - image_histo->size = j; -} - -static VP8LHistogram* HistogramCombineEntropyBin( - VP8LHistogramSet* const image_histo, - VP8LHistogram* cur_combo, - int16_t* const bin_map, int bin_depth, int num_bins, - double combine_cost_factor, int low_effort) { - int bin_id; - VP8LHistogram** const histograms = image_histo->histograms; - - for (bin_id = 0; bin_id < num_bins; ++bin_id) { - const int bin_offset = bin_id * bin_depth; - const int num_histos = bin_map[bin_offset]; - const int idx1 = bin_map[bin_offset + 1]; - int num_combine_failures = 0; - int n; - for (n = 2; n <= num_histos; ++n) { - const int idx2 = bin_map[bin_offset + n]; - if (low_effort) { - // Merge all histograms with the same bin index, irrespective of cost of - // the merged histograms. - VP8LHistogramAdd(histograms[idx1], histograms[idx2], histograms[idx1]); - histograms[idx2]->bit_cost_ = 0.; - } else { - const double bit_cost_idx2 = histograms[idx2]->bit_cost_; - if (bit_cost_idx2 > 0.) { - const double bit_cost_thresh = -bit_cost_idx2 * combine_cost_factor; - const double curr_cost_diff = - HistogramAddEval(histograms[idx1], histograms[idx2], - cur_combo, bit_cost_thresh); - if (curr_cost_diff < bit_cost_thresh) { - // Try to merge two histograms only if the combo is a trivial one or - // the two candidate histograms are already non-trivial. - // For some images, 'try_combine' turns out to be false for a lot of - // histogram pairs. In that case, we fallback to combining - // histograms as usual to avoid increasing the header size. - const int try_combine = - (cur_combo->trivial_symbol_ != VP8L_NON_TRIVIAL_SYM) || - ((histograms[idx1]->trivial_symbol_ == VP8L_NON_TRIVIAL_SYM) && - (histograms[idx2]->trivial_symbol_ == VP8L_NON_TRIVIAL_SYM)); - const int max_combine_failures = 32; - if (try_combine || (num_combine_failures >= max_combine_failures)) { - HistogramSwap(&cur_combo, &histograms[idx1]); - histograms[idx2]->bit_cost_ = 0.; - } else { - ++num_combine_failures; - } - } - } - } - } - if (low_effort) { - // Update the bit_cost for the merged histograms (per bin index). - UpdateHistogramCost(histograms[idx1]); - } - } - HistogramCompactBins(image_histo); - return cur_combo; -} - -static uint32_t MyRand(uint32_t *seed) { - *seed *= 16807U; - if (*seed == 0) { - *seed = 1; - } - return *seed; -} - -// ----------------------------------------------------------------------------- -// Histogram pairs priority queue - -// Pair of histograms. Negative idx1 value means that pair is out-of-date. -typedef struct { - int idx1; - int idx2; - double cost_diff; - double cost_combo; -} HistogramPair; - -typedef struct { - HistogramPair* queue; - int size; - int max_size; -} HistoQueue; - -static int HistoQueueInit(HistoQueue* const histo_queue, const int max_index) { - histo_queue->size = 0; - // max_index^2 for the queue size is safe. If you look at - // HistogramCombineGreedy, and imagine that UpdateQueueFront always pushes - // data to the queue, you insert at most: - // - max_index*(max_index-1)/2 (the first two for loops) - // - max_index - 1 in the last for loop at the first iteration of the while - // loop, max_index - 2 at the second iteration ... therefore - // max_index*(max_index-1)/2 overall too - histo_queue->max_size = max_index * max_index; - // We allocate max_size + 1 because the last element at index "size" is - // used as temporary data (and it could be up to max_size). - histo_queue->queue = WebPSafeMalloc(histo_queue->max_size + 1, - sizeof(*histo_queue->queue)); - return histo_queue->queue != NULL; -} - -static void HistoQueueClear(HistoQueue* const histo_queue) { - assert(histo_queue != NULL); - WebPSafeFree(histo_queue->queue); -} - -static void SwapHistogramPairs(HistogramPair *p1, - HistogramPair *p2) { - const HistogramPair tmp = *p1; - *p1 = *p2; - *p2 = tmp; -} - -// Given a valid priority queue in range [0, queue_size) this function checks -// whether histo_queue[queue_size] should be accepted and swaps it with the -// front if it is smaller. Otherwise, it leaves it as is. -static void UpdateQueueFront(HistoQueue* const histo_queue) { - if (histo_queue->queue[histo_queue->size].cost_diff >= 0) return; - - if (histo_queue->queue[histo_queue->size].cost_diff < - histo_queue->queue[0].cost_diff) { - SwapHistogramPairs(histo_queue->queue, - histo_queue->queue + histo_queue->size); - } - ++histo_queue->size; - - // We cannot add more elements than the capacity. - // The allocation adds an extra element to the official capacity so that - // histo_queue->queue[histo_queue->max_size] is read/written within bound. - assert(histo_queue->size <= histo_queue->max_size); -} - -// ----------------------------------------------------------------------------- - -static void PreparePair(VP8LHistogram** histograms, int idx1, int idx2, - HistogramPair* const pair, - VP8LHistogram* const histos) { - if (idx1 > idx2) { - const int tmp = idx2; - idx2 = idx1; - idx1 = tmp; - } - pair->idx1 = idx1; - pair->idx2 = idx2; - pair->cost_diff = - HistogramAddEval(histograms[idx1], histograms[idx2], histos, 0); - pair->cost_combo = histos->bit_cost_; -} - -// Combines histograms by continuously choosing the one with the highest cost -// reduction. -static int HistogramCombineGreedy(VP8LHistogramSet* const image_histo, - VP8LHistogram* const histos) { - int ok = 0; - int image_histo_size = image_histo->size; - int i, j; - VP8LHistogram** const histograms = image_histo->histograms; - // Indexes of remaining histograms. - int* const clusters = WebPSafeMalloc(image_histo_size, sizeof(*clusters)); - // Priority queue of histogram pairs. - HistoQueue histo_queue; - - if (!HistoQueueInit(&histo_queue, image_histo_size) || clusters == NULL) { - goto End; - } - - for (i = 0; i < image_histo_size; ++i) { - // Initialize clusters indexes. - clusters[i] = i; - for (j = i + 1; j < image_histo_size; ++j) { - // Initialize positions array. - PreparePair(histograms, i, j, &histo_queue.queue[histo_queue.size], - histos); - UpdateQueueFront(&histo_queue); - } - } - - while (image_histo_size > 1 && histo_queue.size > 0) { - HistogramPair* copy_to; - const int idx1 = histo_queue.queue[0].idx1; - const int idx2 = histo_queue.queue[0].idx2; - VP8LHistogramAdd(histograms[idx2], histograms[idx1], histograms[idx1]); - histograms[idx1]->bit_cost_ = histo_queue.queue[0].cost_combo; - // Remove merged histogram. - for (i = 0; i + 1 < image_histo_size; ++i) { - if (clusters[i] >= idx2) { - clusters[i] = clusters[i + 1]; - } - } - --image_histo_size; - - // Remove pairs intersecting the just combined best pair. This will - // therefore pop the head of the queue. - copy_to = histo_queue.queue; - for (i = 0; i < histo_queue.size; ++i) { - HistogramPair* const p = histo_queue.queue + i; - if (p->idx1 == idx1 || p->idx2 == idx1 || - p->idx1 == idx2 || p->idx2 == idx2) { - // Do not copy the invalid pair. - continue; - } - if (p->cost_diff < histo_queue.queue[0].cost_diff) { - // Replace the top of the queue if we found better. - SwapHistogramPairs(histo_queue.queue, p); - } - SwapHistogramPairs(copy_to, p); - ++copy_to; - } - histo_queue.size = (int)(copy_to - histo_queue.queue); - - // Push new pairs formed with combined histogram to the queue. - for (i = 0; i < image_histo_size; ++i) { - if (clusters[i] != idx1) { - PreparePair(histograms, idx1, clusters[i], - &histo_queue.queue[histo_queue.size], histos); - UpdateQueueFront(&histo_queue); - } - } - } - // Move remaining histograms to the beginning of the array. - for (i = 0; i < image_histo_size; ++i) { - if (i != clusters[i]) { // swap the two histograms - HistogramSwap(&histograms[i], &histograms[clusters[i]]); - } - } - - image_histo->size = image_histo_size; - ok = 1; - - End: - WebPSafeFree(clusters); - HistoQueueClear(&histo_queue); - return ok; -} - -static VP8LHistogram* HistogramCombineStochastic( - VP8LHistogramSet* const image_histo, - VP8LHistogram* tmp_histo, - VP8LHistogram* best_combo, - int quality, int min_cluster_size) { - int iter; - uint32_t seed = 0; - int tries_with_no_success = 0; - int image_histo_size = image_histo->size; - const int iter_mult = (quality < 25) ? 2 : 2 + (quality - 25) / 8; - const int outer_iters = image_histo_size * iter_mult; - const int num_pairs = image_histo_size / 2; - const int num_tries_no_success = outer_iters / 2; - VP8LHistogram** const histograms = image_histo->histograms; - - // Collapse similar histograms in 'image_histo'. - ++min_cluster_size; - for (iter = 0; - iter < outer_iters && image_histo_size >= min_cluster_size; - ++iter) { - double best_cost_diff = 0.; - int best_idx1 = -1, best_idx2 = 1; - int j; - const int num_tries = - (num_pairs < image_histo_size) ? num_pairs : image_histo_size; - seed += iter; - for (j = 0; j < num_tries; ++j) { - double curr_cost_diff; - // Choose two histograms at random and try to combine them. - const uint32_t idx1 = MyRand(&seed) % image_histo_size; - const uint32_t tmp = (j & 7) + 1; - const uint32_t diff = - (tmp < 3) ? tmp : MyRand(&seed) % (image_histo_size - 1); - const uint32_t idx2 = (idx1 + diff + 1) % image_histo_size; - if (idx1 == idx2) { - continue; - } - - // Calculate cost reduction on combining. - curr_cost_diff = HistogramAddEval(histograms[idx1], histograms[idx2], - tmp_histo, best_cost_diff); - if (curr_cost_diff < best_cost_diff) { // found a better pair? - HistogramSwap(&best_combo, &tmp_histo); - best_cost_diff = curr_cost_diff; - best_idx1 = idx1; - best_idx2 = idx2; - } - } - - if (best_idx1 >= 0) { - HistogramSwap(&best_combo, &histograms[best_idx1]); - // swap best_idx2 slot with last one (which is now unused) - --image_histo_size; - if (best_idx2 != image_histo_size) { - HistogramSwap(&histograms[image_histo_size], &histograms[best_idx2]); - histograms[image_histo_size] = NULL; - } - tries_with_no_success = 0; - } - if (++tries_with_no_success >= num_tries_no_success) { - break; - } - } - image_histo->size = image_histo_size; - return best_combo; -} - -// ----------------------------------------------------------------------------- -// Histogram refinement - -// Find the best 'out' histogram for each of the 'in' histograms. -// Note: we assume that out[]->bit_cost_ is already up-to-date. -static void HistogramRemap(const VP8LHistogramSet* const orig_histo, - const VP8LHistogramSet* const image_histo, - uint16_t* const symbols) { - int i; - VP8LHistogram** const orig_histograms = orig_histo->histograms; - VP8LHistogram** const histograms = image_histo->histograms; - const int orig_histo_size = orig_histo->size; - const int image_histo_size = image_histo->size; - if (image_histo_size > 1) { - for (i = 0; i < orig_histo_size; ++i) { - int best_out = 0; - double best_bits = - HistogramAddThresh(histograms[0], orig_histograms[i], MAX_COST); - int k; - for (k = 1; k < image_histo_size; ++k) { - const double cur_bits = - HistogramAddThresh(histograms[k], orig_histograms[i], best_bits); - if (cur_bits < best_bits) { - best_bits = cur_bits; - best_out = k; - } - } - symbols[i] = best_out; - } - } else { - assert(image_histo_size == 1); - for (i = 0; i < orig_histo_size; ++i) { - symbols[i] = 0; - } - } - - // Recompute each out based on raw and symbols. - for (i = 0; i < image_histo_size; ++i) { - HistogramClear(histograms[i]); - } - - for (i = 0; i < orig_histo_size; ++i) { - const int idx = symbols[i]; - VP8LHistogramAdd(orig_histograms[i], histograms[idx], histograms[idx]); - } -} - -static double GetCombineCostFactor(int histo_size, int quality) { - double combine_cost_factor = 0.16; - if (quality < 90) { - if (histo_size > 256) combine_cost_factor /= 2.; - if (histo_size > 512) combine_cost_factor /= 2.; - if (histo_size > 1024) combine_cost_factor /= 2.; - if (quality <= 50) combine_cost_factor /= 2.; - } - return combine_cost_factor; -} - -int VP8LGetHistoImageSymbols(int xsize, int ysize, - const VP8LBackwardRefs* const refs, - int quality, int low_effort, - int histo_bits, int cache_bits, - VP8LHistogramSet* const image_histo, - VP8LHistogramSet* const tmp_histos, - uint16_t* const histogram_symbols) { - int ok = 0; - const int histo_xsize = histo_bits ? VP8LSubSampleSize(xsize, histo_bits) : 1; - const int histo_ysize = histo_bits ? VP8LSubSampleSize(ysize, histo_bits) : 1; - const int image_histo_raw_size = histo_xsize * histo_ysize; - const int entropy_combine_num_bins = low_effort ? NUM_PARTITIONS : BIN_SIZE; - - // The bin_map for every bin follows following semantics: - // bin_map[n][0] = num_histo; // The number of histograms in that bin. - // bin_map[n][1] = index of first histogram in that bin; - // bin_map[n][num_histo] = index of last histogram in that bin; - // bin_map[n][num_histo + 1] ... bin_map[n][bin_depth - 1] = unused indices. - const int bin_depth = image_histo_raw_size + 1; - int16_t* bin_map = NULL; - VP8LHistogramSet* const orig_histo = - VP8LAllocateHistogramSet(image_histo_raw_size, cache_bits); - VP8LHistogram* cur_combo; - const int entropy_combine = - (orig_histo->size > entropy_combine_num_bins * 2) && (quality < 100); - - if (orig_histo == NULL) goto Error; - - // Don't attempt linear bin-partition heuristic for: - // histograms of small sizes, as bin_map will be very sparse and; - // Maximum quality (q==100), to preserve the compression gains at that level. - if (entropy_combine) { - const int bin_map_size = bin_depth * entropy_combine_num_bins; - bin_map = (int16_t*)WebPSafeCalloc(bin_map_size, sizeof(*bin_map)); - if (bin_map == NULL) goto Error; - } - - // Construct the histograms from backward references. - HistogramBuild(xsize, histo_bits, refs, orig_histo); - // Copies the histograms and computes its bit_cost. - HistogramCopyAndAnalyze(orig_histo, image_histo); - - cur_combo = tmp_histos->histograms[1]; // pick up working slot - if (entropy_combine) { - const double combine_cost_factor = - GetCombineCostFactor(image_histo_raw_size, quality); - HistogramAnalyzeEntropyBin(orig_histo, bin_map, low_effort); - // Collapse histograms with similar entropy. - cur_combo = HistogramCombineEntropyBin(image_histo, cur_combo, bin_map, - bin_depth, entropy_combine_num_bins, - combine_cost_factor, low_effort); - } - - // Don't combine the histograms using stochastic and greedy heuristics for - // low-effort compression mode. - if (!low_effort || !entropy_combine) { - const float x = quality / 100.f; - // cubic ramp between 1 and MAX_HISTO_GREEDY: - const int threshold_size = (int)(1 + (x * x * x) * (MAX_HISTO_GREEDY - 1)); - cur_combo = HistogramCombineStochastic(image_histo, - tmp_histos->histograms[0], - cur_combo, quality, threshold_size); - if ((image_histo->size <= threshold_size) && - !HistogramCombineGreedy(image_histo, cur_combo)) { - goto Error; - } - } - - // TODO(vikasa): Optimize HistogramRemap for low-effort compression mode also. - // Find the optimal map from original histograms to the final ones. - HistogramRemap(orig_histo, image_histo, histogram_symbols); - - ok = 1; - - Error: - WebPSafeFree(bin_map); - VP8LFreeHistogramSet(orig_histo); - return ok; -} diff --git a/Example/Pods/libwebp/src/enc/histogram.h b/Example/Pods/libwebp/src/enc/histogram.h deleted file mode 100644 index d303d1d5..00000000 --- a/Example/Pods/libwebp/src/enc/histogram.h +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Jyrki Alakuijala (jyrki@google.com) -// -// Models the histograms of literal and distance codes. - -#ifndef WEBP_ENC_HISTOGRAM_H_ -#define WEBP_ENC_HISTOGRAM_H_ - -#include - -#include "./backward_references.h" -#include "../webp/format_constants.h" -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Not a trivial literal symbol. -#define VP8L_NON_TRIVIAL_SYM (0xffffffff) - -// A simple container for histograms of data. -typedef struct { - // literal_ contains green literal, palette-code and - // copy-length-prefix histogram - uint32_t* literal_; // Pointer to the allocated buffer for literal. - uint32_t red_[NUM_LITERAL_CODES]; - uint32_t blue_[NUM_LITERAL_CODES]; - uint32_t alpha_[NUM_LITERAL_CODES]; - // Backward reference prefix-code histogram. - uint32_t distance_[NUM_DISTANCE_CODES]; - int palette_code_bits_; - uint32_t trivial_symbol_; // True, if histograms for Red, Blue & Alpha - // literal symbols are single valued. - double bit_cost_; // cached value of bit cost. - double literal_cost_; // Cached values of dominant entropy costs: - double red_cost_; // literal, red & blue. - double blue_cost_; -} VP8LHistogram; - -// Collection of histograms with fixed capacity, allocated as one -// big memory chunk. Can be destroyed by calling WebPSafeFree(). -typedef struct { - int size; // number of slots currently in use - int max_size; // maximum capacity - VP8LHistogram** histograms; -} VP8LHistogramSet; - -// Create the histogram. -// -// The input data is the PixOrCopy data, which models the literals, stop -// codes and backward references (both distances and lengths). Also: if -// palette_code_bits is >= 0, initialize the histogram with this value. -void VP8LHistogramCreate(VP8LHistogram* const p, - const VP8LBackwardRefs* const refs, - int palette_code_bits); - -// Return the size of the histogram for a given palette_code_bits. -int VP8LGetHistogramSize(int palette_code_bits); - -// Set the palette_code_bits and reset the stats. -void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits); - -// Collect all the references into a histogram (without reset) -void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs, - VP8LHistogram* const histo); - -// Free the memory allocated for the histogram. -void VP8LFreeHistogram(VP8LHistogram* const histo); - -// Free the memory allocated for the histogram set. -void VP8LFreeHistogramSet(VP8LHistogramSet* const histo); - -// Allocate an array of pointer to histograms, allocated and initialized -// using 'cache_bits'. Return NULL in case of memory error. -VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits); - -// Allocate and initialize histogram object with specified 'cache_bits'. -// Returns NULL in case of memory error. -// Special case of VP8LAllocateHistogramSet, with size equals 1. -VP8LHistogram* VP8LAllocateHistogram(int cache_bits); - -// Accumulate a token 'v' into a histogram. -void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo, - const PixOrCopy* const v); - -static WEBP_INLINE int VP8LHistogramNumCodes(int palette_code_bits) { - return NUM_LITERAL_CODES + NUM_LENGTH_CODES + - ((palette_code_bits > 0) ? (1 << palette_code_bits) : 0); -} - -// Builds the histogram image. -int VP8LGetHistoImageSymbols(int xsize, int ysize, - const VP8LBackwardRefs* const refs, - int quality, int low_effort, - int histogram_bits, int cache_bits, - VP8LHistogramSet* const image_in, - VP8LHistogramSet* const tmp_histos, - uint16_t* const histogram_symbols); - -// Returns the entropy for the symbols in the input array. -// Also sets trivial_symbol to the code value, if the array has only one code -// value. Otherwise, set it to VP8L_NON_TRIVIAL_SYM. -double VP8LBitsEntropy(const uint32_t* const array, int n, - uint32_t* const trivial_symbol); - -// Estimate how many bits the combined entropy of literals and distance -// approximately maps to. -double VP8LHistogramEstimateBits(const VP8LHistogram* const p); - -#ifdef __cplusplus -} -#endif - -#endif // WEBP_ENC_HISTOGRAM_H_ diff --git a/Example/Pods/libwebp/src/enc/iterator.c b/Example/Pods/libwebp/src/enc/iterator.c deleted file mode 100644 index 99d960a5..00000000 --- a/Example/Pods/libwebp/src/enc/iterator.c +++ /dev/null @@ -1,456 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// VP8Iterator: block iterator -// -// Author: Skal (pascal.massimino@gmail.com) - -#include - -#include "./vp8enci.h" - -//------------------------------------------------------------------------------ -// VP8Iterator -//------------------------------------------------------------------------------ - -static void InitLeft(VP8EncIterator* const it) { - it->y_left_[-1] = it->u_left_[-1] = it->v_left_[-1] = - (it->y_ > 0) ? 129 : 127; - memset(it->y_left_, 129, 16); - memset(it->u_left_, 129, 8); - memset(it->v_left_, 129, 8); - it->left_nz_[8] = 0; -} - -static void InitTop(VP8EncIterator* const it) { - const VP8Encoder* const enc = it->enc_; - const size_t top_size = enc->mb_w_ * 16; - memset(enc->y_top_, 127, 2 * top_size); - memset(enc->nz_, 0, enc->mb_w_ * sizeof(*enc->nz_)); -} - -void VP8IteratorSetRow(VP8EncIterator* const it, int y) { - VP8Encoder* const enc = it->enc_; - it->x_ = 0; - it->y_ = y; - it->bw_ = &enc->parts_[y & (enc->num_parts_ - 1)]; - it->preds_ = enc->preds_ + y * 4 * enc->preds_w_; - it->nz_ = enc->nz_; - it->mb_ = enc->mb_info_ + y * enc->mb_w_; - it->y_top_ = enc->y_top_; - it->uv_top_ = enc->uv_top_; - InitLeft(it); -} - -void VP8IteratorReset(VP8EncIterator* const it) { - VP8Encoder* const enc = it->enc_; - VP8IteratorSetRow(it, 0); - VP8IteratorSetCountDown(it, enc->mb_w_ * enc->mb_h_); // default - InitTop(it); - InitLeft(it); - memset(it->bit_count_, 0, sizeof(it->bit_count_)); - it->do_trellis_ = 0; -} - -void VP8IteratorSetCountDown(VP8EncIterator* const it, int count_down) { - it->count_down_ = it->count_down0_ = count_down; -} - -int VP8IteratorIsDone(const VP8EncIterator* const it) { - return (it->count_down_ <= 0); -} - -void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it) { - it->enc_ = enc; - it->y_stride_ = enc->pic_->y_stride; - it->uv_stride_ = enc->pic_->uv_stride; - it->yuv_in_ = (uint8_t*)WEBP_ALIGN(it->yuv_mem_); - it->yuv_out_ = it->yuv_in_ + YUV_SIZE_ENC; - it->yuv_out2_ = it->yuv_out_ + YUV_SIZE_ENC; - it->yuv_p_ = it->yuv_out2_ + YUV_SIZE_ENC; - it->lf_stats_ = enc->lf_stats_; - it->percent0_ = enc->percent_; - it->y_left_ = (uint8_t*)WEBP_ALIGN(it->yuv_left_mem_ + 1); - it->u_left_ = it->y_left_ + 16 + 16; - it->v_left_ = it->u_left_ + 16; - VP8IteratorReset(it); -} - -int VP8IteratorProgress(const VP8EncIterator* const it, int delta) { - VP8Encoder* const enc = it->enc_; - if (delta && enc->pic_->progress_hook != NULL) { - const int done = it->count_down0_ - it->count_down_; - const int percent = (it->count_down0_ <= 0) - ? it->percent0_ - : it->percent0_ + delta * done / it->count_down0_; - return WebPReportProgress(enc->pic_, percent, &enc->percent_); - } - return 1; -} - -//------------------------------------------------------------------------------ -// Import the source samples into the cache. Takes care of replicating -// boundary pixels if necessary. - -static WEBP_INLINE int MinSize(int a, int b) { return (a < b) ? a : b; } - -static void ImportBlock(const uint8_t* src, int src_stride, - uint8_t* dst, int w, int h, int size) { - int i; - for (i = 0; i < h; ++i) { - memcpy(dst, src, w); - if (w < size) { - memset(dst + w, dst[w - 1], size - w); - } - dst += BPS; - src += src_stride; - } - for (i = h; i < size; ++i) { - memcpy(dst, dst - BPS, size); - dst += BPS; - } -} - -static void ImportLine(const uint8_t* src, int src_stride, - uint8_t* dst, int len, int total_len) { - int i; - for (i = 0; i < len; ++i, src += src_stride) dst[i] = *src; - for (; i < total_len; ++i) dst[i] = dst[len - 1]; -} - -void VP8IteratorImport(VP8EncIterator* const it, uint8_t* tmp_32) { - const VP8Encoder* const enc = it->enc_; - const int x = it->x_, y = it->y_; - const WebPPicture* const pic = enc->pic_; - const uint8_t* const ysrc = pic->y + (y * pic->y_stride + x) * 16; - const uint8_t* const usrc = pic->u + (y * pic->uv_stride + x) * 8; - const uint8_t* const vsrc = pic->v + (y * pic->uv_stride + x) * 8; - const int w = MinSize(pic->width - x * 16, 16); - const int h = MinSize(pic->height - y * 16, 16); - const int uv_w = (w + 1) >> 1; - const int uv_h = (h + 1) >> 1; - - ImportBlock(ysrc, pic->y_stride, it->yuv_in_ + Y_OFF_ENC, w, h, 16); - ImportBlock(usrc, pic->uv_stride, it->yuv_in_ + U_OFF_ENC, uv_w, uv_h, 8); - ImportBlock(vsrc, pic->uv_stride, it->yuv_in_ + V_OFF_ENC, uv_w, uv_h, 8); - - if (tmp_32 == NULL) return; - - // Import source (uncompressed) samples into boundary. - if (x == 0) { - InitLeft(it); - } else { - if (y == 0) { - it->y_left_[-1] = it->u_left_[-1] = it->v_left_[-1] = 127; - } else { - it->y_left_[-1] = ysrc[- 1 - pic->y_stride]; - it->u_left_[-1] = usrc[- 1 - pic->uv_stride]; - it->v_left_[-1] = vsrc[- 1 - pic->uv_stride]; - } - ImportLine(ysrc - 1, pic->y_stride, it->y_left_, h, 16); - ImportLine(usrc - 1, pic->uv_stride, it->u_left_, uv_h, 8); - ImportLine(vsrc - 1, pic->uv_stride, it->v_left_, uv_h, 8); - } - - it->y_top_ = tmp_32 + 0; - it->uv_top_ = tmp_32 + 16; - if (y == 0) { - memset(tmp_32, 127, 32 * sizeof(*tmp_32)); - } else { - ImportLine(ysrc - pic->y_stride, 1, tmp_32, w, 16); - ImportLine(usrc - pic->uv_stride, 1, tmp_32 + 16, uv_w, 8); - ImportLine(vsrc - pic->uv_stride, 1, tmp_32 + 16 + 8, uv_w, 8); - } -} - -//------------------------------------------------------------------------------ -// Copy back the compressed samples into user space if requested. - -static void ExportBlock(const uint8_t* src, uint8_t* dst, int dst_stride, - int w, int h) { - while (h-- > 0) { - memcpy(dst, src, w); - dst += dst_stride; - src += BPS; - } -} - -void VP8IteratorExport(const VP8EncIterator* const it) { - const VP8Encoder* const enc = it->enc_; - if (enc->config_->show_compressed) { - const int x = it->x_, y = it->y_; - const uint8_t* const ysrc = it->yuv_out_ + Y_OFF_ENC; - const uint8_t* const usrc = it->yuv_out_ + U_OFF_ENC; - const uint8_t* const vsrc = it->yuv_out_ + V_OFF_ENC; - const WebPPicture* const pic = enc->pic_; - uint8_t* const ydst = pic->y + (y * pic->y_stride + x) * 16; - uint8_t* const udst = pic->u + (y * pic->uv_stride + x) * 8; - uint8_t* const vdst = pic->v + (y * pic->uv_stride + x) * 8; - int w = (pic->width - x * 16); - int h = (pic->height - y * 16); - - if (w > 16) w = 16; - if (h > 16) h = 16; - - // Luma plane - ExportBlock(ysrc, ydst, pic->y_stride, w, h); - - { // U/V planes - const int uv_w = (w + 1) >> 1; - const int uv_h = (h + 1) >> 1; - ExportBlock(usrc, udst, pic->uv_stride, uv_w, uv_h); - ExportBlock(vsrc, vdst, pic->uv_stride, uv_w, uv_h); - } - } -} - -//------------------------------------------------------------------------------ -// Non-zero contexts setup/teardown - -// Nz bits: -// 0 1 2 3 Y -// 4 5 6 7 -// 8 9 10 11 -// 12 13 14 15 -// 16 17 U -// 18 19 -// 20 21 V -// 22 23 -// 24 DC-intra16 - -// Convert packed context to byte array -#define BIT(nz, n) (!!((nz) & (1 << (n)))) - -void VP8IteratorNzToBytes(VP8EncIterator* const it) { - const int tnz = it->nz_[0], lnz = it->nz_[-1]; - int* const top_nz = it->top_nz_; - int* const left_nz = it->left_nz_; - - // Top-Y - top_nz[0] = BIT(tnz, 12); - top_nz[1] = BIT(tnz, 13); - top_nz[2] = BIT(tnz, 14); - top_nz[3] = BIT(tnz, 15); - // Top-U - top_nz[4] = BIT(tnz, 18); - top_nz[5] = BIT(tnz, 19); - // Top-V - top_nz[6] = BIT(tnz, 22); - top_nz[7] = BIT(tnz, 23); - // DC - top_nz[8] = BIT(tnz, 24); - - // left-Y - left_nz[0] = BIT(lnz, 3); - left_nz[1] = BIT(lnz, 7); - left_nz[2] = BIT(lnz, 11); - left_nz[3] = BIT(lnz, 15); - // left-U - left_nz[4] = BIT(lnz, 17); - left_nz[5] = BIT(lnz, 19); - // left-V - left_nz[6] = BIT(lnz, 21); - left_nz[7] = BIT(lnz, 23); - // left-DC is special, iterated separately -} - -void VP8IteratorBytesToNz(VP8EncIterator* const it) { - uint32_t nz = 0; - const int* const top_nz = it->top_nz_; - const int* const left_nz = it->left_nz_; - // top - nz |= (top_nz[0] << 12) | (top_nz[1] << 13); - nz |= (top_nz[2] << 14) | (top_nz[3] << 15); - nz |= (top_nz[4] << 18) | (top_nz[5] << 19); - nz |= (top_nz[6] << 22) | (top_nz[7] << 23); - nz |= (top_nz[8] << 24); // we propagate the _top_ bit, esp. for intra4 - // left - nz |= (left_nz[0] << 3) | (left_nz[1] << 7); - nz |= (left_nz[2] << 11); - nz |= (left_nz[4] << 17) | (left_nz[6] << 21); - - *it->nz_ = nz; -} - -#undef BIT - -//------------------------------------------------------------------------------ -// Advance to the next position, doing the bookkeeping. - -void VP8IteratorSaveBoundary(VP8EncIterator* const it) { - VP8Encoder* const enc = it->enc_; - const int x = it->x_, y = it->y_; - const uint8_t* const ysrc = it->yuv_out_ + Y_OFF_ENC; - const uint8_t* const uvsrc = it->yuv_out_ + U_OFF_ENC; - if (x < enc->mb_w_ - 1) { // left - int i; - for (i = 0; i < 16; ++i) { - it->y_left_[i] = ysrc[15 + i * BPS]; - } - for (i = 0; i < 8; ++i) { - it->u_left_[i] = uvsrc[7 + i * BPS]; - it->v_left_[i] = uvsrc[15 + i * BPS]; - } - // top-left (before 'top'!) - it->y_left_[-1] = it->y_top_[15]; - it->u_left_[-1] = it->uv_top_[0 + 7]; - it->v_left_[-1] = it->uv_top_[8 + 7]; - } - if (y < enc->mb_h_ - 1) { // top - memcpy(it->y_top_, ysrc + 15 * BPS, 16); - memcpy(it->uv_top_, uvsrc + 7 * BPS, 8 + 8); - } -} - -int VP8IteratorNext(VP8EncIterator* const it) { - it->preds_ += 4; - it->mb_ += 1; - it->nz_ += 1; - it->y_top_ += 16; - it->uv_top_ += 16; - it->x_ += 1; - if (it->x_ == it->enc_->mb_w_) { - VP8IteratorSetRow(it, ++it->y_); - } - return (0 < --it->count_down_); -} - -//------------------------------------------------------------------------------ -// Helper function to set mode properties - -void VP8SetIntra16Mode(const VP8EncIterator* const it, int mode) { - uint8_t* preds = it->preds_; - int y; - for (y = 0; y < 4; ++y) { - memset(preds, mode, 4); - preds += it->enc_->preds_w_; - } - it->mb_->type_ = 1; -} - -void VP8SetIntra4Mode(const VP8EncIterator* const it, const uint8_t* modes) { - uint8_t* preds = it->preds_; - int y; - for (y = 4; y > 0; --y) { - memcpy(preds, modes, 4 * sizeof(*modes)); - preds += it->enc_->preds_w_; - modes += 4; - } - it->mb_->type_ = 0; -} - -void VP8SetIntraUVMode(const VP8EncIterator* const it, int mode) { - it->mb_->uv_mode_ = mode; -} - -void VP8SetSkip(const VP8EncIterator* const it, int skip) { - it->mb_->skip_ = skip; -} - -void VP8SetSegment(const VP8EncIterator* const it, int segment) { - it->mb_->segment_ = segment; -} - -//------------------------------------------------------------------------------ -// Intra4x4 sub-blocks iteration -// -// We store and update the boundary samples into an array of 37 pixels. They -// are updated as we iterate and reconstructs each intra4x4 blocks in turn. -// The position of the samples has the following snake pattern: -// -// 16|17 18 19 20|21 22 23 24|25 26 27 28|29 30 31 32|33 34 35 36 <- Top-right -// --+-----------+-----------+-----------+-----------+ -// 15| 19| 23| 27| 31| -// 14| 18| 22| 26| 30| -// 13| 17| 21| 25| 29| -// 12|13 14 15 16|17 18 19 20|21 22 23 24|25 26 27 28| -// --+-----------+-----------+-----------+-----------+ -// 11| 15| 19| 23| 27| -// 10| 14| 18| 22| 26| -// 9| 13| 17| 21| 25| -// 8| 9 10 11 12|13 14 15 16|17 18 19 20|21 22 23 24| -// --+-----------+-----------+-----------+-----------+ -// 7| 11| 15| 19| 23| -// 6| 10| 14| 18| 22| -// 5| 9| 13| 17| 21| -// 4| 5 6 7 8| 9 10 11 12|13 14 15 16|17 18 19 20| -// --+-----------+-----------+-----------+-----------+ -// 3| 7| 11| 15| 19| -// 2| 6| 10| 14| 18| -// 1| 5| 9| 13| 17| -// 0| 1 2 3 4| 5 6 7 8| 9 10 11 12|13 14 15 16| -// --+-----------+-----------+-----------+-----------+ - -// Array to record the position of the top sample to pass to the prediction -// functions in dsp.c. -static const uint8_t VP8TopLeftI4[16] = { - 17, 21, 25, 29, - 13, 17, 21, 25, - 9, 13, 17, 21, - 5, 9, 13, 17 -}; - -void VP8IteratorStartI4(VP8EncIterator* const it) { - const VP8Encoder* const enc = it->enc_; - int i; - - it->i4_ = 0; // first 4x4 sub-block - it->i4_top_ = it->i4_boundary_ + VP8TopLeftI4[0]; - - // Import the boundary samples - for (i = 0; i < 17; ++i) { // left - it->i4_boundary_[i] = it->y_left_[15 - i]; - } - for (i = 0; i < 16; ++i) { // top - it->i4_boundary_[17 + i] = it->y_top_[i]; - } - // top-right samples have a special case on the far right of the picture - if (it->x_ < enc->mb_w_ - 1) { - for (i = 16; i < 16 + 4; ++i) { - it->i4_boundary_[17 + i] = it->y_top_[i]; - } - } else { // else, replicate the last valid pixel four times - for (i = 16; i < 16 + 4; ++i) { - it->i4_boundary_[17 + i] = it->i4_boundary_[17 + 15]; - } - } - VP8IteratorNzToBytes(it); // import the non-zero context -} - -int VP8IteratorRotateI4(VP8EncIterator* const it, - const uint8_t* const yuv_out) { - const uint8_t* const blk = yuv_out + VP8Scan[it->i4_]; - uint8_t* const top = it->i4_top_; - int i; - - // Update the cache with 7 fresh samples - for (i = 0; i <= 3; ++i) { - top[-4 + i] = blk[i + 3 * BPS]; // store future top samples - } - if ((it->i4_ & 3) != 3) { // if not on the right sub-blocks #3, #7, #11, #15 - for (i = 0; i <= 2; ++i) { // store future left samples - top[i] = blk[3 + (2 - i) * BPS]; - } - } else { // else replicate top-right samples, as says the specs. - for (i = 0; i <= 3; ++i) { - top[i] = top[i + 4]; - } - } - // move pointers to next sub-block - ++it->i4_; - if (it->i4_ == 16) { // we're done - return 0; - } - - it->i4_top_ = it->i4_boundary_ + VP8TopLeftI4[it->i4_]; - return 1; -} - -//------------------------------------------------------------------------------ - diff --git a/Example/Pods/libwebp/src/enc/near_lossless.c b/Example/Pods/libwebp/src/enc/near_lossless.c deleted file mode 100644 index 9bc0f0e7..00000000 --- a/Example/Pods/libwebp/src/enc/near_lossless.c +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Near-lossless image preprocessing adjusts pixel values to help -// compressibility with a guarantee of maximum deviation between original and -// resulting pixel values. -// -// Author: Jyrki Alakuijala (jyrki@google.com) -// Converted to C by Aleksander Kramarz (akramarz@google.com) - -#include - -#include "../dsp/lossless.h" -#include "../utils/utils.h" -#include "./vp8enci.h" - -#define MIN_DIM_FOR_NEAR_LOSSLESS 64 -#define MAX_LIMIT_BITS 5 - -// Computes quantized pixel value and distance from original value. -static void GetValAndDistance(int a, int initial, int bits, - int* const val, int* const distance) { - const int mask = ~((1 << bits) - 1); - *val = (initial & mask) | (initial >> (8 - bits)); - *distance = 2 * abs(a - *val); -} - -// Clamps the value to range [0, 255]. -static int Clamp8b(int val) { - const int min_val = 0; - const int max_val = 0xff; - return (val < min_val) ? min_val : (val > max_val) ? max_val : val; -} - -// Quantizes values {a, a+(1<> 24, bits) << 24) | - (FindClosestDiscretized((a >> 16) & 0xff, bits) << 16) | - (FindClosestDiscretized((a >> 8) & 0xff, bits) << 8) | - (FindClosestDiscretized(a & 0xff, bits)); -} - -// Checks if distance between corresponding channel values of pixels a and b -// is within the given limit. -static int IsNear(uint32_t a, uint32_t b, int limit) { - int k; - for (k = 0; k < 4; ++k) { - const int delta = - (int)((a >> (k * 8)) & 0xff) - (int)((b >> (k * 8)) & 0xff); - if (delta >= limit || delta <= -limit) { - return 0; - } - } - return 1; -} - -static int IsSmooth(const uint32_t* const prev_row, - const uint32_t* const curr_row, - const uint32_t* const next_row, - int ix, int limit) { - // Check that all pixels in 4-connected neighborhood are smooth. - return (IsNear(curr_row[ix], curr_row[ix - 1], limit) && - IsNear(curr_row[ix], curr_row[ix + 1], limit) && - IsNear(curr_row[ix], prev_row[ix], limit) && - IsNear(curr_row[ix], next_row[ix], limit)); -} - -// Adjusts pixel values of image with given maximum error. -static void NearLossless(int xsize, int ysize, uint32_t* argb, - int limit_bits, uint32_t* copy_buffer) { - int x, y; - const int limit = 1 << limit_bits; - uint32_t* prev_row = copy_buffer; - uint32_t* curr_row = prev_row + xsize; - uint32_t* next_row = curr_row + xsize; - memcpy(copy_buffer, argb, xsize * 2 * sizeof(argb[0])); - - for (y = 1; y < ysize - 1; ++y) { - uint32_t* const curr_argb_row = argb + y * xsize; - uint32_t* const next_argb_row = curr_argb_row + xsize; - memcpy(next_row, next_argb_row, xsize * sizeof(argb[0])); - for (x = 1; x < xsize - 1; ++x) { - if (!IsSmooth(prev_row, curr_row, next_row, x, limit)) { - curr_argb_row[x] = ClosestDiscretizedArgb(curr_row[x], limit_bits); - } - } - { - // Three-way swap. - uint32_t* const temp = prev_row; - prev_row = curr_row; - curr_row = next_row; - next_row = temp; - } - } -} - -static int QualityToLimitBits(int quality) { - // quality mapping: - // 0..19 -> 5 - // 0..39 -> 4 - // 0..59 -> 3 - // 0..79 -> 2 - // 0..99 -> 1 - // 100 -> 0 - return MAX_LIMIT_BITS - quality / 20; -} - -int VP8ApplyNearLossless(int xsize, int ysize, uint32_t* argb, int quality) { - int i; - uint32_t* const copy_buffer = - (uint32_t*)WebPSafeMalloc(xsize * 3, sizeof(*copy_buffer)); - const int limit_bits = QualityToLimitBits(quality); - assert(argb != NULL); - assert(limit_bits >= 0); - assert(limit_bits <= MAX_LIMIT_BITS); - if (copy_buffer == NULL) { - return 0; - } - // For small icon images, don't attempt to apply near-lossless compression. - if (xsize < MIN_DIM_FOR_NEAR_LOSSLESS && ysize < MIN_DIM_FOR_NEAR_LOSSLESS) { - WebPSafeFree(copy_buffer); - return 1; - } - - for (i = limit_bits; i != 0; --i) { - NearLossless(xsize, ysize, argb, i, copy_buffer); - } - WebPSafeFree(copy_buffer); - return 1; -} diff --git a/Example/Pods/libwebp/src/enc/picture.c b/Example/Pods/libwebp/src/enc/picture.c deleted file mode 100644 index 26679a72..00000000 --- a/Example/Pods/libwebp/src/enc/picture.c +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// WebPPicture class basis -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include - -#include "./vp8enci.h" -#include "../dsp/dsp.h" -#include "../utils/utils.h" - -//------------------------------------------------------------------------------ -// WebPPicture -//------------------------------------------------------------------------------ - -static int DummyWriter(const uint8_t* data, size_t data_size, - const WebPPicture* const picture) { - // The following are to prevent 'unused variable' error message. - (void)data; - (void)data_size; - (void)picture; - return 1; -} - -int WebPPictureInitInternal(WebPPicture* picture, int version) { - if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_ENCODER_ABI_VERSION)) { - return 0; // caller/system version mismatch! - } - if (picture != NULL) { - memset(picture, 0, sizeof(*picture)); - picture->writer = DummyWriter; - WebPEncodingSetError(picture, VP8_ENC_OK); - } - return 1; -} - -//------------------------------------------------------------------------------ - -static void WebPPictureResetBufferARGB(WebPPicture* const picture) { - picture->memory_argb_ = NULL; - picture->argb = NULL; - picture->argb_stride = 0; -} - -static void WebPPictureResetBufferYUVA(WebPPicture* const picture) { - picture->memory_ = NULL; - picture->y = picture->u = picture->v = picture->a = NULL; - picture->y_stride = picture->uv_stride = 0; - picture->a_stride = 0; -} - -void WebPPictureResetBuffers(WebPPicture* const picture) { - WebPPictureResetBufferARGB(picture); - WebPPictureResetBufferYUVA(picture); -} - -int WebPPictureAllocARGB(WebPPicture* const picture, int width, int height) { - void* memory; - const uint64_t argb_size = (uint64_t)width * height; - - assert(picture != NULL); - - WebPSafeFree(picture->memory_argb_); - WebPPictureResetBufferARGB(picture); - - if (width <= 0 || height <= 0) { - return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION); - } - // allocate a new buffer. - memory = WebPSafeMalloc(argb_size, sizeof(*picture->argb)); - if (memory == NULL) { - return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); - } - // TODO(skal): align plane to cache line? - picture->memory_argb_ = memory; - picture->argb = (uint32_t*)memory; - picture->argb_stride = width; - return 1; -} - -int WebPPictureAllocYUVA(WebPPicture* const picture, int width, int height) { - const WebPEncCSP uv_csp = picture->colorspace & WEBP_CSP_UV_MASK; - const int has_alpha = picture->colorspace & WEBP_CSP_ALPHA_BIT; - const int y_stride = width; - const int uv_width = (width + 1) >> 1; - const int uv_height = (height + 1) >> 1; - const int uv_stride = uv_width; - int a_width, a_stride; - uint64_t y_size, uv_size, a_size, total_size; - uint8_t* mem; - - assert(picture != NULL); - - WebPSafeFree(picture->memory_); - WebPPictureResetBufferYUVA(picture); - - if (uv_csp != WEBP_YUV420) { - return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION); - } - - // alpha - a_width = has_alpha ? width : 0; - a_stride = a_width; - y_size = (uint64_t)y_stride * height; - uv_size = (uint64_t)uv_stride * uv_height; - a_size = (uint64_t)a_stride * height; - - total_size = y_size + a_size + 2 * uv_size; - - // Security and validation checks - if (width <= 0 || height <= 0 || // luma/alpha param error - uv_width < 0 || uv_height < 0) { // u/v param error - return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION); - } - // allocate a new buffer. - mem = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*mem)); - if (mem == NULL) { - return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); - } - - // From now on, we're in the clear, we can no longer fail... - picture->memory_ = (void*)mem; - picture->y_stride = y_stride; - picture->uv_stride = uv_stride; - picture->a_stride = a_stride; - - // TODO(skal): we could align the y/u/v planes and adjust stride. - picture->y = mem; - mem += y_size; - - picture->u = mem; - mem += uv_size; - picture->v = mem; - mem += uv_size; - - if (a_size > 0) { - picture->a = mem; - mem += a_size; - } - (void)mem; // makes the static analyzer happy - return 1; -} - -int WebPPictureAlloc(WebPPicture* picture) { - if (picture != NULL) { - const int width = picture->width; - const int height = picture->height; - - WebPPictureFree(picture); // erase previous buffer - - if (!picture->use_argb) { - return WebPPictureAllocYUVA(picture, width, height); - } else { - return WebPPictureAllocARGB(picture, width, height); - } - } - return 1; -} - -void WebPPictureFree(WebPPicture* picture) { - if (picture != NULL) { - WebPSafeFree(picture->memory_); - WebPSafeFree(picture->memory_argb_); - WebPPictureResetBuffers(picture); - } -} - -//------------------------------------------------------------------------------ -// WebPMemoryWriter: Write-to-memory - -void WebPMemoryWriterInit(WebPMemoryWriter* writer) { - writer->mem = NULL; - writer->size = 0; - writer->max_size = 0; -} - -int WebPMemoryWrite(const uint8_t* data, size_t data_size, - const WebPPicture* picture) { - WebPMemoryWriter* const w = (WebPMemoryWriter*)picture->custom_ptr; - uint64_t next_size; - if (w == NULL) { - return 1; - } - next_size = (uint64_t)w->size + data_size; - if (next_size > w->max_size) { - uint8_t* new_mem; - uint64_t next_max_size = 2ULL * w->max_size; - if (next_max_size < next_size) next_max_size = next_size; - if (next_max_size < 8192ULL) next_max_size = 8192ULL; - new_mem = (uint8_t*)WebPSafeMalloc(next_max_size, 1); - if (new_mem == NULL) { - return 0; - } - if (w->size > 0) { - memcpy(new_mem, w->mem, w->size); - } - WebPSafeFree(w->mem); - w->mem = new_mem; - // down-cast is ok, thanks to WebPSafeMalloc - w->max_size = (size_t)next_max_size; - } - if (data_size > 0) { - memcpy(w->mem + w->size, data, data_size); - w->size += data_size; - } - return 1; -} - -void WebPMemoryWriterClear(WebPMemoryWriter* writer) { - if (writer != NULL) { - WebPSafeFree(writer->mem); - writer->mem = NULL; - writer->size = 0; - writer->max_size = 0; - } -} - -//------------------------------------------------------------------------------ -// Simplest high-level calls: - -typedef int (*Importer)(WebPPicture* const, const uint8_t* const, int); - -static size_t Encode(const uint8_t* rgba, int width, int height, int stride, - Importer import, float quality_factor, int lossless, - uint8_t** output) { - WebPPicture pic; - WebPConfig config; - WebPMemoryWriter wrt; - int ok; - - if (!WebPConfigPreset(&config, WEBP_PRESET_DEFAULT, quality_factor) || - !WebPPictureInit(&pic)) { - return 0; // shouldn't happen, except if system installation is broken - } - - config.lossless = !!lossless; - pic.use_argb = !!lossless; - pic.width = width; - pic.height = height; - pic.writer = WebPMemoryWrite; - pic.custom_ptr = &wrt; - WebPMemoryWriterInit(&wrt); - - ok = import(&pic, rgba, stride) && WebPEncode(&config, &pic); - WebPPictureFree(&pic); - if (!ok) { - WebPMemoryWriterClear(&wrt); - *output = NULL; - return 0; - } - *output = wrt.mem; - return wrt.size; -} - -#define ENCODE_FUNC(NAME, IMPORTER) \ -size_t NAME(const uint8_t* in, int w, int h, int bps, float q, \ - uint8_t** out) { \ - return Encode(in, w, h, bps, IMPORTER, q, 0, out); \ -} - -ENCODE_FUNC(WebPEncodeRGB, WebPPictureImportRGB) -ENCODE_FUNC(WebPEncodeBGR, WebPPictureImportBGR) -ENCODE_FUNC(WebPEncodeRGBA, WebPPictureImportRGBA) -ENCODE_FUNC(WebPEncodeBGRA, WebPPictureImportBGRA) - -#undef ENCODE_FUNC - -#define LOSSLESS_DEFAULT_QUALITY 70. -#define LOSSLESS_ENCODE_FUNC(NAME, IMPORTER) \ -size_t NAME(const uint8_t* in, int w, int h, int bps, uint8_t** out) { \ - return Encode(in, w, h, bps, IMPORTER, LOSSLESS_DEFAULT_QUALITY, 1, out); \ -} - -LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessRGB, WebPPictureImportRGB) -LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGR, WebPPictureImportBGR) -LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessRGBA, WebPPictureImportRGBA) -LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGRA, WebPPictureImportBGRA) - -#undef LOSSLESS_ENCODE_FUNC - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/enc/picture_csp.c b/Example/Pods/libwebp/src/enc/picture_csp.c deleted file mode 100644 index 0ef5f9ee..00000000 --- a/Example/Pods/libwebp/src/enc/picture_csp.c +++ /dev/null @@ -1,1156 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// WebPPicture utils for colorspace conversion -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include -#include - -#include "./vp8enci.h" -#include "../utils/random.h" -#include "../utils/utils.h" -#include "../dsp/yuv.h" - -// Uncomment to disable gamma-compression during RGB->U/V averaging -#define USE_GAMMA_COMPRESSION - -// If defined, use table to compute x / alpha. -#define USE_INVERSE_ALPHA_TABLE - -static const union { - uint32_t argb; - uint8_t bytes[4]; -} test_endian = { 0xff000000u }; -#define ALPHA_IS_LAST (test_endian.bytes[3] == 0xff) - -//------------------------------------------------------------------------------ -// Detection of non-trivial transparency - -// Returns true if alpha[] has non-0xff values. -static int CheckNonOpaque(const uint8_t* alpha, int width, int height, - int x_step, int y_step) { - if (alpha == NULL) return 0; - while (height-- > 0) { - int x; - for (x = 0; x < width * x_step; x += x_step) { - if (alpha[x] != 0xff) return 1; // TODO(skal): check 4/8 bytes at a time. - } - alpha += y_step; - } - return 0; -} - -// Checking for the presence of non-opaque alpha. -int WebPPictureHasTransparency(const WebPPicture* picture) { - if (picture == NULL) return 0; - if (!picture->use_argb) { - return CheckNonOpaque(picture->a, picture->width, picture->height, - 1, picture->a_stride); - } else { - int x, y; - const uint32_t* argb = picture->argb; - if (argb == NULL) return 0; - for (y = 0; y < picture->height; ++y) { - for (x = 0; x < picture->width; ++x) { - if (argb[x] < 0xff000000u) return 1; // test any alpha values != 0xff - } - argb += picture->argb_stride; - } - } - return 0; -} - -//------------------------------------------------------------------------------ -// Code for gamma correction - -#if defined(USE_GAMMA_COMPRESSION) - -// gamma-compensates loss of resolution during chroma subsampling -#define kGamma 0.80 // for now we use a different gamma value than kGammaF -#define kGammaFix 12 // fixed-point precision for linear values -#define kGammaScale ((1 << kGammaFix) - 1) -#define kGammaTabFix 7 // fixed-point fractional bits precision -#define kGammaTabScale (1 << kGammaTabFix) -#define kGammaTabRounder (kGammaTabScale >> 1) -#define kGammaTabSize (1 << (kGammaFix - kGammaTabFix)) - -static int kLinearToGammaTab[kGammaTabSize + 1]; -static uint16_t kGammaToLinearTab[256]; -static volatile int kGammaTablesOk = 0; - -static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTables(void) { - if (!kGammaTablesOk) { - int v; - const double scale = (double)(1 << kGammaTabFix) / kGammaScale; - const double norm = 1. / 255.; - for (v = 0; v <= 255; ++v) { - kGammaToLinearTab[v] = - (uint16_t)(pow(norm * v, kGamma) * kGammaScale + .5); - } - for (v = 0; v <= kGammaTabSize; ++v) { - kLinearToGammaTab[v] = (int)(255. * pow(scale * v, 1. / kGamma) + .5); - } - kGammaTablesOk = 1; - } -} - -static WEBP_INLINE uint32_t GammaToLinear(uint8_t v) { - return kGammaToLinearTab[v]; -} - -static WEBP_INLINE int Interpolate(int v) { - const int tab_pos = v >> (kGammaTabFix + 2); // integer part - const int x = v & ((kGammaTabScale << 2) - 1); // fractional part - const int v0 = kLinearToGammaTab[tab_pos]; - const int v1 = kLinearToGammaTab[tab_pos + 1]; - const int y = v1 * x + v0 * ((kGammaTabScale << 2) - x); // interpolate - assert(tab_pos + 1 < kGammaTabSize + 1); - return y; -} - -// Convert a linear value 'v' to YUV_FIX+2 fixed-point precision -// U/V value, suitable for RGBToU/V calls. -static WEBP_INLINE int LinearToGamma(uint32_t base_value, int shift) { - const int y = Interpolate(base_value << shift); // final uplifted value - return (y + kGammaTabRounder) >> kGammaTabFix; // descale -} - -#else - -static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTables(void) {} -static WEBP_INLINE uint32_t GammaToLinear(uint8_t v) { return v; } -static WEBP_INLINE int LinearToGamma(uint32_t base_value, int shift) { - return (int)(base_value << shift); -} - -#endif // USE_GAMMA_COMPRESSION - -//------------------------------------------------------------------------------ -// RGB -> YUV conversion - -static int RGBToY(int r, int g, int b, VP8Random* const rg) { - return (rg == NULL) ? VP8RGBToY(r, g, b, YUV_HALF) - : VP8RGBToY(r, g, b, VP8RandomBits(rg, YUV_FIX)); -} - -static int RGBToU(int r, int g, int b, VP8Random* const rg) { - return (rg == NULL) ? VP8RGBToU(r, g, b, YUV_HALF << 2) - : VP8RGBToU(r, g, b, VP8RandomBits(rg, YUV_FIX + 2)); -} - -static int RGBToV(int r, int g, int b, VP8Random* const rg) { - return (rg == NULL) ? VP8RGBToV(r, g, b, YUV_HALF << 2) - : VP8RGBToV(r, g, b, VP8RandomBits(rg, YUV_FIX + 2)); -} - -//------------------------------------------------------------------------------ -// Smart RGB->YUV conversion - -static const int kNumIterations = 6; -static const int kMinDimensionIterativeConversion = 4; - -// We could use SFIX=0 and only uint8_t for fixed_y_t, but it produces some -// banding sometimes. Better use extra precision. -#define SFIX 2 // fixed-point precision of RGB and Y/W -typedef int16_t fixed_t; // signed type with extra SFIX precision for UV -typedef uint16_t fixed_y_t; // unsigned type with extra SFIX precision for W - -#define SHALF (1 << SFIX >> 1) -#define MAX_Y_T ((256 << SFIX) - 1) -#define SROUNDER (1 << (YUV_FIX + SFIX - 1)) - -#if defined(USE_GAMMA_COMPRESSION) - -// float variant of gamma-correction -// We use tables of different size and precision, along with a 'real-world' -// Gamma value close to ~2. -#define kGammaF 2.2 -static float kGammaToLinearTabF[MAX_Y_T + 1]; // size scales with Y_FIX -static float kLinearToGammaTabF[kGammaTabSize + 2]; -static volatile int kGammaTablesFOk = 0; - -static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTablesF(void) { - if (!kGammaTablesFOk) { - int v; - const double norm = 1. / MAX_Y_T; - const double scale = 1. / kGammaTabSize; - for (v = 0; v <= MAX_Y_T; ++v) { - kGammaToLinearTabF[v] = (float)pow(norm * v, kGammaF); - } - for (v = 0; v <= kGammaTabSize; ++v) { - kLinearToGammaTabF[v] = (float)(MAX_Y_T * pow(scale * v, 1. / kGammaF)); - } - // to prevent small rounding errors to cause read-overflow: - kLinearToGammaTabF[kGammaTabSize + 1] = kLinearToGammaTabF[kGammaTabSize]; - kGammaTablesFOk = 1; - } -} - -static WEBP_INLINE float GammaToLinearF(int v) { - return kGammaToLinearTabF[v]; -} - -static WEBP_INLINE int LinearToGammaF(float value) { - const float v = value * kGammaTabSize; - const int tab_pos = (int)v; - const float x = v - (float)tab_pos; // fractional part - const float v0 = kLinearToGammaTabF[tab_pos + 0]; - const float v1 = kLinearToGammaTabF[tab_pos + 1]; - const float y = v1 * x + v0 * (1.f - x); // interpolate - return (int)(y + .5); -} - -#else - -static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTablesF(void) {} -static WEBP_INLINE float GammaToLinearF(int v) { - const float norm = 1.f / MAX_Y_T; - return norm * v; -} -static WEBP_INLINE int LinearToGammaF(float value) { - return (int)(MAX_Y_T * value + .5); -} - -#endif // USE_GAMMA_COMPRESSION - -//------------------------------------------------------------------------------ - -static uint8_t clip_8b(fixed_t v) { - return (!(v & ~0xff)) ? (uint8_t)v : (v < 0) ? 0u : 255u; -} - -static fixed_y_t clip_y(int y) { - return (!(y & ~MAX_Y_T)) ? (fixed_y_t)y : (y < 0) ? 0 : MAX_Y_T; -} - -//------------------------------------------------------------------------------ - -static int RGBToGray(int r, int g, int b) { - const int luma = 19595 * r + 38470 * g + 7471 * b + YUV_HALF; - return (luma >> YUV_FIX); -} - -static float RGBToGrayF(float r, float g, float b) { - return 0.299f * r + 0.587f * g + 0.114f * b; -} - -static int ScaleDown(int a, int b, int c, int d) { - const float A = GammaToLinearF(a); - const float B = GammaToLinearF(b); - const float C = GammaToLinearF(c); - const float D = GammaToLinearF(d); - return LinearToGammaF(0.25f * (A + B + C + D)); -} - -static WEBP_INLINE void UpdateW(const fixed_y_t* src, fixed_y_t* dst, int len) { - while (len-- > 0) { - const float R = GammaToLinearF(src[0]); - const float G = GammaToLinearF(src[1]); - const float B = GammaToLinearF(src[2]); - const float Y = RGBToGrayF(R, G, B); - *dst++ = (fixed_y_t)LinearToGammaF(Y); - src += 3; - } -} - -static int UpdateChroma(const fixed_y_t* src1, - const fixed_y_t* src2, - fixed_t* dst, fixed_y_t* tmp, int len) { - int diff = 0; - while (len--> 0) { - const int r = ScaleDown(src1[0], src1[3], src2[0], src2[3]); - const int g = ScaleDown(src1[1], src1[4], src2[1], src2[4]); - const int b = ScaleDown(src1[2], src1[5], src2[2], src2[5]); - const int W = RGBToGray(r, g, b); - const int r_avg = (src1[0] + src1[3] + src2[0] + src2[3] + 2) >> 2; - const int g_avg = (src1[1] + src1[4] + src2[1] + src2[4] + 2) >> 2; - const int b_avg = (src1[2] + src1[5] + src2[2] + src2[5] + 2) >> 2; - dst[0] = (fixed_t)(r - W); - dst[1] = (fixed_t)(g - W); - dst[2] = (fixed_t)(b - W); - dst += 3; - src1 += 6; - src2 += 6; - if (tmp != NULL) { - tmp[0] = tmp[1] = clip_y(W); - tmp += 2; - } - diff += abs(RGBToGray(r_avg, g_avg, b_avg) - W); - } - return diff; -} - -//------------------------------------------------------------------------------ - -static WEBP_INLINE int Filter(const fixed_t* const A, const fixed_t* const B, - int rightwise) { - int v; - if (!rightwise) { - v = (A[0] * 9 + A[-3] * 3 + B[0] * 3 + B[-3]); - } else { - v = (A[0] * 9 + A[+3] * 3 + B[0] * 3 + B[+3]); - } - return (v + 8) >> 4; -} - -static WEBP_INLINE int Filter2(int A, int B) { return (A * 3 + B + 2) >> 2; } - -//------------------------------------------------------------------------------ - -static WEBP_INLINE fixed_y_t UpLift(uint8_t a) { // 8bit -> SFIX - return ((fixed_y_t)a << SFIX) | SHALF; -} - -static void ImportOneRow(const uint8_t* const r_ptr, - const uint8_t* const g_ptr, - const uint8_t* const b_ptr, - int step, - int pic_width, - fixed_y_t* const dst) { - int i; - for (i = 0; i < pic_width; ++i) { - const int off = i * step; - dst[3 * i + 0] = UpLift(r_ptr[off]); - dst[3 * i + 1] = UpLift(g_ptr[off]); - dst[3 * i + 2] = UpLift(b_ptr[off]); - } - if (pic_width & 1) { // replicate rightmost pixel - memcpy(dst + 3 * pic_width, dst + 3 * (pic_width - 1), 3 * sizeof(*dst)); - } -} - -static void InterpolateTwoRows(const fixed_y_t* const best_y, - const fixed_t* const prev_uv, - const fixed_t* const cur_uv, - const fixed_t* const next_uv, - int w, - fixed_y_t* const out1, - fixed_y_t* const out2) { - int i, k; - { // special boundary case for i==0 - const int W0 = best_y[0]; - const int W1 = best_y[w]; - for (k = 0; k <= 2; ++k) { - out1[k] = clip_y(Filter2(cur_uv[k], prev_uv[k]) + W0); - out2[k] = clip_y(Filter2(cur_uv[k], next_uv[k]) + W1); - } - } - for (i = 1; i < w - 1; ++i) { - const int W0 = best_y[i + 0]; - const int W1 = best_y[i + w]; - const int off = 3 * (i >> 1); - for (k = 0; k <= 2; ++k) { - const int tmp0 = Filter(cur_uv + off + k, prev_uv + off + k, i & 1); - const int tmp1 = Filter(cur_uv + off + k, next_uv + off + k, i & 1); - out1[3 * i + k] = clip_y(tmp0 + W0); - out2[3 * i + k] = clip_y(tmp1 + W1); - } - } - { // special boundary case for i == w - 1 - const int W0 = best_y[i + 0]; - const int W1 = best_y[i + w]; - const int off = 3 * (i >> 1); - for (k = 0; k <= 2; ++k) { - out1[3 * i + k] = clip_y(Filter2(cur_uv[off + k], prev_uv[off + k]) + W0); - out2[3 * i + k] = clip_y(Filter2(cur_uv[off + k], next_uv[off + k]) + W1); - } - } -} - -static WEBP_INLINE uint8_t ConvertRGBToY(int r, int g, int b) { - const int luma = 16839 * r + 33059 * g + 6420 * b + SROUNDER; - return clip_8b(16 + (luma >> (YUV_FIX + SFIX))); -} - -static WEBP_INLINE uint8_t ConvertRGBToU(int r, int g, int b) { - const int u = -9719 * r - 19081 * g + 28800 * b + SROUNDER; - return clip_8b(128 + (u >> (YUV_FIX + SFIX))); -} - -static WEBP_INLINE uint8_t ConvertRGBToV(int r, int g, int b) { - const int v = +28800 * r - 24116 * g - 4684 * b + SROUNDER; - return clip_8b(128 + (v >> (YUV_FIX + SFIX))); -} - -static int ConvertWRGBToYUV(const fixed_y_t* const best_y, - const fixed_t* const best_uv, - WebPPicture* const picture) { - int i, j; - const int w = (picture->width + 1) & ~1; - const int h = (picture->height + 1) & ~1; - const int uv_w = w >> 1; - const int uv_h = h >> 1; - for (j = 0; j < picture->height; ++j) { - for (i = 0; i < picture->width; ++i) { - const int off = 3 * ((i >> 1) + (j >> 1) * uv_w); - const int off2 = i + j * picture->y_stride; - const int W = best_y[i + j * w]; - const int r = best_uv[off + 0] + W; - const int g = best_uv[off + 1] + W; - const int b = best_uv[off + 2] + W; - picture->y[off2] = ConvertRGBToY(r, g, b); - } - } - for (j = 0; j < uv_h; ++j) { - uint8_t* const dst_u = picture->u + j * picture->uv_stride; - uint8_t* const dst_v = picture->v + j * picture->uv_stride; - for (i = 0; i < uv_w; ++i) { - const int off = 3 * (i + j * uv_w); - const int r = best_uv[off + 0]; - const int g = best_uv[off + 1]; - const int b = best_uv[off + 2]; - dst_u[i] = ConvertRGBToU(r, g, b); - dst_v[i] = ConvertRGBToV(r, g, b); - } - } - return 1; -} - -//------------------------------------------------------------------------------ -// Main function - -#define SAFE_ALLOC(W, H, T) ((T*)WebPSafeMalloc((W) * (H), sizeof(T))) - -static int PreprocessARGB(const uint8_t* const r_ptr, - const uint8_t* const g_ptr, - const uint8_t* const b_ptr, - int step, int rgb_stride, - WebPPicture* const picture) { - // we expand the right/bottom border if needed - const int w = (picture->width + 1) & ~1; - const int h = (picture->height + 1) & ~1; - const int uv_w = w >> 1; - const int uv_h = h >> 1; - int i, j, iter; - - // TODO(skal): allocate one big memory chunk. But for now, it's easier - // for valgrind debugging to have several chunks. - fixed_y_t* const tmp_buffer = SAFE_ALLOC(w * 3, 2, fixed_y_t); // scratch - fixed_y_t* const best_y = SAFE_ALLOC(w, h, fixed_y_t); - fixed_y_t* const target_y = SAFE_ALLOC(w, h, fixed_y_t); - fixed_y_t* const best_rgb_y = SAFE_ALLOC(w, 2, fixed_y_t); - fixed_t* const best_uv = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t); - fixed_t* const target_uv = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t); - fixed_t* const best_rgb_uv = SAFE_ALLOC(uv_w * 3, 1, fixed_t); - int ok; - int diff_sum = 0; - const int first_diff_threshold = (int)(2.5 * w * h); - const int min_improvement = 5; // stop if improvement is below this % - const int min_first_improvement = 80; - - if (best_y == NULL || best_uv == NULL || - target_y == NULL || target_uv == NULL || - best_rgb_y == NULL || best_rgb_uv == NULL || - tmp_buffer == NULL) { - ok = WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); - goto End; - } - assert(picture->width >= kMinDimensionIterativeConversion); - assert(picture->height >= kMinDimensionIterativeConversion); - - // Import RGB samples to W/RGB representation. - for (j = 0; j < picture->height; j += 2) { - const int is_last_row = (j == picture->height - 1); - fixed_y_t* const src1 = tmp_buffer; - fixed_y_t* const src2 = tmp_buffer + 3 * w; - const int off1 = j * rgb_stride; - const int off2 = off1 + rgb_stride; - const int uv_off = (j >> 1) * 3 * uv_w; - fixed_y_t* const dst_y = best_y + j * w; - - // prepare two rows of input - ImportOneRow(r_ptr + off1, g_ptr + off1, b_ptr + off1, - step, picture->width, src1); - if (!is_last_row) { - ImportOneRow(r_ptr + off2, g_ptr + off2, b_ptr + off2, - step, picture->width, src2); - } else { - memcpy(src2, src1, 3 * w * sizeof(*src2)); - } - UpdateW(src1, target_y + (j + 0) * w, w); - UpdateW(src2, target_y + (j + 1) * w, w); - diff_sum += UpdateChroma(src1, src2, target_uv + uv_off, dst_y, uv_w); - memcpy(best_uv + uv_off, target_uv + uv_off, 3 * uv_w * sizeof(*best_uv)); - memcpy(dst_y + w, dst_y, w * sizeof(*dst_y)); - } - - // Iterate and resolve clipping conflicts. - for (iter = 0; iter < kNumIterations; ++iter) { - int k; - const fixed_t* cur_uv = best_uv; - const fixed_t* prev_uv = best_uv; - const int old_diff_sum = diff_sum; - diff_sum = 0; - for (j = 0; j < h; j += 2) { - fixed_y_t* const src1 = tmp_buffer; - fixed_y_t* const src2 = tmp_buffer + 3 * w; - { - const fixed_t* const next_uv = cur_uv + ((j < h - 2) ? 3 * uv_w : 0); - InterpolateTwoRows(best_y + j * w, prev_uv, cur_uv, next_uv, - w, src1, src2); - prev_uv = cur_uv; - cur_uv = next_uv; - } - - UpdateW(src1, best_rgb_y + 0 * w, w); - UpdateW(src2, best_rgb_y + 1 * w, w); - diff_sum += UpdateChroma(src1, src2, best_rgb_uv, NULL, uv_w); - - // update two rows of Y and one row of RGB - for (i = 0; i < 2 * w; ++i) { - const int off = i + j * w; - const int diff_y = target_y[off] - best_rgb_y[i]; - const int new_y = (int)best_y[off] + diff_y; - best_y[off] = clip_y(new_y); - } - for (i = 0; i < uv_w; ++i) { - const int off = 3 * (i + (j >> 1) * uv_w); - int W; - for (k = 0; k <= 2; ++k) { - const int diff_uv = (int)target_uv[off + k] - best_rgb_uv[3 * i + k]; - best_uv[off + k] += diff_uv; - } - W = RGBToGray(best_uv[off + 0], best_uv[off + 1], best_uv[off + 2]); - for (k = 0; k <= 2; ++k) { - best_uv[off + k] -= W; - } - } - } - // test exit condition - if (diff_sum > 0) { - const int improvement = 100 * abs(diff_sum - old_diff_sum) / diff_sum; - // Check if first iteration gave good result already, without a large - // jump of improvement (otherwise it means we need to try few extra - // iterations, just to be sure). - if (iter == 0 && diff_sum < first_diff_threshold && - improvement < min_first_improvement) { - break; - } - // then, check if improvement is stalling. - if (improvement < min_improvement) { - break; - } - } else { - break; - } - } - - // final reconstruction - ok = ConvertWRGBToYUV(best_y, best_uv, picture); - - End: - WebPSafeFree(best_y); - WebPSafeFree(best_uv); - WebPSafeFree(target_y); - WebPSafeFree(target_uv); - WebPSafeFree(best_rgb_y); - WebPSafeFree(best_rgb_uv); - WebPSafeFree(tmp_buffer); - return ok; -} -#undef SAFE_ALLOC - -//------------------------------------------------------------------------------ -// "Fast" regular RGB->YUV - -#define SUM4(ptr, step) LinearToGamma( \ - GammaToLinear((ptr)[0]) + \ - GammaToLinear((ptr)[(step)]) + \ - GammaToLinear((ptr)[rgb_stride]) + \ - GammaToLinear((ptr)[rgb_stride + (step)]), 0) \ - -#define SUM2(ptr) \ - LinearToGamma(GammaToLinear((ptr)[0]) + GammaToLinear((ptr)[rgb_stride]), 1) - -#define SUM2ALPHA(ptr) ((ptr)[0] + (ptr)[rgb_stride]) -#define SUM4ALPHA(ptr) (SUM2ALPHA(ptr) + SUM2ALPHA((ptr) + 4)) - -#if defined(USE_INVERSE_ALPHA_TABLE) - -static const int kAlphaFix = 19; -// Following table is (1 << kAlphaFix) / a. The (v * kInvAlpha[a]) >> kAlphaFix -// formula is then equal to v / a in most (99.6%) cases. Note that this table -// and constant are adjusted very tightly to fit 32b arithmetic. -// In particular, they use the fact that the operands for 'v / a' are actually -// derived as v = (a0.p0 + a1.p1 + a2.p2 + a3.p3) and a = a0 + a1 + a2 + a3 -// with ai in [0..255] and pi in [0..1<> (kAlphaFix - 2)) - -#else - -#define DIVIDE_BY_ALPHA(sum, a) (4 * (sum) / (a)) - -#endif // USE_INVERSE_ALPHA_TABLE - -static WEBP_INLINE int LinearToGammaWeighted(const uint8_t* src, - const uint8_t* a_ptr, - uint32_t total_a, int step, - int rgb_stride) { - const uint32_t sum = - a_ptr[0] * GammaToLinear(src[0]) + - a_ptr[step] * GammaToLinear(src[step]) + - a_ptr[rgb_stride] * GammaToLinear(src[rgb_stride]) + - a_ptr[rgb_stride + step] * GammaToLinear(src[rgb_stride + step]); - assert(total_a > 0 && total_a <= 4 * 0xff); -#if defined(USE_INVERSE_ALPHA_TABLE) - assert((uint64_t)sum * kInvAlpha[total_a] < ((uint64_t)1 << 32)); -#endif - return LinearToGamma(DIVIDE_BY_ALPHA(sum, total_a), 0); -} - -static WEBP_INLINE void ConvertRowToY(const uint8_t* const r_ptr, - const uint8_t* const g_ptr, - const uint8_t* const b_ptr, - int step, - uint8_t* const dst_y, - int width, - VP8Random* const rg) { - int i, j; - for (i = 0, j = 0; i < width; i += 1, j += step) { - dst_y[i] = RGBToY(r_ptr[j], g_ptr[j], b_ptr[j], rg); - } -} - -static WEBP_INLINE void AccumulateRGBA(const uint8_t* const r_ptr, - const uint8_t* const g_ptr, - const uint8_t* const b_ptr, - const uint8_t* const a_ptr, - int rgb_stride, - uint16_t* dst, int width) { - int i, j; - // we loop over 2x2 blocks and produce one R/G/B/A value for each. - for (i = 0, j = 0; i < (width >> 1); i += 1, j += 2 * 4, dst += 4) { - const uint32_t a = SUM4ALPHA(a_ptr + j); - int r, g, b; - if (a == 4 * 0xff || a == 0) { - r = SUM4(r_ptr + j, 4); - g = SUM4(g_ptr + j, 4); - b = SUM4(b_ptr + j, 4); - } else { - r = LinearToGammaWeighted(r_ptr + j, a_ptr + j, a, 4, rgb_stride); - g = LinearToGammaWeighted(g_ptr + j, a_ptr + j, a, 4, rgb_stride); - b = LinearToGammaWeighted(b_ptr + j, a_ptr + j, a, 4, rgb_stride); - } - dst[0] = r; - dst[1] = g; - dst[2] = b; - dst[3] = a; - } - if (width & 1) { - const uint32_t a = 2u * SUM2ALPHA(a_ptr + j); - int r, g, b; - if (a == 4 * 0xff || a == 0) { - r = SUM2(r_ptr + j); - g = SUM2(g_ptr + j); - b = SUM2(b_ptr + j); - } else { - r = LinearToGammaWeighted(r_ptr + j, a_ptr + j, a, 0, rgb_stride); - g = LinearToGammaWeighted(g_ptr + j, a_ptr + j, a, 0, rgb_stride); - b = LinearToGammaWeighted(b_ptr + j, a_ptr + j, a, 0, rgb_stride); - } - dst[0] = r; - dst[1] = g; - dst[2] = b; - dst[3] = a; - } -} - -static WEBP_INLINE void AccumulateRGB(const uint8_t* const r_ptr, - const uint8_t* const g_ptr, - const uint8_t* const b_ptr, - int step, int rgb_stride, - uint16_t* dst, int width) { - int i, j; - for (i = 0, j = 0; i < (width >> 1); i += 1, j += 2 * step, dst += 4) { - dst[0] = SUM4(r_ptr + j, step); - dst[1] = SUM4(g_ptr + j, step); - dst[2] = SUM4(b_ptr + j, step); - } - if (width & 1) { - dst[0] = SUM2(r_ptr + j); - dst[1] = SUM2(g_ptr + j); - dst[2] = SUM2(b_ptr + j); - } -} - -static WEBP_INLINE void ConvertRowsToUV(const uint16_t* rgb, - uint8_t* const dst_u, - uint8_t* const dst_v, - int width, - VP8Random* const rg) { - int i; - for (i = 0; i < width; i += 1, rgb += 4) { - const int r = rgb[0], g = rgb[1], b = rgb[2]; - dst_u[i] = RGBToU(r, g, b, rg); - dst_v[i] = RGBToV(r, g, b, rg); - } -} - -static int ImportYUVAFromRGBA(const uint8_t* const r_ptr, - const uint8_t* const g_ptr, - const uint8_t* const b_ptr, - const uint8_t* const a_ptr, - int step, // bytes per pixel - int rgb_stride, // bytes per scanline - float dithering, - int use_iterative_conversion, - WebPPicture* const picture) { - int y; - const int width = picture->width; - const int height = picture->height; - const int has_alpha = CheckNonOpaque(a_ptr, width, height, step, rgb_stride); - const int is_rgb = (r_ptr < b_ptr); // otherwise it's bgr - - picture->colorspace = has_alpha ? WEBP_YUV420A : WEBP_YUV420; - picture->use_argb = 0; - - // disable smart conversion if source is too small (overkill). - if (width < kMinDimensionIterativeConversion || - height < kMinDimensionIterativeConversion) { - use_iterative_conversion = 0; - } - - if (!WebPPictureAllocYUVA(picture, width, height)) { - return 0; - } - if (has_alpha) { - WebPInitAlphaProcessing(); - assert(step == 4); -#if defined(USE_GAMMA_COMPRESSION) && defined(USE_INVERSE_ALPHA_TABLE) - assert(kAlphaFix + kGammaFix <= 31); -#endif - } - - if (use_iterative_conversion) { - InitGammaTablesF(); - if (!PreprocessARGB(r_ptr, g_ptr, b_ptr, step, rgb_stride, picture)) { - return 0; - } - if (has_alpha) { - WebPExtractAlpha(a_ptr, rgb_stride, width, height, - picture->a, picture->a_stride); - } - } else { - const int uv_width = (width + 1) >> 1; - int use_dsp = (step == 3); // use special function in this case - // temporary storage for accumulated R/G/B values during conversion to U/V - uint16_t* const tmp_rgb = - (uint16_t*)WebPSafeMalloc(4 * uv_width, sizeof(*tmp_rgb)); - uint8_t* dst_y = picture->y; - uint8_t* dst_u = picture->u; - uint8_t* dst_v = picture->v; - uint8_t* dst_a = picture->a; - - VP8Random base_rg; - VP8Random* rg = NULL; - if (dithering > 0.) { - VP8InitRandom(&base_rg, dithering); - rg = &base_rg; - use_dsp = 0; // can't use dsp in this case - } - WebPInitConvertARGBToYUV(); - InitGammaTables(); - - if (tmp_rgb == NULL) return 0; // malloc error - - // Downsample Y/U/V planes, two rows at a time - for (y = 0; y < (height >> 1); ++y) { - int rows_have_alpha = has_alpha; - const int off1 = (2 * y + 0) * rgb_stride; - const int off2 = (2 * y + 1) * rgb_stride; - if (use_dsp) { - if (is_rgb) { - WebPConvertRGB24ToY(r_ptr + off1, dst_y, width); - WebPConvertRGB24ToY(r_ptr + off2, dst_y + picture->y_stride, width); - } else { - WebPConvertBGR24ToY(b_ptr + off1, dst_y, width); - WebPConvertBGR24ToY(b_ptr + off2, dst_y + picture->y_stride, width); - } - } else { - ConvertRowToY(r_ptr + off1, g_ptr + off1, b_ptr + off1, step, - dst_y, width, rg); - ConvertRowToY(r_ptr + off2, g_ptr + off2, b_ptr + off2, step, - dst_y + picture->y_stride, width, rg); - } - dst_y += 2 * picture->y_stride; - if (has_alpha) { - rows_have_alpha &= !WebPExtractAlpha(a_ptr + off1, rgb_stride, - width, 2, - dst_a, picture->a_stride); - dst_a += 2 * picture->a_stride; - } - // Collect averaged R/G/B(/A) - if (!rows_have_alpha) { - AccumulateRGB(r_ptr + off1, g_ptr + off1, b_ptr + off1, - step, rgb_stride, tmp_rgb, width); - } else { - AccumulateRGBA(r_ptr + off1, g_ptr + off1, b_ptr + off1, a_ptr + off1, - rgb_stride, tmp_rgb, width); - } - // Convert to U/V - if (rg == NULL) { - WebPConvertRGBA32ToUV(tmp_rgb, dst_u, dst_v, uv_width); - } else { - ConvertRowsToUV(tmp_rgb, dst_u, dst_v, uv_width, rg); - } - dst_u += picture->uv_stride; - dst_v += picture->uv_stride; - } - if (height & 1) { // extra last row - const int off = 2 * y * rgb_stride; - int row_has_alpha = has_alpha; - if (use_dsp) { - if (r_ptr < b_ptr) { - WebPConvertRGB24ToY(r_ptr + off, dst_y, width); - } else { - WebPConvertBGR24ToY(b_ptr + off, dst_y, width); - } - } else { - ConvertRowToY(r_ptr + off, g_ptr + off, b_ptr + off, step, - dst_y, width, rg); - } - if (row_has_alpha) { - row_has_alpha &= !WebPExtractAlpha(a_ptr + off, 0, width, 1, dst_a, 0); - } - // Collect averaged R/G/B(/A) - if (!row_has_alpha) { - // Collect averaged R/G/B - AccumulateRGB(r_ptr + off, g_ptr + off, b_ptr + off, - step, /* rgb_stride = */ 0, tmp_rgb, width); - } else { - AccumulateRGBA(r_ptr + off, g_ptr + off, b_ptr + off, a_ptr + off, - /* rgb_stride = */ 0, tmp_rgb, width); - } - if (rg == NULL) { - WebPConvertRGBA32ToUV(tmp_rgb, dst_u, dst_v, uv_width); - } else { - ConvertRowsToUV(tmp_rgb, dst_u, dst_v, uv_width, rg); - } - } - WebPSafeFree(tmp_rgb); - } - return 1; -} - -#undef SUM4 -#undef SUM2 -#undef SUM4ALPHA -#undef SUM2ALPHA - -//------------------------------------------------------------------------------ -// call for ARGB->YUVA conversion - -static int PictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace, - float dithering, int use_iterative_conversion) { - if (picture == NULL) return 0; - if (picture->argb == NULL) { - return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER); - } else if ((colorspace & WEBP_CSP_UV_MASK) != WEBP_YUV420) { - return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION); - } else { - const uint8_t* const argb = (const uint8_t*)picture->argb; - const uint8_t* const r = ALPHA_IS_LAST ? argb + 2 : argb + 1; - const uint8_t* const g = ALPHA_IS_LAST ? argb + 1 : argb + 2; - const uint8_t* const b = ALPHA_IS_LAST ? argb + 0 : argb + 3; - const uint8_t* const a = ALPHA_IS_LAST ? argb + 3 : argb + 0; - - picture->colorspace = WEBP_YUV420; - return ImportYUVAFromRGBA(r, g, b, a, 4, 4 * picture->argb_stride, - dithering, use_iterative_conversion, picture); - } -} - -int WebPPictureARGBToYUVADithered(WebPPicture* picture, WebPEncCSP colorspace, - float dithering) { - return PictureARGBToYUVA(picture, colorspace, dithering, 0); -} - -int WebPPictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace) { - return PictureARGBToYUVA(picture, colorspace, 0.f, 0); -} - -int WebPPictureSmartARGBToYUVA(WebPPicture* picture) { - return PictureARGBToYUVA(picture, WEBP_YUV420, 0.f, 1); -} - -//------------------------------------------------------------------------------ -// call for YUVA -> ARGB conversion - -int WebPPictureYUVAToARGB(WebPPicture* picture) { - if (picture == NULL) return 0; - if (picture->y == NULL || picture->u == NULL || picture->v == NULL) { - return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER); - } - if ((picture->colorspace & WEBP_CSP_ALPHA_BIT) && picture->a == NULL) { - return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER); - } - if ((picture->colorspace & WEBP_CSP_UV_MASK) != WEBP_YUV420) { - return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION); - } - // Allocate a new argb buffer (discarding the previous one). - if (!WebPPictureAllocARGB(picture, picture->width, picture->height)) return 0; - picture->use_argb = 1; - - // Convert - { - int y; - const int width = picture->width; - const int height = picture->height; - const int argb_stride = 4 * picture->argb_stride; - uint8_t* dst = (uint8_t*)picture->argb; - const uint8_t *cur_u = picture->u, *cur_v = picture->v, *cur_y = picture->y; - WebPUpsampleLinePairFunc upsample = WebPGetLinePairConverter(ALPHA_IS_LAST); - - // First row, with replicated top samples. - upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width); - cur_y += picture->y_stride; - dst += argb_stride; - // Center rows. - for (y = 1; y + 1 < height; y += 2) { - const uint8_t* const top_u = cur_u; - const uint8_t* const top_v = cur_v; - cur_u += picture->uv_stride; - cur_v += picture->uv_stride; - upsample(cur_y, cur_y + picture->y_stride, top_u, top_v, cur_u, cur_v, - dst, dst + argb_stride, width); - cur_y += 2 * picture->y_stride; - dst += 2 * argb_stride; - } - // Last row (if needed), with replicated bottom samples. - if (height > 1 && !(height & 1)) { - upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width); - } - // Insert alpha values if needed, in replacement for the default 0xff ones. - if (picture->colorspace & WEBP_CSP_ALPHA_BIT) { - for (y = 0; y < height; ++y) { - uint32_t* const argb_dst = picture->argb + y * picture->argb_stride; - const uint8_t* const src = picture->a + y * picture->a_stride; - int x; - for (x = 0; x < width; ++x) { - argb_dst[x] = (argb_dst[x] & 0x00ffffffu) | ((uint32_t)src[x] << 24); - } - } - } - } - return 1; -} - -//------------------------------------------------------------------------------ -// automatic import / conversion - -static int Import(WebPPicture* const picture, - const uint8_t* const rgb, int rgb_stride, - int step, int swap_rb, int import_alpha) { - int y; - const uint8_t* const r_ptr = rgb + (swap_rb ? 2 : 0); - const uint8_t* const g_ptr = rgb + 1; - const uint8_t* const b_ptr = rgb + (swap_rb ? 0 : 2); - const uint8_t* const a_ptr = import_alpha ? rgb + 3 : NULL; - const int width = picture->width; - const int height = picture->height; - - if (!picture->use_argb) { - return ImportYUVAFromRGBA(r_ptr, g_ptr, b_ptr, a_ptr, step, rgb_stride, - 0.f /* no dithering */, 0, picture); - } - if (!WebPPictureAlloc(picture)) return 0; - - VP8EncDspARGBInit(); - - if (import_alpha) { - assert(step == 4); - for (y = 0; y < height; ++y) { - uint32_t* const dst = &picture->argb[y * picture->argb_stride]; - const int offset = y * rgb_stride; - VP8PackARGB(a_ptr + offset, r_ptr + offset, g_ptr + offset, - b_ptr + offset, width, dst); - } - } else { - assert(step >= 3); - for (y = 0; y < height; ++y) { - uint32_t* const dst = &picture->argb[y * picture->argb_stride]; - const int offset = y * rgb_stride; - VP8PackRGB(r_ptr + offset, g_ptr + offset, b_ptr + offset, - width, step, dst); - } - } - return 1; -} - -// Public API - -int WebPPictureImportRGB(WebPPicture* picture, - const uint8_t* rgb, int rgb_stride) { - return (picture != NULL) ? Import(picture, rgb, rgb_stride, 3, 0, 0) : 0; -} - -int WebPPictureImportBGR(WebPPicture* picture, - const uint8_t* rgb, int rgb_stride) { - return (picture != NULL) ? Import(picture, rgb, rgb_stride, 3, 1, 0) : 0; -} - -int WebPPictureImportRGBA(WebPPicture* picture, - const uint8_t* rgba, int rgba_stride) { - return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 0, 1) : 0; -} - -int WebPPictureImportBGRA(WebPPicture* picture, - const uint8_t* rgba, int rgba_stride) { - return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 1, 1) : 0; -} - -int WebPPictureImportRGBX(WebPPicture* picture, - const uint8_t* rgba, int rgba_stride) { - return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 0, 0) : 0; -} - -int WebPPictureImportBGRX(WebPPicture* picture, - const uint8_t* rgba, int rgba_stride) { - return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 1, 0) : 0; -} - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/enc/picture_psnr.c b/Example/Pods/libwebp/src/enc/picture_psnr.c deleted file mode 100644 index 40214efc..00000000 --- a/Example/Pods/libwebp/src/enc/picture_psnr.c +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// WebPPicture tools for measuring distortion -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include - -#include "./vp8enci.h" -#include "../utils/utils.h" - -//------------------------------------------------------------------------------ -// local-min distortion -// -// For every pixel in the *reference* picture, we search for the local best -// match in the compressed image. This is not a symmetrical measure. - -#define RADIUS 2 // search radius. Shouldn't be too large. - -static void AccumulateLSIM(const uint8_t* src, int src_stride, - const uint8_t* ref, int ref_stride, - int w, int h, DistoStats* stats) { - int x, y; - double total_sse = 0.; - for (y = 0; y < h; ++y) { - const int y_0 = (y - RADIUS < 0) ? 0 : y - RADIUS; - const int y_1 = (y + RADIUS + 1 >= h) ? h : y + RADIUS + 1; - for (x = 0; x < w; ++x) { - const int x_0 = (x - RADIUS < 0) ? 0 : x - RADIUS; - const int x_1 = (x + RADIUS + 1 >= w) ? w : x + RADIUS + 1; - double best_sse = 255. * 255.; - const double value = (double)ref[y * ref_stride + x]; - int i, j; - for (j = y_0; j < y_1; ++j) { - const uint8_t* const s = src + j * src_stride; - for (i = x_0; i < x_1; ++i) { - const double diff = s[i] - value; - const double sse = diff * diff; - if (sse < best_sse) best_sse = sse; - } - } - total_sse += best_sse; - } - } - stats->w = w * h; - stats->xm = 0; - stats->ym = 0; - stats->xxm = total_sse; - stats->yym = 0; - stats->xxm = 0; -} -#undef RADIUS - -//------------------------------------------------------------------------------ -// Distortion - -// Max value returned in case of exact similarity. -static const double kMinDistortion_dB = 99.; -static float GetPSNR(const double v) { - return (float)((v > 0.) ? -4.3429448 * log(v / (255 * 255.)) - : kMinDistortion_dB); -} - -int WebPPictureDistortion(const WebPPicture* src, const WebPPicture* ref, - int type, float result[5]) { - DistoStats stats[5]; - int w, h; - - memset(stats, 0, sizeof(stats)); - - if (src == NULL || ref == NULL || - src->width != ref->width || src->height != ref->height || - src->use_argb != ref->use_argb || result == NULL) { - return 0; - } - w = src->width; - h = src->height; - - if (src->use_argb == 1) { - if (src->argb == NULL || ref->argb == NULL) { - return 0; - } else { - int i, j, c; - uint8_t* tmp1, *tmp2; - uint8_t* const tmp_plane = - (uint8_t*)WebPSafeMalloc(2ULL * w * h, sizeof(*tmp_plane)); - if (tmp_plane == NULL) return 0; - tmp1 = tmp_plane; - tmp2 = tmp_plane + w * h; - for (c = 0; c < 4; ++c) { - for (j = 0; j < h; ++j) { - for (i = 0; i < w; ++i) { - tmp1[j * w + i] = src->argb[i + j * src->argb_stride] >> (c * 8); - tmp2[j * w + i] = ref->argb[i + j * ref->argb_stride] >> (c * 8); - } - } - if (type >= 2) { - AccumulateLSIM(tmp1, w, tmp2, w, w, h, &stats[c]); - } else { - VP8SSIMAccumulatePlane(tmp1, w, tmp2, w, w, h, &stats[c]); - } - } - free(tmp_plane); - } - } else { - int has_alpha, uv_w, uv_h; - if (src->y == NULL || ref->y == NULL || - src->u == NULL || ref->u == NULL || - src->v == NULL || ref->v == NULL) { - return 0; - } - has_alpha = !!(src->colorspace & WEBP_CSP_ALPHA_BIT); - if (has_alpha != !!(ref->colorspace & WEBP_CSP_ALPHA_BIT) || - (has_alpha && (src->a == NULL || ref->a == NULL))) { - return 0; - } - - uv_w = (src->width + 1) >> 1; - uv_h = (src->height + 1) >> 1; - if (type >= 2) { - AccumulateLSIM(src->y, src->y_stride, ref->y, ref->y_stride, - w, h, &stats[0]); - AccumulateLSIM(src->u, src->uv_stride, ref->u, ref->uv_stride, - uv_w, uv_h, &stats[1]); - AccumulateLSIM(src->v, src->uv_stride, ref->v, ref->uv_stride, - uv_w, uv_h, &stats[2]); - if (has_alpha) { - AccumulateLSIM(src->a, src->a_stride, ref->a, ref->a_stride, - w, h, &stats[3]); - } - } else { - VP8SSIMAccumulatePlane(src->y, src->y_stride, - ref->y, ref->y_stride, - w, h, &stats[0]); - VP8SSIMAccumulatePlane(src->u, src->uv_stride, - ref->u, ref->uv_stride, - uv_w, uv_h, &stats[1]); - VP8SSIMAccumulatePlane(src->v, src->uv_stride, - ref->v, ref->uv_stride, - uv_w, uv_h, &stats[2]); - if (has_alpha) { - VP8SSIMAccumulatePlane(src->a, src->a_stride, - ref->a, ref->a_stride, - w, h, &stats[3]); - } - } - } - // Final stat calculations. - { - int c; - for (c = 0; c <= 4; ++c) { - if (type == 1) { - const double v = VP8SSIMGet(&stats[c]); - result[c] = (float)((v < 1.) ? -10.0 * log10(1. - v) - : kMinDistortion_dB); - } else { - const double v = VP8SSIMGetSquaredError(&stats[c]); - result[c] = GetPSNR(v); - } - // Accumulate forward - if (c < 4) VP8SSIMAddStats(&stats[c], &stats[4]); - } - } - return 1; -} - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/enc/picture_rescale.c b/Example/Pods/libwebp/src/enc/picture_rescale.c deleted file mode 100644 index 9f19e8e8..00000000 --- a/Example/Pods/libwebp/src/enc/picture_rescale.c +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// WebPPicture tools: copy, crop, rescaling and view. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include - -#include "./vp8enci.h" -#include "../utils/rescaler.h" -#include "../utils/utils.h" - -#define HALVE(x) (((x) + 1) >> 1) - -// Grab the 'specs' (writer, *opaque, width, height...) from 'src' and copy them -// into 'dst'. Mark 'dst' as not owning any memory. -static void PictureGrabSpecs(const WebPPicture* const src, - WebPPicture* const dst) { - assert(src != NULL && dst != NULL); - *dst = *src; - WebPPictureResetBuffers(dst); -} - -//------------------------------------------------------------------------------ - -// Adjust top-left corner to chroma sample position. -static void SnapTopLeftPosition(const WebPPicture* const pic, - int* const left, int* const top) { - if (!pic->use_argb) { - *left &= ~1; - *top &= ~1; - } -} - -// Adjust top-left corner and verify that the sub-rectangle is valid. -static int AdjustAndCheckRectangle(const WebPPicture* const pic, - int* const left, int* const top, - int width, int height) { - SnapTopLeftPosition(pic, left, top); - if ((*left) < 0 || (*top) < 0) return 0; - if (width <= 0 || height <= 0) return 0; - if ((*left) + width > pic->width) return 0; - if ((*top) + height > pic->height) return 0; - return 1; -} - -int WebPPictureCopy(const WebPPicture* src, WebPPicture* dst) { - if (src == NULL || dst == NULL) return 0; - if (src == dst) return 1; - - PictureGrabSpecs(src, dst); - if (!WebPPictureAlloc(dst)) return 0; - - if (!src->use_argb) { - WebPCopyPlane(src->y, src->y_stride, - dst->y, dst->y_stride, dst->width, dst->height); - WebPCopyPlane(src->u, src->uv_stride, dst->u, dst->uv_stride, - HALVE(dst->width), HALVE(dst->height)); - WebPCopyPlane(src->v, src->uv_stride, dst->v, dst->uv_stride, - HALVE(dst->width), HALVE(dst->height)); - if (dst->a != NULL) { - WebPCopyPlane(src->a, src->a_stride, - dst->a, dst->a_stride, dst->width, dst->height); - } - } else { - WebPCopyPlane((const uint8_t*)src->argb, 4 * src->argb_stride, - (uint8_t*)dst->argb, 4 * dst->argb_stride, - 4 * dst->width, dst->height); - } - return 1; -} - -int WebPPictureIsView(const WebPPicture* picture) { - if (picture == NULL) return 0; - if (picture->use_argb) { - return (picture->memory_argb_ == NULL); - } - return (picture->memory_ == NULL); -} - -int WebPPictureView(const WebPPicture* src, - int left, int top, int width, int height, - WebPPicture* dst) { - if (src == NULL || dst == NULL) return 0; - - // verify rectangle position. - if (!AdjustAndCheckRectangle(src, &left, &top, width, height)) return 0; - - if (src != dst) { // beware of aliasing! We don't want to leak 'memory_'. - PictureGrabSpecs(src, dst); - } - dst->width = width; - dst->height = height; - if (!src->use_argb) { - dst->y = src->y + top * src->y_stride + left; - dst->u = src->u + (top >> 1) * src->uv_stride + (left >> 1); - dst->v = src->v + (top >> 1) * src->uv_stride + (left >> 1); - dst->y_stride = src->y_stride; - dst->uv_stride = src->uv_stride; - if (src->a != NULL) { - dst->a = src->a + top * src->a_stride + left; - dst->a_stride = src->a_stride; - } - } else { - dst->argb = src->argb + top * src->argb_stride + left; - dst->argb_stride = src->argb_stride; - } - return 1; -} - -//------------------------------------------------------------------------------ -// Picture cropping - -int WebPPictureCrop(WebPPicture* pic, - int left, int top, int width, int height) { - WebPPicture tmp; - - if (pic == NULL) return 0; - if (!AdjustAndCheckRectangle(pic, &left, &top, width, height)) return 0; - - PictureGrabSpecs(pic, &tmp); - tmp.width = width; - tmp.height = height; - if (!WebPPictureAlloc(&tmp)) return 0; - - if (!pic->use_argb) { - const int y_offset = top * pic->y_stride + left; - const int uv_offset = (top / 2) * pic->uv_stride + left / 2; - WebPCopyPlane(pic->y + y_offset, pic->y_stride, - tmp.y, tmp.y_stride, width, height); - WebPCopyPlane(pic->u + uv_offset, pic->uv_stride, - tmp.u, tmp.uv_stride, HALVE(width), HALVE(height)); - WebPCopyPlane(pic->v + uv_offset, pic->uv_stride, - tmp.v, tmp.uv_stride, HALVE(width), HALVE(height)); - - if (tmp.a != NULL) { - const int a_offset = top * pic->a_stride + left; - WebPCopyPlane(pic->a + a_offset, pic->a_stride, - tmp.a, tmp.a_stride, width, height); - } - } else { - const uint8_t* const src = - (const uint8_t*)(pic->argb + top * pic->argb_stride + left); - WebPCopyPlane(src, pic->argb_stride * 4, (uint8_t*)tmp.argb, - tmp.argb_stride * 4, width * 4, height); - } - WebPPictureFree(pic); - *pic = tmp; - return 1; -} - -//------------------------------------------------------------------------------ -// Simple picture rescaler - -static void RescalePlane(const uint8_t* src, - int src_width, int src_height, int src_stride, - uint8_t* dst, - int dst_width, int dst_height, int dst_stride, - rescaler_t* const work, - int num_channels) { - WebPRescaler rescaler; - int y = 0; - WebPRescalerInit(&rescaler, src_width, src_height, - dst, dst_width, dst_height, dst_stride, - num_channels, work); - while (y < src_height) { - y += WebPRescalerImport(&rescaler, src_height - y, - src + y * src_stride, src_stride); - WebPRescalerExport(&rescaler); - } -} - -static void AlphaMultiplyARGB(WebPPicture* const pic, int inverse) { - assert(pic->argb != NULL); - WebPMultARGBRows((uint8_t*)pic->argb, pic->argb_stride * sizeof(*pic->argb), - pic->width, pic->height, inverse); -} - -static void AlphaMultiplyY(WebPPicture* const pic, int inverse) { - if (pic->a != NULL) { - WebPMultRows(pic->y, pic->y_stride, pic->a, pic->a_stride, - pic->width, pic->height, inverse); - } -} - -int WebPPictureRescale(WebPPicture* pic, int width, int height) { - WebPPicture tmp; - int prev_width, prev_height; - rescaler_t* work; - - if (pic == NULL) return 0; - prev_width = pic->width; - prev_height = pic->height; - if (!WebPRescalerGetScaledDimensions( - prev_width, prev_height, &width, &height)) { - return 0; - } - - PictureGrabSpecs(pic, &tmp); - tmp.width = width; - tmp.height = height; - if (!WebPPictureAlloc(&tmp)) return 0; - - if (!pic->use_argb) { - work = (rescaler_t*)WebPSafeMalloc(2ULL * width, sizeof(*work)); - if (work == NULL) { - WebPPictureFree(&tmp); - return 0; - } - // If present, we need to rescale alpha first (for AlphaMultiplyY). - if (pic->a != NULL) { - WebPInitAlphaProcessing(); - RescalePlane(pic->a, prev_width, prev_height, pic->a_stride, - tmp.a, width, height, tmp.a_stride, work, 1); - } - - // We take transparency into account on the luma plane only. That's not - // totally exact blending, but still is a good approximation. - AlphaMultiplyY(pic, 0); - RescalePlane(pic->y, prev_width, prev_height, pic->y_stride, - tmp.y, width, height, tmp.y_stride, work, 1); - AlphaMultiplyY(&tmp, 1); - - RescalePlane(pic->u, - HALVE(prev_width), HALVE(prev_height), pic->uv_stride, - tmp.u, - HALVE(width), HALVE(height), tmp.uv_stride, work, 1); - RescalePlane(pic->v, - HALVE(prev_width), HALVE(prev_height), pic->uv_stride, - tmp.v, - HALVE(width), HALVE(height), tmp.uv_stride, work, 1); - } else { - work = (rescaler_t*)WebPSafeMalloc(2ULL * width * 4, sizeof(*work)); - if (work == NULL) { - WebPPictureFree(&tmp); - return 0; - } - // In order to correctly interpolate colors, we need to apply the alpha - // weighting first (black-matting), scale the RGB values, and remove - // the premultiplication afterward (while preserving the alpha channel). - WebPInitAlphaProcessing(); - AlphaMultiplyARGB(pic, 0); - RescalePlane((const uint8_t*)pic->argb, prev_width, prev_height, - pic->argb_stride * 4, - (uint8_t*)tmp.argb, width, height, - tmp.argb_stride * 4, - work, 4); - AlphaMultiplyARGB(&tmp, 1); - } - WebPPictureFree(pic); - WebPSafeFree(work); - *pic = tmp; - return 1; -} - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/enc/picture_tools.c b/Example/Pods/libwebp/src/enc/picture_tools.c deleted file mode 100644 index bf97af84..00000000 --- a/Example/Pods/libwebp/src/enc/picture_tools.c +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// WebPPicture tools: alpha handling, etc. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include - -#include "./vp8enci.h" -#include "../dsp/yuv.h" - -static WEBP_INLINE uint32_t MakeARGB32(int r, int g, int b) { - return (0xff000000u | (r << 16) | (g << 8) | b); -} - -//------------------------------------------------------------------------------ -// Helper: clean up fully transparent area to help compressibility. - -#define SIZE 8 -#define SIZE2 (SIZE / 2) -static int is_transparent_area(const uint8_t* ptr, int stride, int size) { - int y, x; - for (y = 0; y < size; ++y) { - for (x = 0; x < size; ++x) { - if (ptr[x]) { - return 0; - } - } - ptr += stride; - } - return 1; -} - -static int is_transparent_argb_area(const uint32_t* ptr, int stride, int size) { - int y, x; - for (y = 0; y < size; ++y) { - for (x = 0; x < size; ++x) { - if (ptr[x] & 0xff000000u) { - return 0; - } - } - ptr += stride; - } - return 1; -} - -static void flatten(uint8_t* ptr, int v, int stride, int size) { - int y; - for (y = 0; y < size; ++y) { - memset(ptr, v, size); - ptr += stride; - } -} - -static void flatten_argb(uint32_t* ptr, uint32_t v, int stride, int size) { - int x, y; - for (y = 0; y < size; ++y) { - for (x = 0; x < size; ++x) ptr[x] = v; - ptr += stride; - } -} - -void WebPCleanupTransparentArea(WebPPicture* pic) { - int x, y, w, h; - if (pic == NULL) return; - w = pic->width / SIZE; - h = pic->height / SIZE; - - // note: we ignore the left-overs on right/bottom - if (pic->use_argb) { - uint32_t argb_value = 0; - for (y = 0; y < h; ++y) { - int need_reset = 1; - for (x = 0; x < w; ++x) { - const int off = (y * pic->argb_stride + x) * SIZE; - if (is_transparent_argb_area(pic->argb + off, pic->argb_stride, SIZE)) { - if (need_reset) { - argb_value = pic->argb[off]; - need_reset = 0; - } - flatten_argb(pic->argb + off, argb_value, pic->argb_stride, SIZE); - } else { - need_reset = 1; - } - } - } - } else { - const uint8_t* const a_ptr = pic->a; - int values[3] = { 0 }; - if (a_ptr == NULL) return; // nothing to do - for (y = 0; y < h; ++y) { - int need_reset = 1; - for (x = 0; x < w; ++x) { - const int off_a = (y * pic->a_stride + x) * SIZE; - const int off_y = (y * pic->y_stride + x) * SIZE; - const int off_uv = (y * pic->uv_stride + x) * SIZE2; - if (is_transparent_area(a_ptr + off_a, pic->a_stride, SIZE)) { - if (need_reset) { - values[0] = pic->y[off_y]; - values[1] = pic->u[off_uv]; - values[2] = pic->v[off_uv]; - need_reset = 0; - } - flatten(pic->y + off_y, values[0], pic->y_stride, SIZE); - flatten(pic->u + off_uv, values[1], pic->uv_stride, SIZE2); - flatten(pic->v + off_uv, values[2], pic->uv_stride, SIZE2); - } else { - need_reset = 1; - } - } - } - } -} - -#undef SIZE -#undef SIZE2 - -void WebPCleanupTransparentAreaLossless(WebPPicture* const pic) { - int x, y, w, h; - uint32_t* argb; - assert(pic != NULL && pic->use_argb); - w = pic->width; - h = pic->height; - argb = pic->argb; - - for (y = 0; y < h; ++y) { - for (x = 0; x < w; ++x) { - if ((argb[x] & 0xff000000) == 0) { - argb[x] = 0x00000000; - } - } - argb += pic->argb_stride; - } -} - -//------------------------------------------------------------------------------ -// Blend color and remove transparency info - -#define BLEND(V0, V1, ALPHA) \ - ((((V0) * (255 - (ALPHA)) + (V1) * (ALPHA)) * 0x101) >> 16) -#define BLEND_10BIT(V0, V1, ALPHA) \ - ((((V0) * (1020 - (ALPHA)) + (V1) * (ALPHA)) * 0x101) >> 18) - -void WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb) { - const int red = (background_rgb >> 16) & 0xff; - const int green = (background_rgb >> 8) & 0xff; - const int blue = (background_rgb >> 0) & 0xff; - int x, y; - if (pic == NULL) return; - if (!pic->use_argb) { - const int uv_width = (pic->width >> 1); // omit last pixel during u/v loop - const int Y0 = VP8RGBToY(red, green, blue, YUV_HALF); - // VP8RGBToU/V expects the u/v values summed over four pixels - const int U0 = VP8RGBToU(4 * red, 4 * green, 4 * blue, 4 * YUV_HALF); - const int V0 = VP8RGBToV(4 * red, 4 * green, 4 * blue, 4 * YUV_HALF); - const int has_alpha = pic->colorspace & WEBP_CSP_ALPHA_BIT; - if (!has_alpha || pic->a == NULL) return; // nothing to do - for (y = 0; y < pic->height; ++y) { - // Luma blending - uint8_t* const y_ptr = pic->y + y * pic->y_stride; - uint8_t* const a_ptr = pic->a + y * pic->a_stride; - for (x = 0; x < pic->width; ++x) { - const int alpha = a_ptr[x]; - if (alpha < 0xff) { - y_ptr[x] = BLEND(Y0, y_ptr[x], a_ptr[x]); - } - } - // Chroma blending every even line - if ((y & 1) == 0) { - uint8_t* const u = pic->u + (y >> 1) * pic->uv_stride; - uint8_t* const v = pic->v + (y >> 1) * pic->uv_stride; - uint8_t* const a_ptr2 = - (y + 1 == pic->height) ? a_ptr : a_ptr + pic->a_stride; - for (x = 0; x < uv_width; ++x) { - // Average four alpha values into a single blending weight. - // TODO(skal): might lead to visible contouring. Can we do better? - const int alpha = - a_ptr[2 * x + 0] + a_ptr[2 * x + 1] + - a_ptr2[2 * x + 0] + a_ptr2[2 * x + 1]; - u[x] = BLEND_10BIT(U0, u[x], alpha); - v[x] = BLEND_10BIT(V0, v[x], alpha); - } - if (pic->width & 1) { // rightmost pixel - const int alpha = 2 * (a_ptr[2 * x + 0] + a_ptr2[2 * x + 0]); - u[x] = BLEND_10BIT(U0, u[x], alpha); - v[x] = BLEND_10BIT(V0, v[x], alpha); - } - } - memset(a_ptr, 0xff, pic->width); - } - } else { - uint32_t* argb = pic->argb; - const uint32_t background = MakeARGB32(red, green, blue); - for (y = 0; y < pic->height; ++y) { - for (x = 0; x < pic->width; ++x) { - const int alpha = (argb[x] >> 24) & 0xff; - if (alpha != 0xff) { - if (alpha > 0) { - int r = (argb[x] >> 16) & 0xff; - int g = (argb[x] >> 8) & 0xff; - int b = (argb[x] >> 0) & 0xff; - r = BLEND(red, r, alpha); - g = BLEND(green, g, alpha); - b = BLEND(blue, b, alpha); - argb[x] = MakeARGB32(r, g, b); - } else { - argb[x] = background; - } - } - } - argb += pic->argb_stride; - } - } -} - -#undef BLEND -#undef BLEND_10BIT - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/enc/quant.c b/Example/Pods/libwebp/src/enc/quant.c deleted file mode 100644 index dd6885ab..00000000 --- a/Example/Pods/libwebp/src/enc/quant.c +++ /dev/null @@ -1,1253 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Quantization -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include -#include // for abs() - -#include "./vp8enci.h" -#include "./cost.h" - -#define DO_TRELLIS_I4 1 -#define DO_TRELLIS_I16 1 // not a huge gain, but ok at low bitrate. -#define DO_TRELLIS_UV 0 // disable trellis for UV. Risky. Not worth. -#define USE_TDISTO 1 - -#define MID_ALPHA 64 // neutral value for susceptibility -#define MIN_ALPHA 30 // lowest usable value for susceptibility -#define MAX_ALPHA 100 // higher meaningful value for susceptibility - -#define SNS_TO_DQ 0.9 // Scaling constant between the sns value and the QP - // power-law modulation. Must be strictly less than 1. - -#define I4_PENALTY 14000 // Rate-penalty for quick i4/i16 decision - -// number of non-zero coeffs below which we consider the block very flat -// (and apply a penalty to complex predictions) -#define FLATNESS_LIMIT_I16 10 // I16 mode -#define FLATNESS_LIMIT_I4 3 // I4 mode -#define FLATNESS_LIMIT_UV 2 // UV mode -#define FLATNESS_PENALTY 140 // roughly ~1bit per block - -#define MULT_8B(a, b) (((a) * (b) + 128) >> 8) - -#define RD_DISTO_MULT 256 // distortion multiplier (equivalent of lambda) - -// #define DEBUG_BLOCK - -//------------------------------------------------------------------------------ - -#if defined(DEBUG_BLOCK) - -#include -#include - -static void PrintBlockInfo(const VP8EncIterator* const it, - const VP8ModeScore* const rd) { - int i, j; - const int is_i16 = (it->mb_->type_ == 1); - const uint8_t* const y_in = it->yuv_in_ + Y_OFF_ENC; - const uint8_t* const y_out = it->yuv_out_ + Y_OFF_ENC; - const uint8_t* const uv_in = it->yuv_in_ + U_OFF_ENC; - const uint8_t* const uv_out = it->yuv_out_ + U_OFF_ENC; - printf("SOURCE / OUTPUT / ABS DELTA\n"); - for (j = 0; j < 16; ++j) { - for (i = 0; i < 16; ++i) printf("%3d ", y_in[i + j * BPS]); - printf(" "); - for (i = 0; i < 16; ++i) printf("%3d ", y_out[i + j * BPS]); - printf(" "); - for (i = 0; i < 16; ++i) { - printf("%1d ", abs(y_in[i + j * BPS] - y_out[i + j * BPS])); - } - printf("\n"); - } - printf("\n"); // newline before the U/V block - for (j = 0; j < 8; ++j) { - for (i = 0; i < 8; ++i) printf("%3d ", uv_in[i + j * BPS]); - printf(" "); - for (i = 8; i < 16; ++i) printf("%3d ", uv_in[i + j * BPS]); - printf(" "); - for (i = 0; i < 8; ++i) printf("%3d ", uv_out[i + j * BPS]); - printf(" "); - for (i = 8; i < 16; ++i) printf("%3d ", uv_out[i + j * BPS]); - printf(" "); - for (i = 0; i < 8; ++i) { - printf("%1d ", abs(uv_out[i + j * BPS] - uv_in[i + j * BPS])); - } - printf(" "); - for (i = 8; i < 16; ++i) { - printf("%1d ", abs(uv_out[i + j * BPS] - uv_in[i + j * BPS])); - } - printf("\n"); - } - printf("\nD:%d SD:%d R:%d H:%d nz:0x%x score:%d\n", - (int)rd->D, (int)rd->SD, (int)rd->R, (int)rd->H, (int)rd->nz, - (int)rd->score); - if (is_i16) { - printf("Mode: %d\n", rd->mode_i16); - printf("y_dc_levels:"); - for (i = 0; i < 16; ++i) printf("%3d ", rd->y_dc_levels[i]); - printf("\n"); - } else { - printf("Modes[16]: "); - for (i = 0; i < 16; ++i) printf("%d ", rd->modes_i4[i]); - printf("\n"); - } - printf("y_ac_levels:\n"); - for (j = 0; j < 16; ++j) { - for (i = is_i16 ? 1 : 0; i < 16; ++i) { - printf("%4d ", rd->y_ac_levels[j][i]); - } - printf("\n"); - } - printf("\n"); - printf("uv_levels (mode=%d):\n", rd->mode_uv); - for (j = 0; j < 8; ++j) { - for (i = 0; i < 16; ++i) { - printf("%4d ", rd->uv_levels[j][i]); - } - printf("\n"); - } -} - -#endif // DEBUG_BLOCK - -//------------------------------------------------------------------------------ - -static WEBP_INLINE int clip(int v, int m, int M) { - return v < m ? m : v > M ? M : v; -} - -static const uint8_t kZigzag[16] = { - 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 -}; - -static const uint8_t kDcTable[128] = { - 4, 5, 6, 7, 8, 9, 10, 10, - 11, 12, 13, 14, 15, 16, 17, 17, - 18, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 25, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, - 37, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, - 91, 93, 95, 96, 98, 100, 101, 102, - 104, 106, 108, 110, 112, 114, 116, 118, - 122, 124, 126, 128, 130, 132, 134, 136, - 138, 140, 143, 145, 148, 151, 154, 157 -}; - -static const uint16_t kAcTable[128] = { - 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 60, - 62, 64, 66, 68, 70, 72, 74, 76, - 78, 80, 82, 84, 86, 88, 90, 92, - 94, 96, 98, 100, 102, 104, 106, 108, - 110, 112, 114, 116, 119, 122, 125, 128, - 131, 134, 137, 140, 143, 146, 149, 152, - 155, 158, 161, 164, 167, 170, 173, 177, - 181, 185, 189, 193, 197, 201, 205, 209, - 213, 217, 221, 225, 229, 234, 239, 245, - 249, 254, 259, 264, 269, 274, 279, 284 -}; - -static const uint16_t kAcTable2[128] = { - 8, 8, 9, 10, 12, 13, 15, 17, - 18, 20, 21, 23, 24, 26, 27, 29, - 31, 32, 34, 35, 37, 38, 40, 41, - 43, 44, 46, 48, 49, 51, 52, 54, - 55, 57, 58, 60, 62, 63, 65, 66, - 68, 69, 71, 72, 74, 75, 77, 79, - 80, 82, 83, 85, 86, 88, 89, 93, - 96, 99, 102, 105, 108, 111, 114, 117, - 120, 124, 127, 130, 133, 136, 139, 142, - 145, 148, 151, 155, 158, 161, 164, 167, - 170, 173, 176, 179, 184, 189, 193, 198, - 203, 207, 212, 217, 221, 226, 230, 235, - 240, 244, 249, 254, 258, 263, 268, 274, - 280, 286, 292, 299, 305, 311, 317, 323, - 330, 336, 342, 348, 354, 362, 370, 379, - 385, 393, 401, 409, 416, 424, 432, 440 -}; - -static const uint8_t kBiasMatrices[3][2] = { // [luma-ac,luma-dc,chroma][dc,ac] - { 96, 110 }, { 96, 108 }, { 110, 115 } -}; - -// Sharpening by (slightly) raising the hi-frequency coeffs. -// Hack-ish but helpful for mid-bitrate range. Use with care. -#define SHARPEN_BITS 11 // number of descaling bits for sharpening bias -static const uint8_t kFreqSharpening[16] = { - 0, 30, 60, 90, - 30, 60, 90, 90, - 60, 90, 90, 90, - 90, 90, 90, 90 -}; - -//------------------------------------------------------------------------------ -// Initialize quantization parameters in VP8Matrix - -// Returns the average quantizer -static int ExpandMatrix(VP8Matrix* const m, int type) { - int i, sum; - for (i = 0; i < 2; ++i) { - const int is_ac_coeff = (i > 0); - const int bias = kBiasMatrices[type][is_ac_coeff]; - m->iq_[i] = (1 << QFIX) / m->q_[i]; - m->bias_[i] = BIAS(bias); - // zthresh_ is the exact value such that QUANTDIV(coeff, iQ, B) is: - // * zero if coeff <= zthresh - // * non-zero if coeff > zthresh - m->zthresh_[i] = ((1 << QFIX) - 1 - m->bias_[i]) / m->iq_[i]; - } - for (i = 2; i < 16; ++i) { - m->q_[i] = m->q_[1]; - m->iq_[i] = m->iq_[1]; - m->bias_[i] = m->bias_[1]; - m->zthresh_[i] = m->zthresh_[1]; - } - for (sum = 0, i = 0; i < 16; ++i) { - if (type == 0) { // we only use sharpening for AC luma coeffs - m->sharpen_[i] = (kFreqSharpening[i] * m->q_[i]) >> SHARPEN_BITS; - } else { - m->sharpen_[i] = 0; - } - sum += m->q_[i]; - } - return (sum + 8) >> 4; -} - -static void SetupMatrices(VP8Encoder* enc) { - int i; - const int tlambda_scale = - (enc->method_ >= 4) ? enc->config_->sns_strength - : 0; - const int num_segments = enc->segment_hdr_.num_segments_; - for (i = 0; i < num_segments; ++i) { - VP8SegmentInfo* const m = &enc->dqm_[i]; - const int q = m->quant_; - int q4, q16, quv; - m->y1_.q_[0] = kDcTable[clip(q + enc->dq_y1_dc_, 0, 127)]; - m->y1_.q_[1] = kAcTable[clip(q, 0, 127)]; - - m->y2_.q_[0] = kDcTable[ clip(q + enc->dq_y2_dc_, 0, 127)] * 2; - m->y2_.q_[1] = kAcTable2[clip(q + enc->dq_y2_ac_, 0, 127)]; - - m->uv_.q_[0] = kDcTable[clip(q + enc->dq_uv_dc_, 0, 117)]; - m->uv_.q_[1] = kAcTable[clip(q + enc->dq_uv_ac_, 0, 127)]; - - q4 = ExpandMatrix(&m->y1_, 0); - q16 = ExpandMatrix(&m->y2_, 1); - quv = ExpandMatrix(&m->uv_, 2); - - m->lambda_i4_ = (3 * q4 * q4) >> 7; - m->lambda_i16_ = (3 * q16 * q16); - m->lambda_uv_ = (3 * quv * quv) >> 6; - m->lambda_mode_ = (1 * q4 * q4) >> 7; - m->lambda_trellis_i4_ = (7 * q4 * q4) >> 3; - m->lambda_trellis_i16_ = (q16 * q16) >> 2; - m->lambda_trellis_uv_ = (quv *quv) << 1; - m->tlambda_ = (tlambda_scale * q4) >> 5; - - m->min_disto_ = 10 * m->y1_.q_[0]; // quantization-aware min disto - m->max_edge_ = 0; - } -} - -//------------------------------------------------------------------------------ -// Initialize filtering parameters - -// Very small filter-strength values have close to no visual effect. So we can -// save a little decoding-CPU by turning filtering off for these. -#define FSTRENGTH_CUTOFF 2 - -static void SetupFilterStrength(VP8Encoder* const enc) { - int i; - // level0 is in [0..500]. Using '-f 50' as filter_strength is mid-filtering. - const int level0 = 5 * enc->config_->filter_strength; - for (i = 0; i < NUM_MB_SEGMENTS; ++i) { - VP8SegmentInfo* const m = &enc->dqm_[i]; - // We focus on the quantization of AC coeffs. - const int qstep = kAcTable[clip(m->quant_, 0, 127)] >> 2; - const int base_strength = - VP8FilterStrengthFromDelta(enc->filter_hdr_.sharpness_, qstep); - // Segments with lower complexity ('beta') will be less filtered. - const int f = base_strength * level0 / (256 + m->beta_); - m->fstrength_ = (f < FSTRENGTH_CUTOFF) ? 0 : (f > 63) ? 63 : f; - } - // We record the initial strength (mainly for the case of 1-segment only). - enc->filter_hdr_.level_ = enc->dqm_[0].fstrength_; - enc->filter_hdr_.simple_ = (enc->config_->filter_type == 0); - enc->filter_hdr_.sharpness_ = enc->config_->filter_sharpness; -} - -//------------------------------------------------------------------------------ - -// Note: if you change the values below, remember that the max range -// allowed by the syntax for DQ_UV is [-16,16]. -#define MAX_DQ_UV (6) -#define MIN_DQ_UV (-4) - -// We want to emulate jpeg-like behaviour where the expected "good" quality -// is around q=75. Internally, our "good" middle is around c=50. So we -// map accordingly using linear piece-wise function -static double QualityToCompression(double c) { - const double linear_c = (c < 0.75) ? c * (2. / 3.) : 2. * c - 1.; - // The file size roughly scales as pow(quantizer, 3.). Actually, the - // exponent is somewhere between 2.8 and 3.2, but we're mostly interested - // in the mid-quant range. So we scale the compressibility inversely to - // this power-law: quant ~= compression ^ 1/3. This law holds well for - // low quant. Finer modeling for high-quant would make use of kAcTable[] - // more explicitly. - const double v = pow(linear_c, 1 / 3.); - return v; -} - -static double QualityToJPEGCompression(double c, double alpha) { - // We map the complexity 'alpha' and quality setting 'c' to a compression - // exponent empirically matched to the compression curve of libjpeg6b. - // On average, the WebP output size will be roughly similar to that of a - // JPEG file compressed with same quality factor. - const double amin = 0.30; - const double amax = 0.85; - const double exp_min = 0.4; - const double exp_max = 0.9; - const double slope = (exp_min - exp_max) / (amax - amin); - // Linearly interpolate 'expn' from exp_min to exp_max - // in the [amin, amax] range. - const double expn = (alpha > amax) ? exp_min - : (alpha < amin) ? exp_max - : exp_max + slope * (alpha - amin); - const double v = pow(c, expn); - return v; -} - -static int SegmentsAreEquivalent(const VP8SegmentInfo* const S1, - const VP8SegmentInfo* const S2) { - return (S1->quant_ == S2->quant_) && (S1->fstrength_ == S2->fstrength_); -} - -static void SimplifySegments(VP8Encoder* const enc) { - int map[NUM_MB_SEGMENTS] = { 0, 1, 2, 3 }; - const int num_segments = enc->segment_hdr_.num_segments_; - int num_final_segments = 1; - int s1, s2; - for (s1 = 1; s1 < num_segments; ++s1) { // find similar segments - const VP8SegmentInfo* const S1 = &enc->dqm_[s1]; - int found = 0; - // check if we already have similar segment - for (s2 = 0; s2 < num_final_segments; ++s2) { - const VP8SegmentInfo* const S2 = &enc->dqm_[s2]; - if (SegmentsAreEquivalent(S1, S2)) { - found = 1; - break; - } - } - map[s1] = s2; - if (!found) { - if (num_final_segments != s1) { - enc->dqm_[num_final_segments] = enc->dqm_[s1]; - } - ++num_final_segments; - } - } - if (num_final_segments < num_segments) { // Remap - int i = enc->mb_w_ * enc->mb_h_; - while (i-- > 0) enc->mb_info_[i].segment_ = map[enc->mb_info_[i].segment_]; - enc->segment_hdr_.num_segments_ = num_final_segments; - // Replicate the trailing segment infos (it's mostly cosmetics) - for (i = num_final_segments; i < num_segments; ++i) { - enc->dqm_[i] = enc->dqm_[num_final_segments - 1]; - } - } -} - -void VP8SetSegmentParams(VP8Encoder* const enc, float quality) { - int i; - int dq_uv_ac, dq_uv_dc; - const int num_segments = enc->segment_hdr_.num_segments_; - const double amp = SNS_TO_DQ * enc->config_->sns_strength / 100. / 128.; - const double Q = quality / 100.; - const double c_base = enc->config_->emulate_jpeg_size ? - QualityToJPEGCompression(Q, enc->alpha_ / 255.) : - QualityToCompression(Q); - for (i = 0; i < num_segments; ++i) { - // We modulate the base coefficient to accommodate for the quantization - // susceptibility and allow denser segments to be quantized more. - const double expn = 1. - amp * enc->dqm_[i].alpha_; - const double c = pow(c_base, expn); - const int q = (int)(127. * (1. - c)); - assert(expn > 0.); - enc->dqm_[i].quant_ = clip(q, 0, 127); - } - - // purely indicative in the bitstream (except for the 1-segment case) - enc->base_quant_ = enc->dqm_[0].quant_; - - // fill-in values for the unused segments (required by the syntax) - for (i = num_segments; i < NUM_MB_SEGMENTS; ++i) { - enc->dqm_[i].quant_ = enc->base_quant_; - } - - // uv_alpha_ is normally spread around ~60. The useful range is - // typically ~30 (quite bad) to ~100 (ok to decimate UV more). - // We map it to the safe maximal range of MAX/MIN_DQ_UV for dq_uv. - dq_uv_ac = (enc->uv_alpha_ - MID_ALPHA) * (MAX_DQ_UV - MIN_DQ_UV) - / (MAX_ALPHA - MIN_ALPHA); - // we rescale by the user-defined strength of adaptation - dq_uv_ac = dq_uv_ac * enc->config_->sns_strength / 100; - // and make it safe. - dq_uv_ac = clip(dq_uv_ac, MIN_DQ_UV, MAX_DQ_UV); - // We also boost the dc-uv-quant a little, based on sns-strength, since - // U/V channels are quite more reactive to high quants (flat DC-blocks - // tend to appear, and are unpleasant). - dq_uv_dc = -4 * enc->config_->sns_strength / 100; - dq_uv_dc = clip(dq_uv_dc, -15, 15); // 4bit-signed max allowed - - enc->dq_y1_dc_ = 0; // TODO(skal): dq-lum - enc->dq_y2_dc_ = 0; - enc->dq_y2_ac_ = 0; - enc->dq_uv_dc_ = dq_uv_dc; - enc->dq_uv_ac_ = dq_uv_ac; - - SetupFilterStrength(enc); // initialize segments' filtering, eventually - - if (num_segments > 1) SimplifySegments(enc); - - SetupMatrices(enc); // finalize quantization matrices -} - -//------------------------------------------------------------------------------ -// Form the predictions in cache - -// Must be ordered using {DC_PRED, TM_PRED, V_PRED, H_PRED} as index -const int VP8I16ModeOffsets[4] = { I16DC16, I16TM16, I16VE16, I16HE16 }; -const int VP8UVModeOffsets[4] = { C8DC8, C8TM8, C8VE8, C8HE8 }; - -// Must be indexed using {B_DC_PRED -> B_HU_PRED} as index -const int VP8I4ModeOffsets[NUM_BMODES] = { - I4DC4, I4TM4, I4VE4, I4HE4, I4RD4, I4VR4, I4LD4, I4VL4, I4HD4, I4HU4 -}; - -void VP8MakeLuma16Preds(const VP8EncIterator* const it) { - const uint8_t* const left = it->x_ ? it->y_left_ : NULL; - const uint8_t* const top = it->y_ ? it->y_top_ : NULL; - VP8EncPredLuma16(it->yuv_p_, left, top); -} - -void VP8MakeChroma8Preds(const VP8EncIterator* const it) { - const uint8_t* const left = it->x_ ? it->u_left_ : NULL; - const uint8_t* const top = it->y_ ? it->uv_top_ : NULL; - VP8EncPredChroma8(it->yuv_p_, left, top); -} - -void VP8MakeIntra4Preds(const VP8EncIterator* const it) { - VP8EncPredLuma4(it->yuv_p_, it->i4_top_); -} - -//------------------------------------------------------------------------------ -// Quantize - -// Layout: -// +----+----+ -// |YYYY|UUVV| 0 -// |YYYY|UUVV| 4 -// |YYYY|....| 8 -// |YYYY|....| 12 -// +----+----+ - -const int VP8Scan[16] = { // Luma - 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS, - 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS, - 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS, - 0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS, -}; - -static const int VP8ScanUV[4 + 4] = { - 0 + 0 * BPS, 4 + 0 * BPS, 0 + 4 * BPS, 4 + 4 * BPS, // U - 8 + 0 * BPS, 12 + 0 * BPS, 8 + 4 * BPS, 12 + 4 * BPS // V -}; - -//------------------------------------------------------------------------------ -// Distortion measurement - -static const uint16_t kWeightY[16] = { - 38, 32, 20, 9, 32, 28, 17, 7, 20, 17, 10, 4, 9, 7, 4, 2 -}; - -static const uint16_t kWeightTrellis[16] = { -#if USE_TDISTO == 0 - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 -#else - 30, 27, 19, 11, - 27, 24, 17, 10, - 19, 17, 12, 8, - 11, 10, 8, 6 -#endif -}; - -// Init/Copy the common fields in score. -static void InitScore(VP8ModeScore* const rd) { - rd->D = 0; - rd->SD = 0; - rd->R = 0; - rd->H = 0; - rd->nz = 0; - rd->score = MAX_COST; -} - -static void CopyScore(VP8ModeScore* const dst, const VP8ModeScore* const src) { - dst->D = src->D; - dst->SD = src->SD; - dst->R = src->R; - dst->H = src->H; - dst->nz = src->nz; // note that nz is not accumulated, but just copied. - dst->score = src->score; -} - -static void AddScore(VP8ModeScore* const dst, const VP8ModeScore* const src) { - dst->D += src->D; - dst->SD += src->SD; - dst->R += src->R; - dst->H += src->H; - dst->nz |= src->nz; // here, new nz bits are accumulated. - dst->score += src->score; -} - -//------------------------------------------------------------------------------ -// Performs trellis-optimized quantization. - -// Trellis node -typedef struct { - int8_t prev; // best previous node - int8_t sign; // sign of coeff_i - int16_t level; // level -} Node; - -// Score state -typedef struct { - score_t score; // partial RD score - const uint16_t* costs; // shortcut to cost tables -} ScoreState; - -// If a coefficient was quantized to a value Q (using a neutral bias), -// we test all alternate possibilities between [Q-MIN_DELTA, Q+MAX_DELTA] -// We don't test negative values though. -#define MIN_DELTA 0 // how much lower level to try -#define MAX_DELTA 1 // how much higher -#define NUM_NODES (MIN_DELTA + 1 + MAX_DELTA) -#define NODE(n, l) (nodes[(n)][(l) + MIN_DELTA]) -#define SCORE_STATE(n, l) (score_states[n][(l) + MIN_DELTA]) - -static WEBP_INLINE void SetRDScore(int lambda, VP8ModeScore* const rd) { - rd->score = (rd->R + rd->H) * lambda + RD_DISTO_MULT * (rd->D + rd->SD); -} - -static WEBP_INLINE score_t RDScoreTrellis(int lambda, score_t rate, - score_t distortion) { - return rate * lambda + RD_DISTO_MULT * distortion; -} - -static int TrellisQuantizeBlock(const VP8Encoder* const enc, - int16_t in[16], int16_t out[16], - int ctx0, int coeff_type, - const VP8Matrix* const mtx, - int lambda) { - const ProbaArray* const probas = enc->proba_.coeffs_[coeff_type]; - CostArrayPtr const costs = - (CostArrayPtr)enc->proba_.remapped_costs_[coeff_type]; - const int first = (coeff_type == 0) ? 1 : 0; - Node nodes[16][NUM_NODES]; - ScoreState score_states[2][NUM_NODES]; - ScoreState* ss_cur = &SCORE_STATE(0, MIN_DELTA); - ScoreState* ss_prev = &SCORE_STATE(1, MIN_DELTA); - int best_path[3] = {-1, -1, -1}; // store best-last/best-level/best-previous - score_t best_score; - int n, m, p, last; - - { - score_t cost; - const int thresh = mtx->q_[1] * mtx->q_[1] / 4; - const int last_proba = probas[VP8EncBands[first]][ctx0][0]; - - // compute the position of the last interesting coefficient - last = first - 1; - for (n = 15; n >= first; --n) { - const int j = kZigzag[n]; - const int err = in[j] * in[j]; - if (err > thresh) { - last = n; - break; - } - } - // we don't need to go inspect up to n = 16 coeffs. We can just go up - // to last + 1 (inclusive) without losing much. - if (last < 15) ++last; - - // compute 'skip' score. This is the max score one can do. - cost = VP8BitCost(0, last_proba); - best_score = RDScoreTrellis(lambda, cost, 0); - - // initialize source node. - for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) { - const score_t rate = (ctx0 == 0) ? VP8BitCost(1, last_proba) : 0; - ss_cur[m].score = RDScoreTrellis(lambda, rate, 0); - ss_cur[m].costs = costs[first][ctx0]; - } - } - - // traverse trellis. - for (n = first; n <= last; ++n) { - const int j = kZigzag[n]; - const uint32_t Q = mtx->q_[j]; - const uint32_t iQ = mtx->iq_[j]; - const uint32_t B = BIAS(0x00); // neutral bias - // note: it's important to take sign of the _original_ coeff, - // so we don't have to consider level < 0 afterward. - const int sign = (in[j] < 0); - const uint32_t coeff0 = (sign ? -in[j] : in[j]) + mtx->sharpen_[j]; - int level0 = QUANTDIV(coeff0, iQ, B); - if (level0 > MAX_LEVEL) level0 = MAX_LEVEL; - - { // Swap current and previous score states - ScoreState* const tmp = ss_cur; - ss_cur = ss_prev; - ss_prev = tmp; - } - - // test all alternate level values around level0. - for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) { - Node* const cur = &NODE(n, m); - int level = level0 + m; - const int ctx = (level > 2) ? 2 : level; - const int band = VP8EncBands[n + 1]; - score_t base_score, last_pos_score; - score_t best_cur_score = MAX_COST; - int best_prev = 0; // default, in case - - ss_cur[m].score = MAX_COST; - ss_cur[m].costs = costs[n + 1][ctx]; - if (level > MAX_LEVEL || level < 0) { // node is dead? - continue; - } - - // Compute extra rate cost if last coeff's position is < 15 - { - const score_t last_pos_cost = - (n < 15) ? VP8BitCost(0, probas[band][ctx][0]) : 0; - last_pos_score = RDScoreTrellis(lambda, last_pos_cost, 0); - } - - { - // Compute delta_error = how much coding this level will - // subtract to max_error as distortion. - // Here, distortion = sum of (|coeff_i| - level_i * Q_i)^2 - const int new_error = coeff0 - level * Q; - const int delta_error = - kWeightTrellis[j] * (new_error * new_error - coeff0 * coeff0); - base_score = RDScoreTrellis(lambda, 0, delta_error); - } - - // Inspect all possible non-dead predecessors. Retain only the best one. - for (p = -MIN_DELTA; p <= MAX_DELTA; ++p) { - // Dead nodes (with ss_prev[p].score >= MAX_COST) are automatically - // eliminated since their score can't be better than the current best. - const score_t cost = VP8LevelCost(ss_prev[p].costs, level); - // Examine node assuming it's a non-terminal one. - const score_t score = - base_score + ss_prev[p].score + RDScoreTrellis(lambda, cost, 0); - if (score < best_cur_score) { - best_cur_score = score; - best_prev = p; - } - } - // Store best finding in current node. - cur->sign = sign; - cur->level = level; - cur->prev = best_prev; - ss_cur[m].score = best_cur_score; - - // Now, record best terminal node (and thus best entry in the graph). - if (level != 0) { - const score_t score = best_cur_score + last_pos_score; - if (score < best_score) { - best_score = score; - best_path[0] = n; // best eob position - best_path[1] = m; // best node index - best_path[2] = best_prev; // best predecessor - } - } - } - } - - // Fresh start - memset(in + first, 0, (16 - first) * sizeof(*in)); - memset(out + first, 0, (16 - first) * sizeof(*out)); - if (best_path[0] == -1) { - return 0; // skip! - } - - { - // Unwind the best path. - // Note: best-prev on terminal node is not necessarily equal to the - // best_prev for non-terminal. So we patch best_path[2] in. - int nz = 0; - int best_node = best_path[1]; - n = best_path[0]; - NODE(n, best_node).prev = best_path[2]; // force best-prev for terminal - - for (; n >= first; --n) { - const Node* const node = &NODE(n, best_node); - const int j = kZigzag[n]; - out[n] = node->sign ? -node->level : node->level; - nz |= node->level; - in[j] = out[n] * mtx->q_[j]; - best_node = node->prev; - } - return (nz != 0); - } -} - -#undef NODE - -//------------------------------------------------------------------------------ -// Performs: difference, transform, quantize, back-transform, add -// all at once. Output is the reconstructed block in *yuv_out, and the -// quantized levels in *levels. - -static int ReconstructIntra16(VP8EncIterator* const it, - VP8ModeScore* const rd, - uint8_t* const yuv_out, - int mode) { - const VP8Encoder* const enc = it->enc_; - const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode]; - const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC; - const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; - int nz = 0; - int n; - int16_t tmp[16][16], dc_tmp[16]; - - for (n = 0; n < 16; n += 2) { - VP8FTransform2(src + VP8Scan[n], ref + VP8Scan[n], tmp[n]); - } - VP8FTransformWHT(tmp[0], dc_tmp); - nz |= VP8EncQuantizeBlockWHT(dc_tmp, rd->y_dc_levels, &dqm->y2_) << 24; - - if (DO_TRELLIS_I16 && it->do_trellis_) { - int x, y; - VP8IteratorNzToBytes(it); - for (y = 0, n = 0; y < 4; ++y) { - for (x = 0; x < 4; ++x, ++n) { - const int ctx = it->top_nz_[x] + it->left_nz_[y]; - const int non_zero = - TrellisQuantizeBlock(enc, tmp[n], rd->y_ac_levels[n], ctx, 0, - &dqm->y1_, dqm->lambda_trellis_i16_); - it->top_nz_[x] = it->left_nz_[y] = non_zero; - rd->y_ac_levels[n][0] = 0; - nz |= non_zero << n; - } - } - } else { - for (n = 0; n < 16; n += 2) { - // Zero-out the first coeff, so that: a) nz is correct below, and - // b) finding 'last' non-zero coeffs in SetResidualCoeffs() is simplified. - tmp[n][0] = tmp[n + 1][0] = 0; - nz |= VP8EncQuantize2Blocks(tmp[n], rd->y_ac_levels[n], &dqm->y1_) << n; - assert(rd->y_ac_levels[n + 0][0] == 0); - assert(rd->y_ac_levels[n + 1][0] == 0); - } - } - - // Transform back - VP8TransformWHT(dc_tmp, tmp[0]); - for (n = 0; n < 16; n += 2) { - VP8ITransform(ref + VP8Scan[n], tmp[n], yuv_out + VP8Scan[n], 1); - } - - return nz; -} - -static int ReconstructIntra4(VP8EncIterator* const it, - int16_t levels[16], - const uint8_t* const src, - uint8_t* const yuv_out, - int mode) { - const VP8Encoder* const enc = it->enc_; - const uint8_t* const ref = it->yuv_p_ + VP8I4ModeOffsets[mode]; - const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; - int nz = 0; - int16_t tmp[16]; - - VP8FTransform(src, ref, tmp); - if (DO_TRELLIS_I4 && it->do_trellis_) { - const int x = it->i4_ & 3, y = it->i4_ >> 2; - const int ctx = it->top_nz_[x] + it->left_nz_[y]; - nz = TrellisQuantizeBlock(enc, tmp, levels, ctx, 3, &dqm->y1_, - dqm->lambda_trellis_i4_); - } else { - nz = VP8EncQuantizeBlock(tmp, levels, &dqm->y1_); - } - VP8ITransform(ref, tmp, yuv_out, 0); - return nz; -} - -static int ReconstructUV(VP8EncIterator* const it, VP8ModeScore* const rd, - uint8_t* const yuv_out, int mode) { - const VP8Encoder* const enc = it->enc_; - const uint8_t* const ref = it->yuv_p_ + VP8UVModeOffsets[mode]; - const uint8_t* const src = it->yuv_in_ + U_OFF_ENC; - const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; - int nz = 0; - int n; - int16_t tmp[8][16]; - - for (n = 0; n < 8; n += 2) { - VP8FTransform2(src + VP8ScanUV[n], ref + VP8ScanUV[n], tmp[n]); - } - if (DO_TRELLIS_UV && it->do_trellis_) { - int ch, x, y; - for (ch = 0, n = 0; ch <= 2; ch += 2) { - for (y = 0; y < 2; ++y) { - for (x = 0; x < 2; ++x, ++n) { - const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; - const int non_zero = - TrellisQuantizeBlock(enc, tmp[n], rd->uv_levels[n], ctx, 2, - &dqm->uv_, dqm->lambda_trellis_uv_); - it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = non_zero; - nz |= non_zero << n; - } - } - } - } else { - for (n = 0; n < 8; n += 2) { - nz |= VP8EncQuantize2Blocks(tmp[n], rd->uv_levels[n], &dqm->uv_) << n; - } - } - - for (n = 0; n < 8; n += 2) { - VP8ITransform(ref + VP8ScanUV[n], tmp[n], yuv_out + VP8ScanUV[n], 1); - } - return (nz << 16); -} - -//------------------------------------------------------------------------------ -// RD-opt decision. Reconstruct each modes, evalue distortion and bit-cost. -// Pick the mode is lower RD-cost = Rate + lambda * Distortion. - -static void StoreMaxDelta(VP8SegmentInfo* const dqm, const int16_t DCs[16]) { - // We look at the first three AC coefficients to determine what is the average - // delta between each sub-4x4 block. - const int v0 = abs(DCs[1]); - const int v1 = abs(DCs[4]); - const int v2 = abs(DCs[5]); - int max_v = (v0 > v1) ? v1 : v0; - max_v = (v2 > max_v) ? v2 : max_v; - if (max_v > dqm->max_edge_) dqm->max_edge_ = max_v; -} - -static void SwapModeScore(VP8ModeScore** a, VP8ModeScore** b) { - VP8ModeScore* const tmp = *a; - *a = *b; - *b = tmp; -} - -static void SwapPtr(uint8_t** a, uint8_t** b) { - uint8_t* const tmp = *a; - *a = *b; - *b = tmp; -} - -static void SwapOut(VP8EncIterator* const it) { - SwapPtr(&it->yuv_out_, &it->yuv_out2_); -} - -static score_t IsFlat(const int16_t* levels, int num_blocks, score_t thresh) { - score_t score = 0; - while (num_blocks-- > 0) { // TODO(skal): refine positional scoring? - int i; - for (i = 1; i < 16; ++i) { // omit DC, we're only interested in AC - score += (levels[i] != 0); - if (score > thresh) return 0; - } - levels += 16; - } - return 1; -} - -static void PickBestIntra16(VP8EncIterator* const it, VP8ModeScore* rd) { - const int kNumBlocks = 16; - VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_]; - const int lambda = dqm->lambda_i16_; - const int tlambda = dqm->tlambda_; - const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC; - VP8ModeScore rd_tmp; - VP8ModeScore* rd_cur = &rd_tmp; - VP8ModeScore* rd_best = rd; - int mode; - - rd->mode_i16 = -1; - for (mode = 0; mode < NUM_PRED_MODES; ++mode) { - uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF_ENC; // scratch buffer - rd_cur->mode_i16 = mode; - - // Reconstruct - rd_cur->nz = ReconstructIntra16(it, rd_cur, tmp_dst, mode); - - // Measure RD-score - rd_cur->D = VP8SSE16x16(src, tmp_dst); - rd_cur->SD = - tlambda ? MULT_8B(tlambda, VP8TDisto16x16(src, tmp_dst, kWeightY)) : 0; - rd_cur->H = VP8FixedCostsI16[mode]; - rd_cur->R = VP8GetCostLuma16(it, rd_cur); - if (mode > 0 && - IsFlat(rd_cur->y_ac_levels[0], kNumBlocks, FLATNESS_LIMIT_I16)) { - // penalty to avoid flat area to be mispredicted by complex mode - rd_cur->R += FLATNESS_PENALTY * kNumBlocks; - } - - // Since we always examine Intra16 first, we can overwrite *rd directly. - SetRDScore(lambda, rd_cur); - if (mode == 0 || rd_cur->score < rd_best->score) { - SwapModeScore(&rd_cur, &rd_best); - SwapOut(it); - } - } - if (rd_best != rd) { - memcpy(rd, rd_best, sizeof(*rd)); - } - SetRDScore(dqm->lambda_mode_, rd); // finalize score for mode decision. - VP8SetIntra16Mode(it, rd->mode_i16); - - // we have a blocky macroblock (only DCs are non-zero) with fairly high - // distortion, record max delta so we can later adjust the minimal filtering - // strength needed to smooth these blocks out. - if ((rd->nz & 0xffff) == 0 && rd->D > dqm->min_disto_) { - StoreMaxDelta(dqm, rd->y_dc_levels); - } -} - -//------------------------------------------------------------------------------ - -// return the cost array corresponding to the surrounding prediction modes. -static const uint16_t* GetCostModeI4(VP8EncIterator* const it, - const uint8_t modes[16]) { - const int preds_w = it->enc_->preds_w_; - const int x = (it->i4_ & 3), y = it->i4_ >> 2; - const int left = (x == 0) ? it->preds_[y * preds_w - 1] : modes[it->i4_ - 1]; - const int top = (y == 0) ? it->preds_[-preds_w + x] : modes[it->i4_ - 4]; - return VP8FixedCostsI4[top][left]; -} - -static int PickBestIntra4(VP8EncIterator* const it, VP8ModeScore* const rd) { - const VP8Encoder* const enc = it->enc_; - const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; - const int lambda = dqm->lambda_i4_; - const int tlambda = dqm->tlambda_; - const uint8_t* const src0 = it->yuv_in_ + Y_OFF_ENC; - uint8_t* const best_blocks = it->yuv_out2_ + Y_OFF_ENC; - int total_header_bits = 0; - VP8ModeScore rd_best; - - if (enc->max_i4_header_bits_ == 0) { - return 0; - } - - InitScore(&rd_best); - rd_best.H = 211; // '211' is the value of VP8BitCost(0, 145) - SetRDScore(dqm->lambda_mode_, &rd_best); - VP8IteratorStartI4(it); - do { - const int kNumBlocks = 1; - VP8ModeScore rd_i4; - int mode; - int best_mode = -1; - const uint8_t* const src = src0 + VP8Scan[it->i4_]; - const uint16_t* const mode_costs = GetCostModeI4(it, rd->modes_i4); - uint8_t* best_block = best_blocks + VP8Scan[it->i4_]; - uint8_t* tmp_dst = it->yuv_p_ + I4TMP; // scratch buffer. - - InitScore(&rd_i4); - VP8MakeIntra4Preds(it); - for (mode = 0; mode < NUM_BMODES; ++mode) { - VP8ModeScore rd_tmp; - int16_t tmp_levels[16]; - - // Reconstruct - rd_tmp.nz = - ReconstructIntra4(it, tmp_levels, src, tmp_dst, mode) << it->i4_; - - // Compute RD-score - rd_tmp.D = VP8SSE4x4(src, tmp_dst); - rd_tmp.SD = - tlambda ? MULT_8B(tlambda, VP8TDisto4x4(src, tmp_dst, kWeightY)) - : 0; - rd_tmp.H = mode_costs[mode]; - - // Add flatness penalty - if (mode > 0 && IsFlat(tmp_levels, kNumBlocks, FLATNESS_LIMIT_I4)) { - rd_tmp.R = FLATNESS_PENALTY * kNumBlocks; - } else { - rd_tmp.R = 0; - } - - // early-out check - SetRDScore(lambda, &rd_tmp); - if (best_mode >= 0 && rd_tmp.score >= rd_i4.score) continue; - - // finish computing score - rd_tmp.R += VP8GetCostLuma4(it, tmp_levels); - SetRDScore(lambda, &rd_tmp); - - if (best_mode < 0 || rd_tmp.score < rd_i4.score) { - CopyScore(&rd_i4, &rd_tmp); - best_mode = mode; - SwapPtr(&tmp_dst, &best_block); - memcpy(rd_best.y_ac_levels[it->i4_], tmp_levels, - sizeof(rd_best.y_ac_levels[it->i4_])); - } - } - SetRDScore(dqm->lambda_mode_, &rd_i4); - AddScore(&rd_best, &rd_i4); - if (rd_best.score >= rd->score) { - return 0; - } - total_header_bits += (int)rd_i4.H; // <- equal to mode_costs[best_mode]; - if (total_header_bits > enc->max_i4_header_bits_) { - return 0; - } - // Copy selected samples if not in the right place already. - if (best_block != best_blocks + VP8Scan[it->i4_]) { - VP8Copy4x4(best_block, best_blocks + VP8Scan[it->i4_]); - } - rd->modes_i4[it->i4_] = best_mode; - it->top_nz_[it->i4_ & 3] = it->left_nz_[it->i4_ >> 2] = (rd_i4.nz ? 1 : 0); - } while (VP8IteratorRotateI4(it, best_blocks)); - - // finalize state - CopyScore(rd, &rd_best); - VP8SetIntra4Mode(it, rd->modes_i4); - SwapOut(it); - memcpy(rd->y_ac_levels, rd_best.y_ac_levels, sizeof(rd->y_ac_levels)); - return 1; // select intra4x4 over intra16x16 -} - -//------------------------------------------------------------------------------ - -static void PickBestUV(VP8EncIterator* const it, VP8ModeScore* const rd) { - const int kNumBlocks = 8; - const VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_]; - const int lambda = dqm->lambda_uv_; - const uint8_t* const src = it->yuv_in_ + U_OFF_ENC; - uint8_t* tmp_dst = it->yuv_out2_ + U_OFF_ENC; // scratch buffer - uint8_t* dst0 = it->yuv_out_ + U_OFF_ENC; - uint8_t* dst = dst0; - VP8ModeScore rd_best; - int mode; - - rd->mode_uv = -1; - InitScore(&rd_best); - for (mode = 0; mode < NUM_PRED_MODES; ++mode) { - VP8ModeScore rd_uv; - - // Reconstruct - rd_uv.nz = ReconstructUV(it, &rd_uv, tmp_dst, mode); - - // Compute RD-score - rd_uv.D = VP8SSE16x8(src, tmp_dst); - rd_uv.SD = 0; // not calling TDisto here: it tends to flatten areas. - rd_uv.H = VP8FixedCostsUV[mode]; - rd_uv.R = VP8GetCostUV(it, &rd_uv); - if (mode > 0 && IsFlat(rd_uv.uv_levels[0], kNumBlocks, FLATNESS_LIMIT_UV)) { - rd_uv.R += FLATNESS_PENALTY * kNumBlocks; - } - - SetRDScore(lambda, &rd_uv); - if (mode == 0 || rd_uv.score < rd_best.score) { - CopyScore(&rd_best, &rd_uv); - rd->mode_uv = mode; - memcpy(rd->uv_levels, rd_uv.uv_levels, sizeof(rd->uv_levels)); - SwapPtr(&dst, &tmp_dst); - } - } - VP8SetIntraUVMode(it, rd->mode_uv); - AddScore(rd, &rd_best); - if (dst != dst0) { // copy 16x8 block if needed - VP8Copy16x8(dst, dst0); - } -} - -//------------------------------------------------------------------------------ -// Final reconstruction and quantization. - -static void SimpleQuantize(VP8EncIterator* const it, VP8ModeScore* const rd) { - const VP8Encoder* const enc = it->enc_; - const int is_i16 = (it->mb_->type_ == 1); - int nz = 0; - - if (is_i16) { - nz = ReconstructIntra16(it, rd, it->yuv_out_ + Y_OFF_ENC, it->preds_[0]); - } else { - VP8IteratorStartI4(it); - do { - const int mode = - it->preds_[(it->i4_ & 3) + (it->i4_ >> 2) * enc->preds_w_]; - const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_]; - uint8_t* const dst = it->yuv_out_ + Y_OFF_ENC + VP8Scan[it->i4_]; - VP8MakeIntra4Preds(it); - nz |= ReconstructIntra4(it, rd->y_ac_levels[it->i4_], - src, dst, mode) << it->i4_; - } while (VP8IteratorRotateI4(it, it->yuv_out_ + Y_OFF_ENC)); - } - - nz |= ReconstructUV(it, rd, it->yuv_out_ + U_OFF_ENC, it->mb_->uv_mode_); - rd->nz = nz; -} - -// Refine intra16/intra4 sub-modes based on distortion only (not rate). -static void RefineUsingDistortion(VP8EncIterator* const it, - int try_both_modes, int refine_uv_mode, - VP8ModeScore* const rd) { - score_t best_score = MAX_COST; - score_t score_i4 = (score_t)I4_PENALTY; - int16_t tmp_levels[16][16]; - uint8_t modes_i4[16]; - int nz = 0; - int mode; - int is_i16 = try_both_modes || (it->mb_->type_ == 1); - - if (is_i16) { // First, evaluate Intra16 distortion - int best_mode = -1; - const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC; - for (mode = 0; mode < NUM_PRED_MODES; ++mode) { - const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode]; - const score_t score = VP8SSE16x16(src, ref); - if (score < best_score) { - best_mode = mode; - best_score = score; - } - } - VP8SetIntra16Mode(it, best_mode); - // we'll reconstruct later, if i16 mode actually gets selected - } - - // Next, evaluate Intra4 - if (try_both_modes || !is_i16) { - // We don't evaluate the rate here, but just account for it through a - // constant penalty (i4 mode usually needs more bits compared to i16). - is_i16 = 0; - VP8IteratorStartI4(it); - do { - int best_i4_mode = -1; - score_t best_i4_score = MAX_COST; - const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_]; - - VP8MakeIntra4Preds(it); - for (mode = 0; mode < NUM_BMODES; ++mode) { - const uint8_t* const ref = it->yuv_p_ + VP8I4ModeOffsets[mode]; - const score_t score = VP8SSE4x4(src, ref); - if (score < best_i4_score) { - best_i4_mode = mode; - best_i4_score = score; - } - } - modes_i4[it->i4_] = best_i4_mode; - score_i4 += best_i4_score; - if (score_i4 >= best_score) { - // Intra4 won't be better than Intra16. Bail out and pick Intra16. - is_i16 = 1; - break; - } else { // reconstruct partial block inside yuv_out2_ buffer - uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF_ENC + VP8Scan[it->i4_]; - nz |= ReconstructIntra4(it, tmp_levels[it->i4_], - src, tmp_dst, best_i4_mode) << it->i4_; - } - } while (VP8IteratorRotateI4(it, it->yuv_out2_ + Y_OFF_ENC)); - } - - // Final reconstruction, depending on which mode is selected. - if (!is_i16) { - VP8SetIntra4Mode(it, modes_i4); - memcpy(rd->y_ac_levels, tmp_levels, sizeof(tmp_levels)); - SwapOut(it); - best_score = score_i4; - } else { - nz = ReconstructIntra16(it, rd, it->yuv_out_ + Y_OFF_ENC, it->preds_[0]); - } - - // ... and UV! - if (refine_uv_mode) { - int best_mode = -1; - score_t best_uv_score = MAX_COST; - const uint8_t* const src = it->yuv_in_ + U_OFF_ENC; - for (mode = 0; mode < NUM_PRED_MODES; ++mode) { - const uint8_t* const ref = it->yuv_p_ + VP8UVModeOffsets[mode]; - const score_t score = VP8SSE16x8(src, ref); - if (score < best_uv_score) { - best_mode = mode; - best_uv_score = score; - } - } - VP8SetIntraUVMode(it, best_mode); - } - nz |= ReconstructUV(it, rd, it->yuv_out_ + U_OFF_ENC, it->mb_->uv_mode_); - - rd->nz = nz; - rd->score = best_score; -} - -//------------------------------------------------------------------------------ -// Entry point - -int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, - VP8RDLevel rd_opt) { - int is_skipped; - const int method = it->enc_->method_; - - InitScore(rd); - - // We can perform predictions for Luma16x16 and Chroma8x8 already. - // Luma4x4 predictions needs to be done as-we-go. - VP8MakeLuma16Preds(it); - VP8MakeChroma8Preds(it); - - if (rd_opt > RD_OPT_NONE) { - it->do_trellis_ = (rd_opt >= RD_OPT_TRELLIS_ALL); - PickBestIntra16(it, rd); - if (method >= 2) { - PickBestIntra4(it, rd); - } - PickBestUV(it, rd); - if (rd_opt == RD_OPT_TRELLIS) { // finish off with trellis-optim now - it->do_trellis_ = 1; - SimpleQuantize(it, rd); - } - } else { - // At this point we have heuristically decided intra16 / intra4. - // For method >= 2, pick the best intra4/intra16 based on SSE (~tad slower). - // For method <= 1, we don't re-examine the decision but just go ahead with - // quantization/reconstruction. - RefineUsingDistortion(it, (method >= 2), (method >= 1), rd); - } - is_skipped = (rd->nz == 0); - VP8SetSkip(it, is_skipped); - return is_skipped; -} diff --git a/Example/Pods/libwebp/src/enc/syntax.c b/Example/Pods/libwebp/src/enc/syntax.c deleted file mode 100644 index a0e79ef4..00000000 --- a/Example/Pods/libwebp/src/enc/syntax.c +++ /dev/null @@ -1,383 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Header syntax writing -// -// Author: Skal (pascal.massimino@gmail.com) - -#include - -#include "../utils/utils.h" -#include "../webp/format_constants.h" // RIFF constants -#include "../webp/mux_types.h" // ALPHA_FLAG -#include "./vp8enci.h" - -//------------------------------------------------------------------------------ -// Helper functions - -static int IsVP8XNeeded(const VP8Encoder* const enc) { - return !!enc->has_alpha_; // Currently the only case when VP8X is needed. - // This could change in the future. -} - -static int PutPaddingByte(const WebPPicture* const pic) { - const uint8_t pad_byte[1] = { 0 }; - return !!pic->writer(pad_byte, 1, pic); -} - -//------------------------------------------------------------------------------ -// Writers for header's various pieces (in order of appearance) - -static WebPEncodingError PutRIFFHeader(const VP8Encoder* const enc, - size_t riff_size) { - const WebPPicture* const pic = enc->pic_; - uint8_t riff[RIFF_HEADER_SIZE] = { - 'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P' - }; - assert(riff_size == (uint32_t)riff_size); - PutLE32(riff + TAG_SIZE, (uint32_t)riff_size); - if (!pic->writer(riff, sizeof(riff), pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - return VP8_ENC_OK; -} - -static WebPEncodingError PutVP8XHeader(const VP8Encoder* const enc) { - const WebPPicture* const pic = enc->pic_; - uint8_t vp8x[CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE] = { - 'V', 'P', '8', 'X' - }; - uint32_t flags = 0; - - assert(IsVP8XNeeded(enc)); - assert(pic->width >= 1 && pic->height >= 1); - assert(pic->width <= MAX_CANVAS_SIZE && pic->height <= MAX_CANVAS_SIZE); - - if (enc->has_alpha_) { - flags |= ALPHA_FLAG; - } - - PutLE32(vp8x + TAG_SIZE, VP8X_CHUNK_SIZE); - PutLE32(vp8x + CHUNK_HEADER_SIZE, flags); - PutLE24(vp8x + CHUNK_HEADER_SIZE + 4, pic->width - 1); - PutLE24(vp8x + CHUNK_HEADER_SIZE + 7, pic->height - 1); - if (!pic->writer(vp8x, sizeof(vp8x), pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - return VP8_ENC_OK; -} - -static WebPEncodingError PutAlphaChunk(const VP8Encoder* const enc) { - const WebPPicture* const pic = enc->pic_; - uint8_t alpha_chunk_hdr[CHUNK_HEADER_SIZE] = { - 'A', 'L', 'P', 'H' - }; - - assert(enc->has_alpha_); - - // Alpha chunk header. - PutLE32(alpha_chunk_hdr + TAG_SIZE, enc->alpha_data_size_); - if (!pic->writer(alpha_chunk_hdr, sizeof(alpha_chunk_hdr), pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - - // Alpha chunk data. - if (!pic->writer(enc->alpha_data_, enc->alpha_data_size_, pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - - // Padding. - if ((enc->alpha_data_size_ & 1) && !PutPaddingByte(pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - return VP8_ENC_OK; -} - -static WebPEncodingError PutVP8Header(const WebPPicture* const pic, - size_t vp8_size) { - uint8_t vp8_chunk_hdr[CHUNK_HEADER_SIZE] = { - 'V', 'P', '8', ' ' - }; - assert(vp8_size == (uint32_t)vp8_size); - PutLE32(vp8_chunk_hdr + TAG_SIZE, (uint32_t)vp8_size); - if (!pic->writer(vp8_chunk_hdr, sizeof(vp8_chunk_hdr), pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - return VP8_ENC_OK; -} - -static WebPEncodingError PutVP8FrameHeader(const WebPPicture* const pic, - int profile, size_t size0) { - uint8_t vp8_frm_hdr[VP8_FRAME_HEADER_SIZE]; - uint32_t bits; - - if (size0 >= VP8_MAX_PARTITION0_SIZE) { // partition #0 is too big to fit - return VP8_ENC_ERROR_PARTITION0_OVERFLOW; - } - - // Paragraph 9.1. - bits = 0 // keyframe (1b) - | (profile << 1) // profile (3b) - | (1 << 4) // visible (1b) - | ((uint32_t)size0 << 5); // partition length (19b) - vp8_frm_hdr[0] = (bits >> 0) & 0xff; - vp8_frm_hdr[1] = (bits >> 8) & 0xff; - vp8_frm_hdr[2] = (bits >> 16) & 0xff; - // signature - vp8_frm_hdr[3] = (VP8_SIGNATURE >> 16) & 0xff; - vp8_frm_hdr[4] = (VP8_SIGNATURE >> 8) & 0xff; - vp8_frm_hdr[5] = (VP8_SIGNATURE >> 0) & 0xff; - // dimensions - vp8_frm_hdr[6] = pic->width & 0xff; - vp8_frm_hdr[7] = pic->width >> 8; - vp8_frm_hdr[8] = pic->height & 0xff; - vp8_frm_hdr[9] = pic->height >> 8; - - if (!pic->writer(vp8_frm_hdr, sizeof(vp8_frm_hdr), pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - return VP8_ENC_OK; -} - -// WebP Headers. -static int PutWebPHeaders(const VP8Encoder* const enc, size_t size0, - size_t vp8_size, size_t riff_size) { - WebPPicture* const pic = enc->pic_; - WebPEncodingError err = VP8_ENC_OK; - - // RIFF header. - err = PutRIFFHeader(enc, riff_size); - if (err != VP8_ENC_OK) goto Error; - - // VP8X. - if (IsVP8XNeeded(enc)) { - err = PutVP8XHeader(enc); - if (err != VP8_ENC_OK) goto Error; - } - - // Alpha. - if (enc->has_alpha_) { - err = PutAlphaChunk(enc); - if (err != VP8_ENC_OK) goto Error; - } - - // VP8 header. - err = PutVP8Header(pic, vp8_size); - if (err != VP8_ENC_OK) goto Error; - - // VP8 frame header. - err = PutVP8FrameHeader(pic, enc->profile_, size0); - if (err != VP8_ENC_OK) goto Error; - - // All OK. - return 1; - - // Error. - Error: - return WebPEncodingSetError(pic, err); -} - -// Segmentation header -static void PutSegmentHeader(VP8BitWriter* const bw, - const VP8Encoder* const enc) { - const VP8EncSegmentHeader* const hdr = &enc->segment_hdr_; - const VP8EncProba* const proba = &enc->proba_; - if (VP8PutBitUniform(bw, (hdr->num_segments_ > 1))) { - // We always 'update' the quant and filter strength values - const int update_data = 1; - int s; - VP8PutBitUniform(bw, hdr->update_map_); - if (VP8PutBitUniform(bw, update_data)) { - // we always use absolute values, not relative ones - VP8PutBitUniform(bw, 1); // (segment_feature_mode = 1. Paragraph 9.3.) - for (s = 0; s < NUM_MB_SEGMENTS; ++s) { - VP8PutSignedBits(bw, enc->dqm_[s].quant_, 7); - } - for (s = 0; s < NUM_MB_SEGMENTS; ++s) { - VP8PutSignedBits(bw, enc->dqm_[s].fstrength_, 6); - } - } - if (hdr->update_map_) { - for (s = 0; s < 3; ++s) { - if (VP8PutBitUniform(bw, (proba->segments_[s] != 255u))) { - VP8PutBits(bw, proba->segments_[s], 8); - } - } - } - } -} - -// Filtering parameters header -static void PutFilterHeader(VP8BitWriter* const bw, - const VP8EncFilterHeader* const hdr) { - const int use_lf_delta = (hdr->i4x4_lf_delta_ != 0); - VP8PutBitUniform(bw, hdr->simple_); - VP8PutBits(bw, hdr->level_, 6); - VP8PutBits(bw, hdr->sharpness_, 3); - if (VP8PutBitUniform(bw, use_lf_delta)) { - // '0' is the default value for i4x4_lf_delta_ at frame #0. - const int need_update = (hdr->i4x4_lf_delta_ != 0); - if (VP8PutBitUniform(bw, need_update)) { - // we don't use ref_lf_delta => emit four 0 bits - VP8PutBits(bw, 0, 4); - // we use mode_lf_delta for i4x4 - VP8PutSignedBits(bw, hdr->i4x4_lf_delta_, 6); - VP8PutBits(bw, 0, 3); // all others unused - } - } -} - -// Nominal quantization parameters -static void PutQuant(VP8BitWriter* const bw, - const VP8Encoder* const enc) { - VP8PutBits(bw, enc->base_quant_, 7); - VP8PutSignedBits(bw, enc->dq_y1_dc_, 4); - VP8PutSignedBits(bw, enc->dq_y2_dc_, 4); - VP8PutSignedBits(bw, enc->dq_y2_ac_, 4); - VP8PutSignedBits(bw, enc->dq_uv_dc_, 4); - VP8PutSignedBits(bw, enc->dq_uv_ac_, 4); -} - -// Partition sizes -static int EmitPartitionsSize(const VP8Encoder* const enc, - WebPPicture* const pic) { - uint8_t buf[3 * (MAX_NUM_PARTITIONS - 1)]; - int p; - for (p = 0; p < enc->num_parts_ - 1; ++p) { - const size_t part_size = VP8BitWriterSize(enc->parts_ + p); - if (part_size >= VP8_MAX_PARTITION_SIZE) { - return WebPEncodingSetError(pic, VP8_ENC_ERROR_PARTITION_OVERFLOW); - } - buf[3 * p + 0] = (part_size >> 0) & 0xff; - buf[3 * p + 1] = (part_size >> 8) & 0xff; - buf[3 * p + 2] = (part_size >> 16) & 0xff; - } - return p ? pic->writer(buf, 3 * p, pic) : 1; -} - -//------------------------------------------------------------------------------ - -static int GeneratePartition0(VP8Encoder* const enc) { - VP8BitWriter* const bw = &enc->bw_; - const int mb_size = enc->mb_w_ * enc->mb_h_; - uint64_t pos1, pos2, pos3; - - pos1 = VP8BitWriterPos(bw); - if (!VP8BitWriterInit(bw, mb_size * 7 / 8)) { // ~7 bits per macroblock - return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); - } - VP8PutBitUniform(bw, 0); // colorspace - VP8PutBitUniform(bw, 0); // clamp type - - PutSegmentHeader(bw, enc); - PutFilterHeader(bw, &enc->filter_hdr_); - VP8PutBits(bw, enc->num_parts_ == 8 ? 3 : - enc->num_parts_ == 4 ? 2 : - enc->num_parts_ == 2 ? 1 : 0, 2); - PutQuant(bw, enc); - VP8PutBitUniform(bw, 0); // no proba update - VP8WriteProbas(bw, &enc->proba_); - pos2 = VP8BitWriterPos(bw); - VP8CodeIntraModes(enc); - VP8BitWriterFinish(bw); - - pos3 = VP8BitWriterPos(bw); - - if (enc->pic_->stats) { - enc->pic_->stats->header_bytes[0] = (int)((pos2 - pos1 + 7) >> 3); - enc->pic_->stats->header_bytes[1] = (int)((pos3 - pos2 + 7) >> 3); - enc->pic_->stats->alpha_data_size = (int)enc->alpha_data_size_; - } - if (bw->error_) { - return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); - } - return 1; -} - -void VP8EncFreeBitWriters(VP8Encoder* const enc) { - int p; - VP8BitWriterWipeOut(&enc->bw_); - for (p = 0; p < enc->num_parts_; ++p) { - VP8BitWriterWipeOut(enc->parts_ + p); - } -} - -int VP8EncWrite(VP8Encoder* const enc) { - WebPPicture* const pic = enc->pic_; - VP8BitWriter* const bw = &enc->bw_; - const int task_percent = 19; - const int percent_per_part = task_percent / enc->num_parts_; - const int final_percent = enc->percent_ + task_percent; - int ok = 0; - size_t vp8_size, pad, riff_size; - int p; - - // Partition #0 with header and partition sizes - ok = GeneratePartition0(enc); - if (!ok) return 0; - - // Compute VP8 size - vp8_size = VP8_FRAME_HEADER_SIZE + - VP8BitWriterSize(bw) + - 3 * (enc->num_parts_ - 1); - for (p = 0; p < enc->num_parts_; ++p) { - vp8_size += VP8BitWriterSize(enc->parts_ + p); - } - pad = vp8_size & 1; - vp8_size += pad; - - // Compute RIFF size - // At the minimum it is: "WEBPVP8 nnnn" + VP8 data size. - riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8_size; - if (IsVP8XNeeded(enc)) { // Add size for: VP8X header + data. - riff_size += CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE; - } - if (enc->has_alpha_) { // Add size for: ALPH header + data. - const uint32_t padded_alpha_size = enc->alpha_data_size_ + - (enc->alpha_data_size_ & 1); - riff_size += CHUNK_HEADER_SIZE + padded_alpha_size; - } - // Sanity check. - if (riff_size > 0xfffffffeU) { - return WebPEncodingSetError(pic, VP8_ENC_ERROR_FILE_TOO_BIG); - } - - // Emit headers and partition #0 - { - const uint8_t* const part0 = VP8BitWriterBuf(bw); - const size_t size0 = VP8BitWriterSize(bw); - ok = ok && PutWebPHeaders(enc, size0, vp8_size, riff_size) - && pic->writer(part0, size0, pic) - && EmitPartitionsSize(enc, pic); - VP8BitWriterWipeOut(bw); // will free the internal buffer. - } - - // Token partitions - for (p = 0; p < enc->num_parts_; ++p) { - const uint8_t* const buf = VP8BitWriterBuf(enc->parts_ + p); - const size_t size = VP8BitWriterSize(enc->parts_ + p); - if (size) - ok = ok && pic->writer(buf, size, pic); - VP8BitWriterWipeOut(enc->parts_ + p); // will free the internal buffer. - ok = ok && WebPReportProgress(pic, enc->percent_ + percent_per_part, - &enc->percent_); - } - - // Padding byte - if (ok && pad) { - ok = PutPaddingByte(pic); - } - - enc->coded_size_ = (int)(CHUNK_HEADER_SIZE + riff_size); - ok = ok && WebPReportProgress(pic, final_percent, &enc->percent_); - return ok; -} - -//------------------------------------------------------------------------------ - diff --git a/Example/Pods/libwebp/src/enc/token.c b/Example/Pods/libwebp/src/enc/token.c deleted file mode 100644 index e73256b3..00000000 --- a/Example/Pods/libwebp/src/enc/token.c +++ /dev/null @@ -1,285 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Paginated token buffer -// -// A 'token' is a bit value associated with a probability, either fixed -// or a later-to-be-determined after statistics have been collected. -// For dynamic probability, we just record the slot id (idx) for the probability -// value in the final probability array (uint8_t* probas in VP8EmitTokens). -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include -#include - -#include "./cost.h" -#include "./vp8enci.h" -#include "../utils/utils.h" - -#if !defined(DISABLE_TOKEN_BUFFER) - -// we use pages to reduce the number of memcpy() -#define MIN_PAGE_SIZE 8192 // minimum number of token per page -#define FIXED_PROBA_BIT (1u << 14) - -typedef uint16_t token_t; // bit #15: bit value - // bit #14: flags for constant proba or idx - // bits #0..13: slot or constant proba -struct VP8Tokens { - VP8Tokens* next_; // pointer to next page -}; -// Token data is located in memory just after the next_ field. -// This macro is used to return their address and hide the trick. -#define TOKEN_DATA(p) ((const token_t*)&(p)[1]) - -//------------------------------------------------------------------------------ - -void VP8TBufferInit(VP8TBuffer* const b, int page_size) { - b->tokens_ = NULL; - b->pages_ = NULL; - b->last_page_ = &b->pages_; - b->left_ = 0; - b->page_size_ = (page_size < MIN_PAGE_SIZE) ? MIN_PAGE_SIZE : page_size; - b->error_ = 0; -} - -void VP8TBufferClear(VP8TBuffer* const b) { - if (b != NULL) { - VP8Tokens* p = b->pages_; - while (p != NULL) { - VP8Tokens* const next = p->next_; - WebPSafeFree(p); - p = next; - } - VP8TBufferInit(b, b->page_size_); - } -} - -static int TBufferNewPage(VP8TBuffer* const b) { - VP8Tokens* page = NULL; - if (!b->error_) { - const size_t size = sizeof(*page) + b->page_size_ * sizeof(token_t); - page = (VP8Tokens*)WebPSafeMalloc(1ULL, size); - } - if (page == NULL) { - b->error_ = 1; - return 0; - } - page->next_ = NULL; - - *b->last_page_ = page; - b->last_page_ = &page->next_; - b->left_ = b->page_size_; - b->tokens_ = (token_t*)TOKEN_DATA(page); - return 1; -} - -//------------------------------------------------------------------------------ - -#define TOKEN_ID(t, b, ctx) \ - (NUM_PROBAS * ((ctx) + NUM_CTX * ((b) + NUM_BANDS * (t)))) - -static WEBP_INLINE uint32_t AddToken(VP8TBuffer* const b, - uint32_t bit, uint32_t proba_idx) { - assert(proba_idx < FIXED_PROBA_BIT); - assert(bit <= 1); - if (b->left_ > 0 || TBufferNewPage(b)) { - const int slot = --b->left_; - b->tokens_[slot] = (bit << 15) | proba_idx; - } - return bit; -} - -static WEBP_INLINE void AddConstantToken(VP8TBuffer* const b, - uint32_t bit, uint32_t proba) { - assert(proba < 256); - assert(bit <= 1); - if (b->left_ > 0 || TBufferNewPage(b)) { - const int slot = --b->left_; - b->tokens_[slot] = (bit << 15) | FIXED_PROBA_BIT | proba; - } -} - -int VP8RecordCoeffTokens(const int ctx, const int coeff_type, - int first, int last, - const int16_t* const coeffs, - VP8TBuffer* const tokens) { - int n = first; - uint32_t base_id = TOKEN_ID(coeff_type, n, ctx); - if (!AddToken(tokens, last >= 0, base_id + 0)) { - return 0; - } - - while (n < 16) { - const int c = coeffs[n++]; - const int sign = c < 0; - const uint32_t v = sign ? -c : c; - if (!AddToken(tokens, v != 0, base_id + 1)) { - base_id = TOKEN_ID(coeff_type, VP8EncBands[n], 0); // ctx=0 - continue; - } - if (!AddToken(tokens, v > 1, base_id + 2)) { - base_id = TOKEN_ID(coeff_type, VP8EncBands[n], 1); // ctx=1 - } else { - if (!AddToken(tokens, v > 4, base_id + 3)) { - if (AddToken(tokens, v != 2, base_id + 4)) - AddToken(tokens, v == 4, base_id + 5); - } else if (!AddToken(tokens, v > 10, base_id + 6)) { - if (!AddToken(tokens, v > 6, base_id + 7)) { - AddConstantToken(tokens, v == 6, 159); - } else { - AddConstantToken(tokens, v >= 9, 165); - AddConstantToken(tokens, !(v & 1), 145); - } - } else { - int mask; - const uint8_t* tab; - uint32_t residue = v - 3; - if (residue < (8 << 1)) { // VP8Cat3 (3b) - AddToken(tokens, 0, base_id + 8); - AddToken(tokens, 0, base_id + 9); - residue -= (8 << 0); - mask = 1 << 2; - tab = VP8Cat3; - } else if (residue < (8 << 2)) { // VP8Cat4 (4b) - AddToken(tokens, 0, base_id + 8); - AddToken(tokens, 1, base_id + 9); - residue -= (8 << 1); - mask = 1 << 3; - tab = VP8Cat4; - } else if (residue < (8 << 3)) { // VP8Cat5 (5b) - AddToken(tokens, 1, base_id + 8); - AddToken(tokens, 0, base_id + 10); - residue -= (8 << 2); - mask = 1 << 4; - tab = VP8Cat5; - } else { // VP8Cat6 (11b) - AddToken(tokens, 1, base_id + 8); - AddToken(tokens, 1, base_id + 10); - residue -= (8 << 3); - mask = 1 << 10; - tab = VP8Cat6; - } - while (mask) { - AddConstantToken(tokens, !!(residue & mask), *tab++); - mask >>= 1; - } - } - base_id = TOKEN_ID(coeff_type, VP8EncBands[n], 2); // ctx=2 - } - AddConstantToken(tokens, sign, 128); - if (n == 16 || !AddToken(tokens, n <= last, base_id + 0)) { - return 1; // EOB - } - } - return 1; -} - -#undef TOKEN_ID - -//------------------------------------------------------------------------------ -// This function works, but isn't currently used. Saved for later. - -#if 0 - -static void Record(int bit, proba_t* const stats) { - proba_t p = *stats; - if (p >= 0xffff0000u) { // an overflow is inbound. - p = ((p + 1u) >> 1) & 0x7fff7fffu; // -> divide the stats by 2. - } - // record bit count (lower 16 bits) and increment total count (upper 16 bits). - p += 0x00010000u + bit; - *stats = p; -} - -void VP8TokenToStats(const VP8TBuffer* const b, proba_t* const stats) { - const VP8Tokens* p = b->pages_; - while (p != NULL) { - const int N = (p->next_ == NULL) ? b->left_ : 0; - int n = MAX_NUM_TOKEN; - const token_t* const tokens = TOKEN_DATA(p); - while (n-- > N) { - const token_t token = tokens[n]; - if (!(token & FIXED_PROBA_BIT)) { - Record((token >> 15) & 1, stats + (token & 0x3fffu)); - } - } - p = p->next_; - } -} - -#endif // 0 - -//------------------------------------------------------------------------------ -// Final coding pass, with known probabilities - -int VP8EmitTokens(VP8TBuffer* const b, VP8BitWriter* const bw, - const uint8_t* const probas, int final_pass) { - const VP8Tokens* p = b->pages_; - assert(!b->error_); - while (p != NULL) { - const VP8Tokens* const next = p->next_; - const int N = (next == NULL) ? b->left_ : 0; - int n = b->page_size_; - const token_t* const tokens = TOKEN_DATA(p); - while (n-- > N) { - const token_t token = tokens[n]; - const int bit = (token >> 15) & 1; - if (token & FIXED_PROBA_BIT) { - VP8PutBit(bw, bit, token & 0xffu); // constant proba - } else { - VP8PutBit(bw, bit, probas[token & 0x3fffu]); - } - } - if (final_pass) WebPSafeFree((void*)p); - p = next; - } - if (final_pass) b->pages_ = NULL; - return 1; -} - -// Size estimation -size_t VP8EstimateTokenSize(VP8TBuffer* const b, const uint8_t* const probas) { - size_t size = 0; - const VP8Tokens* p = b->pages_; - assert(!b->error_); - while (p != NULL) { - const VP8Tokens* const next = p->next_; - const int N = (next == NULL) ? b->left_ : 0; - int n = b->page_size_; - const token_t* const tokens = TOKEN_DATA(p); - while (n-- > N) { - const token_t token = tokens[n]; - const int bit = token & (1 << 15); - if (token & FIXED_PROBA_BIT) { - size += VP8BitCost(bit, token & 0xffu); - } else { - size += VP8BitCost(bit, probas[token & 0x3fffu]); - } - } - p = next; - } - return size; -} - -//------------------------------------------------------------------------------ - -#else // DISABLE_TOKEN_BUFFER - -void VP8TBufferInit(VP8TBuffer* const b) { - (void)b; -} -void VP8TBufferClear(VP8TBuffer* const b) { - (void)b; -} - -#endif // !DISABLE_TOKEN_BUFFER - diff --git a/Example/Pods/libwebp/src/enc/tree.c b/Example/Pods/libwebp/src/enc/tree.c deleted file mode 100644 index f141006d..00000000 --- a/Example/Pods/libwebp/src/enc/tree.c +++ /dev/null @@ -1,504 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Coding of token probabilities, intra modes and segments. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./vp8enci.h" - -//------------------------------------------------------------------------------ -// Default probabilities - -// Paragraph 13.5 -const uint8_t - VP8CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = { - { { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } - }, - { { 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128 }, - { 189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128 }, - { 106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128 } - }, - { { 1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128 }, - { 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128 }, - { 78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128 }, - }, - { { 1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128 }, - { 184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128 }, - { 77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128 }, - }, - { { 1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128 }, - { 170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128 }, - { 37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128 } - }, - { { 1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128 }, - { 207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128 }, - { 102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128 } - }, - { { 1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128 }, - { 177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128 }, - { 80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128 } - }, - { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } - } - }, - { { { 198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62 }, - { 131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1 }, - { 68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128 } - }, - { { 1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128 }, - { 184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128 }, - { 81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128 } - }, - { { 1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128 }, - { 99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128 }, - { 23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128 } - }, - { { 1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128 }, - { 109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128 }, - { 44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128 } - }, - { { 1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128 }, - { 94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128 }, - { 22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128 } - }, - { { 1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128 }, - { 124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128 }, - { 35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128 } - }, - { { 1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128 }, - { 121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128 }, - { 45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128 } - }, - { { 1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128 }, - { 203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128 } - } - }, - { { { 253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128 }, - { 175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128 }, - { 73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128 } - }, - { { 1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128 }, - { 239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128 }, - { 155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128 } - }, - { { 1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128 }, - { 201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128 }, - { 69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128 } - }, - { { 1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128 }, - { 141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128 } - }, - { { 1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128 }, - { 149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 } - }, - { { 1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128 } - }, - { { 1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128 } - }, - { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } - } - }, - { { { 202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255 }, - { 126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128 }, - { 61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128 } - }, - { { 1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128 }, - { 166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128 }, - { 39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128 } - }, - { { 1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128 }, - { 124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128 }, - { 24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128 } - }, - { { 1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128 }, - { 149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128 }, - { 28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128 } - }, - { { 1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128 }, - { 123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128 }, - { 20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128 } - }, - { { 1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128 }, - { 168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128 }, - { 47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128 } - }, - { { 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128 }, - { 141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128 }, - { 42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128 } - }, - { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 } - } - } -}; - -void VP8DefaultProbas(VP8Encoder* const enc) { - VP8EncProba* const probas = &enc->proba_; - probas->use_skip_proba_ = 0; - memset(probas->segments_, 255u, sizeof(probas->segments_)); - memcpy(probas->coeffs_, VP8CoeffsProba0, sizeof(VP8CoeffsProba0)); - // Note: we could hard-code the level_costs_ corresponding to VP8CoeffsProba0, - // but that's ~11k of static data. Better call VP8CalculateLevelCosts() later. - probas->dirty_ = 1; -} - -// Paragraph 11.5. 900bytes. -static const uint8_t kBModesProba[NUM_BMODES][NUM_BMODES][NUM_BMODES - 1] = { - { { 231, 120, 48, 89, 115, 113, 120, 152, 112 }, - { 152, 179, 64, 126, 170, 118, 46, 70, 95 }, - { 175, 69, 143, 80, 85, 82, 72, 155, 103 }, - { 56, 58, 10, 171, 218, 189, 17, 13, 152 }, - { 114, 26, 17, 163, 44, 195, 21, 10, 173 }, - { 121, 24, 80, 195, 26, 62, 44, 64, 85 }, - { 144, 71, 10, 38, 171, 213, 144, 34, 26 }, - { 170, 46, 55, 19, 136, 160, 33, 206, 71 }, - { 63, 20, 8, 114, 114, 208, 12, 9, 226 }, - { 81, 40, 11, 96, 182, 84, 29, 16, 36 } }, - { { 134, 183, 89, 137, 98, 101, 106, 165, 148 }, - { 72, 187, 100, 130, 157, 111, 32, 75, 80 }, - { 66, 102, 167, 99, 74, 62, 40, 234, 128 }, - { 41, 53, 9, 178, 241, 141, 26, 8, 107 }, - { 74, 43, 26, 146, 73, 166, 49, 23, 157 }, - { 65, 38, 105, 160, 51, 52, 31, 115, 128 }, - { 104, 79, 12, 27, 217, 255, 87, 17, 7 }, - { 87, 68, 71, 44, 114, 51, 15, 186, 23 }, - { 47, 41, 14, 110, 182, 183, 21, 17, 194 }, - { 66, 45, 25, 102, 197, 189, 23, 18, 22 } }, - { { 88, 88, 147, 150, 42, 46, 45, 196, 205 }, - { 43, 97, 183, 117, 85, 38, 35, 179, 61 }, - { 39, 53, 200, 87, 26, 21, 43, 232, 171 }, - { 56, 34, 51, 104, 114, 102, 29, 93, 77 }, - { 39, 28, 85, 171, 58, 165, 90, 98, 64 }, - { 34, 22, 116, 206, 23, 34, 43, 166, 73 }, - { 107, 54, 32, 26, 51, 1, 81, 43, 31 }, - { 68, 25, 106, 22, 64, 171, 36, 225, 114 }, - { 34, 19, 21, 102, 132, 188, 16, 76, 124 }, - { 62, 18, 78, 95, 85, 57, 50, 48, 51 } }, - { { 193, 101, 35, 159, 215, 111, 89, 46, 111 }, - { 60, 148, 31, 172, 219, 228, 21, 18, 111 }, - { 112, 113, 77, 85, 179, 255, 38, 120, 114 }, - { 40, 42, 1, 196, 245, 209, 10, 25, 109 }, - { 88, 43, 29, 140, 166, 213, 37, 43, 154 }, - { 61, 63, 30, 155, 67, 45, 68, 1, 209 }, - { 100, 80, 8, 43, 154, 1, 51, 26, 71 }, - { 142, 78, 78, 16, 255, 128, 34, 197, 171 }, - { 41, 40, 5, 102, 211, 183, 4, 1, 221 }, - { 51, 50, 17, 168, 209, 192, 23, 25, 82 } }, - { { 138, 31, 36, 171, 27, 166, 38, 44, 229 }, - { 67, 87, 58, 169, 82, 115, 26, 59, 179 }, - { 63, 59, 90, 180, 59, 166, 93, 73, 154 }, - { 40, 40, 21, 116, 143, 209, 34, 39, 175 }, - { 47, 15, 16, 183, 34, 223, 49, 45, 183 }, - { 46, 17, 33, 183, 6, 98, 15, 32, 183 }, - { 57, 46, 22, 24, 128, 1, 54, 17, 37 }, - { 65, 32, 73, 115, 28, 128, 23, 128, 205 }, - { 40, 3, 9, 115, 51, 192, 18, 6, 223 }, - { 87, 37, 9, 115, 59, 77, 64, 21, 47 } }, - { { 104, 55, 44, 218, 9, 54, 53, 130, 226 }, - { 64, 90, 70, 205, 40, 41, 23, 26, 57 }, - { 54, 57, 112, 184, 5, 41, 38, 166, 213 }, - { 30, 34, 26, 133, 152, 116, 10, 32, 134 }, - { 39, 19, 53, 221, 26, 114, 32, 73, 255 }, - { 31, 9, 65, 234, 2, 15, 1, 118, 73 }, - { 75, 32, 12, 51, 192, 255, 160, 43, 51 }, - { 88, 31, 35, 67, 102, 85, 55, 186, 85 }, - { 56, 21, 23, 111, 59, 205, 45, 37, 192 }, - { 55, 38, 70, 124, 73, 102, 1, 34, 98 } }, - { { 125, 98, 42, 88, 104, 85, 117, 175, 82 }, - { 95, 84, 53, 89, 128, 100, 113, 101, 45 }, - { 75, 79, 123, 47, 51, 128, 81, 171, 1 }, - { 57, 17, 5, 71, 102, 57, 53, 41, 49 }, - { 38, 33, 13, 121, 57, 73, 26, 1, 85 }, - { 41, 10, 67, 138, 77, 110, 90, 47, 114 }, - { 115, 21, 2, 10, 102, 255, 166, 23, 6 }, - { 101, 29, 16, 10, 85, 128, 101, 196, 26 }, - { 57, 18, 10, 102, 102, 213, 34, 20, 43 }, - { 117, 20, 15, 36, 163, 128, 68, 1, 26 } }, - { { 102, 61, 71, 37, 34, 53, 31, 243, 192 }, - { 69, 60, 71, 38, 73, 119, 28, 222, 37 }, - { 68, 45, 128, 34, 1, 47, 11, 245, 171 }, - { 62, 17, 19, 70, 146, 85, 55, 62, 70 }, - { 37, 43, 37, 154, 100, 163, 85, 160, 1 }, - { 63, 9, 92, 136, 28, 64, 32, 201, 85 }, - { 75, 15, 9, 9, 64, 255, 184, 119, 16 }, - { 86, 6, 28, 5, 64, 255, 25, 248, 1 }, - { 56, 8, 17, 132, 137, 255, 55, 116, 128 }, - { 58, 15, 20, 82, 135, 57, 26, 121, 40 } }, - { { 164, 50, 31, 137, 154, 133, 25, 35, 218 }, - { 51, 103, 44, 131, 131, 123, 31, 6, 158 }, - { 86, 40, 64, 135, 148, 224, 45, 183, 128 }, - { 22, 26, 17, 131, 240, 154, 14, 1, 209 }, - { 45, 16, 21, 91, 64, 222, 7, 1, 197 }, - { 56, 21, 39, 155, 60, 138, 23, 102, 213 }, - { 83, 12, 13, 54, 192, 255, 68, 47, 28 }, - { 85, 26, 85, 85, 128, 128, 32, 146, 171 }, - { 18, 11, 7, 63, 144, 171, 4, 4, 246 }, - { 35, 27, 10, 146, 174, 171, 12, 26, 128 } }, - { { 190, 80, 35, 99, 180, 80, 126, 54, 45 }, - { 85, 126, 47, 87, 176, 51, 41, 20, 32 }, - { 101, 75, 128, 139, 118, 146, 116, 128, 85 }, - { 56, 41, 15, 176, 236, 85, 37, 9, 62 }, - { 71, 30, 17, 119, 118, 255, 17, 18, 138 }, - { 101, 38, 60, 138, 55, 70, 43, 26, 142 }, - { 146, 36, 19, 30, 171, 255, 97, 27, 20 }, - { 138, 45, 61, 62, 219, 1, 81, 188, 64 }, - { 32, 41, 20, 117, 151, 142, 20, 21, 163 }, - { 112, 19, 12, 61, 195, 128, 48, 4, 24 } } -}; - -static int PutI4Mode(VP8BitWriter* const bw, int mode, - const uint8_t* const prob) { - if (VP8PutBit(bw, mode != B_DC_PRED, prob[0])) { - if (VP8PutBit(bw, mode != B_TM_PRED, prob[1])) { - if (VP8PutBit(bw, mode != B_VE_PRED, prob[2])) { - if (!VP8PutBit(bw, mode >= B_LD_PRED, prob[3])) { - if (VP8PutBit(bw, mode != B_HE_PRED, prob[4])) { - VP8PutBit(bw, mode != B_RD_PRED, prob[5]); - } - } else { - if (VP8PutBit(bw, mode != B_LD_PRED, prob[6])) { - if (VP8PutBit(bw, mode != B_VL_PRED, prob[7])) { - VP8PutBit(bw, mode != B_HD_PRED, prob[8]); - } - } - } - } - } - } - return mode; -} - -static void PutI16Mode(VP8BitWriter* const bw, int mode) { - if (VP8PutBit(bw, (mode == TM_PRED || mode == H_PRED), 156)) { - VP8PutBit(bw, mode == TM_PRED, 128); // TM or HE - } else { - VP8PutBit(bw, mode == V_PRED, 163); // VE or DC - } -} - -static void PutUVMode(VP8BitWriter* const bw, int uv_mode) { - if (VP8PutBit(bw, uv_mode != DC_PRED, 142)) { - if (VP8PutBit(bw, uv_mode != V_PRED, 114)) { - VP8PutBit(bw, uv_mode != H_PRED, 183); // else: TM_PRED - } - } -} - -static void PutSegment(VP8BitWriter* const bw, int s, const uint8_t* p) { - if (VP8PutBit(bw, s >= 2, p[0])) p += 1; - VP8PutBit(bw, s & 1, p[1]); -} - -void VP8CodeIntraModes(VP8Encoder* const enc) { - VP8BitWriter* const bw = &enc->bw_; - VP8EncIterator it; - VP8IteratorInit(enc, &it); - do { - const VP8MBInfo* const mb = it.mb_; - const uint8_t* preds = it.preds_; - if (enc->segment_hdr_.update_map_) { - PutSegment(bw, mb->segment_, enc->proba_.segments_); - } - if (enc->proba_.use_skip_proba_) { - VP8PutBit(bw, mb->skip_, enc->proba_.skip_proba_); - } - if (VP8PutBit(bw, (mb->type_ != 0), 145)) { // i16x16 - PutI16Mode(bw, preds[0]); - } else { - const int preds_w = enc->preds_w_; - const uint8_t* top_pred = preds - preds_w; - int x, y; - for (y = 0; y < 4; ++y) { - int left = preds[-1]; - for (x = 0; x < 4; ++x) { - const uint8_t* const probas = kBModesProba[top_pred[x]][left]; - left = PutI4Mode(bw, preds[x], probas); - } - top_pred = preds; - preds += preds_w; - } - } - PutUVMode(bw, mb->uv_mode_); - } while (VP8IteratorNext(&it)); -} - -//------------------------------------------------------------------------------ -// Paragraph 13 - -const uint8_t - VP8CoeffsUpdateProba[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = { - { { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255 }, - { 250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - } - }, - { { { 217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255 }, - { 234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255 } - }, - { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - } - }, - { { { 186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255 }, - { 251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255 } - }, - { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - } - }, - { { { 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255 }, - { 248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - } - } -}; - -void VP8WriteProbas(VP8BitWriter* const bw, const VP8EncProba* const probas) { - int t, b, c, p; - for (t = 0; t < NUM_TYPES; ++t) { - for (b = 0; b < NUM_BANDS; ++b) { - for (c = 0; c < NUM_CTX; ++c) { - for (p = 0; p < NUM_PROBAS; ++p) { - const uint8_t p0 = probas->coeffs_[t][b][c][p]; - const int update = (p0 != VP8CoeffsProba0[t][b][c][p]); - if (VP8PutBit(bw, update, VP8CoeffsUpdateProba[t][b][c][p])) { - VP8PutBits(bw, p0, 8); - } - } - } - } - } - if (VP8PutBitUniform(bw, probas->use_skip_proba_)) { - VP8PutBits(bw, probas->skip_proba_, 8); - } -} - diff --git a/Example/Pods/libwebp/src/enc/vp8enci.h b/Example/Pods/libwebp/src/enc/vp8enci.h deleted file mode 100644 index b2cc8d19..00000000 --- a/Example/Pods/libwebp/src/enc/vp8enci.h +++ /dev/null @@ -1,536 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// WebP encoder: internal header. -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_ENC_VP8ENCI_H_ -#define WEBP_ENC_VP8ENCI_H_ - -#include // for memcpy() -#include "../dec/common.h" -#include "../dsp/dsp.h" -#include "../utils/bit_writer.h" -#include "../utils/thread.h" -#include "../utils/utils.h" -#include "../webp/encode.h" - -#ifdef WEBP_EXPERIMENTAL_FEATURES -#include "./vp8li.h" -#endif // WEBP_EXPERIMENTAL_FEATURES - -#ifdef __cplusplus -extern "C" { -#endif - -//------------------------------------------------------------------------------ -// Various defines and enums - -// version numbers -#define ENC_MAJ_VERSION 0 -#define ENC_MIN_VERSION 5 -#define ENC_REV_VERSION 0 - -enum { MAX_LF_LEVELS = 64, // Maximum loop filter level - MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost - MAX_LEVEL = 2047 // max level (note: max codable is 2047 + 67) - }; - -typedef enum { // Rate-distortion optimization levels - RD_OPT_NONE = 0, // no rd-opt - RD_OPT_BASIC = 1, // basic scoring (no trellis) - RD_OPT_TRELLIS = 2, // perform trellis-quant on the final decision only - RD_OPT_TRELLIS_ALL = 3 // trellis-quant for every scoring (much slower) -} VP8RDLevel; - -// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline). -// The original or reconstructed samples can be accessed using VP8Scan[]. -// The predicted blocks can be accessed using offsets to yuv_p_ and -// the arrays VP8*ModeOffsets[]. -// * YUV Samples area (yuv_in_/yuv_out_/yuv_out2_) -// (see VP8Scan[] for accessing the blocks, along with -// Y_OFF_ENC/U_OFF_ENC/V_OFF_ENC): -// +----+----+ -// Y_OFF_ENC |YYYY|UUVV| -// U_OFF_ENC |YYYY|UUVV| -// V_OFF_ENC |YYYY|....| <- 25% wasted U/V area -// |YYYY|....| -// +----+----+ -// * Prediction area ('yuv_p_', size = PRED_SIZE_ENC) -// Intra16 predictions (16x16 block each, two per row): -// |I16DC16|I16TM16| -// |I16VE16|I16HE16| -// Chroma U/V predictions (16x8 block each, two per row): -// |C8DC8|C8TM8| -// |C8VE8|C8HE8| -// Intra 4x4 predictions (4x4 block each) -// |I4DC4 I4TM4 I4VE4 I4HE4|I4RD4 I4VR4 I4LD4 I4VL4| -// |I4HD4 I4HU4 I4TMP .....|.......................| <- ~31% wasted -#define YUV_SIZE_ENC (BPS * 16) -#define PRED_SIZE_ENC (32 * BPS + 16 * BPS + 8 * BPS) // I16+Chroma+I4 preds -#define Y_OFF_ENC (0) -#define U_OFF_ENC (16) -#define V_OFF_ENC (16 + 8) - -extern const int VP8Scan[16]; // in quant.c -extern const int VP8UVModeOffsets[4]; // in analyze.c -extern const int VP8I16ModeOffsets[4]; -extern const int VP8I4ModeOffsets[NUM_BMODES]; - -// Layout of prediction blocks -// intra 16x16 -#define I16DC16 (0 * 16 * BPS) -#define I16TM16 (I16DC16 + 16) -#define I16VE16 (1 * 16 * BPS) -#define I16HE16 (I16VE16 + 16) -// chroma 8x8, two U/V blocks side by side (hence: 16x8 each) -#define C8DC8 (2 * 16 * BPS) -#define C8TM8 (C8DC8 + 1 * 16) -#define C8VE8 (2 * 16 * BPS + 8 * BPS) -#define C8HE8 (C8VE8 + 1 * 16) -// intra 4x4 -#define I4DC4 (3 * 16 * BPS + 0) -#define I4TM4 (I4DC4 + 4) -#define I4VE4 (I4DC4 + 8) -#define I4HE4 (I4DC4 + 12) -#define I4RD4 (I4DC4 + 16) -#define I4VR4 (I4DC4 + 20) -#define I4LD4 (I4DC4 + 24) -#define I4VL4 (I4DC4 + 28) -#define I4HD4 (3 * 16 * BPS + 4 * BPS) -#define I4HU4 (I4HD4 + 4) -#define I4TMP (I4HD4 + 8) - -typedef int64_t score_t; // type used for scores, rate, distortion -// Note that MAX_COST is not the maximum allowed by sizeof(score_t), -// in order to allow overflowing computations. -#define MAX_COST ((score_t)0x7fffffffffffffLL) - -#define QFIX 17 -#define BIAS(b) ((b) << (QFIX - 8)) -// Fun fact: this is the _only_ line where we're actually being lossy and -// discarding bits. -static WEBP_INLINE int QUANTDIV(uint32_t n, uint32_t iQ, uint32_t B) { - return (int)((n * iQ + B) >> QFIX); -} - -// Uncomment the following to remove token-buffer code: -// #define DISABLE_TOKEN_BUFFER - -//------------------------------------------------------------------------------ -// Headers - -typedef uint32_t proba_t; // 16b + 16b -typedef uint8_t ProbaArray[NUM_CTX][NUM_PROBAS]; -typedef proba_t StatsArray[NUM_CTX][NUM_PROBAS]; -typedef uint16_t CostArray[NUM_CTX][MAX_VARIABLE_LEVEL + 1]; -typedef const uint16_t* (*CostArrayPtr)[NUM_CTX]; // for easy casting -typedef const uint16_t* CostArrayMap[16][NUM_CTX]; -typedef double LFStats[NUM_MB_SEGMENTS][MAX_LF_LEVELS]; // filter stats - -typedef struct VP8Encoder VP8Encoder; - -// segment features -typedef struct { - int num_segments_; // Actual number of segments. 1 segment only = unused. - int update_map_; // whether to update the segment map or not. - // must be 0 if there's only 1 segment. - int size_; // bit-cost for transmitting the segment map -} VP8EncSegmentHeader; - -// Struct collecting all frame-persistent probabilities. -typedef struct { - uint8_t segments_[3]; // probabilities for segment tree - uint8_t skip_proba_; // final probability of being skipped. - ProbaArray coeffs_[NUM_TYPES][NUM_BANDS]; // 1056 bytes - StatsArray stats_[NUM_TYPES][NUM_BANDS]; // 4224 bytes - CostArray level_cost_[NUM_TYPES][NUM_BANDS]; // 13056 bytes - CostArrayMap remapped_costs_[NUM_TYPES]; // 1536 bytes - int dirty_; // if true, need to call VP8CalculateLevelCosts() - int use_skip_proba_; // Note: we always use skip_proba for now. - int nb_skip_; // number of skipped blocks -} VP8EncProba; - -// Filter parameters. Not actually used in the code (we don't perform -// the in-loop filtering), but filled from user's config -typedef struct { - int simple_; // filtering type: 0=complex, 1=simple - int level_; // base filter level [0..63] - int sharpness_; // [0..7] - int i4x4_lf_delta_; // delta filter level for i4x4 relative to i16x16 -} VP8EncFilterHeader; - -//------------------------------------------------------------------------------ -// Informations about the macroblocks. - -typedef struct { - // block type - unsigned int type_:2; // 0=i4x4, 1=i16x16 - unsigned int uv_mode_:2; - unsigned int skip_:1; - unsigned int segment_:2; - uint8_t alpha_; // quantization-susceptibility -} VP8MBInfo; - -typedef struct VP8Matrix { - uint16_t q_[16]; // quantizer steps - uint16_t iq_[16]; // reciprocals, fixed point. - uint32_t bias_[16]; // rounding bias - uint32_t zthresh_[16]; // value below which a coefficient is zeroed - uint16_t sharpen_[16]; // frequency boosters for slight sharpening -} VP8Matrix; - -typedef struct { - VP8Matrix y1_, y2_, uv_; // quantization matrices - int alpha_; // quant-susceptibility, range [-127,127]. Zero is neutral. - // Lower values indicate a lower risk of blurriness. - int beta_; // filter-susceptibility, range [0,255]. - int quant_; // final segment quantizer. - int fstrength_; // final in-loop filtering strength - int max_edge_; // max edge delta (for filtering strength) - int min_disto_; // minimum distortion required to trigger filtering record - // reactivities - int lambda_i16_, lambda_i4_, lambda_uv_; - int lambda_mode_, lambda_trellis_, tlambda_; - int lambda_trellis_i16_, lambda_trellis_i4_, lambda_trellis_uv_; -} VP8SegmentInfo; - -// Handy transient struct to accumulate score and info during RD-optimization -// and mode evaluation. -typedef struct { - score_t D, SD; // Distortion, spectral distortion - score_t H, R, score; // header bits, rate, score. - int16_t y_dc_levels[16]; // Quantized levels for luma-DC, luma-AC, chroma. - int16_t y_ac_levels[16][16]; - int16_t uv_levels[4 + 4][16]; - int mode_i16; // mode number for intra16 prediction - uint8_t modes_i4[16]; // mode numbers for intra4 predictions - int mode_uv; // mode number of chroma prediction - uint32_t nz; // non-zero blocks -} VP8ModeScore; - -// Iterator structure to iterate through macroblocks, pointing to the -// right neighbouring data (samples, predictions, contexts, ...) -typedef struct { - int x_, y_; // current macroblock - int y_stride_, uv_stride_; // respective strides - uint8_t* yuv_in_; // input samples - uint8_t* yuv_out_; // output samples - uint8_t* yuv_out2_; // secondary buffer swapped with yuv_out_. - uint8_t* yuv_p_; // scratch buffer for prediction - VP8Encoder* enc_; // back-pointer - VP8MBInfo* mb_; // current macroblock - VP8BitWriter* bw_; // current bit-writer - uint8_t* preds_; // intra mode predictors (4x4 blocks) - uint32_t* nz_; // non-zero pattern - uint8_t i4_boundary_[37]; // 32+5 boundary samples needed by intra4x4 - uint8_t* i4_top_; // pointer to the current top boundary sample - int i4_; // current intra4x4 mode being tested - int top_nz_[9]; // top-non-zero context. - int left_nz_[9]; // left-non-zero. left_nz[8] is independent. - uint64_t bit_count_[4][3]; // bit counters for coded levels. - uint64_t luma_bits_; // macroblock bit-cost for luma - uint64_t uv_bits_; // macroblock bit-cost for chroma - LFStats* lf_stats_; // filter stats (borrowed from enc_) - int do_trellis_; // if true, perform extra level optimisation - int count_down_; // number of mb still to be processed - int count_down0_; // starting counter value (for progress) - int percent0_; // saved initial progress percent - - uint8_t* y_left_; // left luma samples (addressable from index -1 to 15). - uint8_t* u_left_; // left u samples (addressable from index -1 to 7) - uint8_t* v_left_; // left v samples (addressable from index -1 to 7) - - uint8_t* y_top_; // top luma samples at position 'x_' - uint8_t* uv_top_; // top u/v samples at position 'x_', packed as 16 bytes - - // memory for storing y/u/v_left_ - uint8_t yuv_left_mem_[17 + 16 + 16 + 8 + WEBP_ALIGN_CST]; - // memory for yuv_* - uint8_t yuv_mem_[3 * YUV_SIZE_ENC + PRED_SIZE_ENC + WEBP_ALIGN_CST]; -} VP8EncIterator; - - // in iterator.c -// must be called first -void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it); -// restart a scan -void VP8IteratorReset(VP8EncIterator* const it); -// reset iterator position to row 'y' -void VP8IteratorSetRow(VP8EncIterator* const it, int y); -// set count down (=number of iterations to go) -void VP8IteratorSetCountDown(VP8EncIterator* const it, int count_down); -// return true if iteration is finished -int VP8IteratorIsDone(const VP8EncIterator* const it); -// Import uncompressed samples from source. -// If tmp_32 is not NULL, import boundary samples too. -// tmp_32 is a 32-bytes scratch buffer that must be aligned in memory. -void VP8IteratorImport(VP8EncIterator* const it, uint8_t* tmp_32); -// export decimated samples -void VP8IteratorExport(const VP8EncIterator* const it); -// go to next macroblock. Returns false if not finished. -int VP8IteratorNext(VP8EncIterator* const it); -// save the yuv_out_ boundary values to top_/left_ arrays for next iterations. -void VP8IteratorSaveBoundary(VP8EncIterator* const it); -// Report progression based on macroblock rows. Return 0 for user-abort request. -int VP8IteratorProgress(const VP8EncIterator* const it, - int final_delta_percent); -// Intra4x4 iterations -void VP8IteratorStartI4(VP8EncIterator* const it); -// returns true if not done. -int VP8IteratorRotateI4(VP8EncIterator* const it, - const uint8_t* const yuv_out); - -// Non-zero context setup/teardown -void VP8IteratorNzToBytes(VP8EncIterator* const it); -void VP8IteratorBytesToNz(VP8EncIterator* const it); - -// Helper functions to set mode properties -void VP8SetIntra16Mode(const VP8EncIterator* const it, int mode); -void VP8SetIntra4Mode(const VP8EncIterator* const it, const uint8_t* modes); -void VP8SetIntraUVMode(const VP8EncIterator* const it, int mode); -void VP8SetSkip(const VP8EncIterator* const it, int skip); -void VP8SetSegment(const VP8EncIterator* const it, int segment); - -//------------------------------------------------------------------------------ -// Paginated token buffer - -typedef struct VP8Tokens VP8Tokens; // struct details in token.c - -typedef struct { -#if !defined(DISABLE_TOKEN_BUFFER) - VP8Tokens* pages_; // first page - VP8Tokens** last_page_; // last page - uint16_t* tokens_; // set to (*last_page_)->tokens_ - int left_; // how many free tokens left before the page is full - int page_size_; // number of tokens per page -#endif - int error_; // true in case of malloc error -} VP8TBuffer; - -// initialize an empty buffer -void VP8TBufferInit(VP8TBuffer* const b, int page_size); -void VP8TBufferClear(VP8TBuffer* const b); // de-allocate pages memory - -#if !defined(DISABLE_TOKEN_BUFFER) - -// Finalizes bitstream when probabilities are known. -// Deletes the allocated token memory if final_pass is true. -int VP8EmitTokens(VP8TBuffer* const b, VP8BitWriter* const bw, - const uint8_t* const probas, int final_pass); - -// record the coding of coefficients without knowing the probabilities yet -int VP8RecordCoeffTokens(const int ctx, const int coeff_type, - int first, int last, - const int16_t* const coeffs, - VP8TBuffer* const tokens); - -// Estimate the final coded size given a set of 'probas'. -size_t VP8EstimateTokenSize(VP8TBuffer* const b, const uint8_t* const probas); - -// unused for now -void VP8TokenToStats(const VP8TBuffer* const b, proba_t* const stats); - -#endif // !DISABLE_TOKEN_BUFFER - -//------------------------------------------------------------------------------ -// VP8Encoder - -struct VP8Encoder { - const WebPConfig* config_; // user configuration and parameters - WebPPicture* pic_; // input / output picture - - // headers - VP8EncFilterHeader filter_hdr_; // filtering information - VP8EncSegmentHeader segment_hdr_; // segment information - - int profile_; // VP8's profile, deduced from Config. - - // dimension, in macroblock units. - int mb_w_, mb_h_; - int preds_w_; // stride of the *preds_ prediction plane (=4*mb_w + 1) - - // number of partitions (1, 2, 4 or 8 = MAX_NUM_PARTITIONS) - int num_parts_; - - // per-partition boolean decoders. - VP8BitWriter bw_; // part0 - VP8BitWriter parts_[MAX_NUM_PARTITIONS]; // token partitions - VP8TBuffer tokens_; // token buffer - - int percent_; // for progress - - // transparency blob - int has_alpha_; - uint8_t* alpha_data_; // non-NULL if transparency is present - uint32_t alpha_data_size_; - WebPWorker alpha_worker_; - - // quantization info (one set of DC/AC dequant factor per segment) - VP8SegmentInfo dqm_[NUM_MB_SEGMENTS]; - int base_quant_; // nominal quantizer value. Only used - // for relative coding of segments' quant. - int alpha_; // global susceptibility (<=> complexity) - int uv_alpha_; // U/V quantization susceptibility - // global offset of quantizers, shared by all segments - int dq_y1_dc_; - int dq_y2_dc_, dq_y2_ac_; - int dq_uv_dc_, dq_uv_ac_; - - // probabilities and statistics - VP8EncProba proba_; - uint64_t sse_[4]; // sum of Y/U/V/A squared errors for all macroblocks - uint64_t sse_count_; // pixel count for the sse_[] stats - int coded_size_; - int residual_bytes_[3][4]; - int block_count_[3]; - - // quality/speed settings - int method_; // 0=fastest, 6=best/slowest. - VP8RDLevel rd_opt_level_; // Deduced from method_. - int max_i4_header_bits_; // partition #0 safeness factor - int thread_level_; // derived from config->thread_level - int do_search_; // derived from config->target_XXX - int use_tokens_; // if true, use token buffer - - // Memory - VP8MBInfo* mb_info_; // contextual macroblock infos (mb_w_ + 1) - uint8_t* preds_; // predictions modes: (4*mb_w+1) * (4*mb_h+1) - uint32_t* nz_; // non-zero bit context: mb_w+1 - uint8_t* y_top_; // top luma samples. - uint8_t* uv_top_; // top u/v samples. - // U and V are packed into 16 bytes (8 U + 8 V) - LFStats* lf_stats_; // autofilter stats (if NULL, autofilter is off) -}; - -//------------------------------------------------------------------------------ -// internal functions. Not public. - - // in tree.c -extern const uint8_t VP8CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS]; -extern const uint8_t - VP8CoeffsUpdateProba[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS]; -// Reset the token probabilities to their initial (default) values -void VP8DefaultProbas(VP8Encoder* const enc); -// Write the token probabilities -void VP8WriteProbas(VP8BitWriter* const bw, const VP8EncProba* const probas); -// Writes the partition #0 modes (that is: all intra modes) -void VP8CodeIntraModes(VP8Encoder* const enc); - - // in syntax.c -// Generates the final bitstream by coding the partition0 and headers, -// and appending an assembly of all the pre-coded token partitions. -// Return true if everything is ok. -int VP8EncWrite(VP8Encoder* const enc); -// Release memory allocated for bit-writing in VP8EncLoop & seq. -void VP8EncFreeBitWriters(VP8Encoder* const enc); - - // in frame.c -extern const uint8_t VP8Cat3[]; -extern const uint8_t VP8Cat4[]; -extern const uint8_t VP8Cat5[]; -extern const uint8_t VP8Cat6[]; - -// Form all the four Intra16x16 predictions in the yuv_p_ cache -void VP8MakeLuma16Preds(const VP8EncIterator* const it); -// Form all the four Chroma8x8 predictions in the yuv_p_ cache -void VP8MakeChroma8Preds(const VP8EncIterator* const it); -// Form all the ten Intra4x4 predictions in the yuv_p_ cache -// for the 4x4 block it->i4_ -void VP8MakeIntra4Preds(const VP8EncIterator* const it); -// Rate calculation -int VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd); -int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]); -int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd); -// Main coding calls -int VP8EncLoop(VP8Encoder* const enc); -int VP8EncTokenLoop(VP8Encoder* const enc); - - // in webpenc.c -// Assign an error code to a picture. Return false for convenience. -int WebPEncodingSetError(const WebPPicture* const pic, WebPEncodingError error); -int WebPReportProgress(const WebPPicture* const pic, - int percent, int* const percent_store); - - // in analysis.c -// Main analysis loop. Decides the segmentations and complexity. -// Assigns a first guess for Intra16 and uvmode_ prediction modes. -int VP8EncAnalyze(VP8Encoder* const enc); - - // in quant.c -// Sets up segment's quantization values, base_quant_ and filter strengths. -void VP8SetSegmentParams(VP8Encoder* const enc, float quality); -// Pick best modes and fills the levels. Returns true if skipped. -int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, - VP8RDLevel rd_opt); - - // in alpha.c -void VP8EncInitAlpha(VP8Encoder* const enc); // initialize alpha compression -int VP8EncStartAlpha(VP8Encoder* const enc); // start alpha coding process -int VP8EncFinishAlpha(VP8Encoder* const enc); // finalize compressed data -int VP8EncDeleteAlpha(VP8Encoder* const enc); // delete compressed data - - // in filter.c - -// SSIM utils -typedef struct { - double w, xm, ym, xxm, xym, yym; -} DistoStats; -void VP8SSIMAddStats(const DistoStats* const src, DistoStats* const dst); -void VP8SSIMAccumulatePlane(const uint8_t* src1, int stride1, - const uint8_t* src2, int stride2, - int W, int H, DistoStats* const stats); -double VP8SSIMGet(const DistoStats* const stats); -double VP8SSIMGetSquaredError(const DistoStats* const stats); - -// autofilter -void VP8InitFilter(VP8EncIterator* const it); -void VP8StoreFilterStats(VP8EncIterator* const it); -void VP8AdjustFilterStrength(VP8EncIterator* const it); - -// returns the approximate filtering strength needed to smooth a edge -// step of 'delta', given a sharpness parameter 'sharpness'. -int VP8FilterStrengthFromDelta(int sharpness, int delta); - - // misc utils for picture_*.c: - -// Remove reference to the ARGB/YUVA buffer (doesn't free anything). -void WebPPictureResetBuffers(WebPPicture* const picture); - -// Allocates ARGB buffer of given dimension (previous one is always free'd). -// Preserves the YUV(A) buffer. Returns false in case of error (invalid param, -// out-of-memory). -int WebPPictureAllocARGB(WebPPicture* const picture, int width, int height); - -// Allocates YUVA buffer of given dimension (previous one is always free'd). -// Uses picture->csp to determine whether an alpha buffer is needed. -// Preserves the ARGB buffer. -// Returns false in case of error (invalid param, out-of-memory). -int WebPPictureAllocYUVA(WebPPicture* const picture, int width, int height); - -// Clean-up the RGB samples under fully transparent area, to help lossless -// compressibility (no guarantee, though). Assumes that pic->use_argb is true. -void WebPCleanupTransparentAreaLossless(WebPPicture* const pic); - - // in near_lossless.c -// Near lossless preprocessing in RGB color-space. -int VP8ApplyNearLossless(int xsize, int ysize, uint32_t* argb, int quality); -// Near lossless adjustment for predictors. -void VP8ApplyNearLosslessPredict(int xsize, int ysize, int pred_bits, - const uint32_t* argb_orig, - uint32_t* argb, uint32_t* argb_scratch, - const uint32_t* const transform_data, - int quality, int subtract_green); -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_ENC_VP8ENCI_H_ */ diff --git a/Example/Pods/libwebp/src/enc/vp8l.c b/Example/Pods/libwebp/src/enc/vp8l.c deleted file mode 100644 index db94e78a..00000000 --- a/Example/Pods/libwebp/src/enc/vp8l.c +++ /dev/null @@ -1,1597 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// main entry for the lossless encoder. -// -// Author: Vikas Arora (vikaas.arora@gmail.com) -// - -#include -#include - -#include "./backward_references.h" -#include "./histogram.h" -#include "./vp8enci.h" -#include "./vp8li.h" -#include "../dsp/lossless.h" -#include "../utils/bit_writer.h" -#include "../utils/huffman_encode.h" -#include "../utils/utils.h" -#include "../webp/format_constants.h" - -#include "./delta_palettization.h" - -#define PALETTE_KEY_RIGHT_SHIFT 22 // Key for 1K buffer. -// Maximum number of histogram images (sub-blocks). -#define MAX_HUFF_IMAGE_SIZE 2600 - -// Palette reordering for smaller sum of deltas (and for smaller storage). - -static int PaletteCompareColorsForQsort(const void* p1, const void* p2) { - const uint32_t a = WebPMemToUint32(p1); - const uint32_t b = WebPMemToUint32(p2); - assert(a != b); - return (a < b) ? -1 : 1; -} - -static WEBP_INLINE uint32_t PaletteComponentDistance(uint32_t v) { - return (v <= 128) ? v : (256 - v); -} - -// Computes a value that is related to the entropy created by the -// palette entry diff. -// -// Note that the last & 0xff is a no-operation in the next statement, but -// removed by most compilers and is here only for regularity of the code. -static WEBP_INLINE uint32_t PaletteColorDistance(uint32_t col1, uint32_t col2) { - const uint32_t diff = VP8LSubPixels(col1, col2); - const int kMoreWeightForRGBThanForAlpha = 9; - uint32_t score; - score = PaletteComponentDistance((diff >> 0) & 0xff); - score += PaletteComponentDistance((diff >> 8) & 0xff); - score += PaletteComponentDistance((diff >> 16) & 0xff); - score *= kMoreWeightForRGBThanForAlpha; - score += PaletteComponentDistance((diff >> 24) & 0xff); - return score; -} - -static WEBP_INLINE void SwapColor(uint32_t* const col1, uint32_t* const col2) { - const uint32_t tmp = *col1; - *col1 = *col2; - *col2 = tmp; -} - -static void GreedyMinimizeDeltas(uint32_t palette[], int num_colors) { - // Find greedily always the closest color of the predicted color to minimize - // deltas in the palette. This reduces storage needs since the - // palette is stored with delta encoding. - uint32_t predict = 0x00000000; - int i, k; - for (i = 0; i < num_colors; ++i) { - int best_ix = i; - uint32_t best_score = ~0U; - for (k = i; k < num_colors; ++k) { - const uint32_t cur_score = PaletteColorDistance(palette[k], predict); - if (best_score > cur_score) { - best_score = cur_score; - best_ix = k; - } - } - SwapColor(&palette[best_ix], &palette[i]); - predict = palette[i]; - } -} - -// The palette has been sorted by alpha. This function checks if the other -// components of the palette have a monotonic development with regards to -// position in the palette. If all have monotonic development, there is -// no benefit to re-organize them greedily. A monotonic development -// would be spotted in green-only situations (like lossy alpha) or gray-scale -// images. -static int PaletteHasNonMonotonousDeltas(uint32_t palette[], int num_colors) { - uint32_t predict = 0x000000; - int i; - uint8_t sign_found = 0x00; - for (i = 0; i < num_colors; ++i) { - const uint32_t diff = VP8LSubPixels(palette[i], predict); - const uint8_t rd = (diff >> 16) & 0xff; - const uint8_t gd = (diff >> 8) & 0xff; - const uint8_t bd = (diff >> 0) & 0xff; - if (rd != 0x00) { - sign_found |= (rd < 0x80) ? 1 : 2; - } - if (gd != 0x00) { - sign_found |= (gd < 0x80) ? 8 : 16; - } - if (bd != 0x00) { - sign_found |= (bd < 0x80) ? 64 : 128; - } - predict = palette[i]; - } - return (sign_found & (sign_found << 1)) != 0; // two consequent signs. -} - -// ----------------------------------------------------------------------------- -// Palette - -// If number of colors in the image is less than or equal to MAX_PALETTE_SIZE, -// creates a palette and returns true, else returns false. -static int AnalyzeAndCreatePalette(const WebPPicture* const pic, - int low_effort, - uint32_t palette[MAX_PALETTE_SIZE], - int* const palette_size) { - int i, x, y, key; - int num_colors = 0; - uint8_t in_use[MAX_PALETTE_SIZE * 4] = { 0 }; - uint32_t colors[MAX_PALETTE_SIZE * 4]; - static const uint32_t kHashMul = 0x1e35a7bd; - const uint32_t* argb = pic->argb; - const int width = pic->width; - const int height = pic->height; - uint32_t last_pix = ~argb[0]; // so we're sure that last_pix != argb[0] - - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - if (argb[x] == last_pix) { - continue; - } - last_pix = argb[x]; - key = (kHashMul * last_pix) >> PALETTE_KEY_RIGHT_SHIFT; - while (1) { - if (!in_use[key]) { - colors[key] = last_pix; - in_use[key] = 1; - ++num_colors; - if (num_colors > MAX_PALETTE_SIZE) { - return 0; - } - break; - } else if (colors[key] == last_pix) { - // The color is already there. - break; - } else { - // Some other color sits there. - // Do linear conflict resolution. - ++key; - key &= (MAX_PALETTE_SIZE * 4 - 1); // key mask for 1K buffer. - } - } - } - argb += pic->argb_stride; - } - - // TODO(skal): could we reuse in_use[] to speed up EncodePalette()? - num_colors = 0; - for (i = 0; i < (int)(sizeof(in_use) / sizeof(in_use[0])); ++i) { - if (in_use[i]) { - palette[num_colors] = colors[i]; - ++num_colors; - } - } - *palette_size = num_colors; - qsort(palette, num_colors, sizeof(*palette), PaletteCompareColorsForQsort); - if (!low_effort && PaletteHasNonMonotonousDeltas(palette, num_colors)) { - GreedyMinimizeDeltas(palette, num_colors); - } - return 1; -} - -// These five modes are evaluated and their respective entropy is computed. -typedef enum { - kDirect = 0, - kSpatial = 1, - kSubGreen = 2, - kSpatialSubGreen = 3, - kPalette = 4, - kNumEntropyIx = 5 -} EntropyIx; - -typedef enum { - kHistoAlpha = 0, - kHistoAlphaPred, - kHistoGreen, - kHistoGreenPred, - kHistoRed, - kHistoRedPred, - kHistoBlue, - kHistoBluePred, - kHistoRedSubGreen, - kHistoRedPredSubGreen, - kHistoBlueSubGreen, - kHistoBluePredSubGreen, - kHistoPalette, - kHistoTotal // Must be last. -} HistoIx; - -static void AddSingleSubGreen(uint32_t p, uint32_t* r, uint32_t* b) { - const uint32_t green = p >> 8; // The upper bits are masked away later. - ++r[((p >> 16) - green) & 0xff]; - ++b[(p - green) & 0xff]; -} - -static void AddSingle(uint32_t p, - uint32_t* a, uint32_t* r, uint32_t* g, uint32_t* b) { - ++a[p >> 24]; - ++r[(p >> 16) & 0xff]; - ++g[(p >> 8) & 0xff]; - ++b[(p & 0xff)]; -} - -static int AnalyzeEntropy(const uint32_t* argb, - int width, int height, int argb_stride, - int use_palette, - EntropyIx* const min_entropy_ix, - int* const red_and_blue_always_zero) { - // Allocate histogram set with cache_bits = 0. - uint32_t* const histo = - (uint32_t*)WebPSafeCalloc(kHistoTotal, sizeof(*histo) * 256); - if (histo != NULL) { - int i, x, y; - const uint32_t* prev_row = argb; - const uint32_t* curr_row = argb + argb_stride; - for (y = 1; y < height; ++y) { - uint32_t prev_pix = curr_row[0]; - for (x = 1; x < width; ++x) { - const uint32_t pix = curr_row[x]; - const uint32_t pix_diff = VP8LSubPixels(pix, prev_pix); - if ((pix_diff == 0) || (pix == prev_row[x])) continue; - prev_pix = pix; - AddSingle(pix, - &histo[kHistoAlpha * 256], - &histo[kHistoRed * 256], - &histo[kHistoGreen * 256], - &histo[kHistoBlue * 256]); - AddSingle(pix_diff, - &histo[kHistoAlphaPred * 256], - &histo[kHistoRedPred * 256], - &histo[kHistoGreenPred * 256], - &histo[kHistoBluePred * 256]); - AddSingleSubGreen(pix, - &histo[kHistoRedSubGreen * 256], - &histo[kHistoBlueSubGreen * 256]); - AddSingleSubGreen(pix_diff, - &histo[kHistoRedPredSubGreen * 256], - &histo[kHistoBluePredSubGreen * 256]); - { - // Approximate the palette by the entropy of the multiplicative hash. - const int hash = ((pix + (pix >> 19)) * 0x39c5fba7) >> 24; - ++histo[kHistoPalette * 256 + (hash & 0xff)]; - } - } - prev_row = curr_row; - curr_row += argb_stride; - } - { - double entropy_comp[kHistoTotal]; - double entropy[kNumEntropyIx]; - EntropyIx k; - EntropyIx last_mode_to_analyze = - use_palette ? kPalette : kSpatialSubGreen; - int j; - // Let's add one zero to the predicted histograms. The zeros are removed - // too efficiently by the pix_diff == 0 comparison, at least one of the - // zeros is likely to exist. - ++histo[kHistoRedPredSubGreen * 256]; - ++histo[kHistoBluePredSubGreen * 256]; - ++histo[kHistoRedPred * 256]; - ++histo[kHistoGreenPred * 256]; - ++histo[kHistoBluePred * 256]; - ++histo[kHistoAlphaPred * 256]; - - for (j = 0; j < kHistoTotal; ++j) { - entropy_comp[j] = VP8LBitsEntropy(&histo[j * 256], 256, NULL); - } - entropy[kDirect] = entropy_comp[kHistoAlpha] + - entropy_comp[kHistoRed] + - entropy_comp[kHistoGreen] + - entropy_comp[kHistoBlue]; - entropy[kSpatial] = entropy_comp[kHistoAlphaPred] + - entropy_comp[kHistoRedPred] + - entropy_comp[kHistoGreenPred] + - entropy_comp[kHistoBluePred]; - entropy[kSubGreen] = entropy_comp[kHistoAlpha] + - entropy_comp[kHistoRedSubGreen] + - entropy_comp[kHistoGreen] + - entropy_comp[kHistoBlueSubGreen]; - entropy[kSpatialSubGreen] = entropy_comp[kHistoAlphaPred] + - entropy_comp[kHistoRedPredSubGreen] + - entropy_comp[kHistoGreenPred] + - entropy_comp[kHistoBluePredSubGreen]; - // Palette mode seems more efficient in a breakeven case. Bias with 1.0. - entropy[kPalette] = entropy_comp[kHistoPalette] - 1.0; - - *min_entropy_ix = kDirect; - for (k = kDirect + 1; k <= last_mode_to_analyze; ++k) { - if (entropy[*min_entropy_ix] > entropy[k]) { - *min_entropy_ix = k; - } - } - *red_and_blue_always_zero = 1; - // Let's check if the histogram of the chosen entropy mode has - // non-zero red and blue values. If all are zero, we can later skip - // the cross color optimization. - { - static const uint8_t kHistoPairs[5][2] = { - { kHistoRed, kHistoBlue }, - { kHistoRedPred, kHistoBluePred }, - { kHistoRedSubGreen, kHistoBlueSubGreen }, - { kHistoRedPredSubGreen, kHistoBluePredSubGreen }, - { kHistoRed, kHistoBlue } - }; - const uint32_t* const red_histo = - &histo[256 * kHistoPairs[*min_entropy_ix][0]]; - const uint32_t* const blue_histo = - &histo[256 * kHistoPairs[*min_entropy_ix][1]]; - for (i = 1; i < 256; ++i) { - if ((red_histo[i] | blue_histo[i]) != 0) { - *red_and_blue_always_zero = 0; - break; - } - } - } - } - free(histo); - return 1; - } else { - return 0; - } -} - -static int GetHistoBits(int method, int use_palette, int width, int height) { - // Make tile size a function of encoding method (Range: 0 to 6). - int histo_bits = (use_palette ? 9 : 7) - method; - while (1) { - const int huff_image_size = VP8LSubSampleSize(width, histo_bits) * - VP8LSubSampleSize(height, histo_bits); - if (huff_image_size <= MAX_HUFF_IMAGE_SIZE) break; - ++histo_bits; - } - return (histo_bits < MIN_HUFFMAN_BITS) ? MIN_HUFFMAN_BITS : - (histo_bits > MAX_HUFFMAN_BITS) ? MAX_HUFFMAN_BITS : histo_bits; -} - -static int GetTransformBits(int method, int histo_bits) { - const int max_transform_bits = (method < 4) ? 6 : (method > 4) ? 4 : 5; - return (histo_bits > max_transform_bits) ? max_transform_bits : histo_bits; -} - -static int AnalyzeAndInit(VP8LEncoder* const enc) { - const WebPPicture* const pic = enc->pic_; - const int width = pic->width; - const int height = pic->height; - const int pix_cnt = width * height; - const WebPConfig* const config = enc->config_; - const int method = config->method; - const int low_effort = (config->method == 0); - // we round the block size up, so we're guaranteed to have - // at max MAX_REFS_BLOCK_PER_IMAGE blocks used: - int refs_block_size = (pix_cnt - 1) / MAX_REFS_BLOCK_PER_IMAGE + 1; - assert(pic != NULL && pic->argb != NULL); - - enc->use_cross_color_ = 0; - enc->use_predict_ = 0; - enc->use_subtract_green_ = 0; - enc->use_palette_ = - AnalyzeAndCreatePalette(pic, low_effort, - enc->palette_, &enc->palette_size_); - - // TODO(jyrki): replace the decision to be based on an actual estimate - // of entropy, or even spatial variance of entropy. - enc->histo_bits_ = GetHistoBits(method, enc->use_palette_, - pic->width, pic->height); - enc->transform_bits_ = GetTransformBits(method, enc->histo_bits_); - - if (low_effort) { - // AnalyzeEntropy is somewhat slow. - enc->use_predict_ = !enc->use_palette_; - enc->use_subtract_green_ = !enc->use_palette_; - enc->use_cross_color_ = 0; - } else { - int red_and_blue_always_zero; - EntropyIx min_entropy_ix; - if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride, - enc->use_palette_, &min_entropy_ix, - &red_and_blue_always_zero)) { - return 0; - } - enc->use_palette_ = (min_entropy_ix == kPalette); - enc->use_subtract_green_ = - (min_entropy_ix == kSubGreen) || (min_entropy_ix == kSpatialSubGreen); - enc->use_predict_ = - (min_entropy_ix == kSpatial) || (min_entropy_ix == kSpatialSubGreen); - enc->use_cross_color_ = red_and_blue_always_zero ? 0 : enc->use_predict_; - } - - if (!VP8LHashChainInit(&enc->hash_chain_, pix_cnt)) return 0; - - // palette-friendly input typically uses less literals - // -> reduce block size a bit - if (enc->use_palette_) refs_block_size /= 2; - VP8LBackwardRefsInit(&enc->refs_[0], refs_block_size); - VP8LBackwardRefsInit(&enc->refs_[1], refs_block_size); - - return 1; -} - -// Returns false in case of memory error. -static int GetHuffBitLengthsAndCodes( - const VP8LHistogramSet* const histogram_image, - HuffmanTreeCode* const huffman_codes) { - int i, k; - int ok = 0; - uint64_t total_length_size = 0; - uint8_t* mem_buf = NULL; - const int histogram_image_size = histogram_image->size; - int max_num_symbols = 0; - uint8_t* buf_rle = NULL; - HuffmanTree* huff_tree = NULL; - - // Iterate over all histograms and get the aggregate number of codes used. - for (i = 0; i < histogram_image_size; ++i) { - const VP8LHistogram* const histo = histogram_image->histograms[i]; - HuffmanTreeCode* const codes = &huffman_codes[5 * i]; - for (k = 0; k < 5; ++k) { - const int num_symbols = - (k == 0) ? VP8LHistogramNumCodes(histo->palette_code_bits_) : - (k == 4) ? NUM_DISTANCE_CODES : 256; - codes[k].num_symbols = num_symbols; - total_length_size += num_symbols; - } - } - - // Allocate and Set Huffman codes. - { - uint16_t* codes; - uint8_t* lengths; - mem_buf = (uint8_t*)WebPSafeCalloc(total_length_size, - sizeof(*lengths) + sizeof(*codes)); - if (mem_buf == NULL) goto End; - - codes = (uint16_t*)mem_buf; - lengths = (uint8_t*)&codes[total_length_size]; - for (i = 0; i < 5 * histogram_image_size; ++i) { - const int bit_length = huffman_codes[i].num_symbols; - huffman_codes[i].codes = codes; - huffman_codes[i].code_lengths = lengths; - codes += bit_length; - lengths += bit_length; - if (max_num_symbols < bit_length) { - max_num_symbols = bit_length; - } - } - } - - buf_rle = (uint8_t*)WebPSafeMalloc(1ULL, max_num_symbols); - huff_tree = (HuffmanTree*)WebPSafeMalloc(3ULL * max_num_symbols, - sizeof(*huff_tree)); - if (buf_rle == NULL || huff_tree == NULL) goto End; - - // Create Huffman trees. - for (i = 0; i < histogram_image_size; ++i) { - HuffmanTreeCode* const codes = &huffman_codes[5 * i]; - VP8LHistogram* const histo = histogram_image->histograms[i]; - VP8LCreateHuffmanTree(histo->literal_, 15, buf_rle, huff_tree, codes + 0); - VP8LCreateHuffmanTree(histo->red_, 15, buf_rle, huff_tree, codes + 1); - VP8LCreateHuffmanTree(histo->blue_, 15, buf_rle, huff_tree, codes + 2); - VP8LCreateHuffmanTree(histo->alpha_, 15, buf_rle, huff_tree, codes + 3); - VP8LCreateHuffmanTree(histo->distance_, 15, buf_rle, huff_tree, codes + 4); - } - ok = 1; - End: - WebPSafeFree(huff_tree); - WebPSafeFree(buf_rle); - if (!ok) { - WebPSafeFree(mem_buf); - memset(huffman_codes, 0, 5 * histogram_image_size * sizeof(*huffman_codes)); - } - return ok; -} - -static void StoreHuffmanTreeOfHuffmanTreeToBitMask( - VP8LBitWriter* const bw, const uint8_t* code_length_bitdepth) { - // RFC 1951 will calm you down if you are worried about this funny sequence. - // This sequence is tuned from that, but more weighted for lower symbol count, - // and more spiking histograms. - static const uint8_t kStorageOrder[CODE_LENGTH_CODES] = { - 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - }; - int i; - // Throw away trailing zeros: - int codes_to_store = CODE_LENGTH_CODES; - for (; codes_to_store > 4; --codes_to_store) { - if (code_length_bitdepth[kStorageOrder[codes_to_store - 1]] != 0) { - break; - } - } - VP8LPutBits(bw, codes_to_store - 4, 4); - for (i = 0; i < codes_to_store; ++i) { - VP8LPutBits(bw, code_length_bitdepth[kStorageOrder[i]], 3); - } -} - -static void ClearHuffmanTreeIfOnlyOneSymbol( - HuffmanTreeCode* const huffman_code) { - int k; - int count = 0; - for (k = 0; k < huffman_code->num_symbols; ++k) { - if (huffman_code->code_lengths[k] != 0) { - ++count; - if (count > 1) return; - } - } - for (k = 0; k < huffman_code->num_symbols; ++k) { - huffman_code->code_lengths[k] = 0; - huffman_code->codes[k] = 0; - } -} - -static void StoreHuffmanTreeToBitMask( - VP8LBitWriter* const bw, - const HuffmanTreeToken* const tokens, const int num_tokens, - const HuffmanTreeCode* const huffman_code) { - int i; - for (i = 0; i < num_tokens; ++i) { - const int ix = tokens[i].code; - const int extra_bits = tokens[i].extra_bits; - VP8LPutBits(bw, huffman_code->codes[ix], huffman_code->code_lengths[ix]); - switch (ix) { - case 16: - VP8LPutBits(bw, extra_bits, 2); - break; - case 17: - VP8LPutBits(bw, extra_bits, 3); - break; - case 18: - VP8LPutBits(bw, extra_bits, 7); - break; - } - } -} - -// 'huff_tree' and 'tokens' are pre-alloacted buffers. -static void StoreFullHuffmanCode(VP8LBitWriter* const bw, - HuffmanTree* const huff_tree, - HuffmanTreeToken* const tokens, - const HuffmanTreeCode* const tree) { - uint8_t code_length_bitdepth[CODE_LENGTH_CODES] = { 0 }; - uint16_t code_length_bitdepth_symbols[CODE_LENGTH_CODES] = { 0 }; - const int max_tokens = tree->num_symbols; - int num_tokens; - HuffmanTreeCode huffman_code; - huffman_code.num_symbols = CODE_LENGTH_CODES; - huffman_code.code_lengths = code_length_bitdepth; - huffman_code.codes = code_length_bitdepth_symbols; - - VP8LPutBits(bw, 0, 1); - num_tokens = VP8LCreateCompressedHuffmanTree(tree, tokens, max_tokens); - { - uint32_t histogram[CODE_LENGTH_CODES] = { 0 }; - uint8_t buf_rle[CODE_LENGTH_CODES] = { 0 }; - int i; - for (i = 0; i < num_tokens; ++i) { - ++histogram[tokens[i].code]; - } - - VP8LCreateHuffmanTree(histogram, 7, buf_rle, huff_tree, &huffman_code); - } - - StoreHuffmanTreeOfHuffmanTreeToBitMask(bw, code_length_bitdepth); - ClearHuffmanTreeIfOnlyOneSymbol(&huffman_code); - { - int trailing_zero_bits = 0; - int trimmed_length = num_tokens; - int write_trimmed_length; - int length; - int i = num_tokens; - while (i-- > 0) { - const int ix = tokens[i].code; - if (ix == 0 || ix == 17 || ix == 18) { - --trimmed_length; // discount trailing zeros - trailing_zero_bits += code_length_bitdepth[ix]; - if (ix == 17) { - trailing_zero_bits += 3; - } else if (ix == 18) { - trailing_zero_bits += 7; - } - } else { - break; - } - } - write_trimmed_length = (trimmed_length > 1 && trailing_zero_bits > 12); - length = write_trimmed_length ? trimmed_length : num_tokens; - VP8LPutBits(bw, write_trimmed_length, 1); - if (write_trimmed_length) { - const int nbits = VP8LBitsLog2Ceiling(trimmed_length - 1); - const int nbitpairs = (nbits == 0) ? 1 : (nbits + 1) / 2; - VP8LPutBits(bw, nbitpairs - 1, 3); - assert(trimmed_length >= 2); - VP8LPutBits(bw, trimmed_length - 2, nbitpairs * 2); - } - StoreHuffmanTreeToBitMask(bw, tokens, length, &huffman_code); - } -} - -// 'huff_tree' and 'tokens' are pre-alloacted buffers. -static void StoreHuffmanCode(VP8LBitWriter* const bw, - HuffmanTree* const huff_tree, - HuffmanTreeToken* const tokens, - const HuffmanTreeCode* const huffman_code) { - int i; - int count = 0; - int symbols[2] = { 0, 0 }; - const int kMaxBits = 8; - const int kMaxSymbol = 1 << kMaxBits; - - // Check whether it's a small tree. - for (i = 0; i < huffman_code->num_symbols && count < 3; ++i) { - if (huffman_code->code_lengths[i] != 0) { - if (count < 2) symbols[count] = i; - ++count; - } - } - - if (count == 0) { // emit minimal tree for empty cases - // bits: small tree marker: 1, count-1: 0, large 8-bit code: 0, code: 0 - VP8LPutBits(bw, 0x01, 4); - } else if (count <= 2 && symbols[0] < kMaxSymbol && symbols[1] < kMaxSymbol) { - VP8LPutBits(bw, 1, 1); // Small tree marker to encode 1 or 2 symbols. - VP8LPutBits(bw, count - 1, 1); - if (symbols[0] <= 1) { - VP8LPutBits(bw, 0, 1); // Code bit for small (1 bit) symbol value. - VP8LPutBits(bw, symbols[0], 1); - } else { - VP8LPutBits(bw, 1, 1); - VP8LPutBits(bw, symbols[0], 8); - } - if (count == 2) { - VP8LPutBits(bw, symbols[1], 8); - } - } else { - StoreFullHuffmanCode(bw, huff_tree, tokens, huffman_code); - } -} - -static WEBP_INLINE void WriteHuffmanCode(VP8LBitWriter* const bw, - const HuffmanTreeCode* const code, - int code_index) { - const int depth = code->code_lengths[code_index]; - const int symbol = code->codes[code_index]; - VP8LPutBits(bw, symbol, depth); -} - -static WEBP_INLINE void WriteHuffmanCodeWithExtraBits( - VP8LBitWriter* const bw, - const HuffmanTreeCode* const code, - int code_index, - int bits, - int n_bits) { - const int depth = code->code_lengths[code_index]; - const int symbol = code->codes[code_index]; - VP8LPutBits(bw, (bits << depth) | symbol, depth + n_bits); -} - -static WebPEncodingError StoreImageToBitMask( - VP8LBitWriter* const bw, int width, int histo_bits, - VP8LBackwardRefs* const refs, - const uint16_t* histogram_symbols, - const HuffmanTreeCode* const huffman_codes) { - const int histo_xsize = histo_bits ? VP8LSubSampleSize(width, histo_bits) : 1; - const int tile_mask = (histo_bits == 0) ? 0 : -(1 << histo_bits); - // x and y trace the position in the image. - int x = 0; - int y = 0; - int tile_x = x & tile_mask; - int tile_y = y & tile_mask; - int histogram_ix = histogram_symbols[0]; - const HuffmanTreeCode* codes = huffman_codes + 5 * histogram_ix; - VP8LRefsCursor c = VP8LRefsCursorInit(refs); - while (VP8LRefsCursorOk(&c)) { - const PixOrCopy* const v = c.cur_pos; - if ((tile_x != (x & tile_mask)) || (tile_y != (y & tile_mask))) { - tile_x = x & tile_mask; - tile_y = y & tile_mask; - histogram_ix = histogram_symbols[(y >> histo_bits) * histo_xsize + - (x >> histo_bits)]; - codes = huffman_codes + 5 * histogram_ix; - } - if (PixOrCopyIsLiteral(v)) { - static const int order[] = { 1, 2, 0, 3 }; - int k; - for (k = 0; k < 4; ++k) { - const int code = PixOrCopyLiteral(v, order[k]); - WriteHuffmanCode(bw, codes + k, code); - } - } else if (PixOrCopyIsCacheIdx(v)) { - const int code = PixOrCopyCacheIdx(v); - const int literal_ix = 256 + NUM_LENGTH_CODES + code; - WriteHuffmanCode(bw, codes, literal_ix); - } else { - int bits, n_bits; - int code; - - const int distance = PixOrCopyDistance(v); - VP8LPrefixEncode(v->len, &code, &n_bits, &bits); - WriteHuffmanCodeWithExtraBits(bw, codes, 256 + code, bits, n_bits); - - // Don't write the distance with the extra bits code since - // the distance can be up to 18 bits of extra bits, and the prefix - // 15 bits, totaling to 33, and our PutBits only supports up to 32 bits. - // TODO(jyrki): optimize this further. - VP8LPrefixEncode(distance, &code, &n_bits, &bits); - WriteHuffmanCode(bw, codes + 4, code); - VP8LPutBits(bw, bits, n_bits); - } - x += PixOrCopyLength(v); - while (x >= width) { - x -= width; - ++y; - } - VP8LRefsCursorNext(&c); - } - return bw->error_ ? VP8_ENC_ERROR_OUT_OF_MEMORY : VP8_ENC_OK; -} - -// Special case of EncodeImageInternal() for cache-bits=0, histo_bits=31 -static WebPEncodingError EncodeImageNoHuffman(VP8LBitWriter* const bw, - const uint32_t* const argb, - VP8LHashChain* const hash_chain, - VP8LBackwardRefs refs_array[2], - int width, int height, - int quality) { - int i; - int max_tokens = 0; - WebPEncodingError err = VP8_ENC_OK; - VP8LBackwardRefs* refs; - HuffmanTreeToken* tokens = NULL; - HuffmanTreeCode huffman_codes[5] = { { 0, NULL, NULL } }; - const uint16_t histogram_symbols[1] = { 0 }; // only one tree, one symbol - int cache_bits = 0; - VP8LHistogramSet* histogram_image = NULL; - HuffmanTree* const huff_tree = (HuffmanTree*)WebPSafeMalloc( - 3ULL * CODE_LENGTH_CODES, sizeof(*huff_tree)); - if (huff_tree == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - // Calculate backward references from ARGB image. - refs = VP8LGetBackwardReferences(width, height, argb, quality, 0, &cache_bits, - hash_chain, refs_array); - if (refs == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - histogram_image = VP8LAllocateHistogramSet(1, cache_bits); - if (histogram_image == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - // Build histogram image and symbols from backward references. - VP8LHistogramStoreRefs(refs, histogram_image->histograms[0]); - - // Create Huffman bit lengths and codes for each histogram image. - assert(histogram_image->size == 1); - if (!GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - // No color cache, no Huffman image. - VP8LPutBits(bw, 0, 1); - - // Find maximum number of symbols for the huffman tree-set. - for (i = 0; i < 5; ++i) { - HuffmanTreeCode* const codes = &huffman_codes[i]; - if (max_tokens < codes->num_symbols) { - max_tokens = codes->num_symbols; - } - } - - tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, sizeof(*tokens)); - if (tokens == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - // Store Huffman codes. - for (i = 0; i < 5; ++i) { - HuffmanTreeCode* const codes = &huffman_codes[i]; - StoreHuffmanCode(bw, huff_tree, tokens, codes); - ClearHuffmanTreeIfOnlyOneSymbol(codes); - } - - // Store actual literals. - err = StoreImageToBitMask(bw, width, 0, refs, histogram_symbols, - huffman_codes); - - Error: - WebPSafeFree(tokens); - WebPSafeFree(huff_tree); - VP8LFreeHistogramSet(histogram_image); - WebPSafeFree(huffman_codes[0].codes); - return err; -} - -static WebPEncodingError EncodeImageInternal(VP8LBitWriter* const bw, - const uint32_t* const argb, - VP8LHashChain* const hash_chain, - VP8LBackwardRefs refs_array[2], - int width, int height, int quality, - int low_effort, int* cache_bits, - int histogram_bits, - size_t init_byte_position, - int* const hdr_size, - int* const data_size) { - WebPEncodingError err = VP8_ENC_OK; - const uint32_t histogram_image_xysize = - VP8LSubSampleSize(width, histogram_bits) * - VP8LSubSampleSize(height, histogram_bits); - VP8LHistogramSet* histogram_image = NULL; - VP8LHistogramSet* tmp_histos = NULL; - int histogram_image_size = 0; - size_t bit_array_size = 0; - HuffmanTree* huff_tree = NULL; - HuffmanTreeToken* tokens = NULL; - HuffmanTreeCode* huffman_codes = NULL; - VP8LBackwardRefs refs; - VP8LBackwardRefs* best_refs; - uint16_t* const histogram_symbols = - (uint16_t*)WebPSafeMalloc(histogram_image_xysize, - sizeof(*histogram_symbols)); - assert(histogram_bits >= MIN_HUFFMAN_BITS); - assert(histogram_bits <= MAX_HUFFMAN_BITS); - assert(hdr_size != NULL); - assert(data_size != NULL); - - VP8LBackwardRefsInit(&refs, refs_array[0].block_size_); - if (histogram_symbols == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - *cache_bits = MAX_COLOR_CACHE_BITS; - // 'best_refs' is the reference to the best backward refs and points to one - // of refs_array[0] or refs_array[1]. - // Calculate backward references from ARGB image. - best_refs = VP8LGetBackwardReferences(width, height, argb, quality, - low_effort, cache_bits, hash_chain, - refs_array); - if (best_refs == NULL || !VP8LBackwardRefsCopy(best_refs, &refs)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - histogram_image = - VP8LAllocateHistogramSet(histogram_image_xysize, *cache_bits); - tmp_histos = VP8LAllocateHistogramSet(2, *cache_bits); - if (histogram_image == NULL || tmp_histos == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - // Build histogram image and symbols from backward references. - if (!VP8LGetHistoImageSymbols(width, height, &refs, quality, low_effort, - histogram_bits, *cache_bits, histogram_image, - tmp_histos, histogram_symbols)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - // Create Huffman bit lengths and codes for each histogram image. - histogram_image_size = histogram_image->size; - bit_array_size = 5 * histogram_image_size; - huffman_codes = (HuffmanTreeCode*)WebPSafeCalloc(bit_array_size, - sizeof(*huffman_codes)); - // Note: some histogram_image entries may point to tmp_histos[], so the latter - // need to outlive the following call to GetHuffBitLengthsAndCodes(). - if (huffman_codes == NULL || - !GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - // Free combined histograms. - VP8LFreeHistogramSet(histogram_image); - histogram_image = NULL; - - // Free scratch histograms. - VP8LFreeHistogramSet(tmp_histos); - tmp_histos = NULL; - - // Color Cache parameters. - if (*cache_bits > 0) { - VP8LPutBits(bw, 1, 1); - VP8LPutBits(bw, *cache_bits, 4); - } else { - VP8LPutBits(bw, 0, 1); - } - - // Huffman image + meta huffman. - { - const int write_histogram_image = (histogram_image_size > 1); - VP8LPutBits(bw, write_histogram_image, 1); - if (write_histogram_image) { - uint32_t* const histogram_argb = - (uint32_t*)WebPSafeMalloc(histogram_image_xysize, - sizeof(*histogram_argb)); - int max_index = 0; - uint32_t i; - if (histogram_argb == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - for (i = 0; i < histogram_image_xysize; ++i) { - const int symbol_index = histogram_symbols[i] & 0xffff; - histogram_argb[i] = (symbol_index << 8); - if (symbol_index >= max_index) { - max_index = symbol_index + 1; - } - } - histogram_image_size = max_index; - - VP8LPutBits(bw, histogram_bits - 2, 3); - err = EncodeImageNoHuffman(bw, histogram_argb, hash_chain, refs_array, - VP8LSubSampleSize(width, histogram_bits), - VP8LSubSampleSize(height, histogram_bits), - quality); - WebPSafeFree(histogram_argb); - if (err != VP8_ENC_OK) goto Error; - } - } - - // Store Huffman codes. - { - int i; - int max_tokens = 0; - huff_tree = (HuffmanTree*)WebPSafeMalloc(3ULL * CODE_LENGTH_CODES, - sizeof(*huff_tree)); - if (huff_tree == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - // Find maximum number of symbols for the huffman tree-set. - for (i = 0; i < 5 * histogram_image_size; ++i) { - HuffmanTreeCode* const codes = &huffman_codes[i]; - if (max_tokens < codes->num_symbols) { - max_tokens = codes->num_symbols; - } - } - tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, - sizeof(*tokens)); - if (tokens == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - for (i = 0; i < 5 * histogram_image_size; ++i) { - HuffmanTreeCode* const codes = &huffman_codes[i]; - StoreHuffmanCode(bw, huff_tree, tokens, codes); - ClearHuffmanTreeIfOnlyOneSymbol(codes); - } - } - - *hdr_size = (int)(VP8LBitWriterNumBytes(bw) - init_byte_position); - // Store actual literals. - err = StoreImageToBitMask(bw, width, histogram_bits, &refs, - histogram_symbols, huffman_codes); - *data_size = - (int)(VP8LBitWriterNumBytes(bw) - init_byte_position - *hdr_size); - - Error: - WebPSafeFree(tokens); - WebPSafeFree(huff_tree); - VP8LFreeHistogramSet(histogram_image); - VP8LFreeHistogramSet(tmp_histos); - VP8LBackwardRefsClear(&refs); - if (huffman_codes != NULL) { - WebPSafeFree(huffman_codes->codes); - WebPSafeFree(huffman_codes); - } - WebPSafeFree(histogram_symbols); - return err; -} - -// ----------------------------------------------------------------------------- -// Transforms - -static void ApplySubtractGreen(VP8LEncoder* const enc, int width, int height, - VP8LBitWriter* const bw) { - VP8LPutBits(bw, TRANSFORM_PRESENT, 1); - VP8LPutBits(bw, SUBTRACT_GREEN, 2); - VP8LSubtractGreenFromBlueAndRed(enc->argb_, width * height); -} - -static WebPEncodingError ApplyPredictFilter(const VP8LEncoder* const enc, - int width, int height, - int quality, int low_effort, - VP8LBitWriter* const bw) { - const int pred_bits = enc->transform_bits_; - const int transform_width = VP8LSubSampleSize(width, pred_bits); - const int transform_height = VP8LSubSampleSize(height, pred_bits); - - VP8LResidualImage(width, height, pred_bits, low_effort, enc->argb_, - enc->argb_scratch_, enc->transform_data_, - enc->config_->exact); - VP8LPutBits(bw, TRANSFORM_PRESENT, 1); - VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2); - assert(pred_bits >= 2); - VP8LPutBits(bw, pred_bits - 2, 3); - return EncodeImageNoHuffman(bw, enc->transform_data_, - (VP8LHashChain*)&enc->hash_chain_, - (VP8LBackwardRefs*)enc->refs_, // cast const away - transform_width, transform_height, - quality); -} - -static WebPEncodingError ApplyCrossColorFilter(const VP8LEncoder* const enc, - int width, int height, - int quality, - VP8LBitWriter* const bw) { - const int ccolor_transform_bits = enc->transform_bits_; - const int transform_width = VP8LSubSampleSize(width, ccolor_transform_bits); - const int transform_height = VP8LSubSampleSize(height, ccolor_transform_bits); - - VP8LColorSpaceTransform(width, height, ccolor_transform_bits, quality, - enc->argb_, enc->transform_data_); - VP8LPutBits(bw, TRANSFORM_PRESENT, 1); - VP8LPutBits(bw, CROSS_COLOR_TRANSFORM, 2); - assert(ccolor_transform_bits >= 2); - VP8LPutBits(bw, ccolor_transform_bits - 2, 3); - return EncodeImageNoHuffman(bw, enc->transform_data_, - (VP8LHashChain*)&enc->hash_chain_, - (VP8LBackwardRefs*)enc->refs_, // cast const away - transform_width, transform_height, - quality); -} - -// ----------------------------------------------------------------------------- - -static WebPEncodingError WriteRiffHeader(const WebPPicture* const pic, - size_t riff_size, size_t vp8l_size) { - uint8_t riff[RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + VP8L_SIGNATURE_SIZE] = { - 'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P', - 'V', 'P', '8', 'L', 0, 0, 0, 0, VP8L_MAGIC_BYTE, - }; - PutLE32(riff + TAG_SIZE, (uint32_t)riff_size); - PutLE32(riff + RIFF_HEADER_SIZE + TAG_SIZE, (uint32_t)vp8l_size); - if (!pic->writer(riff, sizeof(riff), pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - return VP8_ENC_OK; -} - -static int WriteImageSize(const WebPPicture* const pic, - VP8LBitWriter* const bw) { - const int width = pic->width - 1; - const int height = pic->height - 1; - assert(width < WEBP_MAX_DIMENSION && height < WEBP_MAX_DIMENSION); - - VP8LPutBits(bw, width, VP8L_IMAGE_SIZE_BITS); - VP8LPutBits(bw, height, VP8L_IMAGE_SIZE_BITS); - return !bw->error_; -} - -static int WriteRealAlphaAndVersion(VP8LBitWriter* const bw, int has_alpha) { - VP8LPutBits(bw, has_alpha, 1); - VP8LPutBits(bw, VP8L_VERSION, VP8L_VERSION_BITS); - return !bw->error_; -} - -static WebPEncodingError WriteImage(const WebPPicture* const pic, - VP8LBitWriter* const bw, - size_t* const coded_size) { - WebPEncodingError err = VP8_ENC_OK; - const uint8_t* const webpll_data = VP8LBitWriterFinish(bw); - const size_t webpll_size = VP8LBitWriterNumBytes(bw); - const size_t vp8l_size = VP8L_SIGNATURE_SIZE + webpll_size; - const size_t pad = vp8l_size & 1; - const size_t riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8l_size + pad; - - err = WriteRiffHeader(pic, riff_size, vp8l_size); - if (err != VP8_ENC_OK) goto Error; - - if (!pic->writer(webpll_data, webpll_size, pic)) { - err = VP8_ENC_ERROR_BAD_WRITE; - goto Error; - } - - if (pad) { - const uint8_t pad_byte[1] = { 0 }; - if (!pic->writer(pad_byte, 1, pic)) { - err = VP8_ENC_ERROR_BAD_WRITE; - goto Error; - } - } - *coded_size = CHUNK_HEADER_SIZE + riff_size; - return VP8_ENC_OK; - - Error: - return err; -} - -// ----------------------------------------------------------------------------- - -// Allocates the memory for argb (W x H) buffer, 2 rows of context for -// prediction and transform data. -// Flags influencing the memory allocated: -// enc->transform_bits_ -// enc->use_predict_, enc->use_cross_color_ -static WebPEncodingError AllocateTransformBuffer(VP8LEncoder* const enc, - int width, int height) { - WebPEncodingError err = VP8_ENC_OK; - if (enc->argb_ == NULL) { - const int tile_size = 1 << enc->transform_bits_; - const uint64_t image_size = width * height; - // Ensure enough size for tiles, as well as for two scanlines and two - // extra pixels for CopyImageWithPrediction. - const uint64_t argb_scratch_size = - enc->use_predict_ ? tile_size * width + width + 2 : 0; - const int transform_data_size = - (enc->use_predict_ || enc->use_cross_color_) - ? VP8LSubSampleSize(width, enc->transform_bits_) * - VP8LSubSampleSize(height, enc->transform_bits_) - : 0; - const uint64_t total_size = - image_size + WEBP_ALIGN_CST + - argb_scratch_size + WEBP_ALIGN_CST + - (uint64_t)transform_data_size; - uint32_t* mem = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*mem)); - if (mem == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - enc->argb_ = mem; - mem = (uint32_t*)WEBP_ALIGN(mem + image_size); - enc->argb_scratch_ = mem; - mem = (uint32_t*)WEBP_ALIGN(mem + argb_scratch_size); - enc->transform_data_ = mem; - enc->current_width_ = width; - } - Error: - return err; -} - -static void ClearTransformBuffer(VP8LEncoder* const enc) { - WebPSafeFree(enc->argb_); - enc->argb_ = NULL; -} - -static WebPEncodingError MakeInputImageCopy(VP8LEncoder* const enc) { - WebPEncodingError err = VP8_ENC_OK; - const WebPPicture* const picture = enc->pic_; - const int width = picture->width; - const int height = picture->height; - int y; - err = AllocateTransformBuffer(enc, width, height); - if (err != VP8_ENC_OK) return err; - for (y = 0; y < height; ++y) { - memcpy(enc->argb_ + y * width, - picture->argb + y * picture->argb_stride, - width * sizeof(*enc->argb_)); - } - assert(enc->current_width_ == width); - return VP8_ENC_OK; -} - -// ----------------------------------------------------------------------------- - -static void MapToPalette(const uint32_t palette[], int num_colors, - uint32_t* const last_pix, int* const last_idx, - const uint32_t* src, uint8_t* dst, int width) { - int x; - int prev_idx = *last_idx; - uint32_t prev_pix = *last_pix; - for (x = 0; x < width; ++x) { - const uint32_t pix = src[x]; - if (pix != prev_pix) { - int i; - for (i = 0; i < num_colors; ++i) { - if (pix == palette[i]) { - prev_idx = i; - prev_pix = pix; - break; - } - } - } - dst[x] = prev_idx; - } - *last_idx = prev_idx; - *last_pix = prev_pix; -} - -// Remap argb values in src[] to packed palettes entries in dst[] -// using 'row' as a temporary buffer of size 'width'. -// We assume that all src[] values have a corresponding entry in the palette. -// Note: src[] can be the same as dst[] -static WebPEncodingError ApplyPalette(const uint32_t* src, uint32_t src_stride, - uint32_t* dst, uint32_t dst_stride, - const uint32_t* palette, int palette_size, - int width, int height, int xbits) { - // TODO(skal): this tmp buffer is not needed if VP8LBundleColorMap() can be - // made to work in-place. - uint8_t* const tmp_row = (uint8_t*)WebPSafeMalloc(width, sizeof(*tmp_row)); - int i, x, y; - int use_LUT = 1; - - if (tmp_row == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY; - for (i = 0; i < palette_size; ++i) { - if ((palette[i] & 0xffff00ffu) != 0) { - use_LUT = 0; - break; - } - } - - if (use_LUT) { - uint8_t inv_palette[MAX_PALETTE_SIZE] = { 0 }; - for (i = 0; i < palette_size; ++i) { - const int color = (palette[i] >> 8) & 0xff; - inv_palette[color] = i; - } - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - const int color = (src[x] >> 8) & 0xff; - tmp_row[x] = inv_palette[color]; - } - VP8LBundleColorMap(tmp_row, width, xbits, dst); - src += src_stride; - dst += dst_stride; - } - } else { - // Use 1 pixel cache for ARGB pixels. - uint32_t last_pix = palette[0]; - int last_idx = 0; - for (y = 0; y < height; ++y) { - MapToPalette(palette, palette_size, &last_pix, &last_idx, - src, tmp_row, width); - VP8LBundleColorMap(tmp_row, width, xbits, dst); - src += src_stride; - dst += dst_stride; - } - } - WebPSafeFree(tmp_row); - return VP8_ENC_OK; -} - -// Note: Expects "enc->palette_" to be set properly. -static WebPEncodingError MapImageFromPalette(VP8LEncoder* const enc, - int in_place) { - WebPEncodingError err = VP8_ENC_OK; - const WebPPicture* const pic = enc->pic_; - const int width = pic->width; - const int height = pic->height; - const uint32_t* const palette = enc->palette_; - const uint32_t* src = in_place ? enc->argb_ : pic->argb; - const int src_stride = in_place ? enc->current_width_ : pic->argb_stride; - const int palette_size = enc->palette_size_; - int xbits; - - // Replace each input pixel by corresponding palette index. - // This is done line by line. - if (palette_size <= 4) { - xbits = (palette_size <= 2) ? 3 : 2; - } else { - xbits = (palette_size <= 16) ? 1 : 0; - } - - err = AllocateTransformBuffer(enc, VP8LSubSampleSize(width, xbits), height); - if (err != VP8_ENC_OK) return err; - - err = ApplyPalette(src, src_stride, - enc->argb_, enc->current_width_, - palette, palette_size, width, height, xbits); - return err; -} - -// Save palette_[] to bitstream. -static WebPEncodingError EncodePalette(VP8LBitWriter* const bw, - VP8LEncoder* const enc) { - int i; - uint32_t tmp_palette[MAX_PALETTE_SIZE]; - const int palette_size = enc->palette_size_; - const uint32_t* const palette = enc->palette_; - VP8LPutBits(bw, TRANSFORM_PRESENT, 1); - VP8LPutBits(bw, COLOR_INDEXING_TRANSFORM, 2); - assert(palette_size >= 1 && palette_size <= MAX_PALETTE_SIZE); - VP8LPutBits(bw, palette_size - 1, 8); - for (i = palette_size - 1; i >= 1; --i) { - tmp_palette[i] = VP8LSubPixels(palette[i], palette[i - 1]); - } - tmp_palette[0] = palette[0]; - return EncodeImageNoHuffman(bw, tmp_palette, &enc->hash_chain_, enc->refs_, - palette_size, 1, 20 /* quality */); -} - -#ifdef WEBP_EXPERIMENTAL_FEATURES - -static WebPEncodingError EncodeDeltaPalettePredictorImage( - VP8LBitWriter* const bw, VP8LEncoder* const enc, int quality) { - const WebPPicture* const pic = enc->pic_; - const int width = pic->width; - const int height = pic->height; - - const int pred_bits = 5; - const int transform_width = VP8LSubSampleSize(width, pred_bits); - const int transform_height = VP8LSubSampleSize(height, pred_bits); - const int pred = 7; // default is Predictor7 (Top/Left Average) - const int tiles_per_row = VP8LSubSampleSize(width, pred_bits); - const int tiles_per_col = VP8LSubSampleSize(height, pred_bits); - uint32_t* predictors; - int tile_x, tile_y; - WebPEncodingError err = VP8_ENC_OK; - - predictors = (uint32_t*)WebPSafeMalloc(tiles_per_col * tiles_per_row, - sizeof(*predictors)); - if (predictors == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY; - - for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) { - for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) { - predictors[tile_y * tiles_per_row + tile_x] = 0xff000000u | (pred << 8); - } - } - - VP8LPutBits(bw, TRANSFORM_PRESENT, 1); - VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2); - VP8LPutBits(bw, pred_bits - 2, 3); - err = EncodeImageNoHuffman(bw, predictors, &enc->hash_chain_, - (VP8LBackwardRefs*)enc->refs_, // cast const away - transform_width, transform_height, - quality); - WebPSafeFree(predictors); - return err; -} - -#endif // WEBP_EXPERIMENTAL_FEATURES - -// ----------------------------------------------------------------------------- -// VP8LEncoder - -static VP8LEncoder* VP8LEncoderNew(const WebPConfig* const config, - const WebPPicture* const picture) { - VP8LEncoder* const enc = (VP8LEncoder*)WebPSafeCalloc(1ULL, sizeof(*enc)); - if (enc == NULL) { - WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); - return NULL; - } - enc->config_ = config; - enc->pic_ = picture; - - VP8LEncDspInit(); - - return enc; -} - -static void VP8LEncoderDelete(VP8LEncoder* enc) { - if (enc != NULL) { - VP8LHashChainClear(&enc->hash_chain_); - VP8LBackwardRefsClear(&enc->refs_[0]); - VP8LBackwardRefsClear(&enc->refs_[1]); - ClearTransformBuffer(enc); - WebPSafeFree(enc); - } -} - -// ----------------------------------------------------------------------------- -// Main call - -WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, - const WebPPicture* const picture, - VP8LBitWriter* const bw) { - WebPEncodingError err = VP8_ENC_OK; - const int quality = (int)config->quality; - const int low_effort = (config->method == 0); - const int width = picture->width; - const int height = picture->height; - VP8LEncoder* const enc = VP8LEncoderNew(config, picture); - const size_t byte_position = VP8LBitWriterNumBytes(bw); - int use_near_lossless = 0; - int hdr_size = 0; - int data_size = 0; - int use_delta_palettization = 0; - - if (enc == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - // --------------------------------------------------------------------------- - // Analyze image (entropy, num_palettes etc) - - if (!AnalyzeAndInit(enc)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - // Apply near-lossless preprocessing. - use_near_lossless = !enc->use_palette_ && (config->near_lossless < 100); - if (use_near_lossless) { - if (!VP8ApplyNearLossless(width, height, picture->argb, - config->near_lossless)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - } - -#ifdef WEBP_EXPERIMENTAL_FEATURES - if (config->delta_palettization) { - enc->use_predict_ = 1; - enc->use_cross_color_ = 0; - enc->use_subtract_green_ = 0; - enc->use_palette_ = 1; - err = MakeInputImageCopy(enc); - if (err != VP8_ENC_OK) goto Error; - err = WebPSearchOptimalDeltaPalette(enc); - if (err != VP8_ENC_OK) goto Error; - if (enc->use_palette_) { - err = AllocateTransformBuffer(enc, width, height); - if (err != VP8_ENC_OK) goto Error; - err = EncodeDeltaPalettePredictorImage(bw, enc, quality); - if (err != VP8_ENC_OK) goto Error; - use_delta_palettization = 1; - } - } -#endif // WEBP_EXPERIMENTAL_FEATURES - - // Encode palette - if (enc->use_palette_) { - err = EncodePalette(bw, enc); - if (err != VP8_ENC_OK) goto Error; - err = MapImageFromPalette(enc, use_delta_palettization); - if (err != VP8_ENC_OK) goto Error; - } - if (!use_delta_palettization) { - // In case image is not packed. - if (enc->argb_ == NULL) { - err = MakeInputImageCopy(enc); - if (err != VP8_ENC_OK) goto Error; - } - - // ------------------------------------------------------------------------- - // Apply transforms and write transform data. - - if (enc->use_subtract_green_) { - ApplySubtractGreen(enc, enc->current_width_, height, bw); - } - - if (enc->use_predict_) { - err = ApplyPredictFilter(enc, enc->current_width_, height, quality, - low_effort, bw); - if (err != VP8_ENC_OK) goto Error; - } - - if (enc->use_cross_color_) { - err = ApplyCrossColorFilter(enc, enc->current_width_, - height, quality, bw); - if (err != VP8_ENC_OK) goto Error; - } - } - - VP8LPutBits(bw, !TRANSFORM_PRESENT, 1); // No more transforms. - - // --------------------------------------------------------------------------- - // Encode and write the transformed image. - err = EncodeImageInternal(bw, enc->argb_, &enc->hash_chain_, enc->refs_, - enc->current_width_, height, quality, low_effort, - &enc->cache_bits_, enc->histo_bits_, byte_position, - &hdr_size, &data_size); - if (err != VP8_ENC_OK) goto Error; - - if (picture->stats != NULL) { - WebPAuxStats* const stats = picture->stats; - stats->lossless_features = 0; - if (enc->use_predict_) stats->lossless_features |= 1; - if (enc->use_cross_color_) stats->lossless_features |= 2; - if (enc->use_subtract_green_) stats->lossless_features |= 4; - if (enc->use_palette_) stats->lossless_features |= 8; - stats->histogram_bits = enc->histo_bits_; - stats->transform_bits = enc->transform_bits_; - stats->cache_bits = enc->cache_bits_; - stats->palette_size = enc->palette_size_; - stats->lossless_size = (int)(VP8LBitWriterNumBytes(bw) - byte_position); - stats->lossless_hdr_size = hdr_size; - stats->lossless_data_size = data_size; - } - - Error: - VP8LEncoderDelete(enc); - return err; -} - -int VP8LEncodeImage(const WebPConfig* const config, - const WebPPicture* const picture) { - int width, height; - int has_alpha; - size_t coded_size; - int percent = 0; - int initial_size; - WebPEncodingError err = VP8_ENC_OK; - VP8LBitWriter bw; - - if (picture == NULL) return 0; - - if (config == NULL || picture->argb == NULL) { - err = VP8_ENC_ERROR_NULL_PARAMETER; - WebPEncodingSetError(picture, err); - return 0; - } - - width = picture->width; - height = picture->height; - // Initialize BitWriter with size corresponding to 16 bpp to photo images and - // 8 bpp for graphical images. - initial_size = (config->image_hint == WEBP_HINT_GRAPH) ? - width * height : width * height * 2; - if (!VP8LBitWriterInit(&bw, initial_size)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - if (!WebPReportProgress(picture, 1, &percent)) { - UserAbort: - err = VP8_ENC_ERROR_USER_ABORT; - goto Error; - } - // Reset stats (for pure lossless coding) - if (picture->stats != NULL) { - WebPAuxStats* const stats = picture->stats; - memset(stats, 0, sizeof(*stats)); - stats->PSNR[0] = 99.f; - stats->PSNR[1] = 99.f; - stats->PSNR[2] = 99.f; - stats->PSNR[3] = 99.f; - stats->PSNR[4] = 99.f; - } - - // Write image size. - if (!WriteImageSize(picture, &bw)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - has_alpha = WebPPictureHasTransparency(picture); - // Write the non-trivial Alpha flag and lossless version. - if (!WriteRealAlphaAndVersion(&bw, has_alpha)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - if (!WebPReportProgress(picture, 5, &percent)) goto UserAbort; - - // Encode main image stream. - err = VP8LEncodeStream(config, picture, &bw); - if (err != VP8_ENC_OK) goto Error; - - // TODO(skal): have a fine-grained progress report in VP8LEncodeStream(). - if (!WebPReportProgress(picture, 90, &percent)) goto UserAbort; - - // Finish the RIFF chunk. - err = WriteImage(picture, &bw, &coded_size); - if (err != VP8_ENC_OK) goto Error; - - if (!WebPReportProgress(picture, 100, &percent)) goto UserAbort; - - // Save size. - if (picture->stats != NULL) { - picture->stats->coded_size += (int)coded_size; - picture->stats->lossless_size = (int)coded_size; - } - - if (picture->extra_info != NULL) { - const int mb_w = (width + 15) >> 4; - const int mb_h = (height + 15) >> 4; - memset(picture->extra_info, 0, mb_w * mb_h * sizeof(*picture->extra_info)); - } - - Error: - if (bw.error_) err = VP8_ENC_ERROR_OUT_OF_MEMORY; - VP8LBitWriterWipeOut(&bw); - if (err != VP8_ENC_OK) { - WebPEncodingSetError(picture, err); - return 0; - } - return 1; -} - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/enc/vp8li.h b/Example/Pods/libwebp/src/enc/vp8li.h deleted file mode 100644 index 6b6db127..00000000 --- a/Example/Pods/libwebp/src/enc/vp8li.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Lossless encoder: internal header. -// -// Author: Vikas Arora (vikaas.arora@gmail.com) - -#ifndef WEBP_ENC_VP8LI_H_ -#define WEBP_ENC_VP8LI_H_ - -#include "./backward_references.h" -#include "./histogram.h" -#include "../utils/bit_writer.h" -#include "../webp/encode.h" -#include "../webp/format_constants.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - const WebPConfig* config_; // user configuration and parameters - const WebPPicture* pic_; // input picture. - - uint32_t* argb_; // Transformed argb image data. - uint32_t* argb_scratch_; // Scratch memory for argb rows - // (used for prediction). - uint32_t* transform_data_; // Scratch memory for transform data. - int current_width_; // Corresponds to packed image width. - - // Encoding parameters derived from quality parameter. - int histo_bits_; - int transform_bits_; - int cache_bits_; // If equal to 0, don't use color cache. - - // Encoding parameters derived from image characteristics. - int use_cross_color_; - int use_subtract_green_; - int use_predict_; - int use_palette_; - int palette_size_; - uint32_t palette_[MAX_PALETTE_SIZE]; - - // Some 'scratch' (potentially large) objects. - struct VP8LBackwardRefs refs_[2]; // Backward Refs array corresponding to - // LZ77 & RLE coding. - VP8LHashChain hash_chain_; // HashChain data for constructing - // backward references. -} VP8LEncoder; - -//------------------------------------------------------------------------------ -// internal functions. Not public. - -// Encodes the picture. -// Returns 0 if config or picture is NULL or picture doesn't have valid argb -// input. -int VP8LEncodeImage(const WebPConfig* const config, - const WebPPicture* const picture); - -// Encodes the main image stream using the supplied bit writer. -WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, - const WebPPicture* const picture, - VP8LBitWriter* const bw); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_ENC_VP8LI_H_ */ diff --git a/Example/Pods/libwebp/src/enc/webpenc.c b/Example/Pods/libwebp/src/enc/webpenc.c deleted file mode 100644 index fece7369..00000000 --- a/Example/Pods/libwebp/src/enc/webpenc.c +++ /dev/null @@ -1,391 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// WebP encoder: main entry point -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include -#include -#include - -#include "./cost.h" -#include "./vp8enci.h" -#include "./vp8li.h" -#include "../utils/utils.h" - -// #define PRINT_MEMORY_INFO - -#ifdef PRINT_MEMORY_INFO -#include -#endif - -//------------------------------------------------------------------------------ - -int WebPGetEncoderVersion(void) { - return (ENC_MAJ_VERSION << 16) | (ENC_MIN_VERSION << 8) | ENC_REV_VERSION; -} - -//------------------------------------------------------------------------------ -// VP8Encoder -//------------------------------------------------------------------------------ - -static void ResetSegmentHeader(VP8Encoder* const enc) { - VP8EncSegmentHeader* const hdr = &enc->segment_hdr_; - hdr->num_segments_ = enc->config_->segments; - hdr->update_map_ = (hdr->num_segments_ > 1); - hdr->size_ = 0; -} - -static void ResetFilterHeader(VP8Encoder* const enc) { - VP8EncFilterHeader* const hdr = &enc->filter_hdr_; - hdr->simple_ = 1; - hdr->level_ = 0; - hdr->sharpness_ = 0; - hdr->i4x4_lf_delta_ = 0; -} - -static void ResetBoundaryPredictions(VP8Encoder* const enc) { - // init boundary values once for all - // Note: actually, initializing the preds_[] is only needed for intra4. - int i; - uint8_t* const top = enc->preds_ - enc->preds_w_; - uint8_t* const left = enc->preds_ - 1; - for (i = -1; i < 4 * enc->mb_w_; ++i) { - top[i] = B_DC_PRED; - } - for (i = 0; i < 4 * enc->mb_h_; ++i) { - left[i * enc->preds_w_] = B_DC_PRED; - } - enc->nz_[-1] = 0; // constant -} - -// Mapping from config->method_ to coding tools used. -//-------------------+---+---+---+---+---+---+---+ -// Method | 0 | 1 | 2 | 3 |(4)| 5 | 6 | -//-------------------+---+---+---+---+---+---+---+ -// fast probe | x | | | x | | | | -//-------------------+---+---+---+---+---+---+---+ -// dynamic proba | ~ | x | x | x | x | x | x | -//-------------------+---+---+---+---+---+---+---+ -// fast mode analysis| | | | | x | x | x | -//-------------------+---+---+---+---+---+---+---+ -// basic rd-opt | | | | x | x | x | x | -//-------------------+---+---+---+---+---+---+---+ -// disto-refine i4/16| x | x | x | | | | | -//-------------------+---+---+---+---+---+---+---+ -// disto-refine uv | | x | x | | | | | -//-------------------+---+---+---+---+---+---+---+ -// rd-opt i4/16 | | | ~ | x | x | x | x | -//-------------------+---+---+---+---+---+---+---+ -// token buffer (opt)| | | | x | x | x | x | -//-------------------+---+---+---+---+---+---+---+ -// Trellis | | | | | | x |Ful| -//-------------------+---+---+---+---+---+---+---+ -// full-SNS | | | | | x | x | x | -//-------------------+---+---+---+---+---+---+---+ - -static void MapConfigToTools(VP8Encoder* const enc) { - const WebPConfig* const config = enc->config_; - const int method = config->method; - const int limit = 100 - config->partition_limit; - enc->method_ = method; - enc->rd_opt_level_ = (method >= 6) ? RD_OPT_TRELLIS_ALL - : (method >= 5) ? RD_OPT_TRELLIS - : (method >= 3) ? RD_OPT_BASIC - : RD_OPT_NONE; - enc->max_i4_header_bits_ = - 256 * 16 * 16 * // upper bound: up to 16bit per 4x4 block - (limit * limit) / (100 * 100); // ... modulated with a quadratic curve. - - enc->thread_level_ = config->thread_level; - - enc->do_search_ = (config->target_size > 0 || config->target_PSNR > 0); - if (!config->low_memory) { -#if !defined(DISABLE_TOKEN_BUFFER) - enc->use_tokens_ = (enc->rd_opt_level_ >= RD_OPT_BASIC); // need rd stats -#endif - if (enc->use_tokens_) { - enc->num_parts_ = 1; // doesn't work with multi-partition - } - } -} - -// Memory scaling with dimensions: -// memory (bytes) ~= 2.25 * w + 0.0625 * w * h -// -// Typical memory footprint (614x440 picture) -// encoder: 22111 -// info: 4368 -// preds: 17741 -// top samples: 1263 -// non-zero: 175 -// lf-stats: 0 -// total: 45658 -// Transient object sizes: -// VP8EncIterator: 3360 -// VP8ModeScore: 872 -// VP8SegmentInfo: 732 -// VP8EncProba: 18352 -// LFStats: 2048 -// Picture size (yuv): 419328 - -static VP8Encoder* InitVP8Encoder(const WebPConfig* const config, - WebPPicture* const picture) { - VP8Encoder* enc; - const int use_filter = - (config->filter_strength > 0) || (config->autofilter > 0); - const int mb_w = (picture->width + 15) >> 4; - const int mb_h = (picture->height + 15) >> 4; - const int preds_w = 4 * mb_w + 1; - const int preds_h = 4 * mb_h + 1; - const size_t preds_size = preds_w * preds_h * sizeof(*enc->preds_); - const int top_stride = mb_w * 16; - const size_t nz_size = (mb_w + 1) * sizeof(*enc->nz_) + WEBP_ALIGN_CST; - const size_t info_size = mb_w * mb_h * sizeof(*enc->mb_info_); - const size_t samples_size = - 2 * top_stride * sizeof(*enc->y_top_) // top-luma/u/v - + WEBP_ALIGN_CST; // align all - const size_t lf_stats_size = - config->autofilter ? sizeof(*enc->lf_stats_) + WEBP_ALIGN_CST : 0; - uint8_t* mem; - const uint64_t size = (uint64_t)sizeof(*enc) // main struct - + WEBP_ALIGN_CST // cache alignment - + info_size // modes info - + preds_size // prediction modes - + samples_size // top/left samples - + nz_size // coeff context bits - + lf_stats_size; // autofilter stats - -#ifdef PRINT_MEMORY_INFO - printf("===================================\n"); - printf("Memory used:\n" - " encoder: %ld\n" - " info: %ld\n" - " preds: %ld\n" - " top samples: %ld\n" - " non-zero: %ld\n" - " lf-stats: %ld\n" - " total: %ld\n", - sizeof(*enc) + WEBP_ALIGN_CST, info_size, - preds_size, samples_size, nz_size, lf_stats_size, size); - printf("Transient object sizes:\n" - " VP8EncIterator: %ld\n" - " VP8ModeScore: %ld\n" - " VP8SegmentInfo: %ld\n" - " VP8EncProba: %ld\n" - " LFStats: %ld\n", - sizeof(VP8EncIterator), sizeof(VP8ModeScore), - sizeof(VP8SegmentInfo), sizeof(VP8EncProba), - sizeof(LFStats)); - printf("Picture size (yuv): %ld\n", - mb_w * mb_h * 384 * sizeof(uint8_t)); - printf("===================================\n"); -#endif - mem = (uint8_t*)WebPSafeMalloc(size, sizeof(*mem)); - if (mem == NULL) { - WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); - return NULL; - } - enc = (VP8Encoder*)mem; - mem = (uint8_t*)WEBP_ALIGN(mem + sizeof(*enc)); - memset(enc, 0, sizeof(*enc)); - enc->num_parts_ = 1 << config->partitions; - enc->mb_w_ = mb_w; - enc->mb_h_ = mb_h; - enc->preds_w_ = preds_w; - enc->mb_info_ = (VP8MBInfo*)mem; - mem += info_size; - enc->preds_ = ((uint8_t*)mem) + 1 + enc->preds_w_; - mem += preds_size; - enc->nz_ = 1 + (uint32_t*)WEBP_ALIGN(mem); - mem += nz_size; - enc->lf_stats_ = lf_stats_size ? (LFStats*)WEBP_ALIGN(mem) : NULL; - mem += lf_stats_size; - - // top samples (all 16-aligned) - mem = (uint8_t*)WEBP_ALIGN(mem); - enc->y_top_ = (uint8_t*)mem; - enc->uv_top_ = enc->y_top_ + top_stride; - mem += 2 * top_stride; - assert(mem <= (uint8_t*)enc + size); - - enc->config_ = config; - enc->profile_ = use_filter ? ((config->filter_type == 1) ? 0 : 1) : 2; - enc->pic_ = picture; - enc->percent_ = 0; - - MapConfigToTools(enc); - VP8EncDspInit(); - VP8DefaultProbas(enc); - ResetSegmentHeader(enc); - ResetFilterHeader(enc); - ResetBoundaryPredictions(enc); - VP8EncDspCostInit(); - VP8EncInitAlpha(enc); - - // lower quality means smaller output -> we modulate a little the page - // size based on quality. This is just a crude 1rst-order prediction. - { - const float scale = 1.f + config->quality * 5.f / 100.f; // in [1,6] - VP8TBufferInit(&enc->tokens_, (int)(mb_w * mb_h * 4 * scale)); - } - return enc; -} - -static int DeleteVP8Encoder(VP8Encoder* enc) { - int ok = 1; - if (enc != NULL) { - ok = VP8EncDeleteAlpha(enc); - VP8TBufferClear(&enc->tokens_); - WebPSafeFree(enc); - } - return ok; -} - -//------------------------------------------------------------------------------ - -static double GetPSNR(uint64_t err, uint64_t size) { - return (err > 0 && size > 0) ? 10. * log10(255. * 255. * size / err) : 99.; -} - -static void FinalizePSNR(const VP8Encoder* const enc) { - WebPAuxStats* stats = enc->pic_->stats; - const uint64_t size = enc->sse_count_; - const uint64_t* const sse = enc->sse_; - stats->PSNR[0] = (float)GetPSNR(sse[0], size); - stats->PSNR[1] = (float)GetPSNR(sse[1], size / 4); - stats->PSNR[2] = (float)GetPSNR(sse[2], size / 4); - stats->PSNR[3] = (float)GetPSNR(sse[0] + sse[1] + sse[2], size * 3 / 2); - stats->PSNR[4] = (float)GetPSNR(sse[3], size); -} - -static void StoreStats(VP8Encoder* const enc) { - WebPAuxStats* const stats = enc->pic_->stats; - if (stats != NULL) { - int i, s; - for (i = 0; i < NUM_MB_SEGMENTS; ++i) { - stats->segment_level[i] = enc->dqm_[i].fstrength_; - stats->segment_quant[i] = enc->dqm_[i].quant_; - for (s = 0; s <= 2; ++s) { - stats->residual_bytes[s][i] = enc->residual_bytes_[s][i]; - } - } - FinalizePSNR(enc); - stats->coded_size = enc->coded_size_; - for (i = 0; i < 3; ++i) { - stats->block_count[i] = enc->block_count_[i]; - } - } - WebPReportProgress(enc->pic_, 100, &enc->percent_); // done! -} - -int WebPEncodingSetError(const WebPPicture* const pic, - WebPEncodingError error) { - assert((int)error < VP8_ENC_ERROR_LAST); - assert((int)error >= VP8_ENC_OK); - ((WebPPicture*)pic)->error_code = error; - return 0; -} - -int WebPReportProgress(const WebPPicture* const pic, - int percent, int* const percent_store) { - if (percent_store != NULL && percent != *percent_store) { - *percent_store = percent; - if (pic->progress_hook && !pic->progress_hook(percent, pic)) { - // user abort requested - WebPEncodingSetError(pic, VP8_ENC_ERROR_USER_ABORT); - return 0; - } - } - return 1; // ok -} -//------------------------------------------------------------------------------ - -int WebPEncode(const WebPConfig* config, WebPPicture* pic) { - int ok = 0; - - if (pic == NULL) - return 0; - WebPEncodingSetError(pic, VP8_ENC_OK); // all ok so far - if (config == NULL) // bad params - return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER); - if (!WebPValidateConfig(config)) - return WebPEncodingSetError(pic, VP8_ENC_ERROR_INVALID_CONFIGURATION); - if (pic->width <= 0 || pic->height <= 0) - return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION); - if (pic->width > WEBP_MAX_DIMENSION || pic->height > WEBP_MAX_DIMENSION) - return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION); - - if (pic->stats != NULL) memset(pic->stats, 0, sizeof(*pic->stats)); - - if (!config->lossless) { - VP8Encoder* enc = NULL; - - if (!config->exact) { - WebPCleanupTransparentArea(pic); - } - - if (pic->use_argb || pic->y == NULL || pic->u == NULL || pic->v == NULL) { - // Make sure we have YUVA samples. - if (config->preprocessing & 4) { - if (!WebPPictureSmartARGBToYUVA(pic)) { - return 0; - } - } else { - float dithering = 0.f; - if (config->preprocessing & 2) { - const float x = config->quality / 100.f; - const float x2 = x * x; - // slowly decreasing from max dithering at low quality (q->0) - // to 0.5 dithering amplitude at high quality (q->100) - dithering = 1.0f + (0.5f - 1.0f) * x2 * x2; - } - if (!WebPPictureARGBToYUVADithered(pic, WEBP_YUV420, dithering)) { - return 0; - } - } - } - - enc = InitVP8Encoder(config, pic); - if (enc == NULL) return 0; // pic->error is already set. - // Note: each of the tasks below account for 20% in the progress report. - ok = VP8EncAnalyze(enc); - - // Analysis is done, proceed to actual coding. - ok = ok && VP8EncStartAlpha(enc); // possibly done in parallel - if (!enc->use_tokens_) { - ok = ok && VP8EncLoop(enc); - } else { - ok = ok && VP8EncTokenLoop(enc); - } - ok = ok && VP8EncFinishAlpha(enc); - - ok = ok && VP8EncWrite(enc); - StoreStats(enc); - if (!ok) { - VP8EncFreeBitWriters(enc); - } - ok &= DeleteVP8Encoder(enc); // must always be called, even if !ok - } else { - // Make sure we have ARGB samples. - if (pic->argb == NULL && !WebPPictureYUVAToARGB(pic)) { - return 0; - } - - if (!config->exact) { - WebPCleanupTransparentAreaLossless(pic); - } - - ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem. - } - - return ok; -} diff --git a/Example/Pods/libwebp/src/mux/anim_encode.c b/Example/Pods/libwebp/src/mux/anim_encode.c deleted file mode 100644 index fa86eaac..00000000 --- a/Example/Pods/libwebp/src/mux/anim_encode.c +++ /dev/null @@ -1,1404 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// AnimEncoder implementation. -// - -#include -#include -#include - -#include "../utils/utils.h" -#include "../webp/decode.h" -#include "../webp/encode.h" -#include "../webp/format_constants.h" -#include "../webp/mux.h" - -#if defined(_MSC_VER) && _MSC_VER < 1900 -#define snprintf _snprintf -#endif - -#define ERROR_STR_MAX_LENGTH 100 - -//------------------------------------------------------------------------------ -// Internal structs. - -// Stores frame rectangle dimensions. -typedef struct { - int x_offset_, y_offset_, width_, height_; -} FrameRect; - -// Used to store two candidates of encoded data for an animation frame. One of -// the two will be chosen later. -typedef struct { - WebPMuxFrameInfo sub_frame_; // Encoded frame rectangle. - WebPMuxFrameInfo key_frame_; // Encoded frame if it is a key-frame. - int is_key_frame_; // True if 'key_frame' has been chosen. -} EncodedFrame; - -struct WebPAnimEncoder { - const int canvas_width_; // Canvas width. - const int canvas_height_; // Canvas height. - const WebPAnimEncoderOptions options_; // Global encoding options. - - FrameRect prev_rect_; // Previous WebP frame rectangle. - WebPConfig last_config_; // Cached in case a re-encode is needed. - WebPConfig last_config2_; // 2nd cached config; only valid if - // 'options_.allow_mixed' is true. - - WebPPicture* curr_canvas_; // Only pointer; we don't own memory. - - // Canvas buffers. - WebPPicture curr_canvas_copy_; // Possibly modified current canvas. - int curr_canvas_copy_modified_; // True if pixels in 'curr_canvas_copy_' - // differ from those in 'curr_canvas_'. - - WebPPicture prev_canvas_; // Previous canvas. - WebPPicture prev_canvas_disposed_; // Previous canvas disposed to background. - - // Encoded data. - EncodedFrame* encoded_frames_; // Array of encoded frames. - size_t size_; // Number of allocated frames. - size_t start_; // Frame start index. - size_t count_; // Number of valid frames. - size_t flush_count_; // If >0, 'flush_count' frames starting from - // 'start' are ready to be added to mux. - - // key-frame related. - int64_t best_delta_; // min(canvas size - frame size) over the frames. - // Can be negative in certain cases due to - // transparent pixels in a frame. - int keyframe_; // Index of selected key-frame relative to 'start_'. - int count_since_key_frame_; // Frames seen since the last key-frame. - - int first_timestamp_; // Timestamp of the first frame. - int prev_timestamp_; // Timestamp of the last added frame. - int prev_candidate_undecided_; // True if it's not yet decided if previous - // frame would be a sub-frame or a key-frame. - - // Misc. - int is_first_frame_; // True if first frame is yet to be added/being added. - int got_null_frame_; // True if WebPAnimEncoderAdd() has already been called - // with a NULL frame. - - size_t in_frame_count_; // Number of input frames processed so far. - size_t out_frame_count_; // Number of frames added to mux so far. This may be - // different from 'in_frame_count_' due to merging. - - WebPMux* mux_; // Muxer to assemble the WebP bitstream. - char error_str_[ERROR_STR_MAX_LENGTH]; // Error string. Empty if no error. -}; - -// ----------------------------------------------------------------------------- -// Life of WebPAnimEncoder object. - -#define DELTA_INFINITY (1ULL << 32) -#define KEYFRAME_NONE (-1) - -// Reset the counters in the WebPAnimEncoder. -static void ResetCounters(WebPAnimEncoder* const enc) { - enc->start_ = 0; - enc->count_ = 0; - enc->flush_count_ = 0; - enc->best_delta_ = DELTA_INFINITY; - enc->keyframe_ = KEYFRAME_NONE; -} - -static void DisableKeyframes(WebPAnimEncoderOptions* const enc_options) { - enc_options->kmax = INT_MAX; - enc_options->kmin = enc_options->kmax - 1; -} - -#define MAX_CACHED_FRAMES 30 - -static void SanitizeEncoderOptions(WebPAnimEncoderOptions* const enc_options) { - int print_warning = enc_options->verbose; - - if (enc_options->minimize_size) { - DisableKeyframes(enc_options); - } - - if (enc_options->kmin <= 0) { - DisableKeyframes(enc_options); - print_warning = 0; - } - if (enc_options->kmax <= 0) { // All frames will be key-frames. - enc_options->kmin = 0; - enc_options->kmax = 0; - return; - } - - if (enc_options->kmin >= enc_options->kmax) { - enc_options->kmin = enc_options->kmax - 1; - if (print_warning) { - fprintf(stderr, "WARNING: Setting kmin = %d, so that kmin < kmax.\n", - enc_options->kmin); - } - } else { - const int kmin_limit = enc_options->kmax / 2 + 1; - if (enc_options->kmin < kmin_limit && kmin_limit < enc_options->kmax) { - // This ensures that enc.keyframe + kmin >= kmax is always true. So, we - // can flush all the frames in the 'count_since_key_frame == kmax' case. - enc_options->kmin = kmin_limit; - if (print_warning) { - fprintf(stderr, - "WARNING: Setting kmin = %d, so that kmin >= kmax / 2 + 1.\n", - enc_options->kmin); - } - } - } - // Limit the max number of frames that are allocated. - if (enc_options->kmax - enc_options->kmin > MAX_CACHED_FRAMES) { - enc_options->kmin = enc_options->kmax - MAX_CACHED_FRAMES; - if (print_warning) { - fprintf(stderr, - "WARNING: Setting kmin = %d, so that kmax - kmin <= %d.\n", - enc_options->kmin, MAX_CACHED_FRAMES); - } - } - assert(enc_options->kmin < enc_options->kmax); -} - -#undef MAX_CACHED_FRAMES - -static void DefaultEncoderOptions(WebPAnimEncoderOptions* const enc_options) { - enc_options->anim_params.loop_count = 0; - enc_options->anim_params.bgcolor = 0xffffffff; // White. - enc_options->minimize_size = 0; - DisableKeyframes(enc_options); - enc_options->allow_mixed = 0; -} - -int WebPAnimEncoderOptionsInitInternal(WebPAnimEncoderOptions* enc_options, - int abi_version) { - if (enc_options == NULL || - WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_MUX_ABI_VERSION)) { - return 0; - } - DefaultEncoderOptions(enc_options); - return 1; -} - -#define TRANSPARENT_COLOR 0x00ffffff - -static void ClearRectangle(WebPPicture* const picture, - int left, int top, int width, int height) { - int j; - for (j = top; j < top + height; ++j) { - uint32_t* const dst = picture->argb + j * picture->argb_stride; - int i; - for (i = left; i < left + width; ++i) { - dst[i] = TRANSPARENT_COLOR; - } - } -} - -static void WebPUtilClearPic(WebPPicture* const picture, - const FrameRect* const rect) { - if (rect != NULL) { - ClearRectangle(picture, rect->x_offset_, rect->y_offset_, - rect->width_, rect->height_); - } else { - ClearRectangle(picture, 0, 0, picture->width, picture->height); - } -} - -static void MarkNoError(WebPAnimEncoder* const enc) { - enc->error_str_[0] = '\0'; // Empty string. -} - -static void MarkError(WebPAnimEncoder* const enc, const char* str) { - if (snprintf(enc->error_str_, ERROR_STR_MAX_LENGTH, "%s.", str) < 0) { - assert(0); // FIX ME! - } -} - -static void MarkError2(WebPAnimEncoder* const enc, - const char* str, int error_code) { - if (snprintf(enc->error_str_, ERROR_STR_MAX_LENGTH, "%s: %d.", str, - error_code) < 0) { - assert(0); // FIX ME! - } -} - -WebPAnimEncoder* WebPAnimEncoderNewInternal( - int width, int height, const WebPAnimEncoderOptions* enc_options, - int abi_version) { - WebPAnimEncoder* enc; - - if (WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_MUX_ABI_VERSION)) { - return NULL; - } - if (width <= 0 || height <= 0 || - (width * (uint64_t)height) >= MAX_IMAGE_AREA) { - return NULL; - } - - enc = (WebPAnimEncoder*)WebPSafeCalloc(1, sizeof(*enc)); - if (enc == NULL) return NULL; - // sanity inits, so we can call WebPAnimEncoderDelete(): - enc->encoded_frames_ = NULL; - enc->mux_ = NULL; - MarkNoError(enc); - - // Dimensions and options. - *(int*)&enc->canvas_width_ = width; - *(int*)&enc->canvas_height_ = height; - if (enc_options != NULL) { - *(WebPAnimEncoderOptions*)&enc->options_ = *enc_options; - SanitizeEncoderOptions((WebPAnimEncoderOptions*)&enc->options_); - } else { - DefaultEncoderOptions((WebPAnimEncoderOptions*)&enc->options_); - } - - // Canvas buffers. - if (!WebPPictureInit(&enc->curr_canvas_copy_) || - !WebPPictureInit(&enc->prev_canvas_) || - !WebPPictureInit(&enc->prev_canvas_disposed_)) { - goto Err; - } - enc->curr_canvas_copy_.width = width; - enc->curr_canvas_copy_.height = height; - enc->curr_canvas_copy_.use_argb = 1; - if (!WebPPictureAlloc(&enc->curr_canvas_copy_) || - !WebPPictureCopy(&enc->curr_canvas_copy_, &enc->prev_canvas_) || - !WebPPictureCopy(&enc->curr_canvas_copy_, &enc->prev_canvas_disposed_)) { - goto Err; - } - WebPUtilClearPic(&enc->prev_canvas_, NULL); - enc->curr_canvas_copy_modified_ = 1; - - // Encoded frames. - ResetCounters(enc); - // Note: one extra storage is for the previous frame. - enc->size_ = enc->options_.kmax - enc->options_.kmin + 1; - // We need space for at least 2 frames. But when kmin, kmax are both zero, - // enc->size_ will be 1. So we handle that special case below. - if (enc->size_ < 2) enc->size_ = 2; - enc->encoded_frames_ = - (EncodedFrame*)WebPSafeCalloc(enc->size_, sizeof(*enc->encoded_frames_)); - if (enc->encoded_frames_ == NULL) goto Err; - - enc->mux_ = WebPMuxNew(); - if (enc->mux_ == NULL) goto Err; - - enc->count_since_key_frame_ = 0; - enc->first_timestamp_ = 0; - enc->prev_timestamp_ = 0; - enc->prev_candidate_undecided_ = 0; - enc->is_first_frame_ = 1; - enc->got_null_frame_ = 0; - - return enc; // All OK. - - Err: - WebPAnimEncoderDelete(enc); - return NULL; -} - -// Release the data contained by 'encoded_frame'. -static void FrameRelease(EncodedFrame* const encoded_frame) { - if (encoded_frame != NULL) { - WebPDataClear(&encoded_frame->sub_frame_.bitstream); - WebPDataClear(&encoded_frame->key_frame_.bitstream); - memset(encoded_frame, 0, sizeof(*encoded_frame)); - } -} - -void WebPAnimEncoderDelete(WebPAnimEncoder* enc) { - if (enc != NULL) { - WebPPictureFree(&enc->curr_canvas_copy_); - WebPPictureFree(&enc->prev_canvas_); - WebPPictureFree(&enc->prev_canvas_disposed_); - if (enc->encoded_frames_ != NULL) { - size_t i; - for (i = 0; i < enc->size_; ++i) { - FrameRelease(&enc->encoded_frames_[i]); - } - WebPSafeFree(enc->encoded_frames_); - } - WebPMuxDelete(enc->mux_); - WebPSafeFree(enc); - } -} - -// ----------------------------------------------------------------------------- -// Frame addition. - -// Returns cached frame at the given 'position'. -static EncodedFrame* GetFrame(const WebPAnimEncoder* const enc, - size_t position) { - assert(enc->start_ + position < enc->size_); - return &enc->encoded_frames_[enc->start_ + position]; -} - -// Returns true if 'length' number of pixels in 'src' and 'dst' are identical, -// assuming the given step sizes between pixels. -static WEBP_INLINE int ComparePixels(const uint32_t* src, int src_step, - const uint32_t* dst, int dst_step, - int length) { - assert(length > 0); - while (length-- > 0) { - if (*src != *dst) { - return 0; - } - src += src_step; - dst += dst_step; - } - return 1; -} - -static int IsEmptyRect(const FrameRect* const rect) { - return (rect->width_ == 0) || (rect->height_ == 0); -} - -// Assumes that an initial valid guess of change rectangle 'rect' is passed. -static void MinimizeChangeRectangle(const WebPPicture* const src, - const WebPPicture* const dst, - FrameRect* const rect) { - int i, j; - // Sanity checks. - assert(src->width == dst->width && src->height == dst->height); - assert(rect->x_offset_ + rect->width_ <= dst->width); - assert(rect->y_offset_ + rect->height_ <= dst->height); - - // Left boundary. - for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) { - const uint32_t* const src_argb = - &src->argb[rect->y_offset_ * src->argb_stride + i]; - const uint32_t* const dst_argb = - &dst->argb[rect->y_offset_ * dst->argb_stride + i]; - if (ComparePixels(src_argb, src->argb_stride, dst_argb, dst->argb_stride, - rect->height_)) { - --rect->width_; // Redundant column. - ++rect->x_offset_; - } else { - break; - } - } - if (rect->width_ == 0) goto NoChange; - - // Right boundary. - for (i = rect->x_offset_ + rect->width_ - 1; i >= rect->x_offset_; --i) { - const uint32_t* const src_argb = - &src->argb[rect->y_offset_ * src->argb_stride + i]; - const uint32_t* const dst_argb = - &dst->argb[rect->y_offset_ * dst->argb_stride + i]; - if (ComparePixels(src_argb, src->argb_stride, dst_argb, dst->argb_stride, - rect->height_)) { - --rect->width_; // Redundant column. - } else { - break; - } - } - if (rect->width_ == 0) goto NoChange; - - // Top boundary. - for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) { - const uint32_t* const src_argb = - &src->argb[j * src->argb_stride + rect->x_offset_]; - const uint32_t* const dst_argb = - &dst->argb[j * dst->argb_stride + rect->x_offset_]; - if (ComparePixels(src_argb, 1, dst_argb, 1, rect->width_)) { - --rect->height_; // Redundant row. - ++rect->y_offset_; - } else { - break; - } - } - if (rect->height_ == 0) goto NoChange; - - // Bottom boundary. - for (j = rect->y_offset_ + rect->height_ - 1; j >= rect->y_offset_; --j) { - const uint32_t* const src_argb = - &src->argb[j * src->argb_stride + rect->x_offset_]; - const uint32_t* const dst_argb = - &dst->argb[j * dst->argb_stride + rect->x_offset_]; - if (ComparePixels(src_argb, 1, dst_argb, 1, rect->width_)) { - --rect->height_; // Redundant row. - } else { - break; - } - } - if (rect->height_ == 0) goto NoChange; - - if (IsEmptyRect(rect)) { - NoChange: - rect->x_offset_ = 0; - rect->y_offset_ = 0; - rect->width_ = 0; - rect->height_ = 0; - } -} - -// Snap rectangle to even offsets (and adjust dimensions if needed). -static WEBP_INLINE void SnapToEvenOffsets(FrameRect* const rect) { - rect->width_ += (rect->x_offset_ & 1); - rect->height_ += (rect->y_offset_ & 1); - rect->x_offset_ &= ~1; - rect->y_offset_ &= ~1; -} - -// Given previous and current canvas, picks the optimal rectangle for the -// current frame. The initial guess for 'rect' will be the full canvas. -static int GetSubRect(const WebPPicture* const prev_canvas, - const WebPPicture* const curr_canvas, int is_key_frame, - int is_first_frame, int empty_rect_allowed, - FrameRect* const rect, WebPPicture* const sub_frame) { - rect->x_offset_ = 0; - rect->y_offset_ = 0; - rect->width_ = curr_canvas->width; - rect->height_ = curr_canvas->height; - if (!is_key_frame || is_first_frame) { // Optimize frame rectangle. - // Note: This behaves as expected for first frame, as 'prev_canvas' is - // initialized to a fully transparent canvas in the beginning. - MinimizeChangeRectangle(prev_canvas, curr_canvas, rect); - } - - if (IsEmptyRect(rect)) { - if (empty_rect_allowed) { // No need to get 'sub_frame'. - return 1; - } else { // Force a 1x1 rectangle. - rect->width_ = 1; - rect->height_ = 1; - assert(rect->x_offset_ == 0); - assert(rect->y_offset_ == 0); - } - } - - SnapToEvenOffsets(rect); - return WebPPictureView(curr_canvas, rect->x_offset_, rect->y_offset_, - rect->width_, rect->height_, sub_frame); -} - -static void DisposeFrameRectangle(int dispose_method, - const FrameRect* const rect, - WebPPicture* const curr_canvas) { - assert(rect != NULL); - if (dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { - WebPUtilClearPic(curr_canvas, rect); - } -} - -static uint32_t RectArea(const FrameRect* const rect) { - return (uint32_t)rect->width_ * rect->height_; -} - -static int IsBlendingPossible(const WebPPicture* const src, - const WebPPicture* const dst, - const FrameRect* const rect) { - int i, j; - assert(src->width == dst->width && src->height == dst->height); - assert(rect->x_offset_ + rect->width_ <= dst->width); - assert(rect->y_offset_ + rect->height_ <= dst->height); - for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) { - for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) { - const uint32_t src_pixel = src->argb[j * src->argb_stride + i]; - const uint32_t dst_pixel = dst->argb[j * dst->argb_stride + i]; - const uint32_t dst_alpha = dst_pixel >> 24; - if (dst_alpha != 0xff && src_pixel != dst_pixel) { - // In this case, if we use blending, we can't attain the desired - // 'dst_pixel' value for this pixel. So, blending is not possible. - return 0; - } - } - } - return 1; -} - -#define MIN_COLORS_LOSSY 31 // Don't try lossy below this threshold. -#define MAX_COLORS_LOSSLESS 194 // Don't try lossless above this threshold. -#define MAX_COLOR_COUNT 256 // Power of 2 greater than MAX_COLORS_LOSSLESS. -#define HASH_SIZE (MAX_COLOR_COUNT * 4) -#define HASH_RIGHT_SHIFT 22 // 32 - log2(HASH_SIZE). - -// TODO(urvang): Also used in enc/vp8l.c. Move to utils. -// If the number of colors in the 'pic' is at least MAX_COLOR_COUNT, return -// MAX_COLOR_COUNT. Otherwise, return the exact number of colors in the 'pic'. -static int GetColorCount(const WebPPicture* const pic) { - int x, y; - int num_colors = 0; - uint8_t in_use[HASH_SIZE] = { 0 }; - uint32_t colors[HASH_SIZE]; - static const uint32_t kHashMul = 0x1e35a7bd; - const uint32_t* argb = pic->argb; - const int width = pic->width; - const int height = pic->height; - uint32_t last_pix = ~argb[0]; // so we're sure that last_pix != argb[0] - - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - int key; - if (argb[x] == last_pix) { - continue; - } - last_pix = argb[x]; - key = (kHashMul * last_pix) >> HASH_RIGHT_SHIFT; - while (1) { - if (!in_use[key]) { - colors[key] = last_pix; - in_use[key] = 1; - ++num_colors; - if (num_colors >= MAX_COLOR_COUNT) { - return MAX_COLOR_COUNT; // Exact count not needed. - } - break; - } else if (colors[key] == last_pix) { - break; // The color is already there. - } else { - // Some other color sits here, so do linear conflict resolution. - ++key; - key &= (HASH_SIZE - 1); // Key mask. - } - } - } - argb += pic->argb_stride; - } - return num_colors; -} - -#undef MAX_COLOR_COUNT -#undef HASH_SIZE -#undef HASH_RIGHT_SHIFT - -// For pixels in 'rect', replace those pixels in 'dst' that are same as 'src' by -// transparent pixels. -static void IncreaseTransparency(const WebPPicture* const src, - const FrameRect* const rect, - WebPPicture* const dst) { - int i, j; - assert(src != NULL && dst != NULL && rect != NULL); - assert(src->width == dst->width && src->height == dst->height); - for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) { - const uint32_t* const psrc = src->argb + j * src->argb_stride; - uint32_t* const pdst = dst->argb + j * dst->argb_stride; - for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) { - if (psrc[i] == pdst[i]) { - pdst[i] = TRANSPARENT_COLOR; - } - } - } -} - -#undef TRANSPARENT_COLOR - -// Replace similar blocks of pixels by a 'see-through' transparent block -// with uniform average color. -static void FlattenSimilarBlocks(const WebPPicture* const src, - const FrameRect* const rect, - WebPPicture* const dst) { - int i, j; - const int block_size = 8; - const int y_start = (rect->y_offset_ + block_size) & ~(block_size - 1); - const int y_end = (rect->y_offset_ + rect->height_) & ~(block_size - 1); - const int x_start = (rect->x_offset_ + block_size) & ~(block_size - 1); - const int x_end = (rect->x_offset_ + rect->width_) & ~(block_size - 1); - assert(src != NULL && dst != NULL && rect != NULL); - assert(src->width == dst->width && src->height == dst->height); - assert((block_size & (block_size - 1)) == 0); // must be a power of 2 - // Iterate over each block and count similar pixels. - for (j = y_start; j < y_end; j += block_size) { - for (i = x_start; i < x_end; i += block_size) { - int cnt = 0; - int avg_r = 0, avg_g = 0, avg_b = 0; - int x, y; - const uint32_t* const psrc = src->argb + j * src->argb_stride + i; - uint32_t* const pdst = dst->argb + j * dst->argb_stride + i; - for (y = 0; y < block_size; ++y) { - for (x = 0; x < block_size; ++x) { - const uint32_t src_pixel = psrc[x + y * src->argb_stride]; - const int alpha = src_pixel >> 24; - if (alpha == 0xff && - src_pixel == pdst[x + y * dst->argb_stride]) { - ++cnt; - avg_r += (src_pixel >> 16) & 0xff; - avg_g += (src_pixel >> 8) & 0xff; - avg_b += (src_pixel >> 0) & 0xff; - } - } - } - // If we have a fully similar block, we replace it with an - // average transparent block. This compresses better in lossy mode. - if (cnt == block_size * block_size) { - const uint32_t color = (0x00 << 24) | - ((avg_r / cnt) << 16) | - ((avg_g / cnt) << 8) | - ((avg_b / cnt) << 0); - for (y = 0; y < block_size; ++y) { - for (x = 0; x < block_size; ++x) { - pdst[x + y * dst->argb_stride] = color; - } - } - } - } - } -} - -static int EncodeFrame(const WebPConfig* const config, WebPPicture* const pic, - WebPMemoryWriter* const memory) { - pic->use_argb = 1; - pic->writer = WebPMemoryWrite; - pic->custom_ptr = memory; - if (!WebPEncode(config, pic)) { - return 0; - } - return 1; -} - -// Struct representing a candidate encoded frame including its metadata. -typedef struct { - WebPMemoryWriter mem_; - WebPMuxFrameInfo info_; - FrameRect rect_; - int evaluate_; // True if this candidate should be evaluated. -} Candidate; - -// Generates a candidate encoded frame given a picture and metadata. -static WebPEncodingError EncodeCandidate(WebPPicture* const sub_frame, - const FrameRect* const rect, - const WebPConfig* const config, - int use_blending, - Candidate* const candidate) { - WebPEncodingError error_code = VP8_ENC_OK; - assert(candidate != NULL); - memset(candidate, 0, sizeof(*candidate)); - - // Set frame rect and info. - candidate->rect_ = *rect; - candidate->info_.id = WEBP_CHUNK_ANMF; - candidate->info_.x_offset = rect->x_offset_; - candidate->info_.y_offset = rect->y_offset_; - candidate->info_.dispose_method = WEBP_MUX_DISPOSE_NONE; // Set later. - candidate->info_.blend_method = - use_blending ? WEBP_MUX_BLEND : WEBP_MUX_NO_BLEND; - candidate->info_.duration = 0; // Set in next call to WebPAnimEncoderAdd(). - - // Encode picture. - WebPMemoryWriterInit(&candidate->mem_); - - if (!EncodeFrame(config, sub_frame, &candidate->mem_)) { - error_code = sub_frame->error_code; - goto Err; - } - - candidate->evaluate_ = 1; - return error_code; - - Err: - WebPMemoryWriterClear(&candidate->mem_); - return error_code; -} - -static void CopyCurrentCanvas(WebPAnimEncoder* const enc) { - if (enc->curr_canvas_copy_modified_) { - WebPCopyPixels(enc->curr_canvas_, &enc->curr_canvas_copy_); - enc->curr_canvas_copy_modified_ = 0; - } -} - -enum { - LL_DISP_NONE = 0, - LL_DISP_BG, - LOSSY_DISP_NONE, - LOSSY_DISP_BG, - CANDIDATE_COUNT -}; - -// Generates candidates for a given dispose method given pre-filled 'rect' -// and 'sub_frame'. -static WebPEncodingError GenerateCandidates( - WebPAnimEncoder* const enc, Candidate candidates[CANDIDATE_COUNT], - WebPMuxAnimDispose dispose_method, int is_lossless, int is_key_frame, - const FrameRect* const rect, WebPPicture* sub_frame, - const WebPConfig* const config_ll, const WebPConfig* const config_lossy) { - WebPEncodingError error_code = VP8_ENC_OK; - const int is_dispose_none = (dispose_method == WEBP_MUX_DISPOSE_NONE); - Candidate* const candidate_ll = - is_dispose_none ? &candidates[LL_DISP_NONE] : &candidates[LL_DISP_BG]; - Candidate* const candidate_lossy = is_dispose_none - ? &candidates[LOSSY_DISP_NONE] - : &candidates[LOSSY_DISP_BG]; - WebPPicture* const curr_canvas = &enc->curr_canvas_copy_; - const WebPPicture* const prev_canvas = - is_dispose_none ? &enc->prev_canvas_ : &enc->prev_canvas_disposed_; - const int use_blending = - !is_key_frame && - IsBlendingPossible(prev_canvas, curr_canvas, rect); - - // Pick candidates to be tried. - if (!enc->options_.allow_mixed) { - candidate_ll->evaluate_ = is_lossless; - candidate_lossy->evaluate_ = !is_lossless; - } else { // Use a heuristic for trying lossless and/or lossy compression. - const int num_colors = GetColorCount(sub_frame); - candidate_ll->evaluate_ = (num_colors < MAX_COLORS_LOSSLESS); - candidate_lossy->evaluate_ = (num_colors >= MIN_COLORS_LOSSY); - } - - // Generate candidates. - if (candidate_ll->evaluate_) { - CopyCurrentCanvas(enc); - if (use_blending) { - IncreaseTransparency(prev_canvas, rect, curr_canvas); - enc->curr_canvas_copy_modified_ = 1; - } - error_code = EncodeCandidate(sub_frame, rect, config_ll, use_blending, - candidate_ll); - if (error_code != VP8_ENC_OK) return error_code; - } - if (candidate_lossy->evaluate_) { - CopyCurrentCanvas(enc); - if (use_blending) { - FlattenSimilarBlocks(prev_canvas, rect, curr_canvas); - enc->curr_canvas_copy_modified_ = 1; - } - error_code = EncodeCandidate(sub_frame, rect, config_lossy, use_blending, - candidate_lossy); - if (error_code != VP8_ENC_OK) return error_code; - } - return error_code; -} - -#undef MIN_COLORS_LOSSY -#undef MAX_COLORS_LOSSLESS - -static void GetEncodedData(const WebPMemoryWriter* const memory, - WebPData* const encoded_data) { - encoded_data->bytes = memory->mem; - encoded_data->size = memory->size; -} - -// Sets dispose method of the previous frame to be 'dispose_method'. -static void SetPreviousDisposeMethod(WebPAnimEncoder* const enc, - WebPMuxAnimDispose dispose_method) { - const size_t position = enc->count_ - 2; - EncodedFrame* const prev_enc_frame = GetFrame(enc, position); - assert(enc->count_ >= 2); // As current and previous frames are in enc. - - if (enc->prev_candidate_undecided_) { - assert(dispose_method == WEBP_MUX_DISPOSE_NONE); - prev_enc_frame->sub_frame_.dispose_method = dispose_method; - prev_enc_frame->key_frame_.dispose_method = dispose_method; - } else { - WebPMuxFrameInfo* const prev_info = prev_enc_frame->is_key_frame_ - ? &prev_enc_frame->key_frame_ - : &prev_enc_frame->sub_frame_; - prev_info->dispose_method = dispose_method; - } -} - -static int IncreasePreviousDuration(WebPAnimEncoder* const enc, int duration) { - const size_t position = enc->count_ - 1; - EncodedFrame* const prev_enc_frame = GetFrame(enc, position); - int new_duration; - - assert(enc->count_ >= 1); - assert(prev_enc_frame->sub_frame_.duration == - prev_enc_frame->key_frame_.duration); - assert(prev_enc_frame->sub_frame_.duration == - (prev_enc_frame->sub_frame_.duration & (MAX_DURATION - 1))); - assert(duration == (duration & (MAX_DURATION - 1))); - - new_duration = prev_enc_frame->sub_frame_.duration + duration; - if (new_duration >= MAX_DURATION) { // Special case. - // Separate out previous frame from earlier merged frames to avoid overflow. - // We add a 1x1 transparent frame for the previous frame, with blending on. - const FrameRect rect = { 0, 0, 1, 1 }; - const uint8_t lossless_1x1_bytes[] = { - 0x52, 0x49, 0x46, 0x46, 0x14, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, - 0x56, 0x50, 0x38, 0x4c, 0x08, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, - 0x10, 0x88, 0x88, 0x08 - }; - const WebPData lossless_1x1 = { - lossless_1x1_bytes, sizeof(lossless_1x1_bytes) - }; - const uint8_t lossy_1x1_bytes[] = { - 0x52, 0x49, 0x46, 0x46, 0x40, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, - 0x56, 0x50, 0x38, 0x58, 0x0a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x4c, 0x50, 0x48, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x56, 0x50, 0x38, 0x20, 0x18, 0x00, 0x00, 0x00, - 0x30, 0x01, 0x00, 0x9d, 0x01, 0x2a, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, - 0x34, 0x25, 0xa4, 0x00, 0x03, 0x70, 0x00, 0xfe, 0xfb, 0xfd, 0x50, 0x00 - }; - const WebPData lossy_1x1 = { lossy_1x1_bytes, sizeof(lossy_1x1_bytes) }; - const int can_use_lossless = - (enc->last_config_.lossless || enc->options_.allow_mixed); - EncodedFrame* const curr_enc_frame = GetFrame(enc, enc->count_); - curr_enc_frame->is_key_frame_ = 0; - curr_enc_frame->sub_frame_.id = WEBP_CHUNK_ANMF; - curr_enc_frame->sub_frame_.x_offset = 0; - curr_enc_frame->sub_frame_.y_offset = 0; - curr_enc_frame->sub_frame_.dispose_method = WEBP_MUX_DISPOSE_NONE; - curr_enc_frame->sub_frame_.blend_method = WEBP_MUX_BLEND; - curr_enc_frame->sub_frame_.duration = duration; - if (!WebPDataCopy(can_use_lossless ? &lossless_1x1 : &lossy_1x1, - &curr_enc_frame->sub_frame_.bitstream)) { - return 0; - } - ++enc->count_; - ++enc->count_since_key_frame_; - enc->flush_count_ = enc->count_ - 1; - enc->prev_candidate_undecided_ = 0; - enc->prev_rect_ = rect; - } else { // Regular case. - // Increase duration of the previous frame by 'duration'. - prev_enc_frame->sub_frame_.duration = new_duration; - prev_enc_frame->key_frame_.duration = new_duration; - } - return 1; -} - -// Pick the candidate encoded frame with smallest size and release other -// candidates. -// TODO(later): Perhaps a rough SSIM/PSNR produced by the encoder should -// also be a criteria, in addition to sizes. -static void PickBestCandidate(WebPAnimEncoder* const enc, - Candidate* const candidates, int is_key_frame, - EncodedFrame* const encoded_frame) { - int i; - int best_idx = -1; - size_t best_size = ~0; - for (i = 0; i < CANDIDATE_COUNT; ++i) { - if (candidates[i].evaluate_) { - const size_t candidate_size = candidates[i].mem_.size; - if (candidate_size < best_size) { - best_idx = i; - best_size = candidate_size; - } - } - } - assert(best_idx != -1); - for (i = 0; i < CANDIDATE_COUNT; ++i) { - if (candidates[i].evaluate_) { - if (i == best_idx) { - WebPMuxFrameInfo* const dst = is_key_frame - ? &encoded_frame->key_frame_ - : &encoded_frame->sub_frame_; - *dst = candidates[i].info_; - GetEncodedData(&candidates[i].mem_, &dst->bitstream); - if (!is_key_frame) { - // Note: Previous dispose method only matters for non-keyframes. - // Also, we don't want to modify previous dispose method that was - // selected when a non key-frame was assumed. - const WebPMuxAnimDispose prev_dispose_method = - (best_idx == LL_DISP_NONE || best_idx == LOSSY_DISP_NONE) - ? WEBP_MUX_DISPOSE_NONE - : WEBP_MUX_DISPOSE_BACKGROUND; - SetPreviousDisposeMethod(enc, prev_dispose_method); - } - enc->prev_rect_ = candidates[i].rect_; // save for next frame. - } else { - WebPMemoryWriterClear(&candidates[i].mem_); - candidates[i].evaluate_ = 0; - } - } - } -} - -// Depending on the configuration, tries different compressions -// (lossy/lossless), dispose methods, blending methods etc to encode the current -// frame and outputs the best one in 'encoded_frame'. -// 'frame_skipped' will be set to true if this frame should actually be skipped. -static WebPEncodingError SetFrame(WebPAnimEncoder* const enc, - const WebPConfig* const config, - int is_key_frame, - EncodedFrame* const encoded_frame, - int* const frame_skipped) { - int i; - WebPEncodingError error_code = VP8_ENC_OK; - const WebPPicture* const curr_canvas = &enc->curr_canvas_copy_; - const WebPPicture* const prev_canvas = &enc->prev_canvas_; - Candidate candidates[CANDIDATE_COUNT]; - const int is_lossless = config->lossless; - const int is_first_frame = enc->is_first_frame_; - - int try_dispose_none = 1; // Default. - FrameRect rect_none; - WebPPicture sub_frame_none; - // First frame cannot be skipped as there is no 'previous frame' to merge it - // to. So, empty rectangle is not allowed for the first frame. - const int empty_rect_allowed_none = !is_first_frame; - - // If current frame is a key-frame, dispose method of previous frame doesn't - // matter, so we don't try dispose to background. - // Also, if key-frame insertion is on, and previous frame could be picked as - // either a sub-frame or a key-frame, then we can't be sure about what frame - // rectangle would be disposed. In that case too, we don't try dispose to - // background. - const int dispose_bg_possible = - !is_key_frame && !enc->prev_candidate_undecided_; - int try_dispose_bg = 0; // Default. - FrameRect rect_bg; - WebPPicture sub_frame_bg; - - WebPConfig config_ll = *config; - WebPConfig config_lossy = *config; - config_ll.lossless = 1; - config_lossy.lossless = 0; - enc->last_config_ = *config; - enc->last_config2_ = config->lossless ? config_lossy : config_ll; - *frame_skipped = 0; - - if (!WebPPictureInit(&sub_frame_none) || !WebPPictureInit(&sub_frame_bg)) { - return VP8_ENC_ERROR_INVALID_CONFIGURATION; - } - - for (i = 0; i < CANDIDATE_COUNT; ++i) { - candidates[i].evaluate_ = 0; - } - - // Change-rectangle assuming previous frame was DISPOSE_NONE. - GetSubRect(prev_canvas, curr_canvas, is_key_frame, is_first_frame, - empty_rect_allowed_none, &rect_none, &sub_frame_none); - - if (IsEmptyRect(&rect_none)) { - // Don't encode the frame at all. Instead, the duration of the previous - // frame will be increased later. - assert(empty_rect_allowed_none); - *frame_skipped = 1; - goto End; - } - - if (dispose_bg_possible) { - // Change-rectangle assuming previous frame was DISPOSE_BACKGROUND. - WebPPicture* const prev_canvas_disposed = &enc->prev_canvas_disposed_; - WebPCopyPixels(prev_canvas, prev_canvas_disposed); - DisposeFrameRectangle(WEBP_MUX_DISPOSE_BACKGROUND, &enc->prev_rect_, - prev_canvas_disposed); - // Even if there is exact pixel match between 'disposed previous canvas' and - // 'current canvas', we can't skip current frame, as there may not be exact - // pixel match between 'previous canvas' and 'current canvas'. So, we don't - // allow empty rectangle in this case. - GetSubRect(prev_canvas_disposed, curr_canvas, is_key_frame, is_first_frame, - 0 /* empty_rect_allowed */, &rect_bg, &sub_frame_bg); - assert(!IsEmptyRect(&rect_bg)); - - if (enc->options_.minimize_size) { // Try both dispose methods. - try_dispose_bg = 1; - try_dispose_none = 1; - } else if (RectArea(&rect_bg) < RectArea(&rect_none)) { - try_dispose_bg = 1; // Pick DISPOSE_BACKGROUND. - try_dispose_none = 0; - } - } - - if (try_dispose_none) { - error_code = GenerateCandidates( - enc, candidates, WEBP_MUX_DISPOSE_NONE, is_lossless, is_key_frame, - &rect_none, &sub_frame_none, &config_ll, &config_lossy); - if (error_code != VP8_ENC_OK) goto Err; - } - - if (try_dispose_bg) { - assert(!enc->is_first_frame_); - assert(dispose_bg_possible); - error_code = GenerateCandidates( - enc, candidates, WEBP_MUX_DISPOSE_BACKGROUND, is_lossless, is_key_frame, - &rect_bg, &sub_frame_bg, &config_ll, &config_lossy); - if (error_code != VP8_ENC_OK) goto Err; - } - - PickBestCandidate(enc, candidates, is_key_frame, encoded_frame); - - goto End; - - Err: - for (i = 0; i < CANDIDATE_COUNT; ++i) { - if (candidates[i].evaluate_) { - WebPMemoryWriterClear(&candidates[i].mem_); - } - } - - End: - WebPPictureFree(&sub_frame_none); - WebPPictureFree(&sub_frame_bg); - return error_code; -} - -// Calculate the penalty incurred if we encode given frame as a key frame -// instead of a sub-frame. -static int64_t KeyFramePenalty(const EncodedFrame* const encoded_frame) { - return ((int64_t)encoded_frame->key_frame_.bitstream.size - - encoded_frame->sub_frame_.bitstream.size); -} - -static int CacheFrame(WebPAnimEncoder* const enc, - const WebPConfig* const config) { - int ok = 0; - int frame_skipped = 0; - WebPEncodingError error_code = VP8_ENC_OK; - const size_t position = enc->count_; - EncodedFrame* const encoded_frame = GetFrame(enc, position); - - ++enc->count_; - - if (enc->is_first_frame_) { // Add this as a key-frame. - error_code = SetFrame(enc, config, 1, encoded_frame, &frame_skipped); - if (error_code != VP8_ENC_OK) goto End; - assert(frame_skipped == 0); // First frame can't be skipped, even if empty. - assert(position == 0 && enc->count_ == 1); - encoded_frame->is_key_frame_ = 1; - enc->flush_count_ = 0; - enc->count_since_key_frame_ = 0; - enc->prev_candidate_undecided_ = 0; - } else { - ++enc->count_since_key_frame_; - if (enc->count_since_key_frame_ <= enc->options_.kmin) { - // Add this as a frame rectangle. - error_code = SetFrame(enc, config, 0, encoded_frame, &frame_skipped); - if (error_code != VP8_ENC_OK) goto End; - if (frame_skipped) goto Skip; - encoded_frame->is_key_frame_ = 0; - enc->flush_count_ = enc->count_ - 1; - enc->prev_candidate_undecided_ = 0; - } else { - int64_t curr_delta; - - // Add this as a frame rectangle to enc. - error_code = SetFrame(enc, config, 0, encoded_frame, &frame_skipped); - if (error_code != VP8_ENC_OK) goto End; - if (frame_skipped) goto Skip; - - // Add this as a key-frame to enc, too. - error_code = SetFrame(enc, config, 1, encoded_frame, &frame_skipped); - if (error_code != VP8_ENC_OK) goto End; - assert(frame_skipped == 0); // Key-frame cannot be an empty rectangle. - - // Analyze size difference of the two variants. - curr_delta = KeyFramePenalty(encoded_frame); - if (curr_delta <= enc->best_delta_) { // Pick this as the key-frame. - if (enc->keyframe_ != KEYFRAME_NONE) { - EncodedFrame* const old_keyframe = GetFrame(enc, enc->keyframe_); - assert(old_keyframe->is_key_frame_); - old_keyframe->is_key_frame_ = 0; - } - encoded_frame->is_key_frame_ = 1; - enc->keyframe_ = (int)position; - enc->best_delta_ = curr_delta; - enc->flush_count_ = enc->count_ - 1; // We can flush previous frames. - } else { - encoded_frame->is_key_frame_ = 0; - } - // Note: We need '>=' below because when kmin and kmax are both zero, - // count_since_key_frame will always be > kmax. - if (enc->count_since_key_frame_ >= enc->options_.kmax) { - enc->flush_count_ = enc->count_ - 1; - enc->count_since_key_frame_ = 0; - enc->keyframe_ = KEYFRAME_NONE; - enc->best_delta_ = DELTA_INFINITY; - } - enc->prev_candidate_undecided_ = 1; - } - } - - // Update previous to previous and previous canvases for next call. - WebPCopyPixels(enc->curr_canvas_, &enc->prev_canvas_); - enc->is_first_frame_ = 0; - - Skip: - ok = 1; - ++enc->in_frame_count_; - - End: - if (!ok || frame_skipped) { - FrameRelease(encoded_frame); - // We reset some counters, as the frame addition failed/was skipped. - --enc->count_; - if (!enc->is_first_frame_) --enc->count_since_key_frame_; - if (!ok) { - MarkError2(enc, "ERROR adding frame. WebPEncodingError", error_code); - } - } - enc->curr_canvas_->error_code = error_code; // report error_code - assert(ok || error_code != VP8_ENC_OK); - return ok; -} - -static int FlushFrames(WebPAnimEncoder* const enc) { - while (enc->flush_count_ > 0) { - WebPMuxError err; - EncodedFrame* const curr = GetFrame(enc, 0); - const WebPMuxFrameInfo* const info = - curr->is_key_frame_ ? &curr->key_frame_ : &curr->sub_frame_; - assert(enc->mux_ != NULL); - err = WebPMuxPushFrame(enc->mux_, info, 1); - if (err != WEBP_MUX_OK) { - MarkError2(enc, "ERROR adding frame. WebPMuxError", err); - return 0; - } - if (enc->options_.verbose) { - fprintf(stderr, "INFO: Added frame. offset:%d,%d dispose:%d blend:%d\n", - info->x_offset, info->y_offset, info->dispose_method, - info->blend_method); - } - ++enc->out_frame_count_; - FrameRelease(curr); - ++enc->start_; - --enc->flush_count_; - --enc->count_; - if (enc->keyframe_ != KEYFRAME_NONE) --enc->keyframe_; - } - - if (enc->count_ == 1 && enc->start_ != 0) { - // Move enc->start to index 0. - const int enc_start_tmp = (int)enc->start_; - EncodedFrame temp = enc->encoded_frames_[0]; - enc->encoded_frames_[0] = enc->encoded_frames_[enc_start_tmp]; - enc->encoded_frames_[enc_start_tmp] = temp; - FrameRelease(&enc->encoded_frames_[enc_start_tmp]); - enc->start_ = 0; - } - return 1; -} - -#undef DELTA_INFINITY -#undef KEYFRAME_NONE - -int WebPAnimEncoderAdd(WebPAnimEncoder* enc, WebPPicture* frame, int timestamp, - const WebPConfig* encoder_config) { - WebPConfig config; - - if (enc == NULL) { - return 0; - } - MarkNoError(enc); - - if (!enc->is_first_frame_) { - // Make sure timestamps are non-decreasing (integer wrap-around is OK). - const uint32_t prev_frame_duration = - (uint32_t)timestamp - enc->prev_timestamp_; - if (prev_frame_duration >= MAX_DURATION) { - if (frame != NULL) { - frame->error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION; - } - MarkError(enc, "ERROR adding frame: timestamps must be non-decreasing"); - return 0; - } - if (!IncreasePreviousDuration(enc, (int)prev_frame_duration)) { - return 0; - } - } else { - enc->first_timestamp_ = timestamp; - } - - if (frame == NULL) { // Special: last call. - enc->got_null_frame_ = 1; - enc->prev_timestamp_ = timestamp; - return 1; - } - - if (frame->width != enc->canvas_width_ || - frame->height != enc->canvas_height_) { - frame->error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION; - MarkError(enc, "ERROR adding frame: Invalid frame dimensions"); - return 0; - } - - if (!frame->use_argb) { // Convert frame from YUV(A) to ARGB. - if (enc->options_.verbose) { - fprintf(stderr, "WARNING: Converting frame from YUV(A) to ARGB format; " - "this incurs a small loss.\n"); - } - if (!WebPPictureYUVAToARGB(frame)) { - MarkError(enc, "ERROR converting frame from YUV(A) to ARGB"); - return 0; - } - } - - if (encoder_config != NULL) { - config = *encoder_config; - } else { - WebPConfigInit(&config); - config.lossless = 1; - } - assert(enc->curr_canvas_ == NULL); - enc->curr_canvas_ = frame; // Store reference. - assert(enc->curr_canvas_copy_modified_ == 1); - CopyCurrentCanvas(enc); - - if (!CacheFrame(enc, &config)) { - return 0; - } - - if (!FlushFrames(enc)) { - return 0; - } - enc->curr_canvas_ = NULL; - enc->curr_canvas_copy_modified_ = 1; - enc->prev_timestamp_ = timestamp; - return 1; -} - -// ----------------------------------------------------------------------------- -// Bitstream assembly. - -static int DecodeFrameOntoCanvas(const WebPMuxFrameInfo* const frame, - WebPPicture* const canvas) { - const WebPData* const image = &frame->bitstream; - WebPPicture sub_image; - WebPDecoderConfig config; - WebPInitDecoderConfig(&config); - WebPUtilClearPic(canvas, NULL); - if (WebPGetFeatures(image->bytes, image->size, &config.input) != - VP8_STATUS_OK) { - return 0; - } - if (!WebPPictureView(canvas, frame->x_offset, frame->y_offset, - config.input.width, config.input.height, &sub_image)) { - return 0; - } - config.output.is_external_memory = 1; - config.output.colorspace = MODE_BGRA; - config.output.u.RGBA.rgba = (uint8_t*)sub_image.argb; - config.output.u.RGBA.stride = sub_image.argb_stride * 4; - config.output.u.RGBA.size = config.output.u.RGBA.stride * sub_image.height; - - if (WebPDecode(image->bytes, image->size, &config) != VP8_STATUS_OK) { - return 0; - } - return 1; -} - -static int FrameToFullCanvas(WebPAnimEncoder* const enc, - const WebPMuxFrameInfo* const frame, - WebPData* const full_image) { - WebPPicture* const canvas_buf = &enc->curr_canvas_copy_; - WebPMemoryWriter mem1, mem2; - WebPMemoryWriterInit(&mem1); - WebPMemoryWriterInit(&mem2); - - if (!DecodeFrameOntoCanvas(frame, canvas_buf)) goto Err; - if (!EncodeFrame(&enc->last_config_, canvas_buf, &mem1)) goto Err; - GetEncodedData(&mem1, full_image); - - if (enc->options_.allow_mixed) { - if (!EncodeFrame(&enc->last_config_, canvas_buf, &mem2)) goto Err; - if (mem2.size < mem1.size) { - GetEncodedData(&mem2, full_image); - WebPMemoryWriterClear(&mem1); - } else { - WebPMemoryWriterClear(&mem2); - } - } - return 1; - - Err: - WebPMemoryWriterClear(&mem1); - WebPMemoryWriterClear(&mem2); - return 0; -} - -// Convert a single-frame animation to a non-animated image if appropriate. -// TODO(urvang): Can we pick one of the two heuristically (based on frame -// rectangle and/or presence of alpha)? -static WebPMuxError OptimizeSingleFrame(WebPAnimEncoder* const enc, - WebPData* const webp_data) { - WebPMuxError err = WEBP_MUX_OK; - int canvas_width, canvas_height; - WebPMuxFrameInfo frame; - WebPData full_image; - WebPData webp_data2; - WebPMux* const mux = WebPMuxCreate(webp_data, 0); - if (mux == NULL) return WEBP_MUX_BAD_DATA; - assert(enc->out_frame_count_ == 1); - WebPDataInit(&frame.bitstream); - WebPDataInit(&full_image); - WebPDataInit(&webp_data2); - - err = WebPMuxGetFrame(mux, 1, &frame); - if (err != WEBP_MUX_OK) goto End; - if (frame.id != WEBP_CHUNK_ANMF) goto End; // Non-animation: nothing to do. - err = WebPMuxGetCanvasSize(mux, &canvas_width, &canvas_height); - if (err != WEBP_MUX_OK) goto End; - if (!FrameToFullCanvas(enc, &frame, &full_image)) { - err = WEBP_MUX_BAD_DATA; - goto End; - } - err = WebPMuxSetImage(mux, &full_image, 1); - if (err != WEBP_MUX_OK) goto End; - err = WebPMuxAssemble(mux, &webp_data2); - if (err != WEBP_MUX_OK) goto End; - - if (webp_data2.size < webp_data->size) { // Pick 'webp_data2' if smaller. - WebPDataClear(webp_data); - *webp_data = webp_data2; - WebPDataInit(&webp_data2); - } - - End: - WebPDataClear(&frame.bitstream); - WebPDataClear(&full_image); - WebPMuxDelete(mux); - WebPDataClear(&webp_data2); - return err; -} - -int WebPAnimEncoderAssemble(WebPAnimEncoder* enc, WebPData* webp_data) { - WebPMux* mux; - WebPMuxError err; - - if (enc == NULL) { - return 0; - } - MarkNoError(enc); - - if (webp_data == NULL) { - MarkError(enc, "ERROR assembling: NULL input"); - return 0; - } - - if (enc->in_frame_count_ == 0) { - MarkError(enc, "ERROR: No frames to assemble"); - return 0; - } - - if (!enc->got_null_frame_ && enc->in_frame_count_ > 1 && enc->count_ > 0) { - // set duration of the last frame to be avg of durations of previous frames. - const double delta_time = enc->prev_timestamp_ - enc->first_timestamp_; - const int average_duration = (int)(delta_time / (enc->in_frame_count_ - 1)); - if (!IncreasePreviousDuration(enc, average_duration)) { - return 0; - } - } - - // Flush any remaining frames. - enc->flush_count_ = enc->count_; - if (!FlushFrames(enc)) { - return 0; - } - - // Set definitive canvas size. - mux = enc->mux_; - err = WebPMuxSetCanvasSize(mux, enc->canvas_width_, enc->canvas_height_); - if (err != WEBP_MUX_OK) goto Err; - - err = WebPMuxSetAnimationParams(mux, &enc->options_.anim_params); - if (err != WEBP_MUX_OK) goto Err; - - // Assemble into a WebP bitstream. - err = WebPMuxAssemble(mux, webp_data); - if (err != WEBP_MUX_OK) goto Err; - - if (enc->out_frame_count_ == 1) { - err = OptimizeSingleFrame(enc, webp_data); - if (err != WEBP_MUX_OK) goto Err; - } - return 1; - - Err: - MarkError2(enc, "ERROR assembling WebP", err); - return 0; -} - -const char* WebPAnimEncoderGetError(WebPAnimEncoder* enc) { - if (enc == NULL) return NULL; - return enc->error_str_; -} - -// ----------------------------------------------------------------------------- diff --git a/Example/Pods/libwebp/src/mux/muxedit.c b/Example/Pods/libwebp/src/mux/muxedit.c deleted file mode 100644 index b27663f8..00000000 --- a/Example/Pods/libwebp/src/mux/muxedit.c +++ /dev/null @@ -1,696 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Set and delete APIs for mux. -// -// Authors: Urvang (urvang@google.com) -// Vikas (vikasa@google.com) - -#include -#include "./muxi.h" -#include "../utils/utils.h" - -//------------------------------------------------------------------------------ -// Life of a mux object. - -static void MuxInit(WebPMux* const mux) { - assert(mux != NULL); - memset(mux, 0, sizeof(*mux)); - mux->canvas_width_ = 0; // just to be explicit - mux->canvas_height_ = 0; -} - -WebPMux* WebPNewInternal(int version) { - if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_MUX_ABI_VERSION)) { - return NULL; - } else { - WebPMux* const mux = (WebPMux*)WebPSafeMalloc(1ULL, sizeof(WebPMux)); - if (mux != NULL) MuxInit(mux); - return mux; - } -} - -// Delete all images in 'wpi_list'. -static void DeleteAllImages(WebPMuxImage** const wpi_list) { - while (*wpi_list != NULL) { - *wpi_list = MuxImageDelete(*wpi_list); - } -} - -static void MuxRelease(WebPMux* const mux) { - assert(mux != NULL); - DeleteAllImages(&mux->images_); - ChunkListDelete(&mux->vp8x_); - ChunkListDelete(&mux->iccp_); - ChunkListDelete(&mux->anim_); - ChunkListDelete(&mux->exif_); - ChunkListDelete(&mux->xmp_); - ChunkListDelete(&mux->unknown_); -} - -void WebPMuxDelete(WebPMux* mux) { - if (mux != NULL) { - MuxRelease(mux); - WebPSafeFree(mux); - } -} - -//------------------------------------------------------------------------------ -// Helper method(s). - -// Handy MACRO, makes MuxSet() very symmetric to MuxGet(). -#define SWITCH_ID_LIST(INDEX, LIST) \ - if (idx == (INDEX)) { \ - err = ChunkAssignData(&chunk, data, copy_data, tag); \ - if (err == WEBP_MUX_OK) { \ - err = ChunkSetNth(&chunk, (LIST), nth); \ - } \ - return err; \ - } - -static WebPMuxError MuxSet(WebPMux* const mux, uint32_t tag, uint32_t nth, - const WebPData* const data, int copy_data) { - WebPChunk chunk; - WebPMuxError err = WEBP_MUX_NOT_FOUND; - const CHUNK_INDEX idx = ChunkGetIndexFromTag(tag); - assert(mux != NULL); - assert(!IsWPI(kChunks[idx].id)); - - ChunkInit(&chunk); - SWITCH_ID_LIST(IDX_VP8X, &mux->vp8x_); - SWITCH_ID_LIST(IDX_ICCP, &mux->iccp_); - SWITCH_ID_LIST(IDX_ANIM, &mux->anim_); - SWITCH_ID_LIST(IDX_EXIF, &mux->exif_); - SWITCH_ID_LIST(IDX_XMP, &mux->xmp_); - SWITCH_ID_LIST(IDX_UNKNOWN, &mux->unknown_); - return err; -} -#undef SWITCH_ID_LIST - -// Create data for frame/fragment given image data, offsets and duration. -static WebPMuxError CreateFrameFragmentData( - int width, int height, const WebPMuxFrameInfo* const info, int is_frame, - WebPData* const frame_frgm) { - uint8_t* frame_frgm_bytes; - const size_t frame_frgm_size = kChunks[is_frame ? IDX_ANMF : IDX_FRGM].size; - - assert(width > 0 && height > 0 && info->duration >= 0); - assert(info->dispose_method == (info->dispose_method & 1)); - // Note: assertion on upper bounds is done in PutLE24(). - - frame_frgm_bytes = (uint8_t*)WebPSafeMalloc(1ULL, frame_frgm_size); - if (frame_frgm_bytes == NULL) return WEBP_MUX_MEMORY_ERROR; - - PutLE24(frame_frgm_bytes + 0, info->x_offset / 2); - PutLE24(frame_frgm_bytes + 3, info->y_offset / 2); - - if (is_frame) { - PutLE24(frame_frgm_bytes + 6, width - 1); - PutLE24(frame_frgm_bytes + 9, height - 1); - PutLE24(frame_frgm_bytes + 12, info->duration); - frame_frgm_bytes[15] = - (info->blend_method == WEBP_MUX_NO_BLEND ? 2 : 0) | - (info->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND ? 1 : 0); - } - - frame_frgm->bytes = frame_frgm_bytes; - frame_frgm->size = frame_frgm_size; - return WEBP_MUX_OK; -} - -// Outputs image data given a bitstream. The bitstream can either be a -// single-image WebP file or raw VP8/VP8L data. -// Also outputs 'is_lossless' to be true if the given bitstream is lossless. -static WebPMuxError GetImageData(const WebPData* const bitstream, - WebPData* const image, WebPData* const alpha, - int* const is_lossless) { - WebPDataInit(alpha); // Default: no alpha. - if (bitstream->size < TAG_SIZE || - memcmp(bitstream->bytes, "RIFF", TAG_SIZE)) { - // It is NOT webp file data. Return input data as is. - *image = *bitstream; - } else { - // It is webp file data. Extract image data from it. - const WebPMuxImage* wpi; - WebPMux* const mux = WebPMuxCreate(bitstream, 0); - if (mux == NULL) return WEBP_MUX_BAD_DATA; - wpi = mux->images_; - assert(wpi != NULL && wpi->img_ != NULL); - *image = wpi->img_->data_; - if (wpi->alpha_ != NULL) { - *alpha = wpi->alpha_->data_; - } - WebPMuxDelete(mux); - } - *is_lossless = VP8LCheckSignature(image->bytes, image->size); - return WEBP_MUX_OK; -} - -static WebPMuxError DeleteChunks(WebPChunk** chunk_list, uint32_t tag) { - WebPMuxError err = WEBP_MUX_NOT_FOUND; - assert(chunk_list); - while (*chunk_list) { - WebPChunk* const chunk = *chunk_list; - if (chunk->tag_ == tag) { - *chunk_list = ChunkDelete(chunk); - err = WEBP_MUX_OK; - } else { - chunk_list = &chunk->next_; - } - } - return err; -} - -static WebPMuxError MuxDeleteAllNamedData(WebPMux* const mux, uint32_t tag) { - const WebPChunkId id = ChunkGetIdFromTag(tag); - assert(mux != NULL); - if (IsWPI(id)) return WEBP_MUX_INVALID_ARGUMENT; - return DeleteChunks(MuxGetChunkListFromId(mux, id), tag); -} - -//------------------------------------------------------------------------------ -// Set API(s). - -WebPMuxError WebPMuxSetChunk(WebPMux* mux, const char fourcc[4], - const WebPData* chunk_data, int copy_data) { - uint32_t tag; - WebPMuxError err; - if (mux == NULL || fourcc == NULL || chunk_data == NULL || - chunk_data->bytes == NULL || chunk_data->size > MAX_CHUNK_PAYLOAD) { - return WEBP_MUX_INVALID_ARGUMENT; - } - tag = ChunkGetTagFromFourCC(fourcc); - - // Delete existing chunk(s) with the same 'fourcc'. - err = MuxDeleteAllNamedData(mux, tag); - if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; - - // Add the given chunk. - return MuxSet(mux, tag, 1, chunk_data, copy_data); -} - -// Creates a chunk from given 'data' and sets it as 1st chunk in 'chunk_list'. -static WebPMuxError AddDataToChunkList( - const WebPData* const data, int copy_data, uint32_t tag, - WebPChunk** chunk_list) { - WebPChunk chunk; - WebPMuxError err; - ChunkInit(&chunk); - err = ChunkAssignData(&chunk, data, copy_data, tag); - if (err != WEBP_MUX_OK) goto Err; - err = ChunkSetNth(&chunk, chunk_list, 1); - if (err != WEBP_MUX_OK) goto Err; - return WEBP_MUX_OK; - Err: - ChunkRelease(&chunk); - return err; -} - -// Extracts image & alpha data from the given bitstream and then sets wpi.alpha_ -// and wpi.img_ appropriately. -static WebPMuxError SetAlphaAndImageChunks( - const WebPData* const bitstream, int copy_data, WebPMuxImage* const wpi) { - int is_lossless = 0; - WebPData image, alpha; - WebPMuxError err = GetImageData(bitstream, &image, &alpha, &is_lossless); - const int image_tag = - is_lossless ? kChunks[IDX_VP8L].tag : kChunks[IDX_VP8].tag; - if (err != WEBP_MUX_OK) return err; - if (alpha.bytes != NULL) { - err = AddDataToChunkList(&alpha, copy_data, kChunks[IDX_ALPHA].tag, - &wpi->alpha_); - if (err != WEBP_MUX_OK) return err; - } - err = AddDataToChunkList(&image, copy_data, image_tag, &wpi->img_); - if (err != WEBP_MUX_OK) return err; - return MuxImageFinalize(wpi) ? WEBP_MUX_OK : WEBP_MUX_INVALID_ARGUMENT; -} - -WebPMuxError WebPMuxSetImage(WebPMux* mux, const WebPData* bitstream, - int copy_data) { - WebPMuxImage wpi; - WebPMuxError err; - - // Sanity checks. - if (mux == NULL || bitstream == NULL || bitstream->bytes == NULL || - bitstream->size > MAX_CHUNK_PAYLOAD) { - return WEBP_MUX_INVALID_ARGUMENT; - } - - if (mux->images_ != NULL) { - // Only one 'simple image' can be added in mux. So, remove present images. - DeleteAllImages(&mux->images_); - } - - MuxImageInit(&wpi); - err = SetAlphaAndImageChunks(bitstream, copy_data, &wpi); - if (err != WEBP_MUX_OK) goto Err; - - // Add this WebPMuxImage to mux. - err = MuxImagePush(&wpi, &mux->images_); - if (err != WEBP_MUX_OK) goto Err; - - // All is well. - return WEBP_MUX_OK; - - Err: // Something bad happened. - MuxImageRelease(&wpi); - return err; -} - -WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* frame, - int copy_data) { - WebPMuxImage wpi; - WebPMuxError err; - int is_frame; - const WebPData* const bitstream = &frame->bitstream; - - // Sanity checks. - if (mux == NULL || frame == NULL) return WEBP_MUX_INVALID_ARGUMENT; - - is_frame = (frame->id == WEBP_CHUNK_ANMF); - if (!(is_frame || (frame->id == WEBP_CHUNK_FRGM))) { - return WEBP_MUX_INVALID_ARGUMENT; - } - if (frame->id == WEBP_CHUNK_FRGM) { // Dead experiment. - return WEBP_MUX_INVALID_ARGUMENT; - } - - if (bitstream->bytes == NULL || bitstream->size > MAX_CHUNK_PAYLOAD) { - return WEBP_MUX_INVALID_ARGUMENT; - } - - if (mux->images_ != NULL) { - const WebPMuxImage* const image = mux->images_; - const uint32_t image_id = (image->header_ != NULL) ? - ChunkGetIdFromTag(image->header_->tag_) : WEBP_CHUNK_IMAGE; - if (image_id != frame->id) { - return WEBP_MUX_INVALID_ARGUMENT; // Conflicting frame types. - } - } - - MuxImageInit(&wpi); - err = SetAlphaAndImageChunks(bitstream, copy_data, &wpi); - if (err != WEBP_MUX_OK) goto Err; - assert(wpi.img_ != NULL); // As SetAlphaAndImageChunks() was successful. - - { - WebPData frame_frgm; - const uint32_t tag = kChunks[is_frame ? IDX_ANMF : IDX_FRGM].tag; - WebPMuxFrameInfo tmp = *frame; - tmp.x_offset &= ~1; // Snap offsets to even. - tmp.y_offset &= ~1; - if (!is_frame) { // Reset unused values. - tmp.duration = 1; - tmp.dispose_method = WEBP_MUX_DISPOSE_NONE; - tmp.blend_method = WEBP_MUX_BLEND; - } - if (tmp.x_offset < 0 || tmp.x_offset >= MAX_POSITION_OFFSET || - tmp.y_offset < 0 || tmp.y_offset >= MAX_POSITION_OFFSET || - (tmp.duration < 0 || tmp.duration >= MAX_DURATION) || - tmp.dispose_method != (tmp.dispose_method & 1)) { - err = WEBP_MUX_INVALID_ARGUMENT; - goto Err; - } - err = CreateFrameFragmentData(wpi.width_, wpi.height_, &tmp, is_frame, - &frame_frgm); - if (err != WEBP_MUX_OK) goto Err; - // Add frame/fragment chunk (with copy_data = 1). - err = AddDataToChunkList(&frame_frgm, 1, tag, &wpi.header_); - WebPDataClear(&frame_frgm); // frame_frgm owned by wpi.header_ now. - if (err != WEBP_MUX_OK) goto Err; - } - - // Add this WebPMuxImage to mux. - err = MuxImagePush(&wpi, &mux->images_); - if (err != WEBP_MUX_OK) goto Err; - - // All is well. - return WEBP_MUX_OK; - - Err: // Something bad happened. - MuxImageRelease(&wpi); - return err; -} - -WebPMuxError WebPMuxSetAnimationParams(WebPMux* mux, - const WebPMuxAnimParams* params) { - WebPMuxError err; - uint8_t data[ANIM_CHUNK_SIZE]; - const WebPData anim = { data, ANIM_CHUNK_SIZE }; - - if (mux == NULL || params == NULL) return WEBP_MUX_INVALID_ARGUMENT; - if (params->loop_count < 0 || params->loop_count >= MAX_LOOP_COUNT) { - return WEBP_MUX_INVALID_ARGUMENT; - } - - // Delete any existing ANIM chunk(s). - err = MuxDeleteAllNamedData(mux, kChunks[IDX_ANIM].tag); - if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; - - // Set the animation parameters. - PutLE32(data, params->bgcolor); - PutLE16(data + 4, params->loop_count); - return MuxSet(mux, kChunks[IDX_ANIM].tag, 1, &anim, 1); -} - -WebPMuxError WebPMuxSetCanvasSize(WebPMux* mux, - int width, int height) { - WebPMuxError err; - if (mux == NULL) { - return WEBP_MUX_INVALID_ARGUMENT; - } - if (width < 0 || height < 0 || - width > MAX_CANVAS_SIZE || height > MAX_CANVAS_SIZE) { - return WEBP_MUX_INVALID_ARGUMENT; - } - if (width * (uint64_t)height >= MAX_IMAGE_AREA) { - return WEBP_MUX_INVALID_ARGUMENT; - } - if ((width * height) == 0 && (width | height) != 0) { - // one of width / height is zero, but not both -> invalid! - return WEBP_MUX_INVALID_ARGUMENT; - } - // If we already assembled a VP8X chunk, invalidate it. - err = MuxDeleteAllNamedData(mux, kChunks[IDX_VP8X].tag); - if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; - - mux->canvas_width_ = width; - mux->canvas_height_ = height; - return WEBP_MUX_OK; -} - -//------------------------------------------------------------------------------ -// Delete API(s). - -WebPMuxError WebPMuxDeleteChunk(WebPMux* mux, const char fourcc[4]) { - if (mux == NULL || fourcc == NULL) return WEBP_MUX_INVALID_ARGUMENT; - return MuxDeleteAllNamedData(mux, ChunkGetTagFromFourCC(fourcc)); -} - -WebPMuxError WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth) { - if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT; - return MuxImageDeleteNth(&mux->images_, nth); -} - -//------------------------------------------------------------------------------ -// Assembly of the WebP RIFF file. - -static WebPMuxError GetFrameFragmentInfo( - const WebPChunk* const frame_frgm_chunk, - int* const x_offset, int* const y_offset, int* const duration) { - const uint32_t tag = frame_frgm_chunk->tag_; - const int is_frame = (tag == kChunks[IDX_ANMF].tag); - const WebPData* const data = &frame_frgm_chunk->data_; - const size_t expected_data_size = - is_frame ? ANMF_CHUNK_SIZE : FRGM_CHUNK_SIZE; - assert(frame_frgm_chunk != NULL); - assert(tag == kChunks[IDX_ANMF].tag || tag == kChunks[IDX_FRGM].tag); - if (data->size != expected_data_size) return WEBP_MUX_INVALID_ARGUMENT; - - *x_offset = 2 * GetLE24(data->bytes + 0); - *y_offset = 2 * GetLE24(data->bytes + 3); - if (is_frame) *duration = GetLE24(data->bytes + 12); - return WEBP_MUX_OK; -} - -static WebPMuxError GetImageInfo(const WebPMuxImage* const wpi, - int* const x_offset, int* const y_offset, - int* const duration, - int* const width, int* const height) { - const WebPChunk* const frame_frgm_chunk = wpi->header_; - WebPMuxError err; - assert(wpi != NULL); - assert(frame_frgm_chunk != NULL); - - // Get offsets and duration from ANMF/FRGM chunk. - err = GetFrameFragmentInfo(frame_frgm_chunk, x_offset, y_offset, duration); - if (err != WEBP_MUX_OK) return err; - - // Get width and height from VP8/VP8L chunk. - if (width != NULL) *width = wpi->width_; - if (height != NULL) *height = wpi->height_; - return WEBP_MUX_OK; -} - -// Returns the tightest dimension for the canvas considering the image list. -static WebPMuxError GetAdjustedCanvasSize(const WebPMux* const mux, - uint32_t flags, - int* const width, int* const height) { - WebPMuxImage* wpi = NULL; - assert(mux != NULL); - assert(width != NULL && height != NULL); - - wpi = mux->images_; - assert(wpi != NULL); - assert(wpi->img_ != NULL); - - if (wpi->next_ != NULL) { - int max_x = 0; - int max_y = 0; - int64_t image_area = 0; - // if we have a chain of wpi's, header_ is necessarily set - assert(wpi->header_ != NULL); - // Aggregate the bounding box for animation frames & fragmented images. - for (; wpi != NULL; wpi = wpi->next_) { - int x_offset = 0, y_offset = 0, duration = 0, w = 0, h = 0; - const WebPMuxError err = GetImageInfo(wpi, &x_offset, &y_offset, - &duration, &w, &h); - const int max_x_pos = x_offset + w; - const int max_y_pos = y_offset + h; - if (err != WEBP_MUX_OK) return err; - assert(x_offset < MAX_POSITION_OFFSET); - assert(y_offset < MAX_POSITION_OFFSET); - - if (max_x_pos > max_x) max_x = max_x_pos; - if (max_y_pos > max_y) max_y = max_y_pos; - image_area += w * h; - } - *width = max_x; - *height = max_y; - // Crude check to validate that there are no image overlaps/holes for - // fragmented images. Check that the aggregated image area for individual - // fragments exactly matches the image area of the constructed canvas. - // However, the area-match is necessary but not sufficient condition. - if ((flags & FRAGMENTS_FLAG) && (image_area != (max_x * max_y))) { - *width = 0; - *height = 0; - return WEBP_MUX_INVALID_ARGUMENT; - } - } else { - // For a single image, canvas dimensions are same as image dimensions. - *width = wpi->width_; - *height = wpi->height_; - } - return WEBP_MUX_OK; -} - -// VP8X format: -// Total Size : 10, -// Flags : 4 bytes, -// Width : 3 bytes, -// Height : 3 bytes. -static WebPMuxError CreateVP8XChunk(WebPMux* const mux) { - WebPMuxError err = WEBP_MUX_OK; - uint32_t flags = 0; - int width = 0; - int height = 0; - uint8_t data[VP8X_CHUNK_SIZE]; - const WebPData vp8x = { data, VP8X_CHUNK_SIZE }; - const WebPMuxImage* images = NULL; - - assert(mux != NULL); - images = mux->images_; // First image. - if (images == NULL || images->img_ == NULL || - images->img_->data_.bytes == NULL) { - return WEBP_MUX_INVALID_ARGUMENT; - } - - // If VP8X chunk(s) is(are) already present, remove them (and later add new - // VP8X chunk with updated flags). - err = MuxDeleteAllNamedData(mux, kChunks[IDX_VP8X].tag); - if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; - - // Set flags. - if (mux->iccp_ != NULL && mux->iccp_->data_.bytes != NULL) { - flags |= ICCP_FLAG; - } - if (mux->exif_ != NULL && mux->exif_->data_.bytes != NULL) { - flags |= EXIF_FLAG; - } - if (mux->xmp_ != NULL && mux->xmp_->data_.bytes != NULL) { - flags |= XMP_FLAG; - } - if (images->header_ != NULL) { - if (images->header_->tag_ == kChunks[IDX_FRGM].tag) { - // This is a fragmented image. - flags |= FRAGMENTS_FLAG; - } else if (images->header_->tag_ == kChunks[IDX_ANMF].tag) { - // This is an image with animation. - flags |= ANIMATION_FLAG; - } - } - if (MuxImageCount(images, WEBP_CHUNK_ALPHA) > 0) { - flags |= ALPHA_FLAG; // Some images have an alpha channel. - } - - err = GetAdjustedCanvasSize(mux, flags, &width, &height); - if (err != WEBP_MUX_OK) return err; - - if (width <= 0 || height <= 0) { - return WEBP_MUX_INVALID_ARGUMENT; - } - if (width > MAX_CANVAS_SIZE || height > MAX_CANVAS_SIZE) { - return WEBP_MUX_INVALID_ARGUMENT; - } - - if (mux->canvas_width_ != 0 || mux->canvas_height_ != 0) { - if (width > mux->canvas_width_ || height > mux->canvas_height_) { - return WEBP_MUX_INVALID_ARGUMENT; - } - width = mux->canvas_width_; - height = mux->canvas_height_; - } - - if (flags == 0) { - // For Simple Image, VP8X chunk should not be added. - return WEBP_MUX_OK; - } - - if (MuxHasAlpha(images)) { - // This means some frames explicitly/implicitly contain alpha. - // Note: This 'flags' update must NOT be done for a lossless image - // without a VP8X chunk! - flags |= ALPHA_FLAG; - } - - PutLE32(data + 0, flags); // VP8X chunk flags. - PutLE24(data + 4, width - 1); // canvas width. - PutLE24(data + 7, height - 1); // canvas height. - - return MuxSet(mux, kChunks[IDX_VP8X].tag, 1, &vp8x, 1); -} - -// Cleans up 'mux' by removing any unnecessary chunks. -static WebPMuxError MuxCleanup(WebPMux* const mux) { - int num_frames; - int num_fragments; - int num_anim_chunks; - - // If we have an image with a single fragment or frame, and its rectangle - // covers the whole canvas, convert it to a non-animated non-fragmented image - // (to avoid writing FRGM/ANMF chunk unnecessarily). - WebPMuxError err = WebPMuxNumChunks(mux, kChunks[IDX_ANMF].id, &num_frames); - if (err != WEBP_MUX_OK) return err; - err = WebPMuxNumChunks(mux, kChunks[IDX_FRGM].id, &num_fragments); - if (err != WEBP_MUX_OK) return err; - if (num_frames == 1 || num_fragments == 1) { - WebPMuxImage* frame_frag; - err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, 1, &frame_frag); - assert(err == WEBP_MUX_OK); // We know that one frame/fragment does exist. - assert(frame_frag != NULL); - if (frame_frag->header_ != NULL && - ((mux->canvas_width_ == 0 && mux->canvas_height_ == 0) || - (frame_frag->width_ == mux->canvas_width_ && - frame_frag->height_ == mux->canvas_height_))) { - assert(frame_frag->header_->tag_ == kChunks[IDX_ANMF].tag || - frame_frag->header_->tag_ == kChunks[IDX_FRGM].tag); - ChunkDelete(frame_frag->header_); // Removes ANMF/FRGM chunk. - frame_frag->header_ = NULL; - num_frames = 0; - num_fragments = 0; - } - } - // Remove ANIM chunk if this is a non-animated image. - err = WebPMuxNumChunks(mux, kChunks[IDX_ANIM].id, &num_anim_chunks); - if (err != WEBP_MUX_OK) return err; - if (num_anim_chunks >= 1 && num_frames == 0) { - err = MuxDeleteAllNamedData(mux, kChunks[IDX_ANIM].tag); - if (err != WEBP_MUX_OK) return err; - } - return WEBP_MUX_OK; -} - -// Total size of a list of images. -static size_t ImageListDiskSize(const WebPMuxImage* wpi_list) { - size_t size = 0; - while (wpi_list != NULL) { - size += MuxImageDiskSize(wpi_list); - wpi_list = wpi_list->next_; - } - return size; -} - -// Write out the given list of images into 'dst'. -static uint8_t* ImageListEmit(const WebPMuxImage* wpi_list, uint8_t* dst) { - while (wpi_list != NULL) { - dst = MuxImageEmit(wpi_list, dst); - wpi_list = wpi_list->next_; - } - return dst; -} - -WebPMuxError WebPMuxAssemble(WebPMux* mux, WebPData* assembled_data) { - size_t size = 0; - uint8_t* data = NULL; - uint8_t* dst = NULL; - WebPMuxError err; - - if (assembled_data == NULL) { - return WEBP_MUX_INVALID_ARGUMENT; - } - // Clean up returned data, in case something goes wrong. - memset(assembled_data, 0, sizeof(*assembled_data)); - - if (mux == NULL) { - return WEBP_MUX_INVALID_ARGUMENT; - } - - // Finalize mux. - err = MuxCleanup(mux); - if (err != WEBP_MUX_OK) return err; - err = CreateVP8XChunk(mux); - if (err != WEBP_MUX_OK) return err; - - // Allocate data. - size = ChunkListDiskSize(mux->vp8x_) + ChunkListDiskSize(mux->iccp_) - + ChunkListDiskSize(mux->anim_) + ImageListDiskSize(mux->images_) - + ChunkListDiskSize(mux->exif_) + ChunkListDiskSize(mux->xmp_) - + ChunkListDiskSize(mux->unknown_) + RIFF_HEADER_SIZE; - - data = (uint8_t*)WebPSafeMalloc(1ULL, size); - if (data == NULL) return WEBP_MUX_MEMORY_ERROR; - - // Emit header & chunks. - dst = MuxEmitRiffHeader(data, size); - dst = ChunkListEmit(mux->vp8x_, dst); - dst = ChunkListEmit(mux->iccp_, dst); - dst = ChunkListEmit(mux->anim_, dst); - dst = ImageListEmit(mux->images_, dst); - dst = ChunkListEmit(mux->exif_, dst); - dst = ChunkListEmit(mux->xmp_, dst); - dst = ChunkListEmit(mux->unknown_, dst); - assert(dst == data + size); - - // Validate mux. - err = MuxValidate(mux); - if (err != WEBP_MUX_OK) { - WebPSafeFree(data); - data = NULL; - size = 0; - } - - // Finalize data. - assembled_data->bytes = data; - assembled_data->size = size; - - return err; -} - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/mux/muxi.h b/Example/Pods/libwebp/src/mux/muxi.h deleted file mode 100644 index 5e8ba2e8..00000000 --- a/Example/Pods/libwebp/src/mux/muxi.h +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Internal header for mux library. -// -// Author: Urvang (urvang@google.com) - -#ifndef WEBP_MUX_MUXI_H_ -#define WEBP_MUX_MUXI_H_ - -#include -#include "../dec/vp8i.h" -#include "../dec/vp8li.h" -#include "../webp/mux.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//------------------------------------------------------------------------------ -// Defines and constants. - -#define MUX_MAJ_VERSION 0 -#define MUX_MIN_VERSION 3 -#define MUX_REV_VERSION 0 - -// Chunk object. -typedef struct WebPChunk WebPChunk; -struct WebPChunk { - uint32_t tag_; - int owner_; // True if *data_ memory is owned internally. - // VP8X, ANIM, and other internally created chunks - // like ANMF/FRGM are always owned. - WebPData data_; - WebPChunk* next_; -}; - -// MuxImage object. Store a full WebP image (including ANMF/FRGM chunk, ALPH -// chunk and VP8/VP8L chunk), -typedef struct WebPMuxImage WebPMuxImage; -struct WebPMuxImage { - WebPChunk* header_; // Corresponds to WEBP_CHUNK_ANMF/WEBP_CHUNK_FRGM. - WebPChunk* alpha_; // Corresponds to WEBP_CHUNK_ALPHA. - WebPChunk* img_; // Corresponds to WEBP_CHUNK_IMAGE. - WebPChunk* unknown_; // Corresponds to WEBP_CHUNK_UNKNOWN. - int width_; - int height_; - int has_alpha_; // Through ALPH chunk or as part of VP8L. - int is_partial_; // True if only some of the chunks are filled. - WebPMuxImage* next_; -}; - -// Main mux object. Stores data chunks. -struct WebPMux { - WebPMuxImage* images_; - WebPChunk* iccp_; - WebPChunk* exif_; - WebPChunk* xmp_; - WebPChunk* anim_; - WebPChunk* vp8x_; - - WebPChunk* unknown_; - int canvas_width_; - int canvas_height_; -}; - -// CHUNK_INDEX enum: used for indexing within 'kChunks' (defined below) only. -// Note: the reason for having two enums ('WebPChunkId' and 'CHUNK_INDEX') is to -// allow two different chunks to have the same id (e.g. WebPChunkId -// 'WEBP_CHUNK_IMAGE' can correspond to CHUNK_INDEX 'IDX_VP8' or 'IDX_VP8L'). -typedef enum { - IDX_VP8X = 0, - IDX_ICCP, - IDX_ANIM, - IDX_ANMF, - IDX_FRGM, - IDX_ALPHA, - IDX_VP8, - IDX_VP8L, - IDX_EXIF, - IDX_XMP, - IDX_UNKNOWN, - - IDX_NIL, - IDX_LAST_CHUNK -} CHUNK_INDEX; - -#define NIL_TAG 0x00000000u // To signal void chunk. - -typedef struct { - uint32_t tag; - WebPChunkId id; - uint32_t size; -} ChunkInfo; - -extern const ChunkInfo kChunks[IDX_LAST_CHUNK]; - -//------------------------------------------------------------------------------ -// Chunk object management. - -// Initialize. -void ChunkInit(WebPChunk* const chunk); - -// Get chunk index from chunk tag. Returns IDX_UNKNOWN if not found. -CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag); - -// Get chunk id from chunk tag. Returns WEBP_CHUNK_UNKNOWN if not found. -WebPChunkId ChunkGetIdFromTag(uint32_t tag); - -// Convert a fourcc string to a tag. -uint32_t ChunkGetTagFromFourCC(const char fourcc[4]); - -// Get chunk index from fourcc. Returns IDX_UNKNOWN if given fourcc is unknown. -CHUNK_INDEX ChunkGetIndexFromFourCC(const char fourcc[4]); - -// Search for nth chunk with given 'tag' in the chunk list. -// nth = 0 means "last of the list". -WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag); - -// Fill the chunk with the given data. -WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data, - int copy_data, uint32_t tag); - -// Sets 'chunk' at nth position in the 'chunk_list'. -// nth = 0 has the special meaning "last of the list". -// On success ownership is transferred from 'chunk' to the 'chunk_list'. -WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list, - uint32_t nth); - -// Releases chunk and returns chunk->next_. -WebPChunk* ChunkRelease(WebPChunk* const chunk); - -// Deletes given chunk & returns chunk->next_. -WebPChunk* ChunkDelete(WebPChunk* const chunk); - -// Deletes all chunks in the given chunk list. -void ChunkListDelete(WebPChunk** const chunk_list); - -// Returns size of the chunk including chunk header and padding byte (if any). -static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) { - return CHUNK_HEADER_SIZE + ((chunk_size + 1) & ~1U); -} - -// Size of a chunk including header and padding. -static WEBP_INLINE size_t ChunkDiskSize(const WebPChunk* chunk) { - const size_t data_size = chunk->data_.size; - assert(data_size < MAX_CHUNK_PAYLOAD); - return SizeWithPadding(data_size); -} - -// Total size of a list of chunks. -size_t ChunkListDiskSize(const WebPChunk* chunk_list); - -// Write out the given list of chunks into 'dst'. -uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst); - -//------------------------------------------------------------------------------ -// MuxImage object management. - -// Initialize. -void MuxImageInit(WebPMuxImage* const wpi); - -// Releases image 'wpi' and returns wpi->next. -WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi); - -// Delete image 'wpi' and return the next image in the list or NULL. -// 'wpi' can be NULL. -WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi); - -// Count number of images matching the given tag id in the 'wpi_list'. -// If id == WEBP_CHUNK_NIL, all images will be matched. -int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id); - -// Update width/height/has_alpha info from chunks within wpi. -// Also remove ALPH chunk if not needed. -int MuxImageFinalize(WebPMuxImage* const wpi); - -// Check if given ID corresponds to an image related chunk. -static WEBP_INLINE int IsWPI(WebPChunkId id) { - switch (id) { - case WEBP_CHUNK_ANMF: - case WEBP_CHUNK_FRGM: - case WEBP_CHUNK_ALPHA: - case WEBP_CHUNK_IMAGE: return 1; - default: return 0; - } -} - -// Pushes 'wpi' at the end of 'wpi_list'. -WebPMuxError MuxImagePush(const WebPMuxImage* wpi, WebPMuxImage** wpi_list); - -// Delete nth image in the image list. -WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth); - -// Get nth image in the image list. -WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth, - WebPMuxImage** wpi); - -// Total size of the given image. -size_t MuxImageDiskSize(const WebPMuxImage* const wpi); - -// Write out the given image into 'dst'. -uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst); - -//------------------------------------------------------------------------------ -// Helper methods for mux. - -// Checks if the given image list contains at least one image with alpha. -int MuxHasAlpha(const WebPMuxImage* images); - -// Write out RIFF header into 'data', given total data size 'size'. -uint8_t* MuxEmitRiffHeader(uint8_t* const data, size_t size); - -// Returns the list where chunk with given ID is to be inserted in mux. -WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id); - -// Validates the given mux object. -WebPMuxError MuxValidate(const WebPMux* const mux); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_MUX_MUXI_H_ */ diff --git a/Example/Pods/libwebp/src/mux/muxinternal.c b/Example/Pods/libwebp/src/mux/muxinternal.c deleted file mode 100644 index 4babbe82..00000000 --- a/Example/Pods/libwebp/src/mux/muxinternal.c +++ /dev/null @@ -1,551 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Internal objects and utils for mux. -// -// Authors: Urvang (urvang@google.com) -// Vikas (vikasa@google.com) - -#include -#include "./muxi.h" -#include "../utils/utils.h" - -#define UNDEFINED_CHUNK_SIZE (-1) - -const ChunkInfo kChunks[] = { - { MKFOURCC('V', 'P', '8', 'X'), WEBP_CHUNK_VP8X, VP8X_CHUNK_SIZE }, - { MKFOURCC('I', 'C', 'C', 'P'), WEBP_CHUNK_ICCP, UNDEFINED_CHUNK_SIZE }, - { MKFOURCC('A', 'N', 'I', 'M'), WEBP_CHUNK_ANIM, ANIM_CHUNK_SIZE }, - { MKFOURCC('A', 'N', 'M', 'F'), WEBP_CHUNK_ANMF, ANMF_CHUNK_SIZE }, - { MKFOURCC('F', 'R', 'G', 'M'), WEBP_CHUNK_FRGM, FRGM_CHUNK_SIZE }, - { MKFOURCC('A', 'L', 'P', 'H'), WEBP_CHUNK_ALPHA, UNDEFINED_CHUNK_SIZE }, - { MKFOURCC('V', 'P', '8', ' '), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE }, - { MKFOURCC('V', 'P', '8', 'L'), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE }, - { MKFOURCC('E', 'X', 'I', 'F'), WEBP_CHUNK_EXIF, UNDEFINED_CHUNK_SIZE }, - { MKFOURCC('X', 'M', 'P', ' '), WEBP_CHUNK_XMP, UNDEFINED_CHUNK_SIZE }, - { NIL_TAG, WEBP_CHUNK_UNKNOWN, UNDEFINED_CHUNK_SIZE }, - - { NIL_TAG, WEBP_CHUNK_NIL, UNDEFINED_CHUNK_SIZE } -}; - -//------------------------------------------------------------------------------ - -int WebPGetMuxVersion(void) { - return (MUX_MAJ_VERSION << 16) | (MUX_MIN_VERSION << 8) | MUX_REV_VERSION; -} - -//------------------------------------------------------------------------------ -// Life of a chunk object. - -void ChunkInit(WebPChunk* const chunk) { - assert(chunk); - memset(chunk, 0, sizeof(*chunk)); - chunk->tag_ = NIL_TAG; -} - -WebPChunk* ChunkRelease(WebPChunk* const chunk) { - WebPChunk* next; - if (chunk == NULL) return NULL; - if (chunk->owner_) { - WebPDataClear(&chunk->data_); - } - next = chunk->next_; - ChunkInit(chunk); - return next; -} - -//------------------------------------------------------------------------------ -// Chunk misc methods. - -CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag) { - int i; - for (i = 0; kChunks[i].tag != NIL_TAG; ++i) { - if (tag == kChunks[i].tag) return (CHUNK_INDEX)i; - } - return IDX_UNKNOWN; -} - -WebPChunkId ChunkGetIdFromTag(uint32_t tag) { - int i; - for (i = 0; kChunks[i].tag != NIL_TAG; ++i) { - if (tag == kChunks[i].tag) return kChunks[i].id; - } - return WEBP_CHUNK_UNKNOWN; -} - -uint32_t ChunkGetTagFromFourCC(const char fourcc[4]) { - return MKFOURCC(fourcc[0], fourcc[1], fourcc[2], fourcc[3]); -} - -CHUNK_INDEX ChunkGetIndexFromFourCC(const char fourcc[4]) { - const uint32_t tag = ChunkGetTagFromFourCC(fourcc); - return ChunkGetIndexFromTag(tag); -} - -//------------------------------------------------------------------------------ -// Chunk search methods. - -// Returns next chunk in the chunk list with the given tag. -static WebPChunk* ChunkSearchNextInList(WebPChunk* chunk, uint32_t tag) { - while (chunk != NULL && chunk->tag_ != tag) { - chunk = chunk->next_; - } - return chunk; -} - -WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag) { - uint32_t iter = nth; - first = ChunkSearchNextInList(first, tag); - if (first == NULL) return NULL; - - while (--iter != 0) { - WebPChunk* next_chunk = ChunkSearchNextInList(first->next_, tag); - if (next_chunk == NULL) break; - first = next_chunk; - } - return ((nth > 0) && (iter > 0)) ? NULL : first; -} - -// Outputs a pointer to 'prev_chunk->next_', -// where 'prev_chunk' is the pointer to the chunk at position (nth - 1). -// Returns true if nth chunk was found. -static int ChunkSearchListToSet(WebPChunk** chunk_list, uint32_t nth, - WebPChunk*** const location) { - uint32_t count = 0; - assert(chunk_list != NULL); - *location = chunk_list; - - while (*chunk_list != NULL) { - WebPChunk* const cur_chunk = *chunk_list; - ++count; - if (count == nth) return 1; // Found. - chunk_list = &cur_chunk->next_; - *location = chunk_list; - } - - // *chunk_list is ok to be NULL if adding at last location. - return (nth == 0 || (count == nth - 1)) ? 1 : 0; -} - -//------------------------------------------------------------------------------ -// Chunk writer methods. - -WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data, - int copy_data, uint32_t tag) { - // For internally allocated chunks, always copy data & make it owner of data. - if (tag == kChunks[IDX_VP8X].tag || tag == kChunks[IDX_ANIM].tag) { - copy_data = 1; - } - - ChunkRelease(chunk); - - if (data != NULL) { - if (copy_data) { // Copy data. - if (!WebPDataCopy(data, &chunk->data_)) return WEBP_MUX_MEMORY_ERROR; - chunk->owner_ = 1; // Chunk is owner of data. - } else { // Don't copy data. - chunk->data_ = *data; - } - } - chunk->tag_ = tag; - return WEBP_MUX_OK; -} - -WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list, - uint32_t nth) { - WebPChunk* new_chunk; - - if (!ChunkSearchListToSet(chunk_list, nth, &chunk_list)) { - return WEBP_MUX_NOT_FOUND; - } - - new_chunk = (WebPChunk*)WebPSafeMalloc(1ULL, sizeof(*new_chunk)); - if (new_chunk == NULL) return WEBP_MUX_MEMORY_ERROR; - *new_chunk = *chunk; - chunk->owner_ = 0; - new_chunk->next_ = *chunk_list; - *chunk_list = new_chunk; - return WEBP_MUX_OK; -} - -//------------------------------------------------------------------------------ -// Chunk deletion method(s). - -WebPChunk* ChunkDelete(WebPChunk* const chunk) { - WebPChunk* const next = ChunkRelease(chunk); - WebPSafeFree(chunk); - return next; -} - -void ChunkListDelete(WebPChunk** const chunk_list) { - while (*chunk_list != NULL) { - *chunk_list = ChunkDelete(*chunk_list); - } -} - -//------------------------------------------------------------------------------ -// Chunk serialization methods. - -static uint8_t* ChunkEmit(const WebPChunk* const chunk, uint8_t* dst) { - const size_t chunk_size = chunk->data_.size; - assert(chunk); - assert(chunk->tag_ != NIL_TAG); - PutLE32(dst + 0, chunk->tag_); - PutLE32(dst + TAG_SIZE, (uint32_t)chunk_size); - assert(chunk_size == (uint32_t)chunk_size); - memcpy(dst + CHUNK_HEADER_SIZE, chunk->data_.bytes, chunk_size); - if (chunk_size & 1) - dst[CHUNK_HEADER_SIZE + chunk_size] = 0; // Add padding. - return dst + ChunkDiskSize(chunk); -} - -uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst) { - while (chunk_list != NULL) { - dst = ChunkEmit(chunk_list, dst); - chunk_list = chunk_list->next_; - } - return dst; -} - -size_t ChunkListDiskSize(const WebPChunk* chunk_list) { - size_t size = 0; - while (chunk_list != NULL) { - size += ChunkDiskSize(chunk_list); - chunk_list = chunk_list->next_; - } - return size; -} - -//------------------------------------------------------------------------------ -// Life of a MuxImage object. - -void MuxImageInit(WebPMuxImage* const wpi) { - assert(wpi); - memset(wpi, 0, sizeof(*wpi)); -} - -WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi) { - WebPMuxImage* next; - if (wpi == NULL) return NULL; - ChunkDelete(wpi->header_); - ChunkDelete(wpi->alpha_); - ChunkDelete(wpi->img_); - ChunkListDelete(&wpi->unknown_); - - next = wpi->next_; - MuxImageInit(wpi); - return next; -} - -//------------------------------------------------------------------------------ -// MuxImage search methods. - -// Get a reference to appropriate chunk list within an image given chunk tag. -static WebPChunk** GetChunkListFromId(const WebPMuxImage* const wpi, - WebPChunkId id) { - assert(wpi != NULL); - switch (id) { - case WEBP_CHUNK_ANMF: - case WEBP_CHUNK_FRGM: return (WebPChunk**)&wpi->header_; - case WEBP_CHUNK_ALPHA: return (WebPChunk**)&wpi->alpha_; - case WEBP_CHUNK_IMAGE: return (WebPChunk**)&wpi->img_; - default: return NULL; - } -} - -int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id) { - int count = 0; - const WebPMuxImage* current; - for (current = wpi_list; current != NULL; current = current->next_) { - if (id == WEBP_CHUNK_NIL) { - ++count; // Special case: count all images. - } else { - const WebPChunk* const wpi_chunk = *GetChunkListFromId(current, id); - if (wpi_chunk != NULL) { - const WebPChunkId wpi_chunk_id = ChunkGetIdFromTag(wpi_chunk->tag_); - if (wpi_chunk_id == id) ++count; // Count images with a matching 'id'. - } - } - } - return count; -} - -// Outputs a pointer to 'prev_wpi->next_', -// where 'prev_wpi' is the pointer to the image at position (nth - 1). -// Returns true if nth image was found. -static int SearchImageToGetOrDelete(WebPMuxImage** wpi_list, uint32_t nth, - WebPMuxImage*** const location) { - uint32_t count = 0; - assert(wpi_list); - *location = wpi_list; - - if (nth == 0) { - nth = MuxImageCount(*wpi_list, WEBP_CHUNK_NIL); - if (nth == 0) return 0; // Not found. - } - - while (*wpi_list != NULL) { - WebPMuxImage* const cur_wpi = *wpi_list; - ++count; - if (count == nth) return 1; // Found. - wpi_list = &cur_wpi->next_; - *location = wpi_list; - } - return 0; // Not found. -} - -//------------------------------------------------------------------------------ -// MuxImage writer methods. - -WebPMuxError MuxImagePush(const WebPMuxImage* wpi, WebPMuxImage** wpi_list) { - WebPMuxImage* new_wpi; - - while (*wpi_list != NULL) { - WebPMuxImage* const cur_wpi = *wpi_list; - if (cur_wpi->next_ == NULL) break; - wpi_list = &cur_wpi->next_; - } - - new_wpi = (WebPMuxImage*)WebPSafeMalloc(1ULL, sizeof(*new_wpi)); - if (new_wpi == NULL) return WEBP_MUX_MEMORY_ERROR; - *new_wpi = *wpi; - new_wpi->next_ = NULL; - - if (*wpi_list != NULL) { - (*wpi_list)->next_ = new_wpi; - } else { - *wpi_list = new_wpi; - } - return WEBP_MUX_OK; -} - -//------------------------------------------------------------------------------ -// MuxImage deletion methods. - -WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi) { - // Delete the components of wpi. If wpi is NULL this is a noop. - WebPMuxImage* const next = MuxImageRelease(wpi); - WebPSafeFree(wpi); - return next; -} - -WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth) { - assert(wpi_list); - if (!SearchImageToGetOrDelete(wpi_list, nth, &wpi_list)) { - return WEBP_MUX_NOT_FOUND; - } - *wpi_list = MuxImageDelete(*wpi_list); - return WEBP_MUX_OK; -} - -//------------------------------------------------------------------------------ -// MuxImage reader methods. - -WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth, - WebPMuxImage** wpi) { - assert(wpi_list); - assert(wpi); - if (!SearchImageToGetOrDelete((WebPMuxImage**)wpi_list, nth, - (WebPMuxImage***)&wpi_list)) { - return WEBP_MUX_NOT_FOUND; - } - *wpi = (WebPMuxImage*)*wpi_list; - return WEBP_MUX_OK; -} - -//------------------------------------------------------------------------------ -// MuxImage serialization methods. - -// Size of an image. -size_t MuxImageDiskSize(const WebPMuxImage* const wpi) { - size_t size = 0; - if (wpi->header_ != NULL) size += ChunkDiskSize(wpi->header_); - if (wpi->alpha_ != NULL) size += ChunkDiskSize(wpi->alpha_); - if (wpi->img_ != NULL) size += ChunkDiskSize(wpi->img_); - if (wpi->unknown_ != NULL) size += ChunkListDiskSize(wpi->unknown_); - return size; -} - -// Special case as ANMF/FRGM chunk encapsulates other image chunks. -static uint8_t* ChunkEmitSpecial(const WebPChunk* const header, - size_t total_size, uint8_t* dst) { - const size_t header_size = header->data_.size; - const size_t offset_to_next = total_size - CHUNK_HEADER_SIZE; - assert(header->tag_ == kChunks[IDX_ANMF].tag || - header->tag_ == kChunks[IDX_FRGM].tag); - PutLE32(dst + 0, header->tag_); - PutLE32(dst + TAG_SIZE, (uint32_t)offset_to_next); - assert(header_size == (uint32_t)header_size); - memcpy(dst + CHUNK_HEADER_SIZE, header->data_.bytes, header_size); - if (header_size & 1) { - dst[CHUNK_HEADER_SIZE + header_size] = 0; // Add padding. - } - return dst + ChunkDiskSize(header); -} - -uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst) { - // Ordering of chunks to be emitted is strictly as follows: - // 1. ANMF/FRGM chunk (if present). - // 2. ALPH chunk (if present). - // 3. VP8/VP8L chunk. - assert(wpi); - if (wpi->header_ != NULL) { - dst = ChunkEmitSpecial(wpi->header_, MuxImageDiskSize(wpi), dst); - } - if (wpi->alpha_ != NULL) dst = ChunkEmit(wpi->alpha_, dst); - if (wpi->img_ != NULL) dst = ChunkEmit(wpi->img_, dst); - if (wpi->unknown_ != NULL) dst = ChunkListEmit(wpi->unknown_, dst); - return dst; -} - -//------------------------------------------------------------------------------ -// Helper methods for mux. - -int MuxHasAlpha(const WebPMuxImage* images) { - while (images != NULL) { - if (images->has_alpha_) return 1; - images = images->next_; - } - return 0; -} - -uint8_t* MuxEmitRiffHeader(uint8_t* const data, size_t size) { - PutLE32(data + 0, MKFOURCC('R', 'I', 'F', 'F')); - PutLE32(data + TAG_SIZE, (uint32_t)size - CHUNK_HEADER_SIZE); - assert(size == (uint32_t)size); - PutLE32(data + TAG_SIZE + CHUNK_SIZE_BYTES, MKFOURCC('W', 'E', 'B', 'P')); - return data + RIFF_HEADER_SIZE; -} - -WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id) { - assert(mux != NULL); - switch (id) { - case WEBP_CHUNK_VP8X: return (WebPChunk**)&mux->vp8x_; - case WEBP_CHUNK_ICCP: return (WebPChunk**)&mux->iccp_; - case WEBP_CHUNK_ANIM: return (WebPChunk**)&mux->anim_; - case WEBP_CHUNK_EXIF: return (WebPChunk**)&mux->exif_; - case WEBP_CHUNK_XMP: return (WebPChunk**)&mux->xmp_; - default: return (WebPChunk**)&mux->unknown_; - } -} - -static int IsNotCompatible(int feature, int num_items) { - return (feature != 0) != (num_items > 0); -} - -#define NO_FLAG 0 - -// Test basic constraints: -// retrieval, maximum number of chunks by index (use -1 to skip) -// and feature incompatibility (use NO_FLAG to skip). -// On success returns WEBP_MUX_OK and stores the chunk count in *num. -static WebPMuxError ValidateChunk(const WebPMux* const mux, CHUNK_INDEX idx, - WebPFeatureFlags feature, - uint32_t vp8x_flags, - int max, int* num) { - const WebPMuxError err = - WebPMuxNumChunks(mux, kChunks[idx].id, num); - if (err != WEBP_MUX_OK) return err; - if (max > -1 && *num > max) return WEBP_MUX_INVALID_ARGUMENT; - if (feature != NO_FLAG && IsNotCompatible(vp8x_flags & feature, *num)) { - return WEBP_MUX_INVALID_ARGUMENT; - } - return WEBP_MUX_OK; -} - -WebPMuxError MuxValidate(const WebPMux* const mux) { - int num_iccp; - int num_exif; - int num_xmp; - int num_anim; - int num_frames; - int num_fragments; - int num_vp8x; - int num_images; - int num_alpha; - uint32_t flags; - WebPMuxError err; - - // Verify mux is not NULL. - if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT; - - // Verify mux has at least one image. - if (mux->images_ == NULL) return WEBP_MUX_INVALID_ARGUMENT; - - err = WebPMuxGetFeatures(mux, &flags); - if (err != WEBP_MUX_OK) return err; - - // At most one color profile chunk. - err = ValidateChunk(mux, IDX_ICCP, ICCP_FLAG, flags, 1, &num_iccp); - if (err != WEBP_MUX_OK) return err; - - // At most one EXIF metadata. - err = ValidateChunk(mux, IDX_EXIF, EXIF_FLAG, flags, 1, &num_exif); - if (err != WEBP_MUX_OK) return err; - - // At most one XMP metadata. - err = ValidateChunk(mux, IDX_XMP, XMP_FLAG, flags, 1, &num_xmp); - if (err != WEBP_MUX_OK) return err; - - // Animation: ANIMATION_FLAG, ANIM chunk and ANMF chunk(s) are consistent. - // At most one ANIM chunk. - err = ValidateChunk(mux, IDX_ANIM, NO_FLAG, flags, 1, &num_anim); - if (err != WEBP_MUX_OK) return err; - err = ValidateChunk(mux, IDX_ANMF, NO_FLAG, flags, -1, &num_frames); - if (err != WEBP_MUX_OK) return err; - - { - const int has_animation = !!(flags & ANIMATION_FLAG); - if (has_animation && (num_anim == 0 || num_frames == 0)) { - return WEBP_MUX_INVALID_ARGUMENT; - } - if (!has_animation && (num_anim == 1 || num_frames > 0)) { - return WEBP_MUX_INVALID_ARGUMENT; - } - } - - // Fragmentation: FRAGMENTS_FLAG and FRGM chunk(s) are consistent. - err = ValidateChunk(mux, IDX_FRGM, FRAGMENTS_FLAG, flags, -1, &num_fragments); - if (err != WEBP_MUX_OK) return err; - - // Verify either VP8X chunk is present OR there is only one elem in - // mux->images_. - err = ValidateChunk(mux, IDX_VP8X, NO_FLAG, flags, 1, &num_vp8x); - if (err != WEBP_MUX_OK) return err; - err = ValidateChunk(mux, IDX_VP8, NO_FLAG, flags, -1, &num_images); - if (err != WEBP_MUX_OK) return err; - if (num_vp8x == 0 && num_images != 1) return WEBP_MUX_INVALID_ARGUMENT; - - // ALPHA_FLAG & alpha chunk(s) are consistent. - if (MuxHasAlpha(mux->images_)) { - if (num_vp8x > 0) { - // VP8X chunk is present, so it should contain ALPHA_FLAG. - if (!(flags & ALPHA_FLAG)) return WEBP_MUX_INVALID_ARGUMENT; - } else { - // VP8X chunk is not present, so ALPH chunks should NOT be present either. - err = WebPMuxNumChunks(mux, WEBP_CHUNK_ALPHA, &num_alpha); - if (err != WEBP_MUX_OK) return err; - if (num_alpha > 0) return WEBP_MUX_INVALID_ARGUMENT; - } - } else { // Mux doesn't need alpha. So, ALPHA_FLAG should NOT be present. - if (flags & ALPHA_FLAG) return WEBP_MUX_INVALID_ARGUMENT; - } - - // num_fragments & num_images are consistent. - if (num_fragments > 0 && num_images != num_fragments) { - return WEBP_MUX_INVALID_ARGUMENT; - } - - return WEBP_MUX_OK; -} - -#undef NO_FLAG - -//------------------------------------------------------------------------------ - diff --git a/Example/Pods/libwebp/src/mux/muxread.c b/Example/Pods/libwebp/src/mux/muxread.c deleted file mode 100644 index 8957a1e4..00000000 --- a/Example/Pods/libwebp/src/mux/muxread.c +++ /dev/null @@ -1,544 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Read APIs for mux. -// -// Authors: Urvang (urvang@google.com) -// Vikas (vikasa@google.com) - -#include -#include "./muxi.h" -#include "../utils/utils.h" - -//------------------------------------------------------------------------------ -// Helper method(s). - -// Handy MACRO. -#define SWITCH_ID_LIST(INDEX, LIST) \ - if (idx == (INDEX)) { \ - const WebPChunk* const chunk = ChunkSearchList((LIST), nth, \ - kChunks[(INDEX)].tag); \ - if (chunk) { \ - *data = chunk->data_; \ - return WEBP_MUX_OK; \ - } else { \ - return WEBP_MUX_NOT_FOUND; \ - } \ - } - -static WebPMuxError MuxGet(const WebPMux* const mux, CHUNK_INDEX idx, - uint32_t nth, WebPData* const data) { - assert(mux != NULL); - assert(!IsWPI(kChunks[idx].id)); - WebPDataInit(data); - - SWITCH_ID_LIST(IDX_VP8X, mux->vp8x_); - SWITCH_ID_LIST(IDX_ICCP, mux->iccp_); - SWITCH_ID_LIST(IDX_ANIM, mux->anim_); - SWITCH_ID_LIST(IDX_EXIF, mux->exif_); - SWITCH_ID_LIST(IDX_XMP, mux->xmp_); - SWITCH_ID_LIST(IDX_UNKNOWN, mux->unknown_); - return WEBP_MUX_NOT_FOUND; -} -#undef SWITCH_ID_LIST - -// Fill the chunk with the given data (includes chunk header bytes), after some -// verifications. -static WebPMuxError ChunkVerifyAndAssign(WebPChunk* chunk, - const uint8_t* data, size_t data_size, - size_t riff_size, int copy_data) { - uint32_t chunk_size; - WebPData chunk_data; - - // Sanity checks. - if (data_size < CHUNK_HEADER_SIZE) return WEBP_MUX_NOT_ENOUGH_DATA; - chunk_size = GetLE32(data + TAG_SIZE); - - { - const size_t chunk_disk_size = SizeWithPadding(chunk_size); - if (chunk_disk_size > riff_size) return WEBP_MUX_BAD_DATA; - if (chunk_disk_size > data_size) return WEBP_MUX_NOT_ENOUGH_DATA; - } - - // Data assignment. - chunk_data.bytes = data + CHUNK_HEADER_SIZE; - chunk_data.size = chunk_size; - return ChunkAssignData(chunk, &chunk_data, copy_data, GetLE32(data + 0)); -} - -int MuxImageFinalize(WebPMuxImage* const wpi) { - const WebPChunk* const img = wpi->img_; - const WebPData* const image = &img->data_; - const int is_lossless = (img->tag_ == kChunks[IDX_VP8L].tag); - int w, h; - int vp8l_has_alpha = 0; - const int ok = is_lossless ? - VP8LGetInfo(image->bytes, image->size, &w, &h, &vp8l_has_alpha) : - VP8GetInfo(image->bytes, image->size, image->size, &w, &h); - assert(img != NULL); - if (ok) { - // Ignore ALPH chunk accompanying VP8L. - if (is_lossless && (wpi->alpha_ != NULL)) { - ChunkDelete(wpi->alpha_); - wpi->alpha_ = NULL; - } - wpi->width_ = w; - wpi->height_ = h; - wpi->has_alpha_ = vp8l_has_alpha || (wpi->alpha_ != NULL); - } - return ok; -} - -static int MuxImageParse(const WebPChunk* const chunk, int copy_data, - WebPMuxImage* const wpi) { - const uint8_t* bytes = chunk->data_.bytes; - size_t size = chunk->data_.size; - const uint8_t* const last = bytes + size; - WebPChunk subchunk; - size_t subchunk_size; - ChunkInit(&subchunk); - - assert(chunk->tag_ == kChunks[IDX_ANMF].tag || - chunk->tag_ == kChunks[IDX_FRGM].tag); - assert(!wpi->is_partial_); - - // ANMF/FRGM. - { - const size_t hdr_size = (chunk->tag_ == kChunks[IDX_ANMF].tag) ? - ANMF_CHUNK_SIZE : FRGM_CHUNK_SIZE; - const WebPData temp = { bytes, hdr_size }; - // Each of ANMF and FRGM chunk contain a header at the beginning. So, its - // size should at least be 'hdr_size'. - if (size < hdr_size) goto Fail; - ChunkAssignData(&subchunk, &temp, copy_data, chunk->tag_); - } - ChunkSetNth(&subchunk, &wpi->header_, 1); - wpi->is_partial_ = 1; // Waiting for ALPH and/or VP8/VP8L chunks. - - // Rest of the chunks. - subchunk_size = ChunkDiskSize(&subchunk) - CHUNK_HEADER_SIZE; - bytes += subchunk_size; - size -= subchunk_size; - - while (bytes != last) { - ChunkInit(&subchunk); - if (ChunkVerifyAndAssign(&subchunk, bytes, size, size, - copy_data) != WEBP_MUX_OK) { - goto Fail; - } - switch (ChunkGetIdFromTag(subchunk.tag_)) { - case WEBP_CHUNK_ALPHA: - if (wpi->alpha_ != NULL) goto Fail; // Consecutive ALPH chunks. - if (ChunkSetNth(&subchunk, &wpi->alpha_, 1) != WEBP_MUX_OK) goto Fail; - wpi->is_partial_ = 1; // Waiting for a VP8 chunk. - break; - case WEBP_CHUNK_IMAGE: - if (ChunkSetNth(&subchunk, &wpi->img_, 1) != WEBP_MUX_OK) goto Fail; - if (!MuxImageFinalize(wpi)) goto Fail; - wpi->is_partial_ = 0; // wpi is completely filled. - break; - case WEBP_CHUNK_UNKNOWN: - if (wpi->is_partial_) goto Fail; // Encountered an unknown chunk - // before some image chunks. - if (ChunkSetNth(&subchunk, &wpi->unknown_, 0) != WEBP_MUX_OK) goto Fail; - break; - default: - goto Fail; - break; - } - subchunk_size = ChunkDiskSize(&subchunk); - bytes += subchunk_size; - size -= subchunk_size; - } - if (wpi->is_partial_) goto Fail; - return 1; - - Fail: - ChunkRelease(&subchunk); - return 0; -} - -//------------------------------------------------------------------------------ -// Create a mux object from WebP-RIFF data. - -WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data, - int version) { - size_t riff_size; - uint32_t tag; - const uint8_t* end; - WebPMux* mux = NULL; - WebPMuxImage* wpi = NULL; - const uint8_t* data; - size_t size; - WebPChunk chunk; - ChunkInit(&chunk); - - // Sanity checks. - if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_MUX_ABI_VERSION)) { - return NULL; // version mismatch - } - if (bitstream == NULL) return NULL; - - data = bitstream->bytes; - size = bitstream->size; - - if (data == NULL) return NULL; - if (size < RIFF_HEADER_SIZE) return NULL; - if (GetLE32(data + 0) != MKFOURCC('R', 'I', 'F', 'F') || - GetLE32(data + CHUNK_HEADER_SIZE) != MKFOURCC('W', 'E', 'B', 'P')) { - return NULL; - } - - mux = WebPMuxNew(); - if (mux == NULL) return NULL; - - if (size < RIFF_HEADER_SIZE + TAG_SIZE) goto Err; - - tag = GetLE32(data + RIFF_HEADER_SIZE); - if (tag != kChunks[IDX_VP8].tag && - tag != kChunks[IDX_VP8L].tag && - tag != kChunks[IDX_VP8X].tag) { - goto Err; // First chunk should be VP8, VP8L or VP8X. - } - - riff_size = SizeWithPadding(GetLE32(data + TAG_SIZE)); - if (riff_size > MAX_CHUNK_PAYLOAD || riff_size > size) { - goto Err; - } else { - if (riff_size < size) { // Redundant data after last chunk. - size = riff_size; // To make sure we don't read any data beyond mux_size. - } - } - - end = data + size; - data += RIFF_HEADER_SIZE; - size -= RIFF_HEADER_SIZE; - - wpi = (WebPMuxImage*)WebPSafeMalloc(1ULL, sizeof(*wpi)); - if (wpi == NULL) goto Err; - MuxImageInit(wpi); - - // Loop over chunks. - while (data != end) { - size_t data_size; - WebPChunkId id; - WebPChunk** chunk_list; - if (ChunkVerifyAndAssign(&chunk, data, size, riff_size, - copy_data) != WEBP_MUX_OK) { - goto Err; - } - data_size = ChunkDiskSize(&chunk); - id = ChunkGetIdFromTag(chunk.tag_); - switch (id) { - case WEBP_CHUNK_ALPHA: - if (wpi->alpha_ != NULL) goto Err; // Consecutive ALPH chunks. - if (ChunkSetNth(&chunk, &wpi->alpha_, 1) != WEBP_MUX_OK) goto Err; - wpi->is_partial_ = 1; // Waiting for a VP8 chunk. - break; - case WEBP_CHUNK_IMAGE: - if (ChunkSetNth(&chunk, &wpi->img_, 1) != WEBP_MUX_OK) goto Err; - if (!MuxImageFinalize(wpi)) goto Err; - wpi->is_partial_ = 0; // wpi is completely filled. - PushImage: - // Add this to mux->images_ list. - if (MuxImagePush(wpi, &mux->images_) != WEBP_MUX_OK) goto Err; - MuxImageInit(wpi); // Reset for reading next image. - break; - case WEBP_CHUNK_ANMF: - if (wpi->is_partial_) goto Err; // Previous wpi is still incomplete. - if (!MuxImageParse(&chunk, copy_data, wpi)) goto Err; - ChunkRelease(&chunk); - goto PushImage; - break; - default: // A non-image chunk. - if (wpi->is_partial_) goto Err; // Encountered a non-image chunk before - // getting all chunks of an image. - chunk_list = MuxGetChunkListFromId(mux, id); // List to add this chunk. - if (ChunkSetNth(&chunk, chunk_list, 0) != WEBP_MUX_OK) goto Err; - if (id == WEBP_CHUNK_VP8X) { // grab global specs - mux->canvas_width_ = GetLE24(data + 12) + 1; - mux->canvas_height_ = GetLE24(data + 15) + 1; - } - break; - } - data += data_size; - size -= data_size; - ChunkInit(&chunk); - } - - // Validate mux if complete. - if (MuxValidate(mux) != WEBP_MUX_OK) goto Err; - - MuxImageDelete(wpi); - return mux; // All OK; - - Err: // Something bad happened. - ChunkRelease(&chunk); - MuxImageDelete(wpi); - WebPMuxDelete(mux); - return NULL; -} - -//------------------------------------------------------------------------------ -// Get API(s). - -// Validates that the given mux has a single image. -static WebPMuxError ValidateForSingleImage(const WebPMux* const mux) { - const int num_images = MuxImageCount(mux->images_, WEBP_CHUNK_IMAGE); - const int num_frames = MuxImageCount(mux->images_, WEBP_CHUNK_ANMF); - const int num_fragments = MuxImageCount(mux->images_, WEBP_CHUNK_FRGM); - - if (num_images == 0) { - // No images in mux. - return WEBP_MUX_NOT_FOUND; - } else if (num_images == 1 && num_frames == 0 && num_fragments == 0) { - // Valid case (single image). - return WEBP_MUX_OK; - } else { - // Frame/Fragment case OR an invalid mux. - return WEBP_MUX_INVALID_ARGUMENT; - } -} - -// Get the canvas width, height and flags after validating that VP8X/VP8/VP8L -// chunk and canvas size are valid. -static WebPMuxError MuxGetCanvasInfo(const WebPMux* const mux, - int* width, int* height, uint32_t* flags) { - int w, h; - uint32_t f = 0; - WebPData data; - assert(mux != NULL); - - // Check if VP8X chunk is present. - if (MuxGet(mux, IDX_VP8X, 1, &data) == WEBP_MUX_OK) { - if (data.size < VP8X_CHUNK_SIZE) return WEBP_MUX_BAD_DATA; - f = GetLE32(data.bytes + 0); - w = GetLE24(data.bytes + 4) + 1; - h = GetLE24(data.bytes + 7) + 1; - } else { - const WebPMuxImage* const wpi = mux->images_; - // Grab user-forced canvas size as default. - w = mux->canvas_width_; - h = mux->canvas_height_; - if (w == 0 && h == 0 && ValidateForSingleImage(mux) == WEBP_MUX_OK) { - // single image and not forced canvas size => use dimension of first frame - assert(wpi != NULL); - w = wpi->width_; - h = wpi->height_; - } - if (wpi != NULL) { - if (wpi->has_alpha_) f |= ALPHA_FLAG; - } - } - if (w * (uint64_t)h >= MAX_IMAGE_AREA) return WEBP_MUX_BAD_DATA; - - if (width != NULL) *width = w; - if (height != NULL) *height = h; - if (flags != NULL) *flags = f; - return WEBP_MUX_OK; -} - -WebPMuxError WebPMuxGetCanvasSize(const WebPMux* mux, int* width, int* height) { - if (mux == NULL || width == NULL || height == NULL) { - return WEBP_MUX_INVALID_ARGUMENT; - } - return MuxGetCanvasInfo(mux, width, height, NULL); -} - -WebPMuxError WebPMuxGetFeatures(const WebPMux* mux, uint32_t* flags) { - if (mux == NULL || flags == NULL) return WEBP_MUX_INVALID_ARGUMENT; - return MuxGetCanvasInfo(mux, NULL, NULL, flags); -} - -static uint8_t* EmitVP8XChunk(uint8_t* const dst, int width, - int height, uint32_t flags) { - const size_t vp8x_size = CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE; - assert(width >= 1 && height >= 1); - assert(width <= MAX_CANVAS_SIZE && height <= MAX_CANVAS_SIZE); - assert(width * (uint64_t)height < MAX_IMAGE_AREA); - PutLE32(dst, MKFOURCC('V', 'P', '8', 'X')); - PutLE32(dst + TAG_SIZE, VP8X_CHUNK_SIZE); - PutLE32(dst + CHUNK_HEADER_SIZE, flags); - PutLE24(dst + CHUNK_HEADER_SIZE + 4, width - 1); - PutLE24(dst + CHUNK_HEADER_SIZE + 7, height - 1); - return dst + vp8x_size; -} - -// Assemble a single image WebP bitstream from 'wpi'. -static WebPMuxError SynthesizeBitstream(const WebPMuxImage* const wpi, - WebPData* const bitstream) { - uint8_t* dst; - - // Allocate data. - const int need_vp8x = (wpi->alpha_ != NULL); - const size_t vp8x_size = need_vp8x ? CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE : 0; - const size_t alpha_size = need_vp8x ? ChunkDiskSize(wpi->alpha_) : 0; - // Note: No need to output ANMF/FRGM chunk for a single image. - const size_t size = RIFF_HEADER_SIZE + vp8x_size + alpha_size + - ChunkDiskSize(wpi->img_); - uint8_t* const data = (uint8_t*)WebPSafeMalloc(1ULL, size); - if (data == NULL) return WEBP_MUX_MEMORY_ERROR; - - // Main RIFF header. - dst = MuxEmitRiffHeader(data, size); - - if (need_vp8x) { - dst = EmitVP8XChunk(dst, wpi->width_, wpi->height_, ALPHA_FLAG); // VP8X. - dst = ChunkListEmit(wpi->alpha_, dst); // ALPH. - } - - // Bitstream. - dst = ChunkListEmit(wpi->img_, dst); - assert(dst == data + size); - - // Output. - bitstream->bytes = data; - bitstream->size = size; - return WEBP_MUX_OK; -} - -WebPMuxError WebPMuxGetChunk(const WebPMux* mux, const char fourcc[4], - WebPData* chunk_data) { - CHUNK_INDEX idx; - if (mux == NULL || fourcc == NULL || chunk_data == NULL) { - return WEBP_MUX_INVALID_ARGUMENT; - } - idx = ChunkGetIndexFromFourCC(fourcc); - if (IsWPI(kChunks[idx].id)) { // An image chunk. - return WEBP_MUX_INVALID_ARGUMENT; - } else if (idx != IDX_UNKNOWN) { // A known chunk type. - return MuxGet(mux, idx, 1, chunk_data); - } else { // An unknown chunk type. - const WebPChunk* const chunk = - ChunkSearchList(mux->unknown_, 1, ChunkGetTagFromFourCC(fourcc)); - if (chunk == NULL) return WEBP_MUX_NOT_FOUND; - *chunk_data = chunk->data_; - return WEBP_MUX_OK; - } -} - -static WebPMuxError MuxGetImageInternal(const WebPMuxImage* const wpi, - WebPMuxFrameInfo* const info) { - // Set some defaults for unrelated fields. - info->x_offset = 0; - info->y_offset = 0; - info->duration = 1; - info->dispose_method = WEBP_MUX_DISPOSE_NONE; - info->blend_method = WEBP_MUX_BLEND; - // Extract data for related fields. - info->id = ChunkGetIdFromTag(wpi->img_->tag_); - return SynthesizeBitstream(wpi, &info->bitstream); -} - -static WebPMuxError MuxGetFrameFragmentInternal(const WebPMuxImage* const wpi, - WebPMuxFrameInfo* const frame) { - const int is_frame = (wpi->header_->tag_ == kChunks[IDX_ANMF].tag); - const CHUNK_INDEX idx = is_frame ? IDX_ANMF : IDX_FRGM; - const WebPData* frame_frgm_data; - if (!is_frame) return WEBP_MUX_INVALID_ARGUMENT; - assert(wpi->header_ != NULL); // Already checked by WebPMuxGetFrame(). - // Get frame/fragment chunk. - frame_frgm_data = &wpi->header_->data_; - if (frame_frgm_data->size < kChunks[idx].size) return WEBP_MUX_BAD_DATA; - // Extract info. - frame->x_offset = 2 * GetLE24(frame_frgm_data->bytes + 0); - frame->y_offset = 2 * GetLE24(frame_frgm_data->bytes + 3); - if (is_frame) { - const uint8_t bits = frame_frgm_data->bytes[15]; - frame->duration = GetLE24(frame_frgm_data->bytes + 12); - frame->dispose_method = - (bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE; - frame->blend_method = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND; - } else { // Defaults for unused values. - frame->duration = 1; - frame->dispose_method = WEBP_MUX_DISPOSE_NONE; - frame->blend_method = WEBP_MUX_BLEND; - } - frame->id = ChunkGetIdFromTag(wpi->header_->tag_); - return SynthesizeBitstream(wpi, &frame->bitstream); -} - -WebPMuxError WebPMuxGetFrame( - const WebPMux* mux, uint32_t nth, WebPMuxFrameInfo* frame) { - WebPMuxError err; - WebPMuxImage* wpi; - - // Sanity checks. - if (mux == NULL || frame == NULL) { - return WEBP_MUX_INVALID_ARGUMENT; - } - - // Get the nth WebPMuxImage. - err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, nth, &wpi); - if (err != WEBP_MUX_OK) return err; - - // Get frame info. - if (wpi->header_ == NULL) { - return MuxGetImageInternal(wpi, frame); - } else { - return MuxGetFrameFragmentInternal(wpi, frame); - } -} - -WebPMuxError WebPMuxGetAnimationParams(const WebPMux* mux, - WebPMuxAnimParams* params) { - WebPData anim; - WebPMuxError err; - - if (mux == NULL || params == NULL) return WEBP_MUX_INVALID_ARGUMENT; - - err = MuxGet(mux, IDX_ANIM, 1, &anim); - if (err != WEBP_MUX_OK) return err; - if (anim.size < kChunks[WEBP_CHUNK_ANIM].size) return WEBP_MUX_BAD_DATA; - params->bgcolor = GetLE32(anim.bytes); - params->loop_count = GetLE16(anim.bytes + 4); - - return WEBP_MUX_OK; -} - -// Get chunk index from chunk id. Returns IDX_NIL if not found. -static CHUNK_INDEX ChunkGetIndexFromId(WebPChunkId id) { - int i; - for (i = 0; kChunks[i].id != WEBP_CHUNK_NIL; ++i) { - if (id == kChunks[i].id) return (CHUNK_INDEX)i; - } - return IDX_NIL; -} - -// Count number of chunks matching 'tag' in the 'chunk_list'. -// If tag == NIL_TAG, any tag will be matched. -static int CountChunks(const WebPChunk* const chunk_list, uint32_t tag) { - int count = 0; - const WebPChunk* current; - for (current = chunk_list; current != NULL; current = current->next_) { - if (tag == NIL_TAG || current->tag_ == tag) { - count++; // Count chunks whose tags match. - } - } - return count; -} - -WebPMuxError WebPMuxNumChunks(const WebPMux* mux, - WebPChunkId id, int* num_elements) { - if (mux == NULL || num_elements == NULL) { - return WEBP_MUX_INVALID_ARGUMENT; - } - - if (IsWPI(id)) { - *num_elements = MuxImageCount(mux->images_, id); - } else { - WebPChunk* const* chunk_list = MuxGetChunkListFromId(mux, id); - const CHUNK_INDEX idx = ChunkGetIndexFromId(id); - *num_elements = CountChunks(*chunk_list, kChunks[idx].tag); - } - - return WEBP_MUX_OK; -} - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/utils/bit_reader.c b/Example/Pods/libwebp/src/utils/bit_reader.c deleted file mode 100644 index 45198e15..00000000 --- a/Example/Pods/libwebp/src/utils/bit_reader.c +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Boolean decoder non-inlined methods -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifdef HAVE_CONFIG_H -#include "../webp/config.h" -#endif - -#include "./bit_reader_inl.h" - -//------------------------------------------------------------------------------ -// VP8BitReader - -void VP8BitReaderSetBuffer(VP8BitReader* const br, - const uint8_t* const start, - size_t size) { - br->buf_ = start; - br->buf_end_ = start + size; - br->buf_max_ = - (size >= sizeof(lbit_t)) ? start + size - sizeof(lbit_t) + 1 - : start; -} - -void VP8InitBitReader(VP8BitReader* const br, - const uint8_t* const start, size_t size) { - assert(br != NULL); - assert(start != NULL); - assert(size < (1u << 31)); // limit ensured by format and upstream checks - br->range_ = 255 - 1; - br->value_ = 0; - br->bits_ = -8; // to load the very first 8bits - br->eof_ = 0; - VP8BitReaderSetBuffer(br, start, size); - VP8LoadNewBytes(br); -} - -void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset) { - if (br->buf_ != NULL) { - br->buf_ += offset; - br->buf_end_ += offset; - br->buf_max_ += offset; - } -} - -const uint8_t kVP8Log2Range[128] = { - 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0 -}; - -// range = ((range - 1) << kVP8Log2Range[range]) + 1 -const uint8_t kVP8NewRange[128] = { - 127, 127, 191, 127, 159, 191, 223, 127, - 143, 159, 175, 191, 207, 223, 239, 127, - 135, 143, 151, 159, 167, 175, 183, 191, - 199, 207, 215, 223, 231, 239, 247, 127, - 131, 135, 139, 143, 147, 151, 155, 159, - 163, 167, 171, 175, 179, 183, 187, 191, - 195, 199, 203, 207, 211, 215, 219, 223, - 227, 231, 235, 239, 243, 247, 251, 127, - 129, 131, 133, 135, 137, 139, 141, 143, - 145, 147, 149, 151, 153, 155, 157, 159, - 161, 163, 165, 167, 169, 171, 173, 175, - 177, 179, 181, 183, 185, 187, 189, 191, - 193, 195, 197, 199, 201, 203, 205, 207, - 209, 211, 213, 215, 217, 219, 221, 223, - 225, 227, 229, 231, 233, 235, 237, 239, - 241, 243, 245, 247, 249, 251, 253, 127 -}; - -void VP8LoadFinalBytes(VP8BitReader* const br) { - assert(br != NULL && br->buf_ != NULL); - // Only read 8bits at a time - if (br->buf_ < br->buf_end_) { - br->bits_ += 8; - br->value_ = (bit_t)(*br->buf_++) | (br->value_ << 8); - } else if (!br->eof_) { - br->value_ <<= 8; - br->bits_ += 8; - br->eof_ = 1; - } else { - br->bits_ = 0; // This is to avoid undefined behaviour with shifts. - } -} - -//------------------------------------------------------------------------------ -// Higher-level calls - -uint32_t VP8GetValue(VP8BitReader* const br, int bits) { - uint32_t v = 0; - while (bits-- > 0) { - v |= VP8GetBit(br, 0x80) << bits; - } - return v; -} - -int32_t VP8GetSignedValue(VP8BitReader* const br, int bits) { - const int value = VP8GetValue(br, bits); - return VP8Get(br) ? -value : value; -} - -//------------------------------------------------------------------------------ -// VP8LBitReader - -#define VP8L_LOG8_WBITS 4 // Number of bytes needed to store VP8L_WBITS bits. - -#if !defined(WEBP_FORCE_ALIGNED) && \ - (defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || \ - defined(__i386__) || defined(_M_IX86) || \ - defined(__x86_64__) || defined(_M_X64)) -#define VP8L_USE_UNALIGNED_LOAD -#endif - -static const uint32_t kBitMask[VP8L_MAX_NUM_BIT_READ + 1] = { - 0, - 0x000001, 0x000003, 0x000007, 0x00000f, - 0x00001f, 0x00003f, 0x00007f, 0x0000ff, - 0x0001ff, 0x0003ff, 0x0007ff, 0x000fff, - 0x001fff, 0x003fff, 0x007fff, 0x00ffff, - 0x01ffff, 0x03ffff, 0x07ffff, 0x0fffff, - 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff -}; - -void VP8LInitBitReader(VP8LBitReader* const br, const uint8_t* const start, - size_t length) { - size_t i; - vp8l_val_t value = 0; - assert(br != NULL); - assert(start != NULL); - assert(length < 0xfffffff8u); // can't happen with a RIFF chunk. - - br->len_ = length; - br->val_ = 0; - br->bit_pos_ = 0; - br->eos_ = 0; - - if (length > sizeof(br->val_)) { - length = sizeof(br->val_); - } - for (i = 0; i < length; ++i) { - value |= (vp8l_val_t)start[i] << (8 * i); - } - br->val_ = value; - br->pos_ = length; - br->buf_ = start; -} - -void VP8LBitReaderSetBuffer(VP8LBitReader* const br, - const uint8_t* const buf, size_t len) { - assert(br != NULL); - assert(buf != NULL); - assert(len < 0xfffffff8u); // can't happen with a RIFF chunk. - br->buf_ = buf; - br->len_ = len; - // pos_ > len_ should be considered a param error. - br->eos_ = (br->pos_ > br->len_) || VP8LIsEndOfStream(br); -} - -static void VP8LSetEndOfStream(VP8LBitReader* const br) { - br->eos_ = 1; - br->bit_pos_ = 0; // To avoid undefined behaviour with shifts. -} - -// If not at EOS, reload up to VP8L_LBITS byte-by-byte -static void ShiftBytes(VP8LBitReader* const br) { - while (br->bit_pos_ >= 8 && br->pos_ < br->len_) { - br->val_ >>= 8; - br->val_ |= ((vp8l_val_t)br->buf_[br->pos_]) << (VP8L_LBITS - 8); - ++br->pos_; - br->bit_pos_ -= 8; - } - if (VP8LIsEndOfStream(br)) { - VP8LSetEndOfStream(br); - } -} - -void VP8LDoFillBitWindow(VP8LBitReader* const br) { - assert(br->bit_pos_ >= VP8L_WBITS); - // TODO(jzern): given the fixed read size it may be possible to force - // alignment in this block. -#if defined(VP8L_USE_UNALIGNED_LOAD) - if (br->pos_ + sizeof(br->val_) < br->len_) { - br->val_ >>= VP8L_WBITS; - br->bit_pos_ -= VP8L_WBITS; - // The expression below needs a little-endian arch to work correctly. - // This gives a large speedup for decoding speed. - br->val_ |= (vp8l_val_t)WebPMemToUint32(br->buf_ + br->pos_) << - (VP8L_LBITS - VP8L_WBITS); - br->pos_ += VP8L_LOG8_WBITS; - return; - } -#endif - ShiftBytes(br); // Slow path. -} - -uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits) { - assert(n_bits >= 0); - // Flag an error if end_of_stream or n_bits is more than allowed limit. - if (!br->eos_ && n_bits <= VP8L_MAX_NUM_BIT_READ) { - const uint32_t val = VP8LPrefetchBits(br) & kBitMask[n_bits]; - const int new_bits = br->bit_pos_ + n_bits; - br->bit_pos_ = new_bits; - ShiftBytes(br); - return val; - } else { - VP8LSetEndOfStream(br); - return 0; - } -} - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/utils/bit_reader.h b/Example/Pods/libwebp/src/utils/bit_reader.h deleted file mode 100644 index ec3426cd..00000000 --- a/Example/Pods/libwebp/src/utils/bit_reader.h +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Boolean decoder -// -// Author: Skal (pascal.massimino@gmail.com) -// Vikas Arora (vikaas.arora@gmail.com) - -#ifndef WEBP_UTILS_BIT_READER_H_ -#define WEBP_UTILS_BIT_READER_H_ - -#include -#ifdef _MSC_VER -#include // _byteswap_ulong -#endif -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// The Boolean decoder needs to maintain infinite precision on the value_ field. -// However, since range_ is only 8bit, we only need an active window of 8 bits -// for value_. Left bits (MSB) gets zeroed and shifted away when value_ falls -// below 128, range_ is updated, and fresh bits read from the bitstream are -// brought in as LSB. To avoid reading the fresh bits one by one (slow), we -// cache BITS of them ahead. The total of (BITS + 8) bits must fit into a -// natural register (with type bit_t). To fetch BITS bits from bitstream we -// use a type lbit_t. -// -// BITS can be any multiple of 8 from 8 to 56 (inclusive). -// Pick values that fit natural register size. - -#if defined(__i386__) || defined(_M_IX86) // x86 32bit -#define BITS 24 -#elif defined(__x86_64__) || defined(_M_X64) // x86 64bit -#define BITS 56 -#elif defined(__arm__) || defined(_M_ARM) // ARM -#define BITS 24 -#elif defined(__aarch64__) // ARM 64bit -#define BITS 56 -#elif defined(__mips__) // MIPS -#define BITS 24 -#else // reasonable default -#define BITS 24 -#endif - -//------------------------------------------------------------------------------ -// Derived types and constants: -// bit_t = natural register type for storing 'value_' (which is BITS+8 bits) -// range_t = register for 'range_' (which is 8bits only) - -#if (BITS > 24) -typedef uint64_t bit_t; -#else -typedef uint32_t bit_t; -#endif - -typedef uint32_t range_t; - -//------------------------------------------------------------------------------ -// Bitreader - -typedef struct VP8BitReader VP8BitReader; -struct VP8BitReader { - // boolean decoder (keep the field ordering as is!) - bit_t value_; // current value - range_t range_; // current range minus 1. In [127, 254] interval. - int bits_; // number of valid bits left - // read buffer - const uint8_t* buf_; // next byte to be read - const uint8_t* buf_end_; // end of read buffer - const uint8_t* buf_max_; // max packed-read position on buffer - int eof_; // true if input is exhausted -}; - -// Initialize the bit reader and the boolean decoder. -void VP8InitBitReader(VP8BitReader* const br, - const uint8_t* const start, size_t size); -// Sets the working read buffer. -void VP8BitReaderSetBuffer(VP8BitReader* const br, - const uint8_t* const start, size_t size); - -// Update internal pointers to displace the byte buffer by the -// relative offset 'offset'. -void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset); - -// return the next value made of 'num_bits' bits -uint32_t VP8GetValue(VP8BitReader* const br, int num_bits); -static WEBP_INLINE uint32_t VP8Get(VP8BitReader* const br) { - return VP8GetValue(br, 1); -} - -// return the next value with sign-extension. -int32_t VP8GetSignedValue(VP8BitReader* const br, int num_bits); - -// bit_reader_inl.h will implement the following methods: -// static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob) -// static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v) -// and should be included by the .c files that actually need them. -// This is to avoid recompiling the whole library whenever this file is touched, -// and also allowing platform-specific ad-hoc hacks. - -// ----------------------------------------------------------------------------- -// Bitreader for lossless format - -// maximum number of bits (inclusive) the bit-reader can handle: -#define VP8L_MAX_NUM_BIT_READ 24 - -#define VP8L_LBITS 64 // Number of bits prefetched (= bit-size of vp8l_val_t). -#define VP8L_WBITS 32 // Minimum number of bytes ready after VP8LFillBitWindow. - -typedef uint64_t vp8l_val_t; // right now, this bit-reader can only use 64bit. - -typedef struct { - vp8l_val_t val_; // pre-fetched bits - const uint8_t* buf_; // input byte buffer - size_t len_; // buffer length - size_t pos_; // byte position in buf_ - int bit_pos_; // current bit-reading position in val_ - int eos_; // true if a bit was read past the end of buffer -} VP8LBitReader; - -void VP8LInitBitReader(VP8LBitReader* const br, - const uint8_t* const start, - size_t length); - -// Sets a new data buffer. -void VP8LBitReaderSetBuffer(VP8LBitReader* const br, - const uint8_t* const buffer, size_t length); - -// Reads the specified number of bits from read buffer. -// Flags an error in case end_of_stream or n_bits is more than the allowed limit -// of VP8L_MAX_NUM_BIT_READ (inclusive). -// Flags eos_ if this read attempt is going to cross the read buffer. -uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits); - -// Return the prefetched bits, so they can be looked up. -static WEBP_INLINE uint32_t VP8LPrefetchBits(VP8LBitReader* const br) { - return (uint32_t)(br->val_ >> (br->bit_pos_ & (VP8L_LBITS - 1))); -} - -// Returns true if there was an attempt at reading bit past the end of -// the buffer. Doesn't set br->eos_ flag. -static WEBP_INLINE int VP8LIsEndOfStream(const VP8LBitReader* const br) { - assert(br->pos_ <= br->len_); - return br->eos_ || ((br->pos_ == br->len_) && (br->bit_pos_ > VP8L_LBITS)); -} - -// For jumping over a number of bits in the bit stream when accessed with -// VP8LPrefetchBits and VP8LFillBitWindow. -static WEBP_INLINE void VP8LSetBitPos(VP8LBitReader* const br, int val) { - br->bit_pos_ = val; - br->eos_ = VP8LIsEndOfStream(br); -} - -// Advances the read buffer by 4 bytes to make room for reading next 32 bits. -// Speed critical, but infrequent part of the code can be non-inlined. -extern void VP8LDoFillBitWindow(VP8LBitReader* const br); -static WEBP_INLINE void VP8LFillBitWindow(VP8LBitReader* const br) { - if (br->bit_pos_ >= VP8L_WBITS) VP8LDoFillBitWindow(br); -} - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_BIT_READER_H_ */ diff --git a/Example/Pods/libwebp/src/utils/bit_reader_inl.h b/Example/Pods/libwebp/src/utils/bit_reader_inl.h deleted file mode 100644 index 37215702..00000000 --- a/Example/Pods/libwebp/src/utils/bit_reader_inl.h +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Specific inlined methods for boolean decoder [VP8GetBit() ...] -// This file should be included by the .c sources that actually need to call -// these methods. -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_UTILS_BIT_READER_INL_H_ -#define WEBP_UTILS_BIT_READER_INL_H_ - -#ifdef HAVE_CONFIG_H -#include "../webp/config.h" -#endif - -#ifdef WEBP_FORCE_ALIGNED -#include // memcpy -#endif - -#include "../dsp/dsp.h" -#include "./bit_reader.h" -#include "./endian_inl.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//------------------------------------------------------------------------------ -// Derived type lbit_t = natural type for memory I/O - -#if (BITS > 32) -typedef uint64_t lbit_t; -#elif (BITS > 16) -typedef uint32_t lbit_t; -#elif (BITS > 8) -typedef uint16_t lbit_t; -#else -typedef uint8_t lbit_t; -#endif - -extern const uint8_t kVP8Log2Range[128]; -extern const uint8_t kVP8NewRange[128]; - -// special case for the tail byte-reading -void VP8LoadFinalBytes(VP8BitReader* const br); - -//------------------------------------------------------------------------------ -// Inlined critical functions - -// makes sure br->value_ has at least BITS bits worth of data -static WEBP_INLINE void VP8LoadNewBytes(VP8BitReader* const br) { - assert(br != NULL && br->buf_ != NULL); - // Read 'BITS' bits at a time if possible. - if (br->buf_ < br->buf_max_) { - // convert memory type to register type (with some zero'ing!) - bit_t bits; -#if defined(WEBP_FORCE_ALIGNED) - lbit_t in_bits; - memcpy(&in_bits, br->buf_, sizeof(in_bits)); -#elif defined(WEBP_USE_MIPS32) - // This is needed because of un-aligned read. - lbit_t in_bits; - lbit_t* p_buf_ = (lbit_t*)br->buf_; - __asm__ volatile( - ".set push \n\t" - ".set at \n\t" - ".set macro \n\t" - "ulw %[in_bits], 0(%[p_buf_]) \n\t" - ".set pop \n\t" - : [in_bits]"=r"(in_bits) - : [p_buf_]"r"(p_buf_) - : "memory", "at" - ); -#else - const lbit_t in_bits = *(const lbit_t*)br->buf_; -#endif - br->buf_ += BITS >> 3; -#if !defined(WORDS_BIGENDIAN) -#if (BITS > 32) - bits = BSwap64(in_bits); - bits >>= 64 - BITS; -#elif (BITS >= 24) - bits = BSwap32(in_bits); - bits >>= (32 - BITS); -#elif (BITS == 16) - bits = BSwap16(in_bits); -#else // BITS == 8 - bits = (bit_t)in_bits; -#endif // BITS > 32 -#else // WORDS_BIGENDIAN - bits = (bit_t)in_bits; - if (BITS != 8 * sizeof(bit_t)) bits >>= (8 * sizeof(bit_t) - BITS); -#endif - br->value_ = bits | (br->value_ << BITS); - br->bits_ += BITS; - } else { - VP8LoadFinalBytes(br); // no need to be inlined - } -} - -// Read a bit with proba 'prob'. Speed-critical function! -static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob) { - // Don't move this declaration! It makes a big speed difference to store - // 'range' *before* calling VP8LoadNewBytes(), even if this function doesn't - // alter br->range_ value. - range_t range = br->range_; - if (br->bits_ < 0) { - VP8LoadNewBytes(br); - } - { - const int pos = br->bits_; - const range_t split = (range * prob) >> 8; - const range_t value = (range_t)(br->value_ >> pos); -#if defined(__arm__) || defined(_M_ARM) // ARM-specific - const int bit = ((int)(split - value) >> 31) & 1; - if (value > split) { - range -= split + 1; - br->value_ -= (bit_t)(split + 1) << pos; - } else { - range = split; - } -#else // faster version on x86 - int bit; // Don't use 'const int bit = (value > split);", it's slower. - if (value > split) { - range -= split + 1; - br->value_ -= (bit_t)(split + 1) << pos; - bit = 1; - } else { - range = split; - bit = 0; - } -#endif - if (range <= (range_t)0x7e) { - const int shift = kVP8Log2Range[range]; - range = kVP8NewRange[range]; - br->bits_ -= shift; - } - br->range_ = range; - return bit; - } -} - -// simplified version of VP8GetBit() for prob=0x80 (note shift is always 1 here) -static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v) { - if (br->bits_ < 0) { - VP8LoadNewBytes(br); - } - { - const int pos = br->bits_; - const range_t split = br->range_ >> 1; - const range_t value = (range_t)(br->value_ >> pos); - const int32_t mask = (int32_t)(split - value) >> 31; // -1 or 0 - br->bits_ -= 1; - br->range_ += mask; - br->range_ |= 1; - br->value_ -= (bit_t)((split + 1) & mask) << pos; - return (v ^ mask) - mask; - } -} - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // WEBP_UTILS_BIT_READER_INL_H_ diff --git a/Example/Pods/libwebp/src/utils/bit_writer.c b/Example/Pods/libwebp/src/utils/bit_writer.c deleted file mode 100644 index 06442869..00000000 --- a/Example/Pods/libwebp/src/utils/bit_writer.c +++ /dev/null @@ -1,319 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Bit writing and boolean coder -// -// Author: Skal (pascal.massimino@gmail.com) -// Vikas Arora (vikaas.arora@gmail.com) - -#include -#include // for memcpy() -#include - -#include "./bit_writer.h" -#include "./endian_inl.h" -#include "./utils.h" - -//------------------------------------------------------------------------------ -// VP8BitWriter - -static int BitWriterResize(VP8BitWriter* const bw, size_t extra_size) { - uint8_t* new_buf; - size_t new_size; - const uint64_t needed_size_64b = (uint64_t)bw->pos_ + extra_size; - const size_t needed_size = (size_t)needed_size_64b; - if (needed_size_64b != needed_size) { - bw->error_ = 1; - return 0; - } - if (needed_size <= bw->max_pos_) return 1; - // If the following line wraps over 32bit, the test just after will catch it. - new_size = 2 * bw->max_pos_; - if (new_size < needed_size) new_size = needed_size; - if (new_size < 1024) new_size = 1024; - new_buf = (uint8_t*)WebPSafeMalloc(1ULL, new_size); - if (new_buf == NULL) { - bw->error_ = 1; - return 0; - } - if (bw->pos_ > 0) { - assert(bw->buf_ != NULL); - memcpy(new_buf, bw->buf_, bw->pos_); - } - WebPSafeFree(bw->buf_); - bw->buf_ = new_buf; - bw->max_pos_ = new_size; - return 1; -} - -static void Flush(VP8BitWriter* const bw) { - const int s = 8 + bw->nb_bits_; - const int32_t bits = bw->value_ >> s; - assert(bw->nb_bits_ >= 0); - bw->value_ -= bits << s; - bw->nb_bits_ -= 8; - if ((bits & 0xff) != 0xff) { - size_t pos = bw->pos_; - if (!BitWriterResize(bw, bw->run_ + 1)) { - return; - } - if (bits & 0x100) { // overflow -> propagate carry over pending 0xff's - if (pos > 0) bw->buf_[pos - 1]++; - } - if (bw->run_ > 0) { - const int value = (bits & 0x100) ? 0x00 : 0xff; - for (; bw->run_ > 0; --bw->run_) bw->buf_[pos++] = value; - } - bw->buf_[pos++] = bits; - bw->pos_ = pos; - } else { - bw->run_++; // delay writing of bytes 0xff, pending eventual carry. - } -} - -//------------------------------------------------------------------------------ -// renormalization - -static const uint8_t kNorm[128] = { // renorm_sizes[i] = 8 - log2(i) - 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0 -}; - -// range = ((range + 1) << kVP8Log2Range[range]) - 1 -static const uint8_t kNewRange[128] = { - 127, 127, 191, 127, 159, 191, 223, 127, 143, 159, 175, 191, 207, 223, 239, - 127, 135, 143, 151, 159, 167, 175, 183, 191, 199, 207, 215, 223, 231, 239, - 247, 127, 131, 135, 139, 143, 147, 151, 155, 159, 163, 167, 171, 175, 179, - 183, 187, 191, 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239, - 243, 247, 251, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, - 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, - 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, - 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239, - 241, 243, 245, 247, 249, 251, 253, 127 -}; - -int VP8PutBit(VP8BitWriter* const bw, int bit, int prob) { - const int split = (bw->range_ * prob) >> 8; - if (bit) { - bw->value_ += split + 1; - bw->range_ -= split + 1; - } else { - bw->range_ = split; - } - if (bw->range_ < 127) { // emit 'shift' bits out and renormalize - const int shift = kNorm[bw->range_]; - bw->range_ = kNewRange[bw->range_]; - bw->value_ <<= shift; - bw->nb_bits_ += shift; - if (bw->nb_bits_ > 0) Flush(bw); - } - return bit; -} - -int VP8PutBitUniform(VP8BitWriter* const bw, int bit) { - const int split = bw->range_ >> 1; - if (bit) { - bw->value_ += split + 1; - bw->range_ -= split + 1; - } else { - bw->range_ = split; - } - if (bw->range_ < 127) { - bw->range_ = kNewRange[bw->range_]; - bw->value_ <<= 1; - bw->nb_bits_ += 1; - if (bw->nb_bits_ > 0) Flush(bw); - } - return bit; -} - -void VP8PutBits(VP8BitWriter* const bw, uint32_t value, int nb_bits) { - uint32_t mask; - assert(nb_bits > 0 && nb_bits < 32); - for (mask = 1u << (nb_bits - 1); mask; mask >>= 1) - VP8PutBitUniform(bw, value & mask); -} - -void VP8PutSignedBits(VP8BitWriter* const bw, int value, int nb_bits) { - if (!VP8PutBitUniform(bw, value != 0)) - return; - if (value < 0) { - VP8PutBits(bw, ((-value) << 1) | 1, nb_bits + 1); - } else { - VP8PutBits(bw, value << 1, nb_bits + 1); - } -} - -//------------------------------------------------------------------------------ - -int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size) { - bw->range_ = 255 - 1; - bw->value_ = 0; - bw->run_ = 0; - bw->nb_bits_ = -8; - bw->pos_ = 0; - bw->max_pos_ = 0; - bw->error_ = 0; - bw->buf_ = NULL; - return (expected_size > 0) ? BitWriterResize(bw, expected_size) : 1; -} - -uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw) { - VP8PutBits(bw, 0, 9 - bw->nb_bits_); - bw->nb_bits_ = 0; // pad with zeroes - Flush(bw); - return bw->buf_; -} - -int VP8BitWriterAppend(VP8BitWriter* const bw, - const uint8_t* data, size_t size) { - assert(data != NULL); - if (bw->nb_bits_ != -8) return 0; // Flush() must have been called - if (!BitWriterResize(bw, size)) return 0; - memcpy(bw->buf_ + bw->pos_, data, size); - bw->pos_ += size; - return 1; -} - -void VP8BitWriterWipeOut(VP8BitWriter* const bw) { - if (bw != NULL) { - WebPSafeFree(bw->buf_); - memset(bw, 0, sizeof(*bw)); - } -} - -//------------------------------------------------------------------------------ -// VP8LBitWriter - -// This is the minimum amount of size the memory buffer is guaranteed to grow -// when extra space is needed. -#define MIN_EXTRA_SIZE (32768ULL) - -// Returns 1 on success. -static int VP8LBitWriterResize(VP8LBitWriter* const bw, size_t extra_size) { - uint8_t* allocated_buf; - size_t allocated_size; - const size_t max_bytes = bw->end_ - bw->buf_; - const size_t current_size = bw->cur_ - bw->buf_; - const uint64_t size_required_64b = (uint64_t)current_size + extra_size; - const size_t size_required = (size_t)size_required_64b; - if (size_required != size_required_64b) { - bw->error_ = 1; - return 0; - } - if (max_bytes > 0 && size_required <= max_bytes) return 1; - allocated_size = (3 * max_bytes) >> 1; - if (allocated_size < size_required) allocated_size = size_required; - // make allocated size multiple of 1k - allocated_size = (((allocated_size >> 10) + 1) << 10); - allocated_buf = (uint8_t*)WebPSafeMalloc(1ULL, allocated_size); - if (allocated_buf == NULL) { - bw->error_ = 1; - return 0; - } - if (current_size > 0) { - memcpy(allocated_buf, bw->buf_, current_size); - } - WebPSafeFree(bw->buf_); - bw->buf_ = allocated_buf; - bw->cur_ = bw->buf_ + current_size; - bw->end_ = bw->buf_ + allocated_size; - return 1; -} - -int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size) { - memset(bw, 0, sizeof(*bw)); - return VP8LBitWriterResize(bw, expected_size); -} - -void VP8LBitWriterWipeOut(VP8LBitWriter* const bw) { - if (bw != NULL) { - WebPSafeFree(bw->buf_); - memset(bw, 0, sizeof(*bw)); - } -} - -void VP8LPutBitsFlushBits(VP8LBitWriter* const bw) { - // If needed, make some room by flushing some bits out. - if (bw->cur_ + VP8L_WRITER_BYTES > bw->end_) { - const uint64_t extra_size = (bw->end_ - bw->buf_) + MIN_EXTRA_SIZE; - if (extra_size != (size_t)extra_size || - !VP8LBitWriterResize(bw, (size_t)extra_size)) { - bw->cur_ = bw->buf_; - bw->error_ = 1; - return; - } - } - *(vp8l_wtype_t*)bw->cur_ = (vp8l_wtype_t)WSWAP((vp8l_wtype_t)bw->bits_); - bw->cur_ += VP8L_WRITER_BYTES; - bw->bits_ >>= VP8L_WRITER_BITS; - bw->used_ -= VP8L_WRITER_BITS; -} - -void VP8LPutBitsInternal(VP8LBitWriter* const bw, uint32_t bits, int n_bits) { - assert(n_bits <= 32); - // That's the max we can handle: - assert(sizeof(vp8l_wtype_t) == 2); - if (n_bits > 0) { - vp8l_atype_t lbits = bw->bits_; - int used = bw->used_; - // Special case of overflow handling for 32bit accumulator (2-steps flush). -#if VP8L_WRITER_BITS == 16 - if (used + n_bits >= VP8L_WRITER_MAX_BITS) { - // Fill up all the VP8L_WRITER_MAX_BITS so it can be flushed out below. - const int shift = VP8L_WRITER_MAX_BITS - used; - lbits |= (vp8l_atype_t)bits << used; - used = VP8L_WRITER_MAX_BITS; - n_bits -= shift; - bits >>= shift; - assert(n_bits <= VP8L_WRITER_MAX_BITS); - } -#endif - // If needed, make some room by flushing some bits out. - while (used >= VP8L_WRITER_BITS) { - if (bw->cur_ + VP8L_WRITER_BYTES > bw->end_) { - const uint64_t extra_size = (bw->end_ - bw->buf_) + MIN_EXTRA_SIZE; - if (extra_size != (size_t)extra_size || - !VP8LBitWriterResize(bw, (size_t)extra_size)) { - bw->cur_ = bw->buf_; - bw->error_ = 1; - return; - } - } - *(vp8l_wtype_t*)bw->cur_ = (vp8l_wtype_t)WSWAP((vp8l_wtype_t)lbits); - bw->cur_ += VP8L_WRITER_BYTES; - lbits >>= VP8L_WRITER_BITS; - used -= VP8L_WRITER_BITS; - } - bw->bits_ = lbits | ((vp8l_atype_t)bits << used); - bw->used_ = used + n_bits; - } -} - -uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw) { - // flush leftover bits - if (VP8LBitWriterResize(bw, (bw->used_ + 7) >> 3)) { - while (bw->used_ > 0) { - *bw->cur_++ = (uint8_t)bw->bits_; - bw->bits_ >>= 8; - bw->used_ -= 8; - } - bw->used_ = 0; - } - return bw->buf_; -} - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/utils/bit_writer.h b/Example/Pods/libwebp/src/utils/bit_writer.h deleted file mode 100644 index ef360d1d..00000000 --- a/Example/Pods/libwebp/src/utils/bit_writer.h +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Bit writing and boolean coder -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_UTILS_BIT_WRITER_H_ -#define WEBP_UTILS_BIT_WRITER_H_ - -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//------------------------------------------------------------------------------ -// Bit-writing - -typedef struct VP8BitWriter VP8BitWriter; -struct VP8BitWriter { - int32_t range_; // range-1 - int32_t value_; - int run_; // number of outstanding bits - int nb_bits_; // number of pending bits - uint8_t* buf_; // internal buffer. Re-allocated regularly. Not owned. - size_t pos_; - size_t max_pos_; - int error_; // true in case of error -}; - -// Initialize the object. Allocates some initial memory based on expected_size. -int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size); -// Finalize the bitstream coding. Returns a pointer to the internal buffer. -uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw); -// Release any pending memory and zeroes the object. Not a mandatory call. -// Only useful in case of error, when the internal buffer hasn't been grabbed! -void VP8BitWriterWipeOut(VP8BitWriter* const bw); - -int VP8PutBit(VP8BitWriter* const bw, int bit, int prob); -int VP8PutBitUniform(VP8BitWriter* const bw, int bit); -void VP8PutBits(VP8BitWriter* const bw, uint32_t value, int nb_bits); -void VP8PutSignedBits(VP8BitWriter* const bw, int value, int nb_bits); - -// Appends some bytes to the internal buffer. Data is copied. -int VP8BitWriterAppend(VP8BitWriter* const bw, - const uint8_t* data, size_t size); - -// return approximate write position (in bits) -static WEBP_INLINE uint64_t VP8BitWriterPos(const VP8BitWriter* const bw) { - return (uint64_t)(bw->pos_ + bw->run_) * 8 + 8 + bw->nb_bits_; -} - -// Returns a pointer to the internal buffer. -static WEBP_INLINE uint8_t* VP8BitWriterBuf(const VP8BitWriter* const bw) { - return bw->buf_; -} -// Returns the size of the internal buffer. -static WEBP_INLINE size_t VP8BitWriterSize(const VP8BitWriter* const bw) { - return bw->pos_; -} - -//------------------------------------------------------------------------------ -// VP8LBitWriter - -#if defined(__x86_64__) || defined(_M_X64) // 64bit -typedef uint64_t vp8l_atype_t; // accumulator type -typedef uint32_t vp8l_wtype_t; // writing type -#define WSWAP HToLE32 -#define VP8L_WRITER_BYTES 4 // sizeof(vp8l_wtype_t) -#define VP8L_WRITER_BITS 32 // 8 * sizeof(vp8l_wtype_t) -#define VP8L_WRITER_MAX_BITS 64 // 8 * sizeof(vp8l_atype_t) -#else -typedef uint32_t vp8l_atype_t; -typedef uint16_t vp8l_wtype_t; -#define WSWAP HToLE16 -#define VP8L_WRITER_BYTES 2 -#define VP8L_WRITER_BITS 16 -#define VP8L_WRITER_MAX_BITS 32 -#endif - -typedef struct { - vp8l_atype_t bits_; // bit accumulator - int used_; // number of bits used in accumulator - uint8_t* buf_; // start of buffer - uint8_t* cur_; // current write position - uint8_t* end_; // end of buffer - - // After all bits are written (VP8LBitWriterFinish()), the caller must observe - // the state of error_. A value of 1 indicates that a memory allocation - // failure has happened during bit writing. A value of 0 indicates successful - // writing of bits. - int error_; -} VP8LBitWriter; - -static WEBP_INLINE size_t VP8LBitWriterNumBytes(VP8LBitWriter* const bw) { - return (bw->cur_ - bw->buf_) + ((bw->used_ + 7) >> 3); -} - -// Returns false in case of memory allocation error. -int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size); -// Finalize the bitstream coding. Returns a pointer to the internal buffer. -uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw); -// Release any pending memory and zeroes the object. -void VP8LBitWriterWipeOut(VP8LBitWriter* const bw); - -// Internal function for VP8LPutBits flushing 32 bits from the written state. -void VP8LPutBitsFlushBits(VP8LBitWriter* const bw); - -// PutBits internal function used in the 16 bit vp8l_wtype_t case. -void VP8LPutBitsInternal(VP8LBitWriter* const bw, uint32_t bits, int n_bits); - -// This function writes bits into bytes in increasing addresses (little endian), -// and within a byte least-significant-bit first. -// This function can write up to 32 bits in one go, but VP8LBitReader can only -// read 24 bits max (VP8L_MAX_NUM_BIT_READ). -// VP8LBitWriter's error_ flag is set in case of memory allocation error. -static WEBP_INLINE void VP8LPutBits(VP8LBitWriter* const bw, - uint32_t bits, int n_bits) { - if (sizeof(vp8l_wtype_t) == 4) { - if (n_bits > 0) { - if (bw->used_ >= 32) { - VP8LPutBitsFlushBits(bw); - } - bw->bits_ |= (vp8l_atype_t)bits << bw->used_; - bw->used_ += n_bits; - } - } else { - VP8LPutBitsInternal(bw, bits, n_bits); - } -} - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_BIT_WRITER_H_ */ diff --git a/Example/Pods/libwebp/src/utils/color_cache.c b/Example/Pods/libwebp/src/utils/color_cache.c deleted file mode 100644 index f9ff4b54..00000000 --- a/Example/Pods/libwebp/src/utils/color_cache.c +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Color Cache for WebP Lossless -// -// Author: Jyrki Alakuijala (jyrki@google.com) - -#include -#include -#include -#include "./color_cache.h" -#include "../utils/utils.h" - -//------------------------------------------------------------------------------ -// VP8LColorCache. - -int VP8LColorCacheInit(VP8LColorCache* const cc, int hash_bits) { - const int hash_size = 1 << hash_bits; - assert(cc != NULL); - assert(hash_bits > 0); - cc->colors_ = (uint32_t*)WebPSafeCalloc((uint64_t)hash_size, - sizeof(*cc->colors_)); - if (cc->colors_ == NULL) return 0; - cc->hash_shift_ = 32 - hash_bits; - cc->hash_bits_ = hash_bits; - return 1; -} - -void VP8LColorCacheClear(VP8LColorCache* const cc) { - if (cc != NULL) { - WebPSafeFree(cc->colors_); - cc->colors_ = NULL; - } -} - -void VP8LColorCacheCopy(const VP8LColorCache* const src, - VP8LColorCache* const dst) { - assert(src != NULL); - assert(dst != NULL); - assert(src->hash_bits_ == dst->hash_bits_); - memcpy(dst->colors_, src->colors_, - ((size_t)1u << dst->hash_bits_) * sizeof(*dst->colors_)); -} diff --git a/Example/Pods/libwebp/src/utils/color_cache.h b/Example/Pods/libwebp/src/utils/color_cache.h deleted file mode 100644 index a9a9f642..00000000 --- a/Example/Pods/libwebp/src/utils/color_cache.h +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Color Cache for WebP Lossless -// -// Authors: Jyrki Alakuijala (jyrki@google.com) -// Urvang Joshi (urvang@google.com) - -#ifndef WEBP_UTILS_COLOR_CACHE_H_ -#define WEBP_UTILS_COLOR_CACHE_H_ - -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Main color cache struct. -typedef struct { - uint32_t *colors_; // color entries - int hash_shift_; // Hash shift: 32 - hash_bits_. - int hash_bits_; -} VP8LColorCache; - -static const uint32_t kHashMul = 0x1e35a7bd; - -static WEBP_INLINE uint32_t VP8LColorCacheLookup( - const VP8LColorCache* const cc, uint32_t key) { - assert((key >> cc->hash_bits_) == 0u); - return cc->colors_[key]; -} - -static WEBP_INLINE void VP8LColorCacheSet(const VP8LColorCache* const cc, - uint32_t key, uint32_t argb) { - assert((key >> cc->hash_bits_) == 0u); - cc->colors_[key] = argb; -} - -static WEBP_INLINE void VP8LColorCacheInsert(const VP8LColorCache* const cc, - uint32_t argb) { - const uint32_t key = (kHashMul * argb) >> cc->hash_shift_; - cc->colors_[key] = argb; -} - -static WEBP_INLINE int VP8LColorCacheGetIndex(const VP8LColorCache* const cc, - uint32_t argb) { - return (kHashMul * argb) >> cc->hash_shift_; -} - -static WEBP_INLINE int VP8LColorCacheContains(const VP8LColorCache* const cc, - uint32_t argb) { - const uint32_t key = (kHashMul * argb) >> cc->hash_shift_; - return (cc->colors_[key] == argb); -} - -//------------------------------------------------------------------------------ - -// Initializes the color cache with 'hash_bits' bits for the keys. -// Returns false in case of memory error. -int VP8LColorCacheInit(VP8LColorCache* const color_cache, int hash_bits); - -void VP8LColorCacheCopy(const VP8LColorCache* const src, - VP8LColorCache* const dst); - -// Delete the memory associated to color cache. -void VP8LColorCacheClear(VP8LColorCache* const color_cache); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} -#endif - -#endif // WEBP_UTILS_COLOR_CACHE_H_ diff --git a/Example/Pods/libwebp/src/utils/endian_inl.h b/Example/Pods/libwebp/src/utils/endian_inl.h deleted file mode 100644 index e11260ff..00000000 --- a/Example/Pods/libwebp/src/utils/endian_inl.h +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Endian related functions. - -#ifndef WEBP_UTILS_ENDIAN_INL_H_ -#define WEBP_UTILS_ENDIAN_INL_H_ - -#ifdef HAVE_CONFIG_H -#include "../webp/config.h" -#endif - -#include "../dsp/dsp.h" -#include "../webp/types.h" - -// some endian fix (e.g.: mips-gcc doesn't define __BIG_ENDIAN__) -#if !defined(WORDS_BIGENDIAN) && \ - (defined(__BIG_ENDIAN__) || defined(_M_PPC) || \ - (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))) -#define WORDS_BIGENDIAN -#endif - -#if defined(WORDS_BIGENDIAN) -#define HToLE32 BSwap32 -#define HToLE16 BSwap16 -#else -#define HToLE32(x) (x) -#define HToLE16(x) (x) -#endif - -#if !defined(HAVE_CONFIG_H) -#if LOCAL_GCC_PREREQ(4,8) || __has_builtin(__builtin_bswap16) -#define HAVE_BUILTIN_BSWAP16 -#endif -#if LOCAL_GCC_PREREQ(4,3) || __has_builtin(__builtin_bswap32) -#define HAVE_BUILTIN_BSWAP32 -#endif -#if LOCAL_GCC_PREREQ(4,3) || __has_builtin(__builtin_bswap64) -#define HAVE_BUILTIN_BSWAP64 -#endif -#endif // !HAVE_CONFIG_H - -static WEBP_INLINE uint16_t BSwap16(uint16_t x) { -#if defined(HAVE_BUILTIN_BSWAP16) - return __builtin_bswap16(x); -#elif defined(_MSC_VER) - return _byteswap_ushort(x); -#else - // gcc will recognize a 'rorw $8, ...' here: - return (x >> 8) | ((x & 0xff) << 8); -#endif // HAVE_BUILTIN_BSWAP16 -} - -static WEBP_INLINE uint32_t BSwap32(uint32_t x) { -#if defined(WEBP_USE_MIPS32_R2) - uint32_t ret; - __asm__ volatile ( - "wsbh %[ret], %[x] \n\t" - "rotr %[ret], %[ret], 16 \n\t" - : [ret]"=r"(ret) - : [x]"r"(x) - ); - return ret; -#elif defined(HAVE_BUILTIN_BSWAP32) - return __builtin_bswap32(x); -#elif defined(__i386__) || defined(__x86_64__) - uint32_t swapped_bytes; - __asm__ volatile("bswap %0" : "=r"(swapped_bytes) : "0"(x)); - return swapped_bytes; -#elif defined(_MSC_VER) - return (uint32_t)_byteswap_ulong(x); -#else - return (x >> 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | (x << 24); -#endif // HAVE_BUILTIN_BSWAP32 -} - -static WEBP_INLINE uint64_t BSwap64(uint64_t x) { -#if defined(HAVE_BUILTIN_BSWAP64) - return __builtin_bswap64(x); -#elif defined(__x86_64__) - uint64_t swapped_bytes; - __asm__ volatile("bswapq %0" : "=r"(swapped_bytes) : "0"(x)); - return swapped_bytes; -#elif defined(_MSC_VER) - return (uint64_t)_byteswap_uint64(x); -#else // generic code for swapping 64-bit values (suggested by bdb@) - x = ((x & 0xffffffff00000000ull) >> 32) | ((x & 0x00000000ffffffffull) << 32); - x = ((x & 0xffff0000ffff0000ull) >> 16) | ((x & 0x0000ffff0000ffffull) << 16); - x = ((x & 0xff00ff00ff00ff00ull) >> 8) | ((x & 0x00ff00ff00ff00ffull) << 8); - return x; -#endif // HAVE_BUILTIN_BSWAP64 -} - -#endif // WEBP_UTILS_ENDIAN_INL_H_ diff --git a/Example/Pods/libwebp/src/utils/filters.c b/Example/Pods/libwebp/src/utils/filters.c deleted file mode 100644 index 15543b12..00000000 --- a/Example/Pods/libwebp/src/utils/filters.c +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// filter estimation -// -// Author: Urvang (urvang@google.com) - -#include "./filters.h" -#include -#include - -// ----------------------------------------------------------------------------- -// Quick estimate of a potentially interesting filter mode to try. - -#define SMAX 16 -#define SDIFF(a, b) (abs((a) - (b)) >> 4) // Scoring diff, in [0..SMAX) - -static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) { - const int g = a + b - c; - return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit -} - -WEBP_FILTER_TYPE WebPEstimateBestFilter(const uint8_t* data, - int width, int height, int stride) { - int i, j; - int bins[WEBP_FILTER_LAST][SMAX]; - memset(bins, 0, sizeof(bins)); - - // We only sample every other pixels. That's enough. - for (j = 2; j < height - 1; j += 2) { - const uint8_t* const p = data + j * stride; - int mean = p[0]; - for (i = 2; i < width - 1; i += 2) { - const int diff0 = SDIFF(p[i], mean); - const int diff1 = SDIFF(p[i], p[i - 1]); - const int diff2 = SDIFF(p[i], p[i - width]); - const int grad_pred = - GradientPredictor(p[i - 1], p[i - width], p[i - width - 1]); - const int diff3 = SDIFF(p[i], grad_pred); - bins[WEBP_FILTER_NONE][diff0] = 1; - bins[WEBP_FILTER_HORIZONTAL][diff1] = 1; - bins[WEBP_FILTER_VERTICAL][diff2] = 1; - bins[WEBP_FILTER_GRADIENT][diff3] = 1; - mean = (3 * mean + p[i] + 2) >> 2; - } - } - { - int filter; - WEBP_FILTER_TYPE best_filter = WEBP_FILTER_NONE; - int best_score = 0x7fffffff; - for (filter = WEBP_FILTER_NONE; filter < WEBP_FILTER_LAST; ++filter) { - int score = 0; - for (i = 0; i < SMAX; ++i) { - if (bins[filter][i] > 0) { - score += i; - } - } - if (score < best_score) { - best_score = score; - best_filter = (WEBP_FILTER_TYPE)filter; - } - } - return best_filter; - } -} - -#undef SMAX -#undef SDIFF - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/utils/filters.h b/Example/Pods/libwebp/src/utils/filters.h deleted file mode 100644 index 088b132f..00000000 --- a/Example/Pods/libwebp/src/utils/filters.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Spatial prediction using various filters -// -// Author: Urvang (urvang@google.com) - -#ifndef WEBP_UTILS_FILTERS_H_ -#define WEBP_UTILS_FILTERS_H_ - -#include "../webp/types.h" -#include "../dsp/dsp.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Fast estimate of a potentially good filter. -WEBP_FILTER_TYPE WebPEstimateBestFilter(const uint8_t* data, - int width, int height, int stride); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_FILTERS_H_ */ diff --git a/Example/Pods/libwebp/src/utils/huffman.c b/Example/Pods/libwebp/src/utils/huffman.c deleted file mode 100644 index d57376aa..00000000 --- a/Example/Pods/libwebp/src/utils/huffman.c +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Utilities for building and looking up Huffman trees. -// -// Author: Urvang Joshi (urvang@google.com) - -#include -#include -#include -#include "./huffman.h" -#include "../utils/utils.h" -#include "../webp/format_constants.h" - -// Huffman data read via DecodeImageStream is represented in two (red and green) -// bytes. -#define MAX_HTREE_GROUPS 0x10000 - -HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups) { - HTreeGroup* const htree_groups = - (HTreeGroup*)WebPSafeMalloc(num_htree_groups, sizeof(*htree_groups)); - if (htree_groups == NULL) { - return NULL; - } - assert(num_htree_groups <= MAX_HTREE_GROUPS); - return htree_groups; -} - -void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups) { - if (htree_groups != NULL) { - WebPSafeFree(htree_groups); - } -} - -// Returns reverse(reverse(key, len) + 1, len), where reverse(key, len) is the -// bit-wise reversal of the len least significant bits of key. -static WEBP_INLINE uint32_t GetNextKey(uint32_t key, int len) { - uint32_t step = 1 << (len - 1); - while (key & step) { - step >>= 1; - } - return (key & (step - 1)) + step; -} - -// Stores code in table[0], table[step], table[2*step], ..., table[end]. -// Assumes that end is an integer multiple of step. -static WEBP_INLINE void ReplicateValue(HuffmanCode* table, - int step, int end, - HuffmanCode code) { - assert(end % step == 0); - do { - end -= step; - table[end] = code; - } while (end > 0); -} - -// Returns the table width of the next 2nd level table. count is the histogram -// of bit lengths for the remaining symbols, len is the code length of the next -// processed symbol -static WEBP_INLINE int NextTableBitSize(const int* const count, - int len, int root_bits) { - int left = 1 << (len - root_bits); - while (len < MAX_ALLOWED_CODE_LENGTH) { - left -= count[len]; - if (left <= 0) break; - ++len; - left <<= 1; - } - return len - root_bits; -} - -int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits, - const int code_lengths[], int code_lengths_size) { - HuffmanCode* table = root_table; // next available space in table - int total_size = 1 << root_bits; // total size root table + 2nd level table - int* sorted = NULL; // symbols sorted by code length - int len; // current code length - int symbol; // symbol index in original or sorted table - // number of codes of each length: - int count[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 }; - // offsets in sorted table for each length: - int offset[MAX_ALLOWED_CODE_LENGTH + 1]; - - assert(code_lengths_size != 0); - assert(code_lengths != NULL); - assert(root_table != NULL); - assert(root_bits > 0); - - // Build histogram of code lengths. - for (symbol = 0; symbol < code_lengths_size; ++symbol) { - if (code_lengths[symbol] > MAX_ALLOWED_CODE_LENGTH) { - return 0; - } - ++count[code_lengths[symbol]]; - } - - // Error, all code lengths are zeros. - if (count[0] == code_lengths_size) { - return 0; - } - - // Generate offsets into sorted symbol table by code length. - offset[1] = 0; - for (len = 1; len < MAX_ALLOWED_CODE_LENGTH; ++len) { - if (count[len] > (1 << len)) { - return 0; - } - offset[len + 1] = offset[len] + count[len]; - } - - sorted = (int*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted)); - if (sorted == NULL) { - return 0; - } - - // Sort symbols by length, by symbol order within each length. - for (symbol = 0; symbol < code_lengths_size; ++symbol) { - const int symbol_code_length = code_lengths[symbol]; - if (code_lengths[symbol] > 0) { - sorted[offset[symbol_code_length]++] = symbol; - } - } - - // Special case code with only one value. - if (offset[MAX_ALLOWED_CODE_LENGTH] == 1) { - HuffmanCode code; - code.bits = 0; - code.value = (uint16_t)sorted[0]; - ReplicateValue(table, 1, total_size, code); - WebPSafeFree(sorted); - return total_size; - } - - { - int step; // step size to replicate values in current table - uint32_t low = -1; // low bits for current root entry - uint32_t mask = total_size - 1; // mask for low bits - uint32_t key = 0; // reversed prefix code - int num_nodes = 1; // number of Huffman tree nodes - int num_open = 1; // number of open branches in current tree level - int table_bits = root_bits; // key length of current table - int table_size = 1 << table_bits; // size of current table - symbol = 0; - // Fill in root table. - for (len = 1, step = 2; len <= root_bits; ++len, step <<= 1) { - num_open <<= 1; - num_nodes += num_open; - num_open -= count[len]; - if (num_open < 0) { - WebPSafeFree(sorted); - return 0; - } - for (; count[len] > 0; --count[len]) { - HuffmanCode code; - code.bits = (uint8_t)len; - code.value = (uint16_t)sorted[symbol++]; - ReplicateValue(&table[key], step, table_size, code); - key = GetNextKey(key, len); - } - } - - // Fill in 2nd level tables and add pointers to root table. - for (len = root_bits + 1, step = 2; len <= MAX_ALLOWED_CODE_LENGTH; - ++len, step <<= 1) { - num_open <<= 1; - num_nodes += num_open; - num_open -= count[len]; - if (num_open < 0) { - WebPSafeFree(sorted); - return 0; - } - for (; count[len] > 0; --count[len]) { - HuffmanCode code; - if ((key & mask) != low) { - table += table_size; - table_bits = NextTableBitSize(count, len, root_bits); - table_size = 1 << table_bits; - total_size += table_size; - low = key & mask; - root_table[low].bits = (uint8_t)(table_bits + root_bits); - root_table[low].value = (uint16_t)((table - root_table) - low); - } - code.bits = (uint8_t)(len - root_bits); - code.value = (uint16_t)sorted[symbol++]; - ReplicateValue(&table[key >> root_bits], step, table_size, code); - key = GetNextKey(key, len); - } - } - - // Check if tree is full. - if (num_nodes != 2 * offset[MAX_ALLOWED_CODE_LENGTH] - 1) { - WebPSafeFree(sorted); - return 0; - } - } - - WebPSafeFree(sorted); - return total_size; -} diff --git a/Example/Pods/libwebp/src/utils/huffman.h b/Example/Pods/libwebp/src/utils/huffman.h deleted file mode 100644 index c6dd6aaa..00000000 --- a/Example/Pods/libwebp/src/utils/huffman.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Utilities for building and looking up Huffman trees. -// -// Author: Urvang Joshi (urvang@google.com) - -#ifndef WEBP_UTILS_HUFFMAN_H_ -#define WEBP_UTILS_HUFFMAN_H_ - -#include -#include "../webp/format_constants.h" -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define HUFFMAN_TABLE_BITS 8 -#define HUFFMAN_TABLE_MASK ((1 << HUFFMAN_TABLE_BITS) - 1) - -#define LENGTHS_TABLE_BITS 7 -#define LENGTHS_TABLE_MASK ((1 << LENGTHS_TABLE_BITS) - 1) - - -// Huffman lookup table entry -typedef struct { - uint8_t bits; // number of bits used for this symbol - uint16_t value; // symbol value or table offset -} HuffmanCode; - -// long version for holding 32b values -typedef struct { - int bits; // number of bits used for this symbol, - // or an impossible value if not a literal code. - uint32_t value; // 32b packed ARGB value if literal, - // or non-literal symbol otherwise -} HuffmanCode32; - -#define HUFFMAN_PACKED_BITS 6 -#define HUFFMAN_PACKED_TABLE_SIZE (1u << HUFFMAN_PACKED_BITS) - -// Huffman table group. -// Includes special handling for the following cases: -// - is_trivial_literal: one common literal base for RED/BLUE/ALPHA (not GREEN) -// - is_trivial_code: only 1 code (no bit is read from bitstream) -// - use_packed_table: few enough literal symbols, so all the bit codes -// can fit into a small look-up table packed_table[] -// The common literal base, if applicable, is stored in 'literal_arb'. -typedef struct HTreeGroup HTreeGroup; -struct HTreeGroup { - HuffmanCode* htrees[HUFFMAN_CODES_PER_META_CODE]; - int is_trivial_literal; // True, if huffman trees for Red, Blue & Alpha - // Symbols are trivial (have a single code). - uint32_t literal_arb; // If is_trivial_literal is true, this is the - // ARGB value of the pixel, with Green channel - // being set to zero. - int is_trivial_code; // true if is_trivial_literal with only one code - int use_packed_table; // use packed table below for short literal code - // table mapping input bits to a packed values, or escape case to literal code - HuffmanCode32 packed_table[HUFFMAN_PACKED_TABLE_SIZE]; -}; - -// Creates the instance of HTreeGroup with specified number of tree-groups. -HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups); - -// Releases the memory allocated for HTreeGroup. -void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups); - -// Builds Huffman lookup table assuming code lengths are in symbol order. -// The 'code_lengths' is pre-allocated temporary memory buffer used for creating -// the huffman table. -// Returns built table size or 0 in case of error (invalid tree or -// memory error). -int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits, - const int code_lengths[], int code_lengths_size); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // WEBP_UTILS_HUFFMAN_H_ diff --git a/Example/Pods/libwebp/src/utils/huffman_encode.c b/Example/Pods/libwebp/src/utils/huffman_encode.c deleted file mode 100644 index 6421c2be..00000000 --- a/Example/Pods/libwebp/src/utils/huffman_encode.c +++ /dev/null @@ -1,417 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Jyrki Alakuijala (jyrki@google.com) -// -// Entropy encoding (Huffman) for webp lossless. - -#include -#include -#include -#include "./huffman_encode.h" -#include "../utils/utils.h" -#include "../webp/format_constants.h" - -// ----------------------------------------------------------------------------- -// Util function to optimize the symbol map for RLE coding - -// Heuristics for selecting the stride ranges to collapse. -static int ValuesShouldBeCollapsedToStrideAverage(int a, int b) { - return abs(a - b) < 4; -} - -// Change the population counts in a way that the consequent -// Huffman tree compression, especially its RLE-part, give smaller output. -static void OptimizeHuffmanForRle(int length, uint8_t* const good_for_rle, - uint32_t* const counts) { - // 1) Let's make the Huffman code more compatible with rle encoding. - int i; - for (; length >= 0; --length) { - if (length == 0) { - return; // All zeros. - } - if (counts[length - 1] != 0) { - // Now counts[0..length - 1] does not have trailing zeros. - break; - } - } - // 2) Let's mark all population counts that already can be encoded - // with an rle code. - { - // Let's not spoil any of the existing good rle codes. - // Mark any seq of 0's that is longer as 5 as a good_for_rle. - // Mark any seq of non-0's that is longer as 7 as a good_for_rle. - uint32_t symbol = counts[0]; - int stride = 0; - for (i = 0; i < length + 1; ++i) { - if (i == length || counts[i] != symbol) { - if ((symbol == 0 && stride >= 5) || - (symbol != 0 && stride >= 7)) { - int k; - for (k = 0; k < stride; ++k) { - good_for_rle[i - k - 1] = 1; - } - } - stride = 1; - if (i != length) { - symbol = counts[i]; - } - } else { - ++stride; - } - } - } - // 3) Let's replace those population counts that lead to more rle codes. - { - uint32_t stride = 0; - uint32_t limit = counts[0]; - uint32_t sum = 0; - for (i = 0; i < length + 1; ++i) { - if (i == length || good_for_rle[i] || - (i != 0 && good_for_rle[i - 1]) || - !ValuesShouldBeCollapsedToStrideAverage(counts[i], limit)) { - if (stride >= 4 || (stride >= 3 && sum == 0)) { - uint32_t k; - // The stride must end, collapse what we have, if we have enough (4). - uint32_t count = (sum + stride / 2) / stride; - if (count < 1) { - count = 1; - } - if (sum == 0) { - // Don't make an all zeros stride to be upgraded to ones. - count = 0; - } - for (k = 0; k < stride; ++k) { - // We don't want to change value at counts[i], - // that is already belonging to the next stride. Thus - 1. - counts[i - k - 1] = count; - } - } - stride = 0; - sum = 0; - if (i < length - 3) { - // All interesting strides have a count of at least 4, - // at least when non-zeros. - limit = (counts[i] + counts[i + 1] + - counts[i + 2] + counts[i + 3] + 2) / 4; - } else if (i < length) { - limit = counts[i]; - } else { - limit = 0; - } - } - ++stride; - if (i != length) { - sum += counts[i]; - if (stride >= 4) { - limit = (sum + stride / 2) / stride; - } - } - } - } -} - -// A comparer function for two Huffman trees: sorts first by 'total count' -// (more comes first), and then by 'value' (more comes first). -static int CompareHuffmanTrees(const void* ptr1, const void* ptr2) { - const HuffmanTree* const t1 = (const HuffmanTree*)ptr1; - const HuffmanTree* const t2 = (const HuffmanTree*)ptr2; - if (t1->total_count_ > t2->total_count_) { - return -1; - } else if (t1->total_count_ < t2->total_count_) { - return 1; - } else { - assert(t1->value_ != t2->value_); - return (t1->value_ < t2->value_) ? -1 : 1; - } -} - -static void SetBitDepths(const HuffmanTree* const tree, - const HuffmanTree* const pool, - uint8_t* const bit_depths, int level) { - if (tree->pool_index_left_ >= 0) { - SetBitDepths(&pool[tree->pool_index_left_], pool, bit_depths, level + 1); - SetBitDepths(&pool[tree->pool_index_right_], pool, bit_depths, level + 1); - } else { - bit_depths[tree->value_] = level; - } -} - -// Create an optimal Huffman tree. -// -// (data,length): population counts. -// tree_limit: maximum bit depth (inclusive) of the codes. -// bit_depths[]: how many bits are used for the symbol. -// -// Returns 0 when an error has occurred. -// -// The catch here is that the tree cannot be arbitrarily deep -// -// count_limit is the value that is to be faked as the minimum value -// and this minimum value is raised until the tree matches the -// maximum length requirement. -// -// This algorithm is not of excellent performance for very long data blocks, -// especially when population counts are longer than 2**tree_limit, but -// we are not planning to use this with extremely long blocks. -// -// See http://en.wikipedia.org/wiki/Huffman_coding -static void GenerateOptimalTree(const uint32_t* const histogram, - int histogram_size, - HuffmanTree* tree, int tree_depth_limit, - uint8_t* const bit_depths) { - uint32_t count_min; - HuffmanTree* tree_pool; - int tree_size_orig = 0; - int i; - - for (i = 0; i < histogram_size; ++i) { - if (histogram[i] != 0) { - ++tree_size_orig; - } - } - - if (tree_size_orig == 0) { // pretty optimal already! - return; - } - - tree_pool = tree + tree_size_orig; - - // For block sizes with less than 64k symbols we never need to do a - // second iteration of this loop. - // If we actually start running inside this loop a lot, we would perhaps - // be better off with the Katajainen algorithm. - assert(tree_size_orig <= (1 << (tree_depth_limit - 1))); - for (count_min = 1; ; count_min *= 2) { - int tree_size = tree_size_orig; - // We need to pack the Huffman tree in tree_depth_limit bits. - // So, we try by faking histogram entries to be at least 'count_min'. - int idx = 0; - int j; - for (j = 0; j < histogram_size; ++j) { - if (histogram[j] != 0) { - const uint32_t count = - (histogram[j] < count_min) ? count_min : histogram[j]; - tree[idx].total_count_ = count; - tree[idx].value_ = j; - tree[idx].pool_index_left_ = -1; - tree[idx].pool_index_right_ = -1; - ++idx; - } - } - - // Build the Huffman tree. - qsort(tree, tree_size, sizeof(*tree), CompareHuffmanTrees); - - if (tree_size > 1) { // Normal case. - int tree_pool_size = 0; - while (tree_size > 1) { // Finish when we have only one root. - uint32_t count; - tree_pool[tree_pool_size++] = tree[tree_size - 1]; - tree_pool[tree_pool_size++] = tree[tree_size - 2]; - count = tree_pool[tree_pool_size - 1].total_count_ + - tree_pool[tree_pool_size - 2].total_count_; - tree_size -= 2; - { - // Search for the insertion point. - int k; - for (k = 0; k < tree_size; ++k) { - if (tree[k].total_count_ <= count) { - break; - } - } - memmove(tree + (k + 1), tree + k, (tree_size - k) * sizeof(*tree)); - tree[k].total_count_ = count; - tree[k].value_ = -1; - - tree[k].pool_index_left_ = tree_pool_size - 1; - tree[k].pool_index_right_ = tree_pool_size - 2; - tree_size = tree_size + 1; - } - } - SetBitDepths(&tree[0], tree_pool, bit_depths, 0); - } else if (tree_size == 1) { // Trivial case: only one element. - bit_depths[tree[0].value_] = 1; - } - - { - // Test if this Huffman tree satisfies our 'tree_depth_limit' criteria. - int max_depth = bit_depths[0]; - for (j = 1; j < histogram_size; ++j) { - if (max_depth < bit_depths[j]) { - max_depth = bit_depths[j]; - } - } - if (max_depth <= tree_depth_limit) { - break; - } - } - } -} - -// ----------------------------------------------------------------------------- -// Coding of the Huffman tree values - -static HuffmanTreeToken* CodeRepeatedValues(int repetitions, - HuffmanTreeToken* tokens, - int value, int prev_value) { - assert(value <= MAX_ALLOWED_CODE_LENGTH); - if (value != prev_value) { - tokens->code = value; - tokens->extra_bits = 0; - ++tokens; - --repetitions; - } - while (repetitions >= 1) { - if (repetitions < 3) { - int i; - for (i = 0; i < repetitions; ++i) { - tokens->code = value; - tokens->extra_bits = 0; - ++tokens; - } - break; - } else if (repetitions < 7) { - tokens->code = 16; - tokens->extra_bits = repetitions - 3; - ++tokens; - break; - } else { - tokens->code = 16; - tokens->extra_bits = 3; - ++tokens; - repetitions -= 6; - } - } - return tokens; -} - -static HuffmanTreeToken* CodeRepeatedZeros(int repetitions, - HuffmanTreeToken* tokens) { - while (repetitions >= 1) { - if (repetitions < 3) { - int i; - for (i = 0; i < repetitions; ++i) { - tokens->code = 0; // 0-value - tokens->extra_bits = 0; - ++tokens; - } - break; - } else if (repetitions < 11) { - tokens->code = 17; - tokens->extra_bits = repetitions - 3; - ++tokens; - break; - } else if (repetitions < 139) { - tokens->code = 18; - tokens->extra_bits = repetitions - 11; - ++tokens; - break; - } else { - tokens->code = 18; - tokens->extra_bits = 0x7f; // 138 repeated 0s - ++tokens; - repetitions -= 138; - } - } - return tokens; -} - -int VP8LCreateCompressedHuffmanTree(const HuffmanTreeCode* const tree, - HuffmanTreeToken* tokens, int max_tokens) { - HuffmanTreeToken* const starting_token = tokens; - HuffmanTreeToken* const ending_token = tokens + max_tokens; - const int depth_size = tree->num_symbols; - int prev_value = 8; // 8 is the initial value for rle. - int i = 0; - assert(tokens != NULL); - while (i < depth_size) { - const int value = tree->code_lengths[i]; - int k = i + 1; - int runs; - while (k < depth_size && tree->code_lengths[k] == value) ++k; - runs = k - i; - if (value == 0) { - tokens = CodeRepeatedZeros(runs, tokens); - } else { - tokens = CodeRepeatedValues(runs, tokens, value, prev_value); - prev_value = value; - } - i += runs; - assert(tokens <= ending_token); - } - (void)ending_token; // suppress 'unused variable' warning - return (int)(tokens - starting_token); -} - -// ----------------------------------------------------------------------------- - -// Pre-reversed 4-bit values. -static const uint8_t kReversedBits[16] = { - 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, - 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf -}; - -static uint32_t ReverseBits(int num_bits, uint32_t bits) { - uint32_t retval = 0; - int i = 0; - while (i < num_bits) { - i += 4; - retval |= kReversedBits[bits & 0xf] << (MAX_ALLOWED_CODE_LENGTH + 1 - i); - bits >>= 4; - } - retval >>= (MAX_ALLOWED_CODE_LENGTH + 1 - num_bits); - return retval; -} - -// Get the actual bit values for a tree of bit depths. -static void ConvertBitDepthsToSymbols(HuffmanTreeCode* const tree) { - // 0 bit-depth means that the symbol does not exist. - int i; - int len; - uint32_t next_code[MAX_ALLOWED_CODE_LENGTH + 1]; - int depth_count[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 }; - - assert(tree != NULL); - len = tree->num_symbols; - for (i = 0; i < len; ++i) { - const int code_length = tree->code_lengths[i]; - assert(code_length <= MAX_ALLOWED_CODE_LENGTH); - ++depth_count[code_length]; - } - depth_count[0] = 0; // ignore unused symbol - next_code[0] = 0; - { - uint32_t code = 0; - for (i = 1; i <= MAX_ALLOWED_CODE_LENGTH; ++i) { - code = (code + depth_count[i - 1]) << 1; - next_code[i] = code; - } - } - for (i = 0; i < len; ++i) { - const int code_length = tree->code_lengths[i]; - tree->codes[i] = ReverseBits(code_length, next_code[code_length]++); - } -} - -// ----------------------------------------------------------------------------- -// Main entry point - -void VP8LCreateHuffmanTree(uint32_t* const histogram, int tree_depth_limit, - uint8_t* const buf_rle, - HuffmanTree* const huff_tree, - HuffmanTreeCode* const huff_code) { - const int num_symbols = huff_code->num_symbols; - memset(buf_rle, 0, num_symbols * sizeof(*buf_rle)); - OptimizeHuffmanForRle(num_symbols, buf_rle, histogram); - GenerateOptimalTree(histogram, num_symbols, huff_tree, tree_depth_limit, - huff_code->code_lengths); - // Create the actual bit codes for the bit lengths. - ConvertBitDepthsToSymbols(huff_code); -} diff --git a/Example/Pods/libwebp/src/utils/huffman_encode.h b/Example/Pods/libwebp/src/utils/huffman_encode.h deleted file mode 100644 index a1571651..00000000 --- a/Example/Pods/libwebp/src/utils/huffman_encode.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Jyrki Alakuijala (jyrki@google.com) -// -// Entropy encoding (Huffman) for webp lossless - -#ifndef WEBP_UTILS_HUFFMAN_ENCODE_H_ -#define WEBP_UTILS_HUFFMAN_ENCODE_H_ - -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Struct for holding the tree header in coded form. -typedef struct { - uint8_t code; // value (0..15) or escape code (16,17,18) - uint8_t extra_bits; // extra bits for escape codes -} HuffmanTreeToken; - -// Struct to represent the tree codes (depth and bits array). -typedef struct { - int num_symbols; // Number of symbols. - uint8_t* code_lengths; // Code lengths of the symbols. - uint16_t* codes; // Symbol Codes. -} HuffmanTreeCode; - -// Struct to represent the Huffman tree. -typedef struct { - uint32_t total_count_; // Symbol frequency. - int value_; // Symbol value. - int pool_index_left_; // Index for the left sub-tree. - int pool_index_right_; // Index for the right sub-tree. -} HuffmanTree; - -// Turn the Huffman tree into a token sequence. -// Returns the number of tokens used. -int VP8LCreateCompressedHuffmanTree(const HuffmanTreeCode* const tree, - HuffmanTreeToken* tokens, int max_tokens); - -// Create an optimized tree, and tokenize it. -// 'buf_rle' and 'huff_tree' are pre-allocated and the 'tree' is the constructed -// huffman code tree. -void VP8LCreateHuffmanTree(uint32_t* const histogram, int tree_depth_limit, - uint8_t* const buf_rle, HuffmanTree* const huff_tree, - HuffmanTreeCode* const tree); - -#ifdef __cplusplus -} -#endif - -#endif // WEBP_UTILS_HUFFMAN_ENCODE_H_ diff --git a/Example/Pods/libwebp/src/utils/quant_levels.c b/Example/Pods/libwebp/src/utils/quant_levels.c deleted file mode 100644 index d7c8aab9..00000000 --- a/Example/Pods/libwebp/src/utils/quant_levels.c +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Quantize levels for specified number of quantization-levels ([2, 256]). -// Min and max values are preserved (usual 0 and 255 for alpha plane). -// -// Author: Skal (pascal.massimino@gmail.com) - -#include - -#include "./quant_levels.h" - -#define NUM_SYMBOLS 256 - -#define MAX_ITER 6 // Maximum number of convergence steps. -#define ERROR_THRESHOLD 1e-4 // MSE stopping criterion. - -// ----------------------------------------------------------------------------- -// Quantize levels. - -int QuantizeLevels(uint8_t* const data, int width, int height, - int num_levels, uint64_t* const sse) { - int freq[NUM_SYMBOLS] = { 0 }; - int q_level[NUM_SYMBOLS] = { 0 }; - double inv_q_level[NUM_SYMBOLS] = { 0 }; - int min_s = 255, max_s = 0; - const size_t data_size = height * width; - int i, num_levels_in, iter; - double last_err = 1.e38, err = 0.; - const double err_threshold = ERROR_THRESHOLD * data_size; - - if (data == NULL) { - return 0; - } - - if (width <= 0 || height <= 0) { - return 0; - } - - if (num_levels < 2 || num_levels > 256) { - return 0; - } - - { - size_t n; - num_levels_in = 0; - for (n = 0; n < data_size; ++n) { - num_levels_in += (freq[data[n]] == 0); - if (min_s > data[n]) min_s = data[n]; - if (max_s < data[n]) max_s = data[n]; - ++freq[data[n]]; - } - } - - if (num_levels_in <= num_levels) goto End; // nothing to do! - - // Start with uniformly spread centroids. - for (i = 0; i < num_levels; ++i) { - inv_q_level[i] = min_s + (double)(max_s - min_s) * i / (num_levels - 1); - } - - // Fixed values. Won't be changed. - q_level[min_s] = 0; - q_level[max_s] = num_levels - 1; - assert(inv_q_level[0] == min_s); - assert(inv_q_level[num_levels - 1] == max_s); - - // k-Means iterations. - for (iter = 0; iter < MAX_ITER; ++iter) { - double q_sum[NUM_SYMBOLS] = { 0 }; - double q_count[NUM_SYMBOLS] = { 0 }; - int s, slot = 0; - - // Assign classes to representatives. - for (s = min_s; s <= max_s; ++s) { - // Keep track of the nearest neighbour 'slot' - while (slot < num_levels - 1 && - 2 * s > inv_q_level[slot] + inv_q_level[slot + 1]) { - ++slot; - } - if (freq[s] > 0) { - q_sum[slot] += s * freq[s]; - q_count[slot] += freq[s]; - } - q_level[s] = slot; - } - - // Assign new representatives to classes. - if (num_levels > 2) { - for (slot = 1; slot < num_levels - 1; ++slot) { - const double count = q_count[slot]; - if (count > 0.) { - inv_q_level[slot] = q_sum[slot] / count; - } - } - } - - // Compute convergence error. - err = 0.; - for (s = min_s; s <= max_s; ++s) { - const double error = s - inv_q_level[q_level[s]]; - err += freq[s] * error * error; - } - - // Check for convergence: we stop as soon as the error is no - // longer improving. - if (last_err - err < err_threshold) break; - last_err = err; - } - - // Remap the alpha plane to quantized values. - { - // double->int rounding operation can be costly, so we do it - // once for all before remapping. We also perform the data[] -> slot - // mapping, while at it (avoid one indirection in the final loop). - uint8_t map[NUM_SYMBOLS]; - int s; - size_t n; - for (s = min_s; s <= max_s; ++s) { - const int slot = q_level[s]; - map[s] = (uint8_t)(inv_q_level[slot] + .5); - } - // Final pass. - for (n = 0; n < data_size; ++n) { - data[n] = map[data[n]]; - } - } - End: - // Store sum of squared error if needed. - if (sse != NULL) *sse = (uint64_t)err; - - return 1; -} - diff --git a/Example/Pods/libwebp/src/utils/quant_levels.h b/Example/Pods/libwebp/src/utils/quant_levels.h deleted file mode 100644 index 1cb5a32c..00000000 --- a/Example/Pods/libwebp/src/utils/quant_levels.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Alpha plane quantization utility -// -// Author: Vikas Arora (vikasa@google.com) - -#ifndef WEBP_UTILS_QUANT_LEVELS_H_ -#define WEBP_UTILS_QUANT_LEVELS_H_ - -#include - -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Replace the input 'data' of size 'width'x'height' with 'num-levels' -// quantized values. If not NULL, 'sse' will contain the sum of squared error. -// Valid range for 'num_levels' is [2, 256]. -// Returns false in case of error (data is NULL, or parameters are invalid). -int QuantizeLevels(uint8_t* const data, int width, int height, int num_levels, - uint64_t* const sse); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_QUANT_LEVELS_H_ */ diff --git a/Example/Pods/libwebp/src/utils/quant_levels_dec.c b/Example/Pods/libwebp/src/utils/quant_levels_dec.c deleted file mode 100644 index 5b8b8b49..00000000 --- a/Example/Pods/libwebp/src/utils/quant_levels_dec.c +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Implement gradient smoothing: we replace a current alpha value by its -// surrounding average if it's close enough (that is: the change will be less -// than the minimum distance between two quantized level). -// We use sliding window for computing the 2d moving average. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "./quant_levels_dec.h" - -#include // for memset - -#include "./utils.h" - -// #define USE_DITHERING // uncomment to enable ordered dithering (not vital) - -#define FIX 16 // fix-point precision for averaging -#define LFIX 2 // extra precision for look-up table -#define LUT_SIZE ((1 << (8 + LFIX)) - 1) // look-up table size - -#if defined(USE_DITHERING) - -#define DFIX 4 // extra precision for ordered dithering -#define DSIZE 4 // dithering size (must be a power of two) -// cf. http://en.wikipedia.org/wiki/Ordered_dithering -static const uint8_t kOrderedDither[DSIZE][DSIZE] = { - { 0, 8, 2, 10 }, // coefficients are in DFIX fixed-point precision - { 12, 4, 14, 6 }, - { 3, 11, 1, 9 }, - { 15, 7, 13, 5 } -}; - -#else -#define DFIX 0 -#endif - -typedef struct { - int width_, height_; // dimension - int row_; // current input row being processed - uint8_t* src_; // input pointer - uint8_t* dst_; // output pointer - - int radius_; // filter radius (=delay) - int scale_; // normalization factor, in FIX bits precision - - void* mem_; // all memory - - // various scratch buffers - uint16_t* start_; - uint16_t* cur_; - uint16_t* end_; - uint16_t* top_; - uint16_t* average_; - - // input levels distribution - int num_levels_; // number of quantized levels - int min_, max_; // min and max level values - int min_level_dist_; // smallest distance between two consecutive levels - - int16_t* correction_; // size = 1 + 2*LUT_SIZE -> ~4k memory -} SmoothParams; - -//------------------------------------------------------------------------------ - -#define CLIP_MASK (int)(~0U << (8 + DFIX)) -static WEBP_INLINE uint8_t clip_8b(int v) { - return (!(v & CLIP_MASK)) ? (uint8_t)(v >> DFIX) : (v < 0) ? 0u : 255u; -} - -// vertical accumulation -static void VFilter(SmoothParams* const p) { - const uint8_t* src = p->src_; - const int w = p->width_; - uint16_t* const cur = p->cur_; - const uint16_t* const top = p->top_; - uint16_t* const out = p->end_; - uint16_t sum = 0; // all arithmetic is modulo 16bit - int x; - - for (x = 0; x < w; ++x) { - uint16_t new_value; - sum += src[x]; - new_value = top[x] + sum; - out[x] = new_value - cur[x]; // vertical sum of 'r' pixels. - cur[x] = new_value; - } - // move input pointers one row down - p->top_ = p->cur_; - p->cur_ += w; - if (p->cur_ == p->end_) p->cur_ = p->start_; // roll-over - // We replicate edges, as it's somewhat easier as a boundary condition. - // That's why we don't update the 'src' pointer on top/bottom area: - if (p->row_ >= 0 && p->row_ < p->height_ - 1) { - p->src_ += p->width_; - } -} - -// horizontal accumulation. We use mirror replication of missing pixels, as it's -// a little easier to implement (surprisingly). -static void HFilter(SmoothParams* const p) { - const uint16_t* const in = p->end_; - uint16_t* const out = p->average_; - const uint32_t scale = p->scale_; - const int w = p->width_; - const int r = p->radius_; - - int x; - for (x = 0; x <= r; ++x) { // left mirroring - const uint16_t delta = in[x + r - 1] + in[r - x]; - out[x] = (delta * scale) >> FIX; - } - for (; x < w - r; ++x) { // bulk middle run - const uint16_t delta = in[x + r] - in[x - r - 1]; - out[x] = (delta * scale) >> FIX; - } - for (; x < w; ++x) { // right mirroring - const uint16_t delta = - 2 * in[w - 1] - in[2 * w - 2 - r - x] - in[x - r - 1]; - out[x] = (delta * scale) >> FIX; - } -} - -// emit one filtered output row -static void ApplyFilter(SmoothParams* const p) { - const uint16_t* const average = p->average_; - const int w = p->width_; - const int16_t* const correction = p->correction_; -#if defined(USE_DITHERING) - const uint8_t* const dither = kOrderedDither[p->row_ % DSIZE]; -#endif - uint8_t* const dst = p->dst_; - int x; - for (x = 0; x < w; ++x) { - const int v = dst[x]; - if (v < p->max_ && v > p->min_) { - const int c = (v << DFIX) + correction[average[x] - (v << LFIX)]; -#if defined(USE_DITHERING) - dst[x] = clip_8b(c + dither[x % DSIZE]); -#else - dst[x] = clip_8b(c); -#endif - } - } - p->dst_ += w; // advance output pointer -} - -//------------------------------------------------------------------------------ -// Initialize correction table - -static void InitCorrectionLUT(int16_t* const lut, int min_dist) { - // The correction curve is: - // f(x) = x for x <= threshold2 - // f(x) = 0 for x >= threshold1 - // and a linear interpolation for range x=[threshold2, threshold1] - // (along with f(-x) = -f(x) symmetry). - // Note that: threshold2 = 3/4 * threshold1 - const int threshold1 = min_dist << LFIX; - const int threshold2 = (3 * threshold1) >> 2; - const int max_threshold = threshold2 << DFIX; - const int delta = threshold1 - threshold2; - int i; - for (i = 1; i <= LUT_SIZE; ++i) { - int c = (i <= threshold2) ? (i << DFIX) - : (i < threshold1) ? max_threshold * (threshold1 - i) / delta - : 0; - c >>= LFIX; - lut[+i] = +c; - lut[-i] = -c; - } - lut[0] = 0; -} - -static void CountLevels(const uint8_t* const data, int size, - SmoothParams* const p) { - int i, last_level; - uint8_t used_levels[256] = { 0 }; - p->min_ = 255; - p->max_ = 0; - for (i = 0; i < size; ++i) { - const int v = data[i]; - if (v < p->min_) p->min_ = v; - if (v > p->max_) p->max_ = v; - used_levels[v] = 1; - } - // Compute the mininum distance between two non-zero levels. - p->min_level_dist_ = p->max_ - p->min_; - last_level = -1; - for (i = 0; i < 256; ++i) { - if (used_levels[i]) { - ++p->num_levels_; - if (last_level >= 0) { - const int level_dist = i - last_level; - if (level_dist < p->min_level_dist_) { - p->min_level_dist_ = level_dist; - } - } - last_level = i; - } - } -} - -// Initialize all params. -static int InitParams(uint8_t* const data, int width, int height, - int radius, SmoothParams* const p) { - const int R = 2 * radius + 1; // total size of the kernel - - const size_t size_scratch_m = (R + 1) * width * sizeof(*p->start_); - const size_t size_m = width * sizeof(*p->average_); - const size_t size_lut = (1 + 2 * LUT_SIZE) * sizeof(*p->correction_); - const size_t total_size = size_scratch_m + size_m + size_lut; - uint8_t* mem = (uint8_t*)WebPSafeMalloc(1U, total_size); - - if (mem == NULL) return 0; - p->mem_ = (void*)mem; - - p->start_ = (uint16_t*)mem; - p->cur_ = p->start_; - p->end_ = p->start_ + R * width; - p->top_ = p->end_ - width; - memset(p->top_, 0, width * sizeof(*p->top_)); - mem += size_scratch_m; - - p->average_ = (uint16_t*)mem; - mem += size_m; - - p->width_ = width; - p->height_ = height; - p->src_ = data; - p->dst_ = data; - p->radius_ = radius; - p->scale_ = (1 << (FIX + LFIX)) / (R * R); // normalization constant - p->row_ = -radius; - - // analyze the input distribution so we can best-fit the threshold - CountLevels(data, width * height, p); - - // correction table - p->correction_ = ((int16_t*)mem) + LUT_SIZE; - InitCorrectionLUT(p->correction_, p->min_level_dist_); - - return 1; -} - -static void CleanupParams(SmoothParams* const p) { - WebPSafeFree(p->mem_); -} - -int WebPDequantizeLevels(uint8_t* const data, int width, int height, - int strength) { - const int radius = 4 * strength / 100; - if (strength < 0 || strength > 100) return 0; - if (data == NULL || width <= 0 || height <= 0) return 0; // bad params - if (radius > 0) { - SmoothParams p; - memset(&p, 0, sizeof(p)); - if (!InitParams(data, width, height, radius, &p)) return 0; - if (p.num_levels_ > 2) { - for (; p.row_ < p.height_; ++p.row_) { - VFilter(&p); // accumulate average of input - // Need to wait few rows in order to prime the filter, - // before emitting some output. - if (p.row_ >= p.radius_) { - HFilter(&p); - ApplyFilter(&p); - } - } - } - CleanupParams(&p); - } - return 1; -} diff --git a/Example/Pods/libwebp/src/utils/quant_levels_dec.h b/Example/Pods/libwebp/src/utils/quant_levels_dec.h deleted file mode 100644 index 9aab0680..00000000 --- a/Example/Pods/libwebp/src/utils/quant_levels_dec.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Alpha plane de-quantization utility -// -// Author: Vikas Arora (vikasa@google.com) - -#ifndef WEBP_UTILS_QUANT_LEVELS_DEC_H_ -#define WEBP_UTILS_QUANT_LEVELS_DEC_H_ - -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Apply post-processing to input 'data' of size 'width'x'height' assuming that -// the source was quantized to a reduced number of levels. -// Strength is in [0..100] and controls the amount of dithering applied. -// Returns false in case of error (data is NULL, invalid parameters, -// malloc failure, ...). -int WebPDequantizeLevels(uint8_t* const data, int width, int height, - int strength); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_QUANT_LEVELS_DEC_H_ */ diff --git a/Example/Pods/libwebp/src/utils/random.c b/Example/Pods/libwebp/src/utils/random.c deleted file mode 100644 index 24e96ad6..00000000 --- a/Example/Pods/libwebp/src/utils/random.c +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Pseudo-random utilities -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include "./random.h" - -//------------------------------------------------------------------------------ - -// 31b-range values -static const uint32_t kRandomTable[VP8_RANDOM_TABLE_SIZE] = { - 0x0de15230, 0x03b31886, 0x775faccb, 0x1c88626a, 0x68385c55, 0x14b3b828, - 0x4a85fef8, 0x49ddb84b, 0x64fcf397, 0x5c550289, 0x4a290000, 0x0d7ec1da, - 0x5940b7ab, 0x5492577d, 0x4e19ca72, 0x38d38c69, 0x0c01ee65, 0x32a1755f, - 0x5437f652, 0x5abb2c32, 0x0faa57b1, 0x73f533e7, 0x685feeda, 0x7563cce2, - 0x6e990e83, 0x4730a7ed, 0x4fc0d9c6, 0x496b153c, 0x4f1403fa, 0x541afb0c, - 0x73990b32, 0x26d7cb1c, 0x6fcc3706, 0x2cbb77d8, 0x75762f2a, 0x6425ccdd, - 0x24b35461, 0x0a7d8715, 0x220414a8, 0x141ebf67, 0x56b41583, 0x73e502e3, - 0x44cab16f, 0x28264d42, 0x73baaefb, 0x0a50ebed, 0x1d6ab6fb, 0x0d3ad40b, - 0x35db3b68, 0x2b081e83, 0x77ce6b95, 0x5181e5f0, 0x78853bbc, 0x009f9494, - 0x27e5ed3c -}; - -void VP8InitRandom(VP8Random* const rg, float dithering) { - memcpy(rg->tab_, kRandomTable, sizeof(rg->tab_)); - rg->index1_ = 0; - rg->index2_ = 31; - rg->amp_ = (dithering < 0.0) ? 0 - : (dithering > 1.0) ? (1 << VP8_RANDOM_DITHER_FIX) - : (uint32_t)((1 << VP8_RANDOM_DITHER_FIX) * dithering); -} - -//------------------------------------------------------------------------------ - diff --git a/Example/Pods/libwebp/src/utils/random.h b/Example/Pods/libwebp/src/utils/random.h deleted file mode 100644 index c392a615..00000000 --- a/Example/Pods/libwebp/src/utils/random.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Pseudo-random utilities -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_UTILS_RANDOM_H_ -#define WEBP_UTILS_RANDOM_H_ - -#include -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define VP8_RANDOM_DITHER_FIX 8 // fixed-point precision for dithering -#define VP8_RANDOM_TABLE_SIZE 55 - -typedef struct { - int index1_, index2_; - uint32_t tab_[VP8_RANDOM_TABLE_SIZE]; - int amp_; -} VP8Random; - -// Initializes random generator with an amplitude 'dithering' in range [0..1]. -void VP8InitRandom(VP8Random* const rg, float dithering); - -// Returns a centered pseudo-random number with 'num_bits' amplitude. -// (uses D.Knuth's Difference-based random generator). -// 'amp' is in VP8_RANDOM_DITHER_FIX fixed-point precision. -static WEBP_INLINE int VP8RandomBits2(VP8Random* const rg, int num_bits, - int amp) { - int diff; - assert(num_bits + VP8_RANDOM_DITHER_FIX <= 31); - diff = rg->tab_[rg->index1_] - rg->tab_[rg->index2_]; - if (diff < 0) diff += (1u << 31); - rg->tab_[rg->index1_] = diff; - if (++rg->index1_ == VP8_RANDOM_TABLE_SIZE) rg->index1_ = 0; - if (++rg->index2_ == VP8_RANDOM_TABLE_SIZE) rg->index2_ = 0; - // sign-extend, 0-center - diff = (int)((uint32_t)diff << 1) >> (32 - num_bits); - diff = (diff * amp) >> VP8_RANDOM_DITHER_FIX; // restrict range - diff += 1 << (num_bits - 1); // shift back to 0.5-center - return diff; -} - -static WEBP_INLINE int VP8RandomBits(VP8Random* const rg, int num_bits) { - return VP8RandomBits2(rg, num_bits, rg->amp_); -} - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_RANDOM_H_ */ diff --git a/Example/Pods/libwebp/src/utils/rescaler.c b/Example/Pods/libwebp/src/utils/rescaler.c deleted file mode 100644 index 00c9300b..00000000 --- a/Example/Pods/libwebp/src/utils/rescaler.c +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Rescaling functions -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include -#include -#include "../dsp/dsp.h" -#include "./rescaler.h" - -//------------------------------------------------------------------------------ - -void WebPRescalerInit(WebPRescaler* const wrk, int src_width, int src_height, - uint8_t* const dst, - int dst_width, int dst_height, int dst_stride, - int num_channels, rescaler_t* const work) { - const int x_add = src_width, x_sub = dst_width; - const int y_add = src_height, y_sub = dst_height; - wrk->x_expand = (src_width < dst_width); - wrk->y_expand = (src_height < dst_height); - wrk->src_width = src_width; - wrk->src_height = src_height; - wrk->dst_width = dst_width; - wrk->dst_height = dst_height; - wrk->src_y = 0; - wrk->dst_y = 0; - wrk->dst = dst; - wrk->dst_stride = dst_stride; - wrk->num_channels = num_channels; - - // for 'x_expand', we use bilinear interpolation - wrk->x_add = wrk->x_expand ? (x_sub - 1) : x_add; - wrk->x_sub = wrk->x_expand ? (x_add - 1) : x_sub; - if (!wrk->x_expand) { // fx_scale is not used otherwise - wrk->fx_scale = WEBP_RESCALER_FRAC(1, wrk->x_sub); - } - // vertical scaling parameters - wrk->y_add = wrk->y_expand ? y_add - 1 : y_add; - wrk->y_sub = wrk->y_expand ? y_sub - 1 : y_sub; - wrk->y_accum = wrk->y_expand ? wrk->y_sub : wrk->y_add; - if (!wrk->y_expand) { - // this is WEBP_RESCALER_FRAC(dst_height, x_add * y_add) without the cast. - const uint64_t ratio = - (uint64_t)dst_height * WEBP_RESCALER_ONE / (wrk->x_add * wrk->y_add); - if (ratio != (uint32_t)ratio) { - // We can't represent the ratio with the current fixed-point precision. - // => We special-case fxy_scale = 0, in WebPRescalerExportRow(). - wrk->fxy_scale = 0; - } else { - wrk->fxy_scale = (uint32_t)ratio; - } - wrk->fy_scale = WEBP_RESCALER_FRAC(1, wrk->y_sub); - } else { - wrk->fy_scale = WEBP_RESCALER_FRAC(1, wrk->x_add); - // wrk->fxy_scale is unused here. - } - wrk->irow = work; - wrk->frow = work + num_channels * dst_width; - memset(work, 0, 2 * dst_width * num_channels * sizeof(*work)); - - WebPRescalerDspInit(); -} - -int WebPRescalerGetScaledDimensions(int src_width, int src_height, - int* const scaled_width, - int* const scaled_height) { - assert(scaled_width != NULL); - assert(scaled_height != NULL); - { - int width = *scaled_width; - int height = *scaled_height; - - // if width is unspecified, scale original proportionally to height ratio. - if (width == 0) { - width = (src_width * height + src_height / 2) / src_height; - } - // if height is unspecified, scale original proportionally to width ratio. - if (height == 0) { - height = (src_height * width + src_width / 2) / src_width; - } - // Check if the overall dimensions still make sense. - if (width <= 0 || height <= 0) { - return 0; - } - - *scaled_width = width; - *scaled_height = height; - return 1; - } -} - -//------------------------------------------------------------------------------ -// all-in-one calls - -int WebPRescaleNeededLines(const WebPRescaler* const wrk, int max_num_lines) { - const int num_lines = (wrk->y_accum + wrk->y_sub - 1) / wrk->y_sub; - return (num_lines > max_num_lines) ? max_num_lines : num_lines; -} - -int WebPRescalerImport(WebPRescaler* const wrk, int num_lines, - const uint8_t* src, int src_stride) { - int total_imported = 0; - while (total_imported < num_lines && !WebPRescalerHasPendingOutput(wrk)) { - if (wrk->y_expand) { - rescaler_t* const tmp = wrk->irow; - wrk->irow = wrk->frow; - wrk->frow = tmp; - } - WebPRescalerImportRow(wrk, src); - if (!wrk->y_expand) { // Accumulate the contribution of the new row. - int x; - for (x = 0; x < wrk->num_channels * wrk->dst_width; ++x) { - wrk->irow[x] += wrk->frow[x]; - } - } - ++wrk->src_y; - src += src_stride; - ++total_imported; - wrk->y_accum -= wrk->y_sub; - } - return total_imported; -} - -int WebPRescalerExport(WebPRescaler* const rescaler) { - int total_exported = 0; - while (WebPRescalerHasPendingOutput(rescaler)) { - WebPRescalerExportRow(rescaler); - ++total_exported; - } - return total_exported; -} - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/utils/rescaler.h b/Example/Pods/libwebp/src/utils/rescaler.h deleted file mode 100644 index 98b01a76..00000000 --- a/Example/Pods/libwebp/src/utils/rescaler.h +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Rescaling functions -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_UTILS_RESCALER_H_ -#define WEBP_UTILS_RESCALER_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "../webp/types.h" - -#define WEBP_RESCALER_RFIX 32 // fixed-point precision for multiplies -#define WEBP_RESCALER_ONE (1ull << WEBP_RESCALER_RFIX) -#define WEBP_RESCALER_FRAC(x, y) \ - ((uint32_t)(((uint64_t)(x) << WEBP_RESCALER_RFIX) / (y))) - -// Structure used for on-the-fly rescaling -typedef uint32_t rescaler_t; // type for side-buffer -typedef struct WebPRescaler WebPRescaler; -struct WebPRescaler { - int x_expand; // true if we're expanding in the x direction - int y_expand; // true if we're expanding in the y direction - int num_channels; // bytes to jump between pixels - uint32_t fx_scale; // fixed-point scaling factors - uint32_t fy_scale; // '' - uint32_t fxy_scale; // '' - int y_accum; // vertical accumulator - int y_add, y_sub; // vertical increments - int x_add, x_sub; // horizontal increments - int src_width, src_height; // source dimensions - int dst_width, dst_height; // destination dimensions - int src_y, dst_y; // row counters for input and output - uint8_t* dst; - int dst_stride; - rescaler_t* irow, *frow; // work buffer -}; - -// Initialize a rescaler given scratch area 'work' and dimensions of src & dst. -void WebPRescalerInit(WebPRescaler* const rescaler, - int src_width, int src_height, - uint8_t* const dst, - int dst_width, int dst_height, int dst_stride, - int num_channels, - rescaler_t* const work); - -// If either 'scaled_width' or 'scaled_height' (but not both) is 0 the value -// will be calculated preserving the aspect ratio, otherwise the values are -// left unmodified. Returns true on success, false if either value is 0 after -// performing the scaling calculation. -int WebPRescalerGetScaledDimensions(int src_width, int src_height, - int* const scaled_width, - int* const scaled_height); - -// Returns the number of input lines needed next to produce one output line, -// considering that the maximum available input lines are 'max_num_lines'. -int WebPRescaleNeededLines(const WebPRescaler* const rescaler, - int max_num_lines); - -// Import multiple rows over all channels, until at least one row is ready to -// be exported. Returns the actual number of lines that were imported. -int WebPRescalerImport(WebPRescaler* const rescaler, int num_rows, - const uint8_t* src, int src_stride); - -// Export as many rows as possible. Return the numbers of rows written. -int WebPRescalerExport(WebPRescaler* const rescaler); - -// Return true if input is finished -static WEBP_INLINE -int WebPRescalerInputDone(const WebPRescaler* const rescaler) { - return (rescaler->src_y >= rescaler->src_height); -} -// Return true if output is finished -static WEBP_INLINE -int WebPRescalerOutputDone(const WebPRescaler* const rescaler) { - return (rescaler->dst_y >= rescaler->dst_height); -} - -// Return true if there are pending output rows ready. -static WEBP_INLINE -int WebPRescalerHasPendingOutput(const WebPRescaler* const rescaler) { - return !WebPRescalerOutputDone(rescaler) && (rescaler->y_accum <= 0); -} - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_RESCALER_H_ */ diff --git a/Example/Pods/libwebp/src/utils/thread.c b/Example/Pods/libwebp/src/utils/thread.c deleted file mode 100644 index 93f76227..00000000 --- a/Example/Pods/libwebp/src/utils/thread.c +++ /dev/null @@ -1,358 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Multi-threaded worker -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include // for memset() -#include "./thread.h" -#include "./utils.h" - -#ifdef WEBP_USE_THREAD - -#if defined(_WIN32) - -#include -typedef HANDLE pthread_t; -typedef CRITICAL_SECTION pthread_mutex_t; - -#if _WIN32_WINNT >= 0x0600 // Windows Vista / Server 2008 or greater -#define USE_WINDOWS_CONDITION_VARIABLE -typedef CONDITION_VARIABLE pthread_cond_t; -#else -typedef struct { - HANDLE waiting_sem_; - HANDLE received_sem_; - HANDLE signal_event_; -} pthread_cond_t; -#endif // _WIN32_WINNT >= 0x600 - -#ifndef WINAPI_FAMILY_PARTITION -#define WINAPI_PARTITION_DESKTOP 1 -#define WINAPI_FAMILY_PARTITION(x) x -#endif - -#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -#define USE_CREATE_THREAD -#endif - -#else // !_WIN32 - -#include - -#endif // _WIN32 - -struct WebPWorkerImpl { - pthread_mutex_t mutex_; - pthread_cond_t condition_; - pthread_t thread_; -}; - -#if defined(_WIN32) - -//------------------------------------------------------------------------------ -// simplistic pthread emulation layer - -#include - -// _beginthreadex requires __stdcall -#define THREADFN unsigned int __stdcall -#define THREAD_RETURN(val) (unsigned int)((DWORD_PTR)val) - -#if _WIN32_WINNT >= 0x0501 // Windows XP or greater -#define WaitForSingleObject(obj, timeout) \ - WaitForSingleObjectEx(obj, timeout, FALSE /*bAlertable*/) -#endif - -static int pthread_create(pthread_t* const thread, const void* attr, - unsigned int (__stdcall *start)(void*), void* arg) { - (void)attr; -#ifdef USE_CREATE_THREAD - *thread = CreateThread(NULL, /* lpThreadAttributes */ - 0, /* dwStackSize */ - start, - arg, - 0, /* dwStackSize */ - NULL); /* lpThreadId */ -#else - *thread = (pthread_t)_beginthreadex(NULL, /* void *security */ - 0, /* unsigned stack_size */ - start, - arg, - 0, /* unsigned initflag */ - NULL); /* unsigned *thrdaddr */ -#endif - if (*thread == NULL) return 1; - SetThreadPriority(*thread, THREAD_PRIORITY_ABOVE_NORMAL); - return 0; -} - -static int pthread_join(pthread_t thread, void** value_ptr) { - (void)value_ptr; - return (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0 || - CloseHandle(thread) == 0); -} - -// Mutex -static int pthread_mutex_init(pthread_mutex_t* const mutex, void* mutexattr) { - (void)mutexattr; -#if _WIN32_WINNT >= 0x0600 // Windows Vista / Server 2008 or greater - InitializeCriticalSectionEx(mutex, 0 /*dwSpinCount*/, 0 /*Flags*/); -#else - InitializeCriticalSection(mutex); -#endif - return 0; -} - -static int pthread_mutex_lock(pthread_mutex_t* const mutex) { - EnterCriticalSection(mutex); - return 0; -} - -static int pthread_mutex_unlock(pthread_mutex_t* const mutex) { - LeaveCriticalSection(mutex); - return 0; -} - -static int pthread_mutex_destroy(pthread_mutex_t* const mutex) { - DeleteCriticalSection(mutex); - return 0; -} - -// Condition -static int pthread_cond_destroy(pthread_cond_t* const condition) { - int ok = 1; -#ifdef USE_WINDOWS_CONDITION_VARIABLE - (void)condition; -#else - ok &= (CloseHandle(condition->waiting_sem_) != 0); - ok &= (CloseHandle(condition->received_sem_) != 0); - ok &= (CloseHandle(condition->signal_event_) != 0); -#endif - return !ok; -} - -static int pthread_cond_init(pthread_cond_t* const condition, void* cond_attr) { - (void)cond_attr; -#ifdef USE_WINDOWS_CONDITION_VARIABLE - InitializeConditionVariable(condition); -#else - condition->waiting_sem_ = CreateSemaphore(NULL, 0, 1, NULL); - condition->received_sem_ = CreateSemaphore(NULL, 0, 1, NULL); - condition->signal_event_ = CreateEvent(NULL, FALSE, FALSE, NULL); - if (condition->waiting_sem_ == NULL || - condition->received_sem_ == NULL || - condition->signal_event_ == NULL) { - pthread_cond_destroy(condition); - return 1; - } -#endif - return 0; -} - -static int pthread_cond_signal(pthread_cond_t* const condition) { - int ok = 1; -#ifdef USE_WINDOWS_CONDITION_VARIABLE - WakeConditionVariable(condition); -#else - if (WaitForSingleObject(condition->waiting_sem_, 0) == WAIT_OBJECT_0) { - // a thread is waiting in pthread_cond_wait: allow it to be notified - ok = SetEvent(condition->signal_event_); - // wait until the event is consumed so the signaler cannot consume - // the event via its own pthread_cond_wait. - ok &= (WaitForSingleObject(condition->received_sem_, INFINITE) != - WAIT_OBJECT_0); - } -#endif - return !ok; -} - -static int pthread_cond_wait(pthread_cond_t* const condition, - pthread_mutex_t* const mutex) { - int ok; -#ifdef USE_WINDOWS_CONDITION_VARIABLE - ok = SleepConditionVariableCS(condition, mutex, INFINITE); -#else - // note that there is a consumer available so the signal isn't dropped in - // pthread_cond_signal - if (!ReleaseSemaphore(condition->waiting_sem_, 1, NULL)) - return 1; - // now unlock the mutex so pthread_cond_signal may be issued - pthread_mutex_unlock(mutex); - ok = (WaitForSingleObject(condition->signal_event_, INFINITE) == - WAIT_OBJECT_0); - ok &= ReleaseSemaphore(condition->received_sem_, 1, NULL); - pthread_mutex_lock(mutex); -#endif - return !ok; -} - -#else // !_WIN32 -# define THREADFN void* -# define THREAD_RETURN(val) val -#endif // _WIN32 - -//------------------------------------------------------------------------------ - -static void Execute(WebPWorker* const worker); // Forward declaration. - -static THREADFN ThreadLoop(void* ptr) { - WebPWorker* const worker = (WebPWorker*)ptr; - int done = 0; - while (!done) { - pthread_mutex_lock(&worker->impl_->mutex_); - while (worker->status_ == OK) { // wait in idling mode - pthread_cond_wait(&worker->impl_->condition_, &worker->impl_->mutex_); - } - if (worker->status_ == WORK) { - Execute(worker); - worker->status_ = OK; - } else if (worker->status_ == NOT_OK) { // finish the worker - done = 1; - } - // signal to the main thread that we're done (for Sync()) - pthread_cond_signal(&worker->impl_->condition_); - pthread_mutex_unlock(&worker->impl_->mutex_); - } - return THREAD_RETURN(NULL); // Thread is finished -} - -// main thread state control -static void ChangeState(WebPWorker* const worker, - WebPWorkerStatus new_status) { - // No-op when attempting to change state on a thread that didn't come up. - // Checking status_ without acquiring the lock first would result in a data - // race. - if (worker->impl_ == NULL) return; - - pthread_mutex_lock(&worker->impl_->mutex_); - if (worker->status_ >= OK) { - // wait for the worker to finish - while (worker->status_ != OK) { - pthread_cond_wait(&worker->impl_->condition_, &worker->impl_->mutex_); - } - // assign new status and release the working thread if needed - if (new_status != OK) { - worker->status_ = new_status; - pthread_cond_signal(&worker->impl_->condition_); - } - } - pthread_mutex_unlock(&worker->impl_->mutex_); -} - -#endif // WEBP_USE_THREAD - -//------------------------------------------------------------------------------ - -static void Init(WebPWorker* const worker) { - memset(worker, 0, sizeof(*worker)); - worker->status_ = NOT_OK; -} - -static int Sync(WebPWorker* const worker) { -#ifdef WEBP_USE_THREAD - ChangeState(worker, OK); -#endif - assert(worker->status_ <= OK); - return !worker->had_error; -} - -static int Reset(WebPWorker* const worker) { - int ok = 1; - worker->had_error = 0; - if (worker->status_ < OK) { -#ifdef WEBP_USE_THREAD - worker->impl_ = (WebPWorkerImpl*)WebPSafeCalloc(1, sizeof(*worker->impl_)); - if (worker->impl_ == NULL) { - return 0; - } - if (pthread_mutex_init(&worker->impl_->mutex_, NULL)) { - goto Error; - } - if (pthread_cond_init(&worker->impl_->condition_, NULL)) { - pthread_mutex_destroy(&worker->impl_->mutex_); - goto Error; - } - pthread_mutex_lock(&worker->impl_->mutex_); - ok = !pthread_create(&worker->impl_->thread_, NULL, ThreadLoop, worker); - if (ok) worker->status_ = OK; - pthread_mutex_unlock(&worker->impl_->mutex_); - if (!ok) { - pthread_mutex_destroy(&worker->impl_->mutex_); - pthread_cond_destroy(&worker->impl_->condition_); - Error: - WebPSafeFree(worker->impl_); - worker->impl_ = NULL; - return 0; - } -#else - worker->status_ = OK; -#endif - } else if (worker->status_ > OK) { - ok = Sync(worker); - } - assert(!ok || (worker->status_ == OK)); - return ok; -} - -static void Execute(WebPWorker* const worker) { - if (worker->hook != NULL) { - worker->had_error |= !worker->hook(worker->data1, worker->data2); - } -} - -static void Launch(WebPWorker* const worker) { -#ifdef WEBP_USE_THREAD - ChangeState(worker, WORK); -#else - Execute(worker); -#endif -} - -static void End(WebPWorker* const worker) { -#ifdef WEBP_USE_THREAD - if (worker->impl_ != NULL) { - ChangeState(worker, NOT_OK); - pthread_join(worker->impl_->thread_, NULL); - pthread_mutex_destroy(&worker->impl_->mutex_); - pthread_cond_destroy(&worker->impl_->condition_); - WebPSafeFree(worker->impl_); - worker->impl_ = NULL; - } -#else - worker->status_ = NOT_OK; - assert(worker->impl_ == NULL); -#endif - assert(worker->status_ == NOT_OK); -} - -//------------------------------------------------------------------------------ - -static WebPWorkerInterface g_worker_interface = { - Init, Reset, Sync, Launch, Execute, End -}; - -int WebPSetWorkerInterface(const WebPWorkerInterface* const winterface) { - if (winterface == NULL || - winterface->Init == NULL || winterface->Reset == NULL || - winterface->Sync == NULL || winterface->Launch == NULL || - winterface->Execute == NULL || winterface->End == NULL) { - return 0; - } - g_worker_interface = *winterface; - return 1; -} - -const WebPWorkerInterface* WebPGetWorkerInterface(void) { - return &g_worker_interface; -} - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/utils/thread.h b/Example/Pods/libwebp/src/utils/thread.h deleted file mode 100644 index 84083118..00000000 --- a/Example/Pods/libwebp/src/utils/thread.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Multi-threaded worker -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_UTILS_THREAD_H_ -#define WEBP_UTILS_THREAD_H_ - -#ifdef HAVE_CONFIG_H -#include "../webp/config.h" -#endif - -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// State of the worker thread object -typedef enum { - NOT_OK = 0, // object is unusable - OK, // ready to work - WORK // busy finishing the current task -} WebPWorkerStatus; - -// Function to be called by the worker thread. Takes two opaque pointers as -// arguments (data1 and data2), and should return false in case of error. -typedef int (*WebPWorkerHook)(void*, void*); - -// Platform-dependent implementation details for the worker. -typedef struct WebPWorkerImpl WebPWorkerImpl; - -// Synchronization object used to launch job in the worker thread -typedef struct { - WebPWorkerImpl* impl_; - WebPWorkerStatus status_; - WebPWorkerHook hook; // hook to call - void* data1; // first argument passed to 'hook' - void* data2; // second argument passed to 'hook' - int had_error; // return value of the last call to 'hook' -} WebPWorker; - -// The interface for all thread-worker related functions. All these functions -// must be implemented. -typedef struct { - // Must be called first, before any other method. - void (*Init)(WebPWorker* const worker); - // Must be called to initialize the object and spawn the thread. Re-entrant. - // Will potentially launch the thread. Returns false in case of error. - int (*Reset)(WebPWorker* const worker); - // Makes sure the previous work is finished. Returns true if worker->had_error - // was not set and no error condition was triggered by the working thread. - int (*Sync)(WebPWorker* const worker); - // Triggers the thread to call hook() with data1 and data2 arguments. These - // hook/data1/data2 values can be changed at any time before calling this - // function, but not be changed afterward until the next call to Sync(). - void (*Launch)(WebPWorker* const worker); - // This function is similar to Launch() except that it calls the - // hook directly instead of using a thread. Convenient to bypass the thread - // mechanism while still using the WebPWorker structs. Sync() must - // still be called afterward (for error reporting). - void (*Execute)(WebPWorker* const worker); - // Kill the thread and terminate the object. To use the object again, one - // must call Reset() again. - void (*End)(WebPWorker* const worker); -} WebPWorkerInterface; - -// Install a new set of threading functions, overriding the defaults. This -// should be done before any workers are started, i.e., before any encoding or -// decoding takes place. The contents of the interface struct are copied, it -// is safe to free the corresponding memory after this call. This function is -// not thread-safe. Return false in case of invalid pointer or methods. -WEBP_EXTERN(int) WebPSetWorkerInterface( - const WebPWorkerInterface* const winterface); - -// Retrieve the currently set thread worker interface. -WEBP_EXTERN(const WebPWorkerInterface*) WebPGetWorkerInterface(void); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_THREAD_H_ */ diff --git a/Example/Pods/libwebp/src/utils/utils.c b/Example/Pods/libwebp/src/utils/utils.c deleted file mode 100644 index d8e30930..00000000 --- a/Example/Pods/libwebp/src/utils/utils.c +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Misc. common utility functions -// -// Author: Skal (pascal.massimino@gmail.com) - -#include -#include // for memcpy() -#include "../webp/decode.h" -#include "../webp/encode.h" -#include "./utils.h" - -// If PRINT_MEM_INFO is defined, extra info (like total memory used, number of -// alloc/free etc) is printed. For debugging/tuning purpose only (it's slow, -// and not multi-thread safe!). -// An interesting alternative is valgrind's 'massif' tool: -// http://valgrind.org/docs/manual/ms-manual.html -// Here is an example command line: -/* valgrind --tool=massif --massif-out-file=massif.out \ - --stacks=yes --alloc-fn=WebPSafeAlloc --alloc-fn=WebPSafeCalloc - ms_print massif.out -*/ -// In addition: -// * if PRINT_MEM_TRAFFIC is defined, all the details of the malloc/free cycles -// are printed. -// * if MALLOC_FAIL_AT is defined, the global environment variable -// $MALLOC_FAIL_AT is used to simulate a memory error when calloc or malloc -// is called for the nth time. Example usage: -// export MALLOC_FAIL_AT=50 && ./examples/cwebp input.png -// * if MALLOC_LIMIT is defined, the global environment variable $MALLOC_LIMIT -// sets the maximum amount of memory (in bytes) made available to libwebp. -// This can be used to emulate environment with very limited memory. -// Example: export MALLOC_LIMIT=64000000 && ./examples/dwebp picture.webp - -// #define PRINT_MEM_INFO -// #define PRINT_MEM_TRAFFIC -// #define MALLOC_FAIL_AT -// #define MALLOC_LIMIT - -//------------------------------------------------------------------------------ -// Checked memory allocation - -#if defined(PRINT_MEM_INFO) - -#include - -static int num_malloc_calls = 0; -static int num_calloc_calls = 0; -static int num_free_calls = 0; -static int countdown_to_fail = 0; // 0 = off - -typedef struct MemBlock MemBlock; -struct MemBlock { - void* ptr_; - size_t size_; - MemBlock* next_; -}; - -static MemBlock* all_blocks = NULL; -static size_t total_mem = 0; -static size_t total_mem_allocated = 0; -static size_t high_water_mark = 0; -static size_t mem_limit = 0; - -static int exit_registered = 0; - -static void PrintMemInfo(void) { - fprintf(stderr, "\nMEMORY INFO:\n"); - fprintf(stderr, "num calls to: malloc = %4d\n", num_malloc_calls); - fprintf(stderr, " calloc = %4d\n", num_calloc_calls); - fprintf(stderr, " free = %4d\n", num_free_calls); - fprintf(stderr, "total_mem: %u\n", (uint32_t)total_mem); - fprintf(stderr, "total_mem allocated: %u\n", (uint32_t)total_mem_allocated); - fprintf(stderr, "high-water mark: %u\n", (uint32_t)high_water_mark); - while (all_blocks != NULL) { - MemBlock* b = all_blocks; - all_blocks = b->next_; - free(b); - } -} - -static void Increment(int* const v) { - if (!exit_registered) { -#if defined(MALLOC_FAIL_AT) - { - const char* const malloc_fail_at_str = getenv("MALLOC_FAIL_AT"); - if (malloc_fail_at_str != NULL) { - countdown_to_fail = atoi(malloc_fail_at_str); - } - } -#endif -#if defined(MALLOC_LIMIT) - { - const char* const malloc_limit_str = getenv("MALLOC_LIMIT"); - if (malloc_limit_str != NULL) { - mem_limit = atoi(malloc_limit_str); - } - } -#endif - (void)countdown_to_fail; - (void)mem_limit; - atexit(PrintMemInfo); - exit_registered = 1; - } - ++*v; -} - -static void AddMem(void* ptr, size_t size) { - if (ptr != NULL) { - MemBlock* const b = (MemBlock*)malloc(sizeof(*b)); - if (b == NULL) abort(); - b->next_ = all_blocks; - all_blocks = b; - b->ptr_ = ptr; - b->size_ = size; - total_mem += size; - total_mem_allocated += size; -#if defined(PRINT_MEM_TRAFFIC) -#if defined(MALLOC_FAIL_AT) - fprintf(stderr, "fail-count: %5d [mem=%u]\n", - num_malloc_calls + num_calloc_calls, (uint32_t)total_mem); -#else - fprintf(stderr, "Mem: %u (+%u)\n", (uint32_t)total_mem, (uint32_t)size); -#endif -#endif - if (total_mem > high_water_mark) high_water_mark = total_mem; - } -} - -static void SubMem(void* ptr) { - if (ptr != NULL) { - MemBlock** b = &all_blocks; - // Inefficient search, but that's just for debugging. - while (*b != NULL && (*b)->ptr_ != ptr) b = &(*b)->next_; - if (*b == NULL) { - fprintf(stderr, "Invalid pointer free! (%p)\n", ptr); - abort(); - } - { - MemBlock* const block = *b; - *b = block->next_; - total_mem -= block->size_; -#if defined(PRINT_MEM_TRAFFIC) - fprintf(stderr, "Mem: %u (-%u)\n", - (uint32_t)total_mem, (uint32_t)block->size_); -#endif - free(block); - } - } -} - -#else -#define Increment(v) do {} while (0) -#define AddMem(p, s) do {} while (0) -#define SubMem(p) do {} while (0) -#endif - -// Returns 0 in case of overflow of nmemb * size. -static int CheckSizeArgumentsOverflow(uint64_t nmemb, size_t size) { - const uint64_t total_size = nmemb * size; - if (nmemb == 0) return 1; - if ((uint64_t)size > WEBP_MAX_ALLOCABLE_MEMORY / nmemb) return 0; - if (total_size != (size_t)total_size) return 0; -#if defined(PRINT_MEM_INFO) && defined(MALLOC_FAIL_AT) - if (countdown_to_fail > 0 && --countdown_to_fail == 0) { - return 0; // fake fail! - } -#endif -#if defined(MALLOC_LIMIT) - if (mem_limit > 0 && total_mem + total_size >= mem_limit) { - return 0; // fake fail! - } -#endif - - return 1; -} - -void* WebPSafeMalloc(uint64_t nmemb, size_t size) { - void* ptr; - Increment(&num_malloc_calls); - if (!CheckSizeArgumentsOverflow(nmemb, size)) return NULL; - assert(nmemb * size > 0); - ptr = malloc((size_t)(nmemb * size)); - AddMem(ptr, (size_t)(nmemb * size)); - return ptr; -} - -void* WebPSafeCalloc(uint64_t nmemb, size_t size) { - void* ptr; - Increment(&num_calloc_calls); - if (!CheckSizeArgumentsOverflow(nmemb, size)) return NULL; - assert(nmemb * size > 0); - ptr = calloc((size_t)nmemb, size); - AddMem(ptr, (size_t)(nmemb * size)); - return ptr; -} - -void WebPSafeFree(void* const ptr) { - if (ptr != NULL) { - Increment(&num_free_calls); - SubMem(ptr); - } - free(ptr); -} - -// Public API function. -void WebPFree(void* ptr) { - free(ptr); -} - -//------------------------------------------------------------------------------ - -void WebPCopyPlane(const uint8_t* src, int src_stride, - uint8_t* dst, int dst_stride, int width, int height) { - assert(src != NULL && dst != NULL); - assert(src_stride >= width && dst_stride >= width); - while (height-- > 0) { - memcpy(dst, src, width); - src += src_stride; - dst += dst_stride; - } -} - -void WebPCopyPixels(const WebPPicture* const src, WebPPicture* const dst) { - assert(src != NULL && dst != NULL); - assert(src->width == dst->width && src->height == dst->height); - assert(src->use_argb && dst->use_argb); - WebPCopyPlane((uint8_t*)src->argb, 4 * src->argb_stride, (uint8_t*)dst->argb, - 4 * dst->argb_stride, 4 * src->width, src->height); -} - -//------------------------------------------------------------------------------ diff --git a/Example/Pods/libwebp/src/utils/utils.h b/Example/Pods/libwebp/src/utils/utils.h deleted file mode 100644 index f506d668..00000000 --- a/Example/Pods/libwebp/src/utils/utils.h +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Misc. common utility functions -// -// Authors: Skal (pascal.massimino@gmail.com) -// Urvang (urvang@google.com) - -#ifndef WEBP_UTILS_UTILS_H_ -#define WEBP_UTILS_UTILS_H_ - -#ifdef HAVE_CONFIG_H -#include "../webp/config.h" -#endif - -#include - -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//------------------------------------------------------------------------------ -// Memory allocation - -// This is the maximum memory amount that libwebp will ever try to allocate. -#define WEBP_MAX_ALLOCABLE_MEMORY (1ULL << 40) - -// size-checking safe malloc/calloc: verify that the requested size is not too -// large, or return NULL. You don't need to call these for constructs like -// malloc(sizeof(foo)), but only if there's picture-dependent size involved -// somewhere (like: malloc(num_pixels * sizeof(*something))). That's why this -// safe malloc() borrows the signature from calloc(), pointing at the dangerous -// underlying multiply involved. -WEBP_EXTERN(void*) WebPSafeMalloc(uint64_t nmemb, size_t size); -// Note that WebPSafeCalloc() expects the second argument type to be 'size_t' -// in order to favor the "calloc(num_foo, sizeof(foo))" pattern. -WEBP_EXTERN(void*) WebPSafeCalloc(uint64_t nmemb, size_t size); - -// Companion deallocation function to the above allocations. -WEBP_EXTERN(void) WebPSafeFree(void* const ptr); - -//------------------------------------------------------------------------------ -// Alignment - -#define WEBP_ALIGN_CST 31 -#define WEBP_ALIGN(PTR) ((uintptr_t)((PTR) + WEBP_ALIGN_CST) & ~WEBP_ALIGN_CST) - -#if defined(WEBP_FORCE_ALIGNED) -#include -// memcpy() is the safe way of moving potentially unaligned 32b memory. -static WEBP_INLINE uint32_t WebPMemToUint32(const uint8_t* const ptr) { - uint32_t A; - memcpy(&A, (const int*)ptr, sizeof(A)); - return A; -} -static WEBP_INLINE void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) { - memcpy(ptr, &val, sizeof(val)); -} -#else -static WEBP_INLINE uint32_t WebPMemToUint32(const uint8_t* const ptr) { - return *(const uint32_t*)ptr; -} -static WEBP_INLINE void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) { - *(uint32_t*)ptr = val; -} -#endif - -//------------------------------------------------------------------------------ -// Reading/writing data. - -// Read 16, 24 or 32 bits stored in little-endian order. -static WEBP_INLINE int GetLE16(const uint8_t* const data) { - return (int)(data[0] << 0) | (data[1] << 8); -} - -static WEBP_INLINE int GetLE24(const uint8_t* const data) { - return GetLE16(data) | (data[2] << 16); -} - -static WEBP_INLINE uint32_t GetLE32(const uint8_t* const data) { - return GetLE16(data) | ((uint32_t)GetLE16(data + 2) << 16); -} - -// Store 16, 24 or 32 bits in little-endian order. -static WEBP_INLINE void PutLE16(uint8_t* const data, int val) { - assert(val < (1 << 16)); - data[0] = (val >> 0); - data[1] = (val >> 8); -} - -static WEBP_INLINE void PutLE24(uint8_t* const data, int val) { - assert(val < (1 << 24)); - PutLE16(data, val & 0xffff); - data[2] = (val >> 16); -} - -static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) { - PutLE16(data, (int)(val & 0xffff)); - PutLE16(data + 2, (int)(val >> 16)); -} - -// Returns (int)floor(log2(n)). n must be > 0. -// use GNU builtins where available. -#if defined(__GNUC__) && \ - ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4) -static WEBP_INLINE int BitsLog2Floor(uint32_t n) { - return 31 ^ __builtin_clz(n); -} -#elif defined(_MSC_VER) && _MSC_VER > 1310 && \ - (defined(_M_X64) || defined(_M_IX86)) -#include -#pragma intrinsic(_BitScanReverse) - -static WEBP_INLINE int BitsLog2Floor(uint32_t n) { - unsigned long first_set_bit; - _BitScanReverse(&first_set_bit, n); - return first_set_bit; -} -#else -static WEBP_INLINE int BitsLog2Floor(uint32_t n) { - int log = 0; - uint32_t value = n; - int i; - - for (i = 4; i >= 0; --i) { - const int shift = (1 << i); - const uint32_t x = value >> shift; - if (x != 0) { - value = x; - log += shift; - } - } - return log; -} -#endif - -//------------------------------------------------------------------------------ -// Pixel copying. - -struct WebPPicture; - -// Copy width x height pixels from 'src' to 'dst' honoring the strides. -WEBP_EXTERN(void) WebPCopyPlane(const uint8_t* src, int src_stride, - uint8_t* dst, int dst_stride, - int width, int height); - -// Copy ARGB pixels from 'src' to 'dst' honoring strides. 'src' and 'dst' are -// assumed to be already allocated and using ARGB data. -WEBP_EXTERN(void) WebPCopyPixels(const struct WebPPicture* const src, - struct WebPPicture* const dst); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_UTILS_H_ */ diff --git a/Example/Pods/libwebp/src/webp/decode.h b/Example/Pods/libwebp/src/webp/decode.h deleted file mode 100644 index 143e4fbe..00000000 --- a/Example/Pods/libwebp/src/webp/decode.h +++ /dev/null @@ -1,488 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Main decoding functions for WebP images. -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_WEBP_DECODE_H_ -#define WEBP_WEBP_DECODE_H_ - -#include "./types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define WEBP_DECODER_ABI_VERSION 0x0208 // MAJOR(8b) + MINOR(8b) - -// Note: forward declaring enumerations is not allowed in (strict) C and C++, -// the types are left here for reference. -// typedef enum VP8StatusCode VP8StatusCode; -// typedef enum WEBP_CSP_MODE WEBP_CSP_MODE; -typedef struct WebPRGBABuffer WebPRGBABuffer; -typedef struct WebPYUVABuffer WebPYUVABuffer; -typedef struct WebPDecBuffer WebPDecBuffer; -typedef struct WebPIDecoder WebPIDecoder; -typedef struct WebPBitstreamFeatures WebPBitstreamFeatures; -typedef struct WebPDecoderOptions WebPDecoderOptions; -typedef struct WebPDecoderConfig WebPDecoderConfig; - -// Return the decoder's version number, packed in hexadecimal using 8bits for -// each of major/minor/revision. E.g: v2.5.7 is 0x020507. -WEBP_EXTERN(int) WebPGetDecoderVersion(void); - -// Retrieve basic header information: width, height. -// This function will also validate the header and return 0 in -// case of formatting error. -// Pointers 'width' and 'height' can be passed NULL if deemed irrelevant. -WEBP_EXTERN(int) WebPGetInfo(const uint8_t* data, size_t data_size, - int* width, int* height); - -// Decodes WebP images pointed to by 'data' and returns RGBA samples, along -// with the dimensions in *width and *height. The ordering of samples in -// memory is R, G, B, A, R, G, B, A... in scan order (endian-independent). -// The returned pointer should be deleted calling WebPFree(). -// Returns NULL in case of error. -WEBP_EXTERN(uint8_t*) WebPDecodeRGBA(const uint8_t* data, size_t data_size, - int* width, int* height); - -// Same as WebPDecodeRGBA, but returning A, R, G, B, A, R, G, B... ordered data. -WEBP_EXTERN(uint8_t*) WebPDecodeARGB(const uint8_t* data, size_t data_size, - int* width, int* height); - -// Same as WebPDecodeRGBA, but returning B, G, R, A, B, G, R, A... ordered data. -WEBP_EXTERN(uint8_t*) WebPDecodeBGRA(const uint8_t* data, size_t data_size, - int* width, int* height); - -// Same as WebPDecodeRGBA, but returning R, G, B, R, G, B... ordered data. -// If the bitstream contains transparency, it is ignored. -WEBP_EXTERN(uint8_t*) WebPDecodeRGB(const uint8_t* data, size_t data_size, - int* width, int* height); - -// Same as WebPDecodeRGB, but returning B, G, R, B, G, R... ordered data. -WEBP_EXTERN(uint8_t*) WebPDecodeBGR(const uint8_t* data, size_t data_size, - int* width, int* height); - - -// Decode WebP images pointed to by 'data' to Y'UV format(*). The pointer -// returned is the Y samples buffer. Upon return, *u and *v will point to -// the U and V chroma data. These U and V buffers need NOT be passed to -// WebPFree(), unlike the returned Y luma one. The dimension of the U and V -// planes are both (*width + 1) / 2 and (*height + 1)/ 2. -// Upon return, the Y buffer has a stride returned as '*stride', while U and V -// have a common stride returned as '*uv_stride'. -// Return NULL in case of error. -// (*) Also named Y'CbCr. See: http://en.wikipedia.org/wiki/YCbCr -WEBP_EXTERN(uint8_t*) WebPDecodeYUV(const uint8_t* data, size_t data_size, - int* width, int* height, - uint8_t** u, uint8_t** v, - int* stride, int* uv_stride); - -// Releases memory returned by the WebPDecode*() functions above. -WEBP_EXTERN(void) WebPFree(void* ptr); - -// These five functions are variants of the above ones, that decode the image -// directly into a pre-allocated buffer 'output_buffer'. The maximum storage -// available in this buffer is indicated by 'output_buffer_size'. If this -// storage is not sufficient (or an error occurred), NULL is returned. -// Otherwise, output_buffer is returned, for convenience. -// The parameter 'output_stride' specifies the distance (in bytes) -// between scanlines. Hence, output_buffer_size is expected to be at least -// output_stride x picture-height. -WEBP_EXTERN(uint8_t*) WebPDecodeRGBAInto( - const uint8_t* data, size_t data_size, - uint8_t* output_buffer, size_t output_buffer_size, int output_stride); -WEBP_EXTERN(uint8_t*) WebPDecodeARGBInto( - const uint8_t* data, size_t data_size, - uint8_t* output_buffer, size_t output_buffer_size, int output_stride); -WEBP_EXTERN(uint8_t*) WebPDecodeBGRAInto( - const uint8_t* data, size_t data_size, - uint8_t* output_buffer, size_t output_buffer_size, int output_stride); - -// RGB and BGR variants. Here too the transparency information, if present, -// will be dropped and ignored. -WEBP_EXTERN(uint8_t*) WebPDecodeRGBInto( - const uint8_t* data, size_t data_size, - uint8_t* output_buffer, size_t output_buffer_size, int output_stride); -WEBP_EXTERN(uint8_t*) WebPDecodeBGRInto( - const uint8_t* data, size_t data_size, - uint8_t* output_buffer, size_t output_buffer_size, int output_stride); - -// WebPDecodeYUVInto() is a variant of WebPDecodeYUV() that operates directly -// into pre-allocated luma/chroma plane buffers. This function requires the -// strides to be passed: one for the luma plane and one for each of the -// chroma ones. The size of each plane buffer is passed as 'luma_size', -// 'u_size' and 'v_size' respectively. -// Pointer to the luma plane ('*luma') is returned or NULL if an error occurred -// during decoding (or because some buffers were found to be too small). -WEBP_EXTERN(uint8_t*) WebPDecodeYUVInto( - const uint8_t* data, size_t data_size, - uint8_t* luma, size_t luma_size, int luma_stride, - uint8_t* u, size_t u_size, int u_stride, - uint8_t* v, size_t v_size, int v_stride); - -//------------------------------------------------------------------------------ -// Output colorspaces and buffer - -// Colorspaces -// Note: the naming describes the byte-ordering of packed samples in memory. -// For instance, MODE_BGRA relates to samples ordered as B,G,R,A,B,G,R,A,... -// Non-capital names (e.g.:MODE_Argb) relates to pre-multiplied RGB channels. -// RGBA-4444 and RGB-565 colorspaces are represented by following byte-order: -// RGBA-4444: [r3 r2 r1 r0 g3 g2 g1 g0], [b3 b2 b1 b0 a3 a2 a1 a0], ... -// RGB-565: [r4 r3 r2 r1 r0 g5 g4 g3], [g2 g1 g0 b4 b3 b2 b1 b0], ... -// In the case WEBP_SWAP_16BITS_CSP is defined, the bytes are swapped for -// these two modes: -// RGBA-4444: [b3 b2 b1 b0 a3 a2 a1 a0], [r3 r2 r1 r0 g3 g2 g1 g0], ... -// RGB-565: [g2 g1 g0 b4 b3 b2 b1 b0], [r4 r3 r2 r1 r0 g5 g4 g3], ... - -typedef enum WEBP_CSP_MODE { - MODE_RGB = 0, MODE_RGBA = 1, - MODE_BGR = 2, MODE_BGRA = 3, - MODE_ARGB = 4, MODE_RGBA_4444 = 5, - MODE_RGB_565 = 6, - // RGB-premultiplied transparent modes (alpha value is preserved) - MODE_rgbA = 7, - MODE_bgrA = 8, - MODE_Argb = 9, - MODE_rgbA_4444 = 10, - // YUV modes must come after RGB ones. - MODE_YUV = 11, MODE_YUVA = 12, // yuv 4:2:0 - MODE_LAST = 13 -} WEBP_CSP_MODE; - -// Some useful macros: -static WEBP_INLINE int WebPIsPremultipliedMode(WEBP_CSP_MODE mode) { - return (mode == MODE_rgbA || mode == MODE_bgrA || mode == MODE_Argb || - mode == MODE_rgbA_4444); -} - -static WEBP_INLINE int WebPIsAlphaMode(WEBP_CSP_MODE mode) { - return (mode == MODE_RGBA || mode == MODE_BGRA || mode == MODE_ARGB || - mode == MODE_RGBA_4444 || mode == MODE_YUVA || - WebPIsPremultipliedMode(mode)); -} - -static WEBP_INLINE int WebPIsRGBMode(WEBP_CSP_MODE mode) { - return (mode < MODE_YUV); -} - -//------------------------------------------------------------------------------ -// WebPDecBuffer: Generic structure for describing the output sample buffer. - -struct WebPRGBABuffer { // view as RGBA - uint8_t* rgba; // pointer to RGBA samples - int stride; // stride in bytes from one scanline to the next. - size_t size; // total size of the *rgba buffer. -}; - -struct WebPYUVABuffer { // view as YUVA - uint8_t* y, *u, *v, *a; // pointer to luma, chroma U/V, alpha samples - int y_stride; // luma stride - int u_stride, v_stride; // chroma strides - int a_stride; // alpha stride - size_t y_size; // luma plane size - size_t u_size, v_size; // chroma planes size - size_t a_size; // alpha-plane size -}; - -// Output buffer -struct WebPDecBuffer { - WEBP_CSP_MODE colorspace; // Colorspace. - int width, height; // Dimensions. - int is_external_memory; // If true, 'internal_memory' pointer is not used. - union { - WebPRGBABuffer RGBA; - WebPYUVABuffer YUVA; - } u; // Nameless union of buffer parameters. - uint32_t pad[4]; // padding for later use - - uint8_t* private_memory; // Internally allocated memory (only when - // is_external_memory is false). Should not be used - // externally, but accessed via the buffer union. -}; - -// Internal, version-checked, entry point -WEBP_EXTERN(int) WebPInitDecBufferInternal(WebPDecBuffer*, int); - -// Initialize the structure as empty. Must be called before any other use. -// Returns false in case of version mismatch -static WEBP_INLINE int WebPInitDecBuffer(WebPDecBuffer* buffer) { - return WebPInitDecBufferInternal(buffer, WEBP_DECODER_ABI_VERSION); -} - -// Free any memory associated with the buffer. Must always be called last. -// Note: doesn't free the 'buffer' structure itself. -WEBP_EXTERN(void) WebPFreeDecBuffer(WebPDecBuffer* buffer); - -//------------------------------------------------------------------------------ -// Enumeration of the status codes - -typedef enum VP8StatusCode { - VP8_STATUS_OK = 0, - VP8_STATUS_OUT_OF_MEMORY, - VP8_STATUS_INVALID_PARAM, - VP8_STATUS_BITSTREAM_ERROR, - VP8_STATUS_UNSUPPORTED_FEATURE, - VP8_STATUS_SUSPENDED, - VP8_STATUS_USER_ABORT, - VP8_STATUS_NOT_ENOUGH_DATA -} VP8StatusCode; - -//------------------------------------------------------------------------------ -// Incremental decoding -// -// This API allows streamlined decoding of partial data. -// Picture can be incrementally decoded as data become available thanks to the -// WebPIDecoder object. This object can be left in a SUSPENDED state if the -// picture is only partially decoded, pending additional input. -// Code example: -// -// WebPInitDecBuffer(&buffer); -// buffer.colorspace = mode; -// ... -// WebPIDecoder* idec = WebPINewDecoder(&buffer); -// while (has_more_data) { -// // ... (get additional data) -// status = WebPIAppend(idec, new_data, new_data_size); -// if (status != VP8_STATUS_SUSPENDED || -// break; -// } -// -// // The above call decodes the current available buffer. -// // Part of the image can now be refreshed by calling to -// // WebPIDecGetRGB()/WebPIDecGetYUVA() etc. -// } -// WebPIDelete(idec); - -// Creates a new incremental decoder with the supplied buffer parameter. -// This output_buffer can be passed NULL, in which case a default output buffer -// is used (with MODE_RGB). Otherwise, an internal reference to 'output_buffer' -// is kept, which means that the lifespan of 'output_buffer' must be larger than -// that of the returned WebPIDecoder object. -// The supplied 'output_buffer' content MUST NOT be changed between calls to -// WebPIAppend() or WebPIUpdate() unless 'output_buffer.is_external_memory' is -// set to 1. In such a case, it is allowed to modify the pointers, size and -// stride of output_buffer.u.RGBA or output_buffer.u.YUVA, provided they remain -// within valid bounds. -// All other fields of WebPDecBuffer MUST remain constant between calls. -// Returns NULL if the allocation failed. -WEBP_EXTERN(WebPIDecoder*) WebPINewDecoder(WebPDecBuffer* output_buffer); - -// This function allocates and initializes an incremental-decoder object, which -// will output the RGB/A samples specified by 'csp' into a preallocated -// buffer 'output_buffer'. The size of this buffer is at least -// 'output_buffer_size' and the stride (distance in bytes between two scanlines) -// is specified by 'output_stride'. -// Additionally, output_buffer can be passed NULL in which case the output -// buffer will be allocated automatically when the decoding starts. The -// colorspace 'csp' is taken into account for allocating this buffer. All other -// parameters are ignored. -// Returns NULL if the allocation failed, or if some parameters are invalid. -WEBP_EXTERN(WebPIDecoder*) WebPINewRGB( - WEBP_CSP_MODE csp, - uint8_t* output_buffer, size_t output_buffer_size, int output_stride); - -// This function allocates and initializes an incremental-decoder object, which -// will output the raw luma/chroma samples into a preallocated planes if -// supplied. The luma plane is specified by its pointer 'luma', its size -// 'luma_size' and its stride 'luma_stride'. Similarly, the chroma-u plane -// is specified by the 'u', 'u_size' and 'u_stride' parameters, and the chroma-v -// plane by 'v' and 'v_size'. And same for the alpha-plane. The 'a' pointer -// can be pass NULL in case one is not interested in the transparency plane. -// Conversely, 'luma' can be passed NULL if no preallocated planes are supplied. -// In this case, the output buffer will be automatically allocated (using -// MODE_YUVA) when decoding starts. All parameters are then ignored. -// Returns NULL if the allocation failed or if a parameter is invalid. -WEBP_EXTERN(WebPIDecoder*) WebPINewYUVA( - uint8_t* luma, size_t luma_size, int luma_stride, - uint8_t* u, size_t u_size, int u_stride, - uint8_t* v, size_t v_size, int v_stride, - uint8_t* a, size_t a_size, int a_stride); - -// Deprecated version of the above, without the alpha plane. -// Kept for backward compatibility. -WEBP_EXTERN(WebPIDecoder*) WebPINewYUV( - uint8_t* luma, size_t luma_size, int luma_stride, - uint8_t* u, size_t u_size, int u_stride, - uint8_t* v, size_t v_size, int v_stride); - -// Deletes the WebPIDecoder object and associated memory. Must always be called -// if WebPINewDecoder, WebPINewRGB or WebPINewYUV succeeded. -WEBP_EXTERN(void) WebPIDelete(WebPIDecoder* idec); - -// Copies and decodes the next available data. Returns VP8_STATUS_OK when -// the image is successfully decoded. Returns VP8_STATUS_SUSPENDED when more -// data is expected. Returns error in other cases. -WEBP_EXTERN(VP8StatusCode) WebPIAppend( - WebPIDecoder* idec, const uint8_t* data, size_t data_size); - -// A variant of the above function to be used when data buffer contains -// partial data from the beginning. In this case data buffer is not copied -// to the internal memory. -// Note that the value of the 'data' pointer can change between calls to -// WebPIUpdate, for instance when the data buffer is resized to fit larger data. -WEBP_EXTERN(VP8StatusCode) WebPIUpdate( - WebPIDecoder* idec, const uint8_t* data, size_t data_size); - -// Returns the RGB/A image decoded so far. Returns NULL if output params -// are not initialized yet. The RGB/A output type corresponds to the colorspace -// specified during call to WebPINewDecoder() or WebPINewRGB(). -// *last_y is the index of last decoded row in raster scan order. Some pointers -// (*last_y, *width etc.) can be NULL if corresponding information is not -// needed. -WEBP_EXTERN(uint8_t*) WebPIDecGetRGB( - const WebPIDecoder* idec, int* last_y, - int* width, int* height, int* stride); - -// Same as above function to get a YUVA image. Returns pointer to the luma -// plane or NULL in case of error. If there is no alpha information -// the alpha pointer '*a' will be returned NULL. -WEBP_EXTERN(uint8_t*) WebPIDecGetYUVA( - const WebPIDecoder* idec, int* last_y, - uint8_t** u, uint8_t** v, uint8_t** a, - int* width, int* height, int* stride, int* uv_stride, int* a_stride); - -// Deprecated alpha-less version of WebPIDecGetYUVA(): it will ignore the -// alpha information (if present). Kept for backward compatibility. -static WEBP_INLINE uint8_t* WebPIDecGetYUV( - const WebPIDecoder* idec, int* last_y, uint8_t** u, uint8_t** v, - int* width, int* height, int* stride, int* uv_stride) { - return WebPIDecGetYUVA(idec, last_y, u, v, NULL, width, height, - stride, uv_stride, NULL); -} - -// Generic call to retrieve information about the displayable area. -// If non NULL, the left/right/width/height pointers are filled with the visible -// rectangular area so far. -// Returns NULL in case the incremental decoder object is in an invalid state. -// Otherwise returns the pointer to the internal representation. This structure -// is read-only, tied to WebPIDecoder's lifespan and should not be modified. -WEBP_EXTERN(const WebPDecBuffer*) WebPIDecodedArea( - const WebPIDecoder* idec, int* left, int* top, int* width, int* height); - -//------------------------------------------------------------------------------ -// Advanced decoding parametrization -// -// Code sample for using the advanced decoding API -/* - // A) Init a configuration object - WebPDecoderConfig config; - CHECK(WebPInitDecoderConfig(&config)); - - // B) optional: retrieve the bitstream's features. - CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK); - - // C) Adjust 'config', if needed - config.no_fancy_upsampling = 1; - config.output.colorspace = MODE_BGRA; - // etc. - - // Note that you can also make config.output point to an externally - // supplied memory buffer, provided it's big enough to store the decoded - // picture. Otherwise, config.output will just be used to allocate memory - // and store the decoded picture. - - // D) Decode! - CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK); - - // E) Decoded image is now in config.output (and config.output.u.RGBA) - - // F) Reclaim memory allocated in config's object. It's safe to call - // this function even if the memory is external and wasn't allocated - // by WebPDecode(). - WebPFreeDecBuffer(&config.output); -*/ - -// Features gathered from the bitstream -struct WebPBitstreamFeatures { - int width; // Width in pixels, as read from the bitstream. - int height; // Height in pixels, as read from the bitstream. - int has_alpha; // True if the bitstream contains an alpha channel. - int has_animation; // True if the bitstream is an animation. - int format; // 0 = undefined (/mixed), 1 = lossy, 2 = lossless - - uint32_t pad[5]; // padding for later use -}; - -// Internal, version-checked, entry point -WEBP_EXTERN(VP8StatusCode) WebPGetFeaturesInternal( - const uint8_t*, size_t, WebPBitstreamFeatures*, int); - -// Retrieve features from the bitstream. The *features structure is filled -// with information gathered from the bitstream. -// Returns VP8_STATUS_OK when the features are successfully retrieved. Returns -// VP8_STATUS_NOT_ENOUGH_DATA when more data is needed to retrieve the -// features from headers. Returns error in other cases. -static WEBP_INLINE VP8StatusCode WebPGetFeatures( - const uint8_t* data, size_t data_size, - WebPBitstreamFeatures* features) { - return WebPGetFeaturesInternal(data, data_size, features, - WEBP_DECODER_ABI_VERSION); -} - -// Decoding options -struct WebPDecoderOptions { - int bypass_filtering; // if true, skip the in-loop filtering - int no_fancy_upsampling; // if true, use faster pointwise upsampler - int use_cropping; // if true, cropping is applied _first_ - int crop_left, crop_top; // top-left position for cropping. - // Will be snapped to even values. - int crop_width, crop_height; // dimension of the cropping area - int use_scaling; // if true, scaling is applied _afterward_ - int scaled_width, scaled_height; // final resolution - int use_threads; // if true, use multi-threaded decoding - int dithering_strength; // dithering strength (0=Off, 100=full) - int flip; // flip output vertically - int alpha_dithering_strength; // alpha dithering strength in [0..100] - - uint32_t pad[5]; // padding for later use -}; - -// Main object storing the configuration for advanced decoding. -struct WebPDecoderConfig { - WebPBitstreamFeatures input; // Immutable bitstream features (optional) - WebPDecBuffer output; // Output buffer (can point to external mem) - WebPDecoderOptions options; // Decoding options -}; - -// Internal, version-checked, entry point -WEBP_EXTERN(int) WebPInitDecoderConfigInternal(WebPDecoderConfig*, int); - -// Initialize the configuration as empty. This function must always be -// called first, unless WebPGetFeatures() is to be called. -// Returns false in case of mismatched version. -static WEBP_INLINE int WebPInitDecoderConfig(WebPDecoderConfig* config) { - return WebPInitDecoderConfigInternal(config, WEBP_DECODER_ABI_VERSION); -} - -// Instantiate a new incremental decoder object with the requested -// configuration. The bitstream can be passed using 'data' and 'data_size' -// parameter, in which case the features will be parsed and stored into -// config->input. Otherwise, 'data' can be NULL and no parsing will occur. -// Note that 'config' can be NULL too, in which case a default configuration -// is used. -// The return WebPIDecoder object must always be deleted calling WebPIDelete(). -// Returns NULL in case of error (and config->status will then reflect -// the error condition). -WEBP_EXTERN(WebPIDecoder*) WebPIDecode(const uint8_t* data, size_t data_size, - WebPDecoderConfig* config); - -// Non-incremental version. This version decodes the full data at once, taking -// 'config' into account. Returns decoding status (which should be VP8_STATUS_OK -// if the decoding was successful). -WEBP_EXTERN(VP8StatusCode) WebPDecode(const uint8_t* data, size_t data_size, - WebPDecoderConfig* config); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_WEBP_DECODE_H_ */ diff --git a/Example/Pods/libwebp/src/webp/demux.h b/Example/Pods/libwebp/src/webp/demux.h deleted file mode 100644 index 454f6914..00000000 --- a/Example/Pods/libwebp/src/webp/demux.h +++ /dev/null @@ -1,358 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Demux API. -// Enables extraction of image and extended format data from WebP files. - -// Code Example: Demuxing WebP data to extract all the frames, ICC profile -// and EXIF/XMP metadata. -/* - WebPDemuxer* demux = WebPDemux(&webp_data); - - uint32_t width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH); - uint32_t height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT); - // ... (Get information about the features present in the WebP file). - uint32_t flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS); - - // ... (Iterate over all frames). - WebPIterator iter; - if (WebPDemuxGetFrame(demux, 1, &iter)) { - do { - // ... (Consume 'iter'; e.g. Decode 'iter.fragment' with WebPDecode(), - // ... and get other frame properties like width, height, offsets etc. - // ... see 'struct WebPIterator' below for more info). - } while (WebPDemuxNextFrame(&iter)); - WebPDemuxReleaseIterator(&iter); - } - - // ... (Extract metadata). - WebPChunkIterator chunk_iter; - if (flags & ICCP_FLAG) WebPDemuxGetChunk(demux, "ICCP", 1, &chunk_iter); - // ... (Consume the ICC profile in 'chunk_iter.chunk'). - WebPDemuxReleaseChunkIterator(&chunk_iter); - if (flags & EXIF_FLAG) WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter); - // ... (Consume the EXIF metadata in 'chunk_iter.chunk'). - WebPDemuxReleaseChunkIterator(&chunk_iter); - if (flags & XMP_FLAG) WebPDemuxGetChunk(demux, "XMP ", 1, &chunk_iter); - // ... (Consume the XMP metadata in 'chunk_iter.chunk'). - WebPDemuxReleaseChunkIterator(&chunk_iter); - WebPDemuxDelete(demux); -*/ - -#ifndef WEBP_WEBP_DEMUX_H_ -#define WEBP_WEBP_DEMUX_H_ - -#include "./decode.h" // for WEBP_CSP_MODE -#include "./mux_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define WEBP_DEMUX_ABI_VERSION 0x0107 // MAJOR(8b) + MINOR(8b) - -// Note: forward declaring enumerations is not allowed in (strict) C and C++, -// the types are left here for reference. -// typedef enum WebPDemuxState WebPDemuxState; -// typedef enum WebPFormatFeature WebPFormatFeature; -typedef struct WebPDemuxer WebPDemuxer; -typedef struct WebPIterator WebPIterator; -typedef struct WebPChunkIterator WebPChunkIterator; -typedef struct WebPAnimInfo WebPAnimInfo; -typedef struct WebPAnimDecoderOptions WebPAnimDecoderOptions; - -//------------------------------------------------------------------------------ - -// Returns the version number of the demux library, packed in hexadecimal using -// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507. -WEBP_EXTERN(int) WebPGetDemuxVersion(void); - -//------------------------------------------------------------------------------ -// Life of a Demux object - -typedef enum WebPDemuxState { - WEBP_DEMUX_PARSE_ERROR = -1, // An error occurred while parsing. - WEBP_DEMUX_PARSING_HEADER = 0, // Not enough data to parse full header. - WEBP_DEMUX_PARSED_HEADER = 1, // Header parsing complete, - // data may be available. - WEBP_DEMUX_DONE = 2 // Entire file has been parsed. -} WebPDemuxState; - -// Internal, version-checked, entry point -WEBP_EXTERN(WebPDemuxer*) WebPDemuxInternal( - const WebPData*, int, WebPDemuxState*, int); - -// Parses the full WebP file given by 'data'. For single images the WebP file -// header alone or the file header and the chunk header may be absent. -// Returns a WebPDemuxer object on successful parse, NULL otherwise. -static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) { - return WebPDemuxInternal(data, 0, NULL, WEBP_DEMUX_ABI_VERSION); -} - -// Parses the possibly incomplete WebP file given by 'data'. -// If 'state' is non-NULL it will be set to indicate the status of the demuxer. -// Returns NULL in case of error or if there isn't enough data to start parsing; -// and a WebPDemuxer object on successful parse. -// Note that WebPDemuxer keeps internal pointers to 'data' memory segment. -// If this data is volatile, the demuxer object should be deleted (by calling -// WebPDemuxDelete()) and WebPDemuxPartial() called again on the new data. -// This is usually an inexpensive operation. -static WEBP_INLINE WebPDemuxer* WebPDemuxPartial( - const WebPData* data, WebPDemuxState* state) { - return WebPDemuxInternal(data, 1, state, WEBP_DEMUX_ABI_VERSION); -} - -// Frees memory associated with 'dmux'. -WEBP_EXTERN(void) WebPDemuxDelete(WebPDemuxer* dmux); - -//------------------------------------------------------------------------------ -// Data/information extraction. - -typedef enum WebPFormatFeature { - WEBP_FF_FORMAT_FLAGS, // Extended format flags present in the 'VP8X' chunk. - WEBP_FF_CANVAS_WIDTH, - WEBP_FF_CANVAS_HEIGHT, - WEBP_FF_LOOP_COUNT, - WEBP_FF_BACKGROUND_COLOR, - WEBP_FF_FRAME_COUNT // Number of frames present in the demux object. - // In case of a partial demux, this is the number of - // frames seen so far, with the last frame possibly - // being partial. -} WebPFormatFeature; - -// Get the 'feature' value from the 'dmux'. -// NOTE: values are only valid if WebPDemux() was used or WebPDemuxPartial() -// returned a state > WEBP_DEMUX_PARSING_HEADER. -WEBP_EXTERN(uint32_t) WebPDemuxGetI( - const WebPDemuxer* dmux, WebPFormatFeature feature); - -//------------------------------------------------------------------------------ -// Frame iteration. - -struct WebPIterator { - int frame_num; - int num_frames; // equivalent to WEBP_FF_FRAME_COUNT. - int x_offset, y_offset; // offset relative to the canvas. - int width, height; // dimensions of this frame. - int duration; // display duration in milliseconds. - WebPMuxAnimDispose dispose_method; // dispose method for the frame. - int complete; // true if 'fragment' contains a full frame. partial images - // may still be decoded with the WebP incremental decoder. - WebPData fragment; // The frame given by 'frame_num'. Note for historical - // reasons this is called a fragment. - int has_alpha; // True if the frame contains transparency. - WebPMuxAnimBlend blend_method; // Blend operation for the frame. - - uint32_t pad[2]; // padding for later use. - void* private_; // for internal use only. -}; - -// Retrieves frame 'frame_number' from 'dmux'. -// 'iter->fragment' points to the frame on return from this function. -// Setting 'frame_number' equal to 0 will return the last frame of the image. -// Returns false if 'dmux' is NULL or frame 'frame_number' is not present. -// Call WebPDemuxReleaseIterator() when use of the iterator is complete. -// NOTE: 'dmux' must persist for the lifetime of 'iter'. -WEBP_EXTERN(int) WebPDemuxGetFrame( - const WebPDemuxer* dmux, int frame_number, WebPIterator* iter); - -// Sets 'iter->fragment' to point to the next ('iter->frame_num' + 1) or -// previous ('iter->frame_num' - 1) frame. These functions do not loop. -// Returns true on success, false otherwise. -WEBP_EXTERN(int) WebPDemuxNextFrame(WebPIterator* iter); -WEBP_EXTERN(int) WebPDemuxPrevFrame(WebPIterator* iter); - -// Releases any memory associated with 'iter'. -// Must be called before any subsequent calls to WebPDemuxGetChunk() on the same -// iter. Also, must be called before destroying the associated WebPDemuxer with -// WebPDemuxDelete(). -WEBP_EXTERN(void) WebPDemuxReleaseIterator(WebPIterator* iter); - -//------------------------------------------------------------------------------ -// Chunk iteration. - -struct WebPChunkIterator { - // The current and total number of chunks with the fourcc given to - // WebPDemuxGetChunk(). - int chunk_num; - int num_chunks; - WebPData chunk; // The payload of the chunk. - - uint32_t pad[6]; // padding for later use - void* private_; -}; - -// Retrieves the 'chunk_number' instance of the chunk with id 'fourcc' from -// 'dmux'. -// 'fourcc' is a character array containing the fourcc of the chunk to return, -// e.g., "ICCP", "XMP ", "EXIF", etc. -// Setting 'chunk_number' equal to 0 will return the last chunk in a set. -// Returns true if the chunk is found, false otherwise. Image related chunk -// payloads are accessed through WebPDemuxGetFrame() and related functions. -// Call WebPDemuxReleaseChunkIterator() when use of the iterator is complete. -// NOTE: 'dmux' must persist for the lifetime of the iterator. -WEBP_EXTERN(int) WebPDemuxGetChunk(const WebPDemuxer* dmux, - const char fourcc[4], int chunk_number, - WebPChunkIterator* iter); - -// Sets 'iter->chunk' to point to the next ('iter->chunk_num' + 1) or previous -// ('iter->chunk_num' - 1) chunk. These functions do not loop. -// Returns true on success, false otherwise. -WEBP_EXTERN(int) WebPDemuxNextChunk(WebPChunkIterator* iter); -WEBP_EXTERN(int) WebPDemuxPrevChunk(WebPChunkIterator* iter); - -// Releases any memory associated with 'iter'. -// Must be called before destroying the associated WebPDemuxer with -// WebPDemuxDelete(). -WEBP_EXTERN(void) WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter); - -//------------------------------------------------------------------------------ -// WebPAnimDecoder API -// -// This API allows decoding (possibly) animated WebP images. -// -// Code Example: -/* - WebPAnimDecoderOptions dec_options; - WebPAnimDecoderOptionsInit(&dec_options); - // Tune 'dec_options' as needed. - WebPAnimDecoder* dec = WebPAnimDecoderNew(webp_data, &dec_options); - WebPAnimInfo anim_info; - WebPAnimDecoderGetInfo(dec, &anim_info); - for (uint32_t i = 0; i < anim_info.loop_count; ++i) { - while (WebPAnimDecoderHasMoreFrames(dec)) { - uint8_t* buf; - int timestamp; - WebPAnimDecoderGetNext(dec, &buf, ×tamp); - // ... (Render 'buf' based on 'timestamp'). - // ... (Do NOT free 'buf', as it is owned by 'dec'). - } - WebPAnimDecoderReset(dec); - } - const WebPDemuxer* demuxer = WebPAnimDecoderGetDemuxer(dec); - // ... (Do something using 'demuxer'; e.g. get EXIF/XMP/ICC data). - WebPAnimDecoderDelete(dec); -*/ - -typedef struct WebPAnimDecoder WebPAnimDecoder; // Main opaque object. - -// Global options. -struct WebPAnimDecoderOptions { - // Output colorspace. Only the following modes are supported: - // MODE_RGBA, MODE_BGRA, MODE_rgbA and MODE_bgrA. - WEBP_CSP_MODE color_mode; - int use_threads; // If true, use multi-threaded decoding. - uint32_t padding[7]; // Padding for later use. -}; - -// Internal, version-checked, entry point. -WEBP_EXTERN(int) WebPAnimDecoderOptionsInitInternal( - WebPAnimDecoderOptions*, int); - -// Should always be called, to initialize a fresh WebPAnimDecoderOptions -// structure before modification. Returns false in case of version mismatch. -// WebPAnimDecoderOptionsInit() must have succeeded before using the -// 'dec_options' object. -static WEBP_INLINE int WebPAnimDecoderOptionsInit( - WebPAnimDecoderOptions* dec_options) { - return WebPAnimDecoderOptionsInitInternal(dec_options, - WEBP_DEMUX_ABI_VERSION); -} - -// Internal, version-checked, entry point. -WEBP_EXTERN(WebPAnimDecoder*) WebPAnimDecoderNewInternal( - const WebPData*, const WebPAnimDecoderOptions*, int); - -// Creates and initializes a WebPAnimDecoder object. -// Parameters: -// webp_data - (in) WebP bitstream. This should remain unchanged during the -// lifetime of the output WebPAnimDecoder object. -// dec_options - (in) decoding options. Can be passed NULL to choose -// reasonable defaults (in particular, color mode MODE_RGBA -// will be picked). -// Returns: -// A pointer to the newly created WebPAnimDecoder object, or NULL in case of -// parsing error, invalid option or memory error. -static WEBP_INLINE WebPAnimDecoder* WebPAnimDecoderNew( - const WebPData* webp_data, const WebPAnimDecoderOptions* dec_options) { - return WebPAnimDecoderNewInternal(webp_data, dec_options, - WEBP_DEMUX_ABI_VERSION); -} - -// Global information about the animation.. -struct WebPAnimInfo { - uint32_t canvas_width; - uint32_t canvas_height; - uint32_t loop_count; - uint32_t bgcolor; - uint32_t frame_count; - uint32_t pad[4]; // padding for later use -}; - -// Get global information about the animation. -// Parameters: -// dec - (in) decoder instance to get information from. -// info - (out) global information fetched from the animation. -// Returns: -// True on success. -WEBP_EXTERN(int) WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec, - WebPAnimInfo* info); - -// Fetch the next frame from 'dec' based on options supplied to -// WebPAnimDecoderNew(). This will be a fully reconstructed canvas of size -// 'canvas_width * 4 * canvas_height', and not just the frame sub-rectangle. The -// returned buffer 'buf' is valid only until the next call to -// WebPAnimDecoderGetNext(), WebPAnimDecoderReset() or WebPAnimDecoderDelete(). -// Parameters: -// dec - (in/out) decoder instance from which the next frame is to be fetched. -// buf - (out) decoded frame. -// timestamp - (out) timestamp of the frame in milliseconds. -// Returns: -// False if any of the arguments are NULL, or if there is a parsing or -// decoding error, or if there are no more frames. Otherwise, returns true. -WEBP_EXTERN(int) WebPAnimDecoderGetNext(WebPAnimDecoder* dec, - uint8_t** buf, int* timestamp); - -// Check if there are more frames left to decode. -// Parameters: -// dec - (in) decoder instance to be checked. -// Returns: -// True if 'dec' is not NULL and some frames are yet to be decoded. -// Otherwise, returns false. -WEBP_EXTERN(int) WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec); - -// Resets the WebPAnimDecoder object, so that next call to -// WebPAnimDecoderGetNext() will restart decoding from 1st frame. This would be -// helpful when all frames need to be decoded multiple times (e.g. -// info.loop_count times) without destroying and recreating the 'dec' object. -// Parameters: -// dec - (in/out) decoder instance to be reset -WEBP_EXTERN(void) WebPAnimDecoderReset(WebPAnimDecoder* dec); - -// Grab the internal demuxer object. -// Getting the demuxer object can be useful if one wants to use operations only -// available through demuxer; e.g. to get XMP/EXIF/ICC metadata. The returned -// demuxer object is owned by 'dec' and is valid only until the next call to -// WebPAnimDecoderDelete(). -// -// Parameters: -// dec - (in) decoder instance from which the demuxer object is to be fetched. -WEBP_EXTERN(const WebPDemuxer*) WebPAnimDecoderGetDemuxer( - const WebPAnimDecoder* dec); - -// Deletes the WebPAnimDecoder object. -// Parameters: -// dec - (in/out) decoder instance to be deleted -WEBP_EXTERN(void) WebPAnimDecoderDelete(WebPAnimDecoder* dec); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_WEBP_DEMUX_H_ */ diff --git a/Example/Pods/libwebp/src/webp/encode.h b/Example/Pods/libwebp/src/webp/encode.h deleted file mode 100644 index c382ea76..00000000 --- a/Example/Pods/libwebp/src/webp/encode.h +++ /dev/null @@ -1,527 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// WebP encoder: main interface -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_WEBP_ENCODE_H_ -#define WEBP_WEBP_ENCODE_H_ - -#include "./types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define WEBP_ENCODER_ABI_VERSION 0x0209 // MAJOR(8b) + MINOR(8b) - -// Note: forward declaring enumerations is not allowed in (strict) C and C++, -// the types are left here for reference. -// typedef enum WebPImageHint WebPImageHint; -// typedef enum WebPEncCSP WebPEncCSP; -// typedef enum WebPPreset WebPPreset; -// typedef enum WebPEncodingError WebPEncodingError; -typedef struct WebPConfig WebPConfig; -typedef struct WebPPicture WebPPicture; // main structure for I/O -typedef struct WebPAuxStats WebPAuxStats; -typedef struct WebPMemoryWriter WebPMemoryWriter; - -// Return the encoder's version number, packed in hexadecimal using 8bits for -// each of major/minor/revision. E.g: v2.5.7 is 0x020507. -WEBP_EXTERN(int) WebPGetEncoderVersion(void); - -//------------------------------------------------------------------------------ -// One-stop-shop call! No questions asked: - -// Returns the size of the compressed data (pointed to by *output), or 0 if -// an error occurred. The compressed data must be released by the caller -// using the call 'WebPFree(*output)'. -// These functions compress using the lossy format, and the quality_factor -// can go from 0 (smaller output, lower quality) to 100 (best quality, -// larger output). -WEBP_EXTERN(size_t) WebPEncodeRGB(const uint8_t* rgb, - int width, int height, int stride, - float quality_factor, uint8_t** output); -WEBP_EXTERN(size_t) WebPEncodeBGR(const uint8_t* bgr, - int width, int height, int stride, - float quality_factor, uint8_t** output); -WEBP_EXTERN(size_t) WebPEncodeRGBA(const uint8_t* rgba, - int width, int height, int stride, - float quality_factor, uint8_t** output); -WEBP_EXTERN(size_t) WebPEncodeBGRA(const uint8_t* bgra, - int width, int height, int stride, - float quality_factor, uint8_t** output); - -// These functions are the equivalent of the above, but compressing in a -// lossless manner. Files are usually larger than lossy format, but will -// not suffer any compression loss. -WEBP_EXTERN(size_t) WebPEncodeLosslessRGB(const uint8_t* rgb, - int width, int height, int stride, - uint8_t** output); -WEBP_EXTERN(size_t) WebPEncodeLosslessBGR(const uint8_t* bgr, - int width, int height, int stride, - uint8_t** output); -WEBP_EXTERN(size_t) WebPEncodeLosslessRGBA(const uint8_t* rgba, - int width, int height, int stride, - uint8_t** output); -WEBP_EXTERN(size_t) WebPEncodeLosslessBGRA(const uint8_t* bgra, - int width, int height, int stride, - uint8_t** output); - -// Releases memory returned by the WebPEncode*() functions above. -WEBP_EXTERN(void) WebPFree(void* ptr); - -//------------------------------------------------------------------------------ -// Coding parameters - -// Image characteristics hint for the underlying encoder. -typedef enum WebPImageHint { - WEBP_HINT_DEFAULT = 0, // default preset. - WEBP_HINT_PICTURE, // digital picture, like portrait, inner shot - WEBP_HINT_PHOTO, // outdoor photograph, with natural lighting - WEBP_HINT_GRAPH, // Discrete tone image (graph, map-tile etc). - WEBP_HINT_LAST -} WebPImageHint; - -// Compression parameters. -struct WebPConfig { - int lossless; // Lossless encoding (0=lossy(default), 1=lossless). - float quality; // between 0 (smallest file) and 100 (biggest) - int method; // quality/speed trade-off (0=fast, 6=slower-better) - - WebPImageHint image_hint; // Hint for image type (lossless only for now). - - // Parameters related to lossy compression only: - int target_size; // if non-zero, set the desired target size in bytes. - // Takes precedence over the 'compression' parameter. - float target_PSNR; // if non-zero, specifies the minimal distortion to - // try to achieve. Takes precedence over target_size. - int segments; // maximum number of segments to use, in [1..4] - int sns_strength; // Spatial Noise Shaping. 0=off, 100=maximum. - int filter_strength; // range: [0 = off .. 100 = strongest] - int filter_sharpness; // range: [0 = off .. 7 = least sharp] - int filter_type; // filtering type: 0 = simple, 1 = strong (only used - // if filter_strength > 0 or autofilter > 0) - int autofilter; // Auto adjust filter's strength [0 = off, 1 = on] - int alpha_compression; // Algorithm for encoding the alpha plane (0 = none, - // 1 = compressed with WebP lossless). Default is 1. - int alpha_filtering; // Predictive filtering method for alpha plane. - // 0: none, 1: fast, 2: best. Default if 1. - int alpha_quality; // Between 0 (smallest size) and 100 (lossless). - // Default is 100. - int pass; // number of entropy-analysis passes (in [1..10]). - - int show_compressed; // if true, export the compressed picture back. - // In-loop filtering is not applied. - int preprocessing; // preprocessing filter: - // 0=none, 1=segment-smooth, 2=pseudo-random dithering - int partitions; // log2(number of token partitions) in [0..3]. Default - // is set to 0 for easier progressive decoding. - int partition_limit; // quality degradation allowed to fit the 512k limit - // on prediction modes coding (0: no degradation, - // 100: maximum possible degradation). - int emulate_jpeg_size; // If true, compression parameters will be remapped - // to better match the expected output size from - // JPEG compression. Generally, the output size will - // be similar but the degradation will be lower. - int thread_level; // If non-zero, try and use multi-threaded encoding. - int low_memory; // If set, reduce memory usage (but increase CPU use). - - int near_lossless; // Near lossless encoding [0 = off(default) .. 100]. - // This feature is experimental. - int exact; // if non-zero, preserve the exact RGB values under - // transparent area. Otherwise, discard this invisible - // RGB information for better compression. The default - // value is 0. - -#ifdef WEBP_EXPERIMENTAL_FEATURES - int delta_palettization; - uint32_t pad[2]; // padding for later use -#else - uint32_t pad[3]; // padding for later use -#endif // WEBP_EXPERIMENTAL_FEATURES -}; - -// Enumerate some predefined settings for WebPConfig, depending on the type -// of source picture. These presets are used when calling WebPConfigPreset(). -typedef enum WebPPreset { - WEBP_PRESET_DEFAULT = 0, // default preset. - WEBP_PRESET_PICTURE, // digital picture, like portrait, inner shot - WEBP_PRESET_PHOTO, // outdoor photograph, with natural lighting - WEBP_PRESET_DRAWING, // hand or line drawing, with high-contrast details - WEBP_PRESET_ICON, // small-sized colorful images - WEBP_PRESET_TEXT // text-like -} WebPPreset; - -// Internal, version-checked, entry point -WEBP_EXTERN(int) WebPConfigInitInternal(WebPConfig*, WebPPreset, float, int); - -// Should always be called, to initialize a fresh WebPConfig structure before -// modification. Returns false in case of version mismatch. WebPConfigInit() -// must have succeeded before using the 'config' object. -// Note that the default values are lossless=0 and quality=75. -static WEBP_INLINE int WebPConfigInit(WebPConfig* config) { - return WebPConfigInitInternal(config, WEBP_PRESET_DEFAULT, 75.f, - WEBP_ENCODER_ABI_VERSION); -} - -// This function will initialize the configuration according to a predefined -// set of parameters (referred to by 'preset') and a given quality factor. -// This function can be called as a replacement to WebPConfigInit(). Will -// return false in case of error. -static WEBP_INLINE int WebPConfigPreset(WebPConfig* config, - WebPPreset preset, float quality) { - return WebPConfigInitInternal(config, preset, quality, - WEBP_ENCODER_ABI_VERSION); -} - -// Activate the lossless compression mode with the desired efficiency level -// between 0 (fastest, lowest compression) and 9 (slower, best compression). -// A good default level is '6', providing a fair tradeoff between compression -// speed and final compressed size. -// This function will overwrite several fields from config: 'method', 'quality' -// and 'lossless'. Returns false in case of parameter error. -WEBP_EXTERN(int) WebPConfigLosslessPreset(WebPConfig* config, int level); - -// Returns true if 'config' is non-NULL and all configuration parameters are -// within their valid ranges. -WEBP_EXTERN(int) WebPValidateConfig(const WebPConfig* config); - -//------------------------------------------------------------------------------ -// Input / Output -// Structure for storing auxiliary statistics (mostly for lossy encoding). - -struct WebPAuxStats { - int coded_size; // final size - - float PSNR[5]; // peak-signal-to-noise ratio for Y/U/V/All/Alpha - int block_count[3]; // number of intra4/intra16/skipped macroblocks - int header_bytes[2]; // approximate number of bytes spent for header - // and mode-partition #0 - int residual_bytes[3][4]; // approximate number of bytes spent for - // DC/AC/uv coefficients for each (0..3) segments. - int segment_size[4]; // number of macroblocks in each segments - int segment_quant[4]; // quantizer values for each segments - int segment_level[4]; // filtering strength for each segments [0..63] - - int alpha_data_size; // size of the transparency data - int layer_data_size; // size of the enhancement layer data - - // lossless encoder statistics - uint32_t lossless_features; // bit0:predictor bit1:cross-color transform - // bit2:subtract-green bit3:color indexing - int histogram_bits; // number of precision bits of histogram - int transform_bits; // precision bits for transform - int cache_bits; // number of bits for color cache lookup - int palette_size; // number of color in palette, if used - int lossless_size; // final lossless size - int lossless_hdr_size; // lossless header (transform, huffman etc) size - int lossless_data_size; // lossless image data size - - uint32_t pad[2]; // padding for later use -}; - -// Signature for output function. Should return true if writing was successful. -// data/data_size is the segment of data to write, and 'picture' is for -// reference (and so one can make use of picture->custom_ptr). -typedef int (*WebPWriterFunction)(const uint8_t* data, size_t data_size, - const WebPPicture* picture); - -// WebPMemoryWrite: a special WebPWriterFunction that writes to memory using -// the following WebPMemoryWriter object (to be set as a custom_ptr). -struct WebPMemoryWriter { - uint8_t* mem; // final buffer (of size 'max_size', larger than 'size'). - size_t size; // final size - size_t max_size; // total capacity - uint32_t pad[1]; // padding for later use -}; - -// The following must be called first before any use. -WEBP_EXTERN(void) WebPMemoryWriterInit(WebPMemoryWriter* writer); - -// The following must be called to deallocate writer->mem memory. The 'writer' -// object itself is not deallocated. -WEBP_EXTERN(void) WebPMemoryWriterClear(WebPMemoryWriter* writer); -// The custom writer to be used with WebPMemoryWriter as custom_ptr. Upon -// completion, writer.mem and writer.size will hold the coded data. -// writer.mem must be freed by calling WebPMemoryWriterClear. -WEBP_EXTERN(int) WebPMemoryWrite(const uint8_t* data, size_t data_size, - const WebPPicture* picture); - -// Progress hook, called from time to time to report progress. It can return -// false to request an abort of the encoding process, or true otherwise if -// everything is OK. -typedef int (*WebPProgressHook)(int percent, const WebPPicture* picture); - -// Color spaces. -typedef enum WebPEncCSP { - // chroma sampling - WEBP_YUV420 = 0, // 4:2:0 - WEBP_YUV420A = 4, // alpha channel variant - WEBP_CSP_UV_MASK = 3, // bit-mask to get the UV sampling factors - WEBP_CSP_ALPHA_BIT = 4 // bit that is set if alpha is present -} WebPEncCSP; - -// Encoding error conditions. -typedef enum WebPEncodingError { - VP8_ENC_OK = 0, - VP8_ENC_ERROR_OUT_OF_MEMORY, // memory error allocating objects - VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY, // memory error while flushing bits - VP8_ENC_ERROR_NULL_PARAMETER, // a pointer parameter is NULL - VP8_ENC_ERROR_INVALID_CONFIGURATION, // configuration is invalid - VP8_ENC_ERROR_BAD_DIMENSION, // picture has invalid width/height - VP8_ENC_ERROR_PARTITION0_OVERFLOW, // partition is bigger than 512k - VP8_ENC_ERROR_PARTITION_OVERFLOW, // partition is bigger than 16M - VP8_ENC_ERROR_BAD_WRITE, // error while flushing bytes - VP8_ENC_ERROR_FILE_TOO_BIG, // file is bigger than 4G - VP8_ENC_ERROR_USER_ABORT, // abort request by user - VP8_ENC_ERROR_LAST // list terminator. always last. -} WebPEncodingError; - -// maximum width/height allowed (inclusive), in pixels -#define WEBP_MAX_DIMENSION 16383 - -// Main exchange structure (input samples, output bytes, statistics) -struct WebPPicture { - // INPUT - ////////////// - // Main flag for encoder selecting between ARGB or YUV input. - // It is recommended to use ARGB input (*argb, argb_stride) for lossless - // compression, and YUV input (*y, *u, *v, etc.) for lossy compression - // since these are the respective native colorspace for these formats. - int use_argb; - - // YUV input (mostly used for input to lossy compression) - WebPEncCSP colorspace; // colorspace: should be YUV420 for now (=Y'CbCr). - int width, height; // dimensions (less or equal to WEBP_MAX_DIMENSION) - uint8_t *y, *u, *v; // pointers to luma/chroma planes. - int y_stride, uv_stride; // luma/chroma strides. - uint8_t* a; // pointer to the alpha plane - int a_stride; // stride of the alpha plane - uint32_t pad1[2]; // padding for later use - - // ARGB input (mostly used for input to lossless compression) - uint32_t* argb; // Pointer to argb (32 bit) plane. - int argb_stride; // This is stride in pixels units, not bytes. - uint32_t pad2[3]; // padding for later use - - // OUTPUT - /////////////// - // Byte-emission hook, to store compressed bytes as they are ready. - WebPWriterFunction writer; // can be NULL - void* custom_ptr; // can be used by the writer. - - // map for extra information (only for lossy compression mode) - int extra_info_type; // 1: intra type, 2: segment, 3: quant - // 4: intra-16 prediction mode, - // 5: chroma prediction mode, - // 6: bit cost, 7: distortion - uint8_t* extra_info; // if not NULL, points to an array of size - // ((width + 15) / 16) * ((height + 15) / 16) that - // will be filled with a macroblock map, depending - // on extra_info_type. - - // STATS AND REPORTS - /////////////////////////// - // Pointer to side statistics (updated only if not NULL) - WebPAuxStats* stats; - - // Error code for the latest error encountered during encoding - WebPEncodingError error_code; - - // If not NULL, report progress during encoding. - WebPProgressHook progress_hook; - - void* user_data; // this field is free to be set to any value and - // used during callbacks (like progress-report e.g.). - - uint32_t pad3[3]; // padding for later use - - // Unused for now - uint8_t *pad4, *pad5; - uint32_t pad6[8]; // padding for later use - - // PRIVATE FIELDS - //////////////////// - void* memory_; // row chunk of memory for yuva planes - void* memory_argb_; // and for argb too. - void* pad7[2]; // padding for later use -}; - -// Internal, version-checked, entry point -WEBP_EXTERN(int) WebPPictureInitInternal(WebPPicture*, int); - -// Should always be called, to initialize the structure. Returns false in case -// of version mismatch. WebPPictureInit() must have succeeded before using the -// 'picture' object. -// Note that, by default, use_argb is false and colorspace is WEBP_YUV420. -static WEBP_INLINE int WebPPictureInit(WebPPicture* picture) { - return WebPPictureInitInternal(picture, WEBP_ENCODER_ABI_VERSION); -} - -//------------------------------------------------------------------------------ -// WebPPicture utils - -// Convenience allocation / deallocation based on picture->width/height: -// Allocate y/u/v buffers as per colorspace/width/height specification. -// Note! This function will free the previous buffer if needed. -// Returns false in case of memory error. -WEBP_EXTERN(int) WebPPictureAlloc(WebPPicture* picture); - -// Release the memory allocated by WebPPictureAlloc() or WebPPictureImport*(). -// Note that this function does _not_ free the memory used by the 'picture' -// object itself. -// Besides memory (which is reclaimed) all other fields of 'picture' are -// preserved. -WEBP_EXTERN(void) WebPPictureFree(WebPPicture* picture); - -// Copy the pixels of *src into *dst, using WebPPictureAlloc. Upon return, *dst -// will fully own the copied pixels (this is not a view). The 'dst' picture need -// not be initialized as its content is overwritten. -// Returns false in case of memory allocation error. -WEBP_EXTERN(int) WebPPictureCopy(const WebPPicture* src, WebPPicture* dst); - -// Compute PSNR, SSIM or LSIM distortion metric between two pictures. Results -// are in dB, stored in result[] in the Y/U/V/Alpha/All or B/G/R/A/All order. -// Returns false in case of error (src and ref don't have same dimension, ...) -// Warning: this function is rather CPU-intensive. -WEBP_EXTERN(int) WebPPictureDistortion( - const WebPPicture* src, const WebPPicture* ref, - int metric_type, // 0 = PSNR, 1 = SSIM, 2 = LSIM - float result[5]); - -// self-crops a picture to the rectangle defined by top/left/width/height. -// Returns false in case of memory allocation error, or if the rectangle is -// outside of the source picture. -// The rectangle for the view is defined by the top-left corner pixel -// coordinates (left, top) as well as its width and height. This rectangle -// must be fully be comprised inside the 'src' source picture. If the source -// picture uses the YUV420 colorspace, the top and left coordinates will be -// snapped to even values. -WEBP_EXTERN(int) WebPPictureCrop(WebPPicture* picture, - int left, int top, int width, int height); - -// Extracts a view from 'src' picture into 'dst'. The rectangle for the view -// is defined by the top-left corner pixel coordinates (left, top) as well -// as its width and height. This rectangle must be fully be comprised inside -// the 'src' source picture. If the source picture uses the YUV420 colorspace, -// the top and left coordinates will be snapped to even values. -// Picture 'src' must out-live 'dst' picture. Self-extraction of view is allowed -// ('src' equal to 'dst') as a mean of fast-cropping (but note that doing so, -// the original dimension will be lost). Picture 'dst' need not be initialized -// with WebPPictureInit() if it is different from 'src', since its content will -// be overwritten. -// Returns false in case of memory allocation error or invalid parameters. -WEBP_EXTERN(int) WebPPictureView(const WebPPicture* src, - int left, int top, int width, int height, - WebPPicture* dst); - -// Returns true if the 'picture' is actually a view and therefore does -// not own the memory for pixels. -WEBP_EXTERN(int) WebPPictureIsView(const WebPPicture* picture); - -// Rescale a picture to new dimension width x height. -// If either 'width' or 'height' (but not both) is 0 the corresponding -// dimension will be calculated preserving the aspect ratio. -// No gamma correction is applied. -// Returns false in case of error (invalid parameter or insufficient memory). -WEBP_EXTERN(int) WebPPictureRescale(WebPPicture* pic, int width, int height); - -// Colorspace conversion function to import RGB samples. -// Previous buffer will be free'd, if any. -// *rgb buffer should have a size of at least height * rgb_stride. -// Returns false in case of memory error. -WEBP_EXTERN(int) WebPPictureImportRGB( - WebPPicture* picture, const uint8_t* rgb, int rgb_stride); -// Same, but for RGBA buffer. -WEBP_EXTERN(int) WebPPictureImportRGBA( - WebPPicture* picture, const uint8_t* rgba, int rgba_stride); -// Same, but for RGBA buffer. Imports the RGB direct from the 32-bit format -// input buffer ignoring the alpha channel. Avoids needing to copy the data -// to a temporary 24-bit RGB buffer to import the RGB only. -WEBP_EXTERN(int) WebPPictureImportRGBX( - WebPPicture* picture, const uint8_t* rgbx, int rgbx_stride); - -// Variants of the above, but taking BGR(A|X) input. -WEBP_EXTERN(int) WebPPictureImportBGR( - WebPPicture* picture, const uint8_t* bgr, int bgr_stride); -WEBP_EXTERN(int) WebPPictureImportBGRA( - WebPPicture* picture, const uint8_t* bgra, int bgra_stride); -WEBP_EXTERN(int) WebPPictureImportBGRX( - WebPPicture* picture, const uint8_t* bgrx, int bgrx_stride); - -// Converts picture->argb data to the YUV420A format. The 'colorspace' -// parameter is deprecated and should be equal to WEBP_YUV420. -// Upon return, picture->use_argb is set to false. The presence of real -// non-opaque transparent values is detected, and 'colorspace' will be -// adjusted accordingly. Note that this method is lossy. -// Returns false in case of error. -WEBP_EXTERN(int) WebPPictureARGBToYUVA(WebPPicture* picture, - WebPEncCSP /*colorspace = WEBP_YUV420*/); - -// Same as WebPPictureARGBToYUVA(), but the conversion is done using -// pseudo-random dithering with a strength 'dithering' between -// 0.0 (no dithering) and 1.0 (maximum dithering). This is useful -// for photographic picture. -WEBP_EXTERN(int) WebPPictureARGBToYUVADithered( - WebPPicture* picture, WebPEncCSP colorspace, float dithering); - -// Performs 'smart' RGBA->YUVA420 downsampling and colorspace conversion. -// Downsampling is handled with extra care in case of color clipping. This -// method is roughly 2x slower than WebPPictureARGBToYUVA() but produces better -// YUV representation. -// Returns false in case of error. -WEBP_EXTERN(int) WebPPictureSmartARGBToYUVA(WebPPicture* picture); - -// Converts picture->yuv to picture->argb and sets picture->use_argb to true. -// The input format must be YUV_420 or YUV_420A. -// Note that the use of this method is discouraged if one has access to the -// raw ARGB samples, since using YUV420 is comparatively lossy. Also, the -// conversion from YUV420 to ARGB incurs a small loss too. -// Returns false in case of error. -WEBP_EXTERN(int) WebPPictureYUVAToARGB(WebPPicture* picture); - -// Helper function: given a width x height plane of RGBA or YUV(A) samples -// clean-up the YUV or RGB samples under fully transparent area, to help -// compressibility (no guarantee, though). -WEBP_EXTERN(void) WebPCleanupTransparentArea(WebPPicture* picture); - -// Scan the picture 'picture' for the presence of non fully opaque alpha values. -// Returns true in such case. Otherwise returns false (indicating that the -// alpha plane can be ignored altogether e.g.). -WEBP_EXTERN(int) WebPPictureHasTransparency(const WebPPicture* picture); - -// Remove the transparency information (if present) by blending the color with -// the background color 'background_rgb' (specified as 24bit RGB triplet). -// After this call, all alpha values are reset to 0xff. -WEBP_EXTERN(void) WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb); - -//------------------------------------------------------------------------------ -// Main call - -// Main encoding call, after config and picture have been initialized. -// 'picture' must be less than 16384x16384 in dimension (cf WEBP_MAX_DIMENSION), -// and the 'config' object must be a valid one. -// Returns false in case of error, true otherwise. -// In case of error, picture->error_code is updated accordingly. -// 'picture' can hold the source samples in both YUV(A) or ARGB input, depending -// on the value of 'picture->use_argb'. It is highly recommended to use -// the former for lossy encoding, and the latter for lossless encoding -// (when config.lossless is true). Automatic conversion from one format to -// another is provided but they both incur some loss. -WEBP_EXTERN(int) WebPEncode(const WebPConfig* config, WebPPicture* picture); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_WEBP_ENCODE_H_ */ diff --git a/Example/Pods/libwebp/src/webp/extras.h b/Example/Pods/libwebp/src/webp/extras.h deleted file mode 100644 index 1c24be2e..00000000 --- a/Example/Pods/libwebp/src/webp/extras.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// - -#ifndef WEBP_WEBP_EXTRAS_H_ -#define WEBP_WEBP_EXTRAS_H_ - -#include "./types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "./encode.h" - -#define WEBP_EXTRAS_ABI_VERSION 0x0000 // MAJOR(8b) + MINOR(8b) - -//------------------------------------------------------------------------------ - -// Returns the version number of the extras library, packed in hexadecimal using -// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507. -WEBP_EXTERN(int) WebPGetExtrasVersion(void); - -//------------------------------------------------------------------------------ -// Ad-hoc colorspace importers. - -// Import luma sample (gray scale image) into 'picture'. The 'picture' -// width and height must be set prior to calling this function. -WEBP_EXTERN(int) WebPImportGray(const uint8_t* gray, WebPPicture* picture); - -// Import rgb sample in RGB565 packed format into 'picture'. The 'picture' -// width and height must be set prior to calling this function. -WEBP_EXTERN(int) WebPImportRGB565(const uint8_t* rgb565, WebPPicture* pic); - -// Import rgb sample in RGB4444 packed format into 'picture'. The 'picture' -// width and height must be set prior to calling this function. -WEBP_EXTERN(int) WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_WEBP_EXTRAS_H_ */ diff --git a/Example/Pods/libwebp/src/webp/format_constants.h b/Example/Pods/libwebp/src/webp/format_constants.h deleted file mode 100644 index b6e78a64..00000000 --- a/Example/Pods/libwebp/src/webp/format_constants.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Internal header for constants related to WebP file format. -// -// Author: Urvang (urvang@google.com) - -#ifndef WEBP_WEBP_FORMAT_CONSTANTS_H_ -#define WEBP_WEBP_FORMAT_CONSTANTS_H_ - -// Create fourcc of the chunk from the chunk tag characters. -#define MKFOURCC(a, b, c, d) ((a) | (b) << 8 | (c) << 16 | (uint32_t)(d) << 24) - -// VP8 related constants. -#define VP8_SIGNATURE 0x9d012a // Signature in VP8 data. -#define VP8_MAX_PARTITION0_SIZE (1 << 19) // max size of mode partition -#define VP8_MAX_PARTITION_SIZE (1 << 24) // max size for token partition -#define VP8_FRAME_HEADER_SIZE 10 // Size of the frame header within VP8 data. - -// VP8L related constants. -#define VP8L_SIGNATURE_SIZE 1 // VP8L signature size. -#define VP8L_MAGIC_BYTE 0x2f // VP8L signature byte. -#define VP8L_IMAGE_SIZE_BITS 14 // Number of bits used to store - // width and height. -#define VP8L_VERSION_BITS 3 // 3 bits reserved for version. -#define VP8L_VERSION 0 // version 0 -#define VP8L_FRAME_HEADER_SIZE 5 // Size of the VP8L frame header. - -#define MAX_PALETTE_SIZE 256 -#define MAX_CACHE_BITS 11 -#define HUFFMAN_CODES_PER_META_CODE 5 -#define ARGB_BLACK 0xff000000 - -#define DEFAULT_CODE_LENGTH 8 -#define MAX_ALLOWED_CODE_LENGTH 15 - -#define NUM_LITERAL_CODES 256 -#define NUM_LENGTH_CODES 24 -#define NUM_DISTANCE_CODES 40 -#define CODE_LENGTH_CODES 19 - -#define MIN_HUFFMAN_BITS 2 // min number of Huffman bits -#define MAX_HUFFMAN_BITS 9 // max number of Huffman bits - -#define TRANSFORM_PRESENT 1 // The bit to be written when next data - // to be read is a transform. -#define NUM_TRANSFORMS 4 // Maximum number of allowed transform - // in a bitstream. -typedef enum { - PREDICTOR_TRANSFORM = 0, - CROSS_COLOR_TRANSFORM = 1, - SUBTRACT_GREEN = 2, - COLOR_INDEXING_TRANSFORM = 3 -} VP8LImageTransformType; - -// Alpha related constants. -#define ALPHA_HEADER_LEN 1 -#define ALPHA_NO_COMPRESSION 0 -#define ALPHA_LOSSLESS_COMPRESSION 1 -#define ALPHA_PREPROCESSED_LEVELS 1 - -// Mux related constants. -#define TAG_SIZE 4 // Size of a chunk tag (e.g. "VP8L"). -#define CHUNK_SIZE_BYTES 4 // Size needed to store chunk's size. -#define CHUNK_HEADER_SIZE 8 // Size of a chunk header. -#define RIFF_HEADER_SIZE 12 // Size of the RIFF header ("RIFFnnnnWEBP"). -#define ANMF_CHUNK_SIZE 16 // Size of an ANMF chunk. -#define ANIM_CHUNK_SIZE 6 // Size of an ANIM chunk. -#define FRGM_CHUNK_SIZE 6 // Size of a FRGM chunk. -#define VP8X_CHUNK_SIZE 10 // Size of a VP8X chunk. - -#define MAX_CANVAS_SIZE (1 << 24) // 24-bit max for VP8X width/height. -#define MAX_IMAGE_AREA (1ULL << 32) // 32-bit max for width x height. -#define MAX_LOOP_COUNT (1 << 16) // maximum value for loop-count -#define MAX_DURATION (1 << 24) // maximum duration -#define MAX_POSITION_OFFSET (1 << 24) // maximum frame/fragment x/y offset - -// Maximum chunk payload is such that adding the header and padding won't -// overflow a uint32_t. -#define MAX_CHUNK_PAYLOAD (~0U - CHUNK_HEADER_SIZE - 1) - -#endif /* WEBP_WEBP_FORMAT_CONSTANTS_H_ */ diff --git a/Example/Pods/libwebp/src/webp/mux.h b/Example/Pods/libwebp/src/webp/mux.h deleted file mode 100644 index b72658c7..00000000 --- a/Example/Pods/libwebp/src/webp/mux.h +++ /dev/null @@ -1,530 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// RIFF container manipulation and encoding for WebP images. -// -// Authors: Urvang (urvang@google.com) -// Vikas (vikasa@google.com) - -#ifndef WEBP_WEBP_MUX_H_ -#define WEBP_WEBP_MUX_H_ - -#include "./mux_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define WEBP_MUX_ABI_VERSION 0x0106 // MAJOR(8b) + MINOR(8b) - -//------------------------------------------------------------------------------ -// Mux API -// -// This API allows manipulation of WebP container images containing features -// like color profile, metadata, animation and fragmented images. -// -// Code Example#1: Create a WebPMux object with image data, color profile and -// XMP metadata. -/* - int copy_data = 0; - WebPMux* mux = WebPMuxNew(); - // ... (Prepare image data). - WebPMuxSetImage(mux, &image, copy_data); - // ... (Prepare ICCP color profile data). - WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data); - // ... (Prepare XMP metadata). - WebPMuxSetChunk(mux, "XMP ", &xmp, copy_data); - // Get data from mux in WebP RIFF format. - WebPMuxAssemble(mux, &output_data); - WebPMuxDelete(mux); - // ... (Consume output_data; e.g. write output_data.bytes to file). - WebPDataClear(&output_data); -*/ - -// Code Example#2: Get image and color profile data from a WebP file. -/* - int copy_data = 0; - // ... (Read data from file). - WebPMux* mux = WebPMuxCreate(&data, copy_data); - WebPMuxGetFrame(mux, 1, &image); - // ... (Consume image; e.g. call WebPDecode() to decode the data). - WebPMuxGetChunk(mux, "ICCP", &icc_profile); - // ... (Consume icc_data). - WebPMuxDelete(mux); - free(data); -*/ - -// Note: forward declaring enumerations is not allowed in (strict) C and C++, -// the types are left here for reference. -// typedef enum WebPMuxError WebPMuxError; -// typedef enum WebPChunkId WebPChunkId; -typedef struct WebPMux WebPMux; // main opaque object. -typedef struct WebPMuxFrameInfo WebPMuxFrameInfo; -typedef struct WebPMuxAnimParams WebPMuxAnimParams; -typedef struct WebPAnimEncoderOptions WebPAnimEncoderOptions; - -// Error codes -typedef enum WebPMuxError { - WEBP_MUX_OK = 1, - WEBP_MUX_NOT_FOUND = 0, - WEBP_MUX_INVALID_ARGUMENT = -1, - WEBP_MUX_BAD_DATA = -2, - WEBP_MUX_MEMORY_ERROR = -3, - WEBP_MUX_NOT_ENOUGH_DATA = -4 -} WebPMuxError; - -// IDs for different types of chunks. -typedef enum WebPChunkId { - WEBP_CHUNK_VP8X, // VP8X - WEBP_CHUNK_ICCP, // ICCP - WEBP_CHUNK_ANIM, // ANIM - WEBP_CHUNK_ANMF, // ANMF - WEBP_CHUNK_FRGM, // FRGM - WEBP_CHUNK_ALPHA, // ALPH - WEBP_CHUNK_IMAGE, // VP8/VP8L - WEBP_CHUNK_EXIF, // EXIF - WEBP_CHUNK_XMP, // XMP - WEBP_CHUNK_UNKNOWN, // Other chunks. - WEBP_CHUNK_NIL -} WebPChunkId; - -//------------------------------------------------------------------------------ - -// Returns the version number of the mux library, packed in hexadecimal using -// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507. -WEBP_EXTERN(int) WebPGetMuxVersion(void); - -//------------------------------------------------------------------------------ -// Life of a Mux object - -// Internal, version-checked, entry point -WEBP_EXTERN(WebPMux*) WebPNewInternal(int); - -// Creates an empty mux object. -// Returns: -// A pointer to the newly created empty mux object. -// Or NULL in case of memory error. -static WEBP_INLINE WebPMux* WebPMuxNew(void) { - return WebPNewInternal(WEBP_MUX_ABI_VERSION); -} - -// Deletes the mux object. -// Parameters: -// mux - (in/out) object to be deleted -WEBP_EXTERN(void) WebPMuxDelete(WebPMux* mux); - -//------------------------------------------------------------------------------ -// Mux creation. - -// Internal, version-checked, entry point -WEBP_EXTERN(WebPMux*) WebPMuxCreateInternal(const WebPData*, int, int); - -// Creates a mux object from raw data given in WebP RIFF format. -// Parameters: -// bitstream - (in) the bitstream data in WebP RIFF format -// copy_data - (in) value 1 indicates given data WILL be copied to the mux -// object and value 0 indicates data will NOT be copied. -// Returns: -// A pointer to the mux object created from given data - on success. -// NULL - In case of invalid data or memory error. -static WEBP_INLINE WebPMux* WebPMuxCreate(const WebPData* bitstream, - int copy_data) { - return WebPMuxCreateInternal(bitstream, copy_data, WEBP_MUX_ABI_VERSION); -} - -//------------------------------------------------------------------------------ -// Non-image chunks. - -// Note: Only non-image related chunks should be managed through chunk APIs. -// (Image related chunks are: "ANMF", "FRGM", "VP8 ", "VP8L" and "ALPH"). -// To add, get and delete images, use WebPMuxSetImage(), WebPMuxPushFrame(), -// WebPMuxGetFrame() and WebPMuxDeleteFrame(). - -// Adds a chunk with id 'fourcc' and data 'chunk_data' in the mux object. -// Any existing chunk(s) with the same id will be removed. -// Parameters: -// mux - (in/out) object to which the chunk is to be added -// fourcc - (in) a character array containing the fourcc of the given chunk; -// e.g., "ICCP", "XMP ", "EXIF" etc. -// chunk_data - (in) the chunk data to be added -// copy_data - (in) value 1 indicates given data WILL be copied to the mux -// object and value 0 indicates data will NOT be copied. -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux, fourcc or chunk_data is NULL -// or if fourcc corresponds to an image chunk. -// WEBP_MUX_MEMORY_ERROR - on memory allocation error. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxSetChunk( - WebPMux* mux, const char fourcc[4], const WebPData* chunk_data, - int copy_data); - -// Gets a reference to the data of the chunk with id 'fourcc' in the mux object. -// The caller should NOT free the returned data. -// Parameters: -// mux - (in) object from which the chunk data is to be fetched -// fourcc - (in) a character array containing the fourcc of the chunk; -// e.g., "ICCP", "XMP ", "EXIF" etc. -// chunk_data - (out) returned chunk data -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux, fourcc or chunk_data is NULL -// or if fourcc corresponds to an image chunk. -// WEBP_MUX_NOT_FOUND - If mux does not contain a chunk with the given id. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxGetChunk( - const WebPMux* mux, const char fourcc[4], WebPData* chunk_data); - -// Deletes the chunk with the given 'fourcc' from the mux object. -// Parameters: -// mux - (in/out) object from which the chunk is to be deleted -// fourcc - (in) a character array containing the fourcc of the chunk; -// e.g., "ICCP", "XMP ", "EXIF" etc. -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux or fourcc is NULL -// or if fourcc corresponds to an image chunk. -// WEBP_MUX_NOT_FOUND - If mux does not contain a chunk with the given fourcc. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxDeleteChunk( - WebPMux* mux, const char fourcc[4]); - -//------------------------------------------------------------------------------ -// Images. - -// Encapsulates data about a single frame/fragment. -struct WebPMuxFrameInfo { - WebPData bitstream; // image data: can be a raw VP8/VP8L bitstream - // or a single-image WebP file. - int x_offset; // x-offset of the frame. - int y_offset; // y-offset of the frame. - int duration; // duration of the frame (in milliseconds). - - WebPChunkId id; // frame type: should be one of WEBP_CHUNK_ANMF, - // WEBP_CHUNK_FRGM or WEBP_CHUNK_IMAGE - WebPMuxAnimDispose dispose_method; // Disposal method for the frame. - WebPMuxAnimBlend blend_method; // Blend operation for the frame. - uint32_t pad[1]; // padding for later use -}; - -// Sets the (non-animated and non-fragmented) image in the mux object. -// Note: Any existing images (including frames/fragments) will be removed. -// Parameters: -// mux - (in/out) object in which the image is to be set -// bitstream - (in) can be a raw VP8/VP8L bitstream or a single-image -// WebP file (non-animated and non-fragmented) -// copy_data - (in) value 1 indicates given data WILL be copied to the mux -// object and value 0 indicates data will NOT be copied. -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL or bitstream is NULL. -// WEBP_MUX_MEMORY_ERROR - on memory allocation error. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxSetImage( - WebPMux* mux, const WebPData* bitstream, int copy_data); - -// Adds a frame at the end of the mux object. -// Notes: (1) frame.id should be one of WEBP_CHUNK_ANMF or WEBP_CHUNK_FRGM -// (2) For setting a non-animated non-fragmented image, use -// WebPMuxSetImage() instead. -// (3) Type of frame being pushed must be same as the frames in mux. -// (4) As WebP only supports even offsets, any odd offset will be snapped -// to an even location using: offset &= ~1 -// Parameters: -// mux - (in/out) object to which the frame is to be added -// frame - (in) frame data. -// copy_data - (in) value 1 indicates given data WILL be copied to the mux -// object and value 0 indicates data will NOT be copied. -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL -// or if content of 'frame' is invalid. -// WEBP_MUX_MEMORY_ERROR - on memory allocation error. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxPushFrame( - WebPMux* mux, const WebPMuxFrameInfo* frame, int copy_data); - -// Gets the nth frame from the mux object. -// The content of 'frame->bitstream' is allocated using malloc(), and NOT -// owned by the 'mux' object. It MUST be deallocated by the caller by calling -// WebPDataClear(). -// nth=0 has a special meaning - last position. -// Parameters: -// mux - (in) object from which the info is to be fetched -// nth - (in) index of the frame in the mux object -// frame - (out) data of the returned frame -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL. -// WEBP_MUX_NOT_FOUND - if there are less than nth frames in the mux object. -// WEBP_MUX_BAD_DATA - if nth frame chunk in mux is invalid. -// WEBP_MUX_MEMORY_ERROR - on memory allocation error. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxGetFrame( - const WebPMux* mux, uint32_t nth, WebPMuxFrameInfo* frame); - -// Deletes a frame from the mux object. -// nth=0 has a special meaning - last position. -// Parameters: -// mux - (in/out) object from which a frame is to be deleted -// nth - (in) The position from which the frame is to be deleted -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL. -// WEBP_MUX_NOT_FOUND - If there are less than nth frames in the mux object -// before deletion. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth); - -//------------------------------------------------------------------------------ -// Animation. - -// Animation parameters. -struct WebPMuxAnimParams { - uint32_t bgcolor; // Background color of the canvas stored (in MSB order) as: - // Bits 00 to 07: Alpha. - // Bits 08 to 15: Red. - // Bits 16 to 23: Green. - // Bits 24 to 31: Blue. - int loop_count; // Number of times to repeat the animation [0 = infinite]. -}; - -// Sets the animation parameters in the mux object. Any existing ANIM chunks -// will be removed. -// Parameters: -// mux - (in/out) object in which ANIM chunk is to be set/added -// params - (in) animation parameters. -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux or params is NULL. -// WEBP_MUX_MEMORY_ERROR - on memory allocation error. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxSetAnimationParams( - WebPMux* mux, const WebPMuxAnimParams* params); - -// Gets the animation parameters from the mux object. -// Parameters: -// mux - (in) object from which the animation parameters to be fetched -// params - (out) animation parameters extracted from the ANIM chunk -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux or params is NULL. -// WEBP_MUX_NOT_FOUND - if ANIM chunk is not present in mux object. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxGetAnimationParams( - const WebPMux* mux, WebPMuxAnimParams* params); - -//------------------------------------------------------------------------------ -// Misc Utilities. - -// Sets the canvas size for the mux object. The width and height can be -// specified explicitly or left as zero (0, 0). -// * When width and height are specified explicitly, then this frame bound is -// enforced during subsequent calls to WebPMuxAssemble() and an error is -// reported if any animated frame does not completely fit within the canvas. -// * When unspecified (0, 0), the constructed canvas will get the frame bounds -// from the bounding-box over all frames after calling WebPMuxAssemble(). -// Parameters: -// mux - (in) object to which the canvas size is to be set -// width - (in) canvas width -// height - (in) canvas height -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL; or -// width or height are invalid or out of bounds -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxSetCanvasSize(WebPMux* mux, - int width, int height); - -// Gets the canvas size from the mux object. -// Note: This method assumes that the VP8X chunk, if present, is up-to-date. -// That is, the mux object hasn't been modified since the last call to -// WebPMuxAssemble() or WebPMuxCreate(). -// Parameters: -// mux - (in) object from which the canvas size is to be fetched -// width - (out) canvas width -// height - (out) canvas height -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux, width or height is NULL. -// WEBP_MUX_BAD_DATA - if VP8X/VP8/VP8L chunk or canvas size is invalid. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxGetCanvasSize(const WebPMux* mux, - int* width, int* height); - -// Gets the feature flags from the mux object. -// Note: This method assumes that the VP8X chunk, if present, is up-to-date. -// That is, the mux object hasn't been modified since the last call to -// WebPMuxAssemble() or WebPMuxCreate(). -// Parameters: -// mux - (in) object from which the features are to be fetched -// flags - (out) the flags specifying which features are present in the -// mux object. This will be an OR of various flag values. -// Enum 'WebPFeatureFlags' can be used to test individual flag values. -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux or flags is NULL. -// WEBP_MUX_BAD_DATA - if VP8X/VP8/VP8L chunk or canvas size is invalid. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxGetFeatures(const WebPMux* mux, - uint32_t* flags); - -// Gets number of chunks with the given 'id' in the mux object. -// Parameters: -// mux - (in) object from which the info is to be fetched -// id - (in) chunk id specifying the type of chunk -// num_elements - (out) number of chunks with the given chunk id -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux, or num_elements is NULL. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxNumChunks(const WebPMux* mux, - WebPChunkId id, int* num_elements); - -// Assembles all chunks in WebP RIFF format and returns in 'assembled_data'. -// This function also validates the mux object. -// Note: The content of 'assembled_data' will be ignored and overwritten. -// Also, the content of 'assembled_data' is allocated using malloc(), and NOT -// owned by the 'mux' object. It MUST be deallocated by the caller by calling -// WebPDataClear(). It's always safe to call WebPDataClear() upon return, -// even in case of error. -// Parameters: -// mux - (in/out) object whose chunks are to be assembled -// assembled_data - (out) assembled WebP data -// Returns: -// WEBP_MUX_BAD_DATA - if mux object is invalid. -// WEBP_MUX_INVALID_ARGUMENT - if mux or assembled_data is NULL. -// WEBP_MUX_MEMORY_ERROR - on memory allocation error. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxAssemble(WebPMux* mux, - WebPData* assembled_data); - -//------------------------------------------------------------------------------ -// WebPAnimEncoder API -// -// This API allows encoding (possibly) animated WebP images. -// -// Code Example: -/* - WebPAnimEncoderOptions enc_options; - WebPAnimEncoderOptionsInit(&enc_options); - // Tune 'enc_options' as needed. - WebPAnimEncoder* enc = WebPAnimEncoderNew(width, height, &enc_options); - while() { - WebPConfig config; - WebPConfigInit(&config); - // Tune 'config' as needed. - WebPAnimEncoderAdd(enc, frame, timestamp_ms, &config); - } - WebPAnimEncoderAdd(enc, NULL, timestamp_ms, NULL); - WebPAnimEncoderAssemble(enc, webp_data); - WebPAnimEncoderDelete(enc); - // Write the 'webp_data' to a file, or re-mux it further. -*/ - -typedef struct WebPAnimEncoder WebPAnimEncoder; // Main opaque object. - -// Forward declarations. Defined in encode.h. -struct WebPPicture; -struct WebPConfig; - -// Global options. -struct WebPAnimEncoderOptions { - WebPMuxAnimParams anim_params; // Animation parameters. - int minimize_size; // If true, minimize the output size (slow). Implicitly - // disables key-frame insertion. - int kmin; - int kmax; // Minimum and maximum distance between consecutive key - // frames in the output. The library may insert some key - // frames as needed to satisfy this criteria. - // Note that these conditions should hold: kmax > kmin - // and kmin >= kmax / 2 + 1. Also, if kmin == 0, then - // key-frame insertion is disabled; and if kmax == 0, - // then all frames will be key-frames. - int allow_mixed; // If true, use mixed compression mode; may choose - // either lossy and lossless for each frame. - int verbose; // If true, print info and warning messages to stderr. - - uint32_t padding[4]; // Padding for later use. -}; - -// Internal, version-checked, entry point. -WEBP_EXTERN(int) WebPAnimEncoderOptionsInitInternal( - WebPAnimEncoderOptions*, int); - -// Should always be called, to initialize a fresh WebPAnimEncoderOptions -// structure before modification. Returns false in case of version mismatch. -// WebPAnimEncoderOptionsInit() must have succeeded before using the -// 'enc_options' object. -static WEBP_INLINE int WebPAnimEncoderOptionsInit( - WebPAnimEncoderOptions* enc_options) { - return WebPAnimEncoderOptionsInitInternal(enc_options, WEBP_MUX_ABI_VERSION); -} - -// Internal, version-checked, entry point. -WEBP_EXTERN(WebPAnimEncoder*) WebPAnimEncoderNewInternal( - int, int, const WebPAnimEncoderOptions*, int); - -// Creates and initializes a WebPAnimEncoder object. -// Parameters: -// width/height - (in) canvas width and height of the animation. -// enc_options - (in) encoding options; can be passed NULL to pick -// reasonable defaults. -// Returns: -// A pointer to the newly created WebPAnimEncoder object. -// Or NULL in case of memory error. -static WEBP_INLINE WebPAnimEncoder* WebPAnimEncoderNew( - int width, int height, const WebPAnimEncoderOptions* enc_options) { - return WebPAnimEncoderNewInternal(width, height, enc_options, - WEBP_MUX_ABI_VERSION); -} - -// Optimize the given frame for WebP, encode it and add it to the -// WebPAnimEncoder object. -// The last call to 'WebPAnimEncoderAdd' should be with frame = NULL, which -// indicates that no more frames are to be added. This call is also used to -// determine the duration of the last frame. -// Parameters: -// enc - (in/out) object to which the frame is to be added. -// frame - (in/out) frame data in ARGB or YUV(A) format. If it is in YUV(A) -// format, it will be converted to ARGB, which incurs a small loss. -// timestamp_ms - (in) timestamp of this frame in milliseconds. -// Duration of a frame would be calculated as -// "timestamp of next frame - timestamp of this frame". -// Hence, timestamps should be in non-decreasing order. -// config - (in) encoding options; can be passed NULL to pick -// reasonable defaults. -// Returns: -// On error, returns false and frame->error_code is set appropriately. -// Otherwise, returns true. -WEBP_EXTERN(int) WebPAnimEncoderAdd( - WebPAnimEncoder* enc, struct WebPPicture* frame, int timestamp_ms, - const struct WebPConfig* config); - -// Assemble all frames added so far into a WebP bitstream. -// This call should be preceded by a call to 'WebPAnimEncoderAdd' with -// frame = NULL; if not, the duration of the last frame will be internally -// estimated. -// Parameters: -// enc - (in/out) object from which the frames are to be assembled. -// webp_data - (out) generated WebP bitstream. -// Returns: -// True on success. -WEBP_EXTERN(int) WebPAnimEncoderAssemble(WebPAnimEncoder* enc, - WebPData* webp_data); - -// Get error string corresponding to the most recent call using 'enc'. The -// returned string is owned by 'enc' and is valid only until the next call to -// WebPAnimEncoderAdd() or WebPAnimEncoderAssemble() or WebPAnimEncoderDelete(). -// Parameters: -// enc - (in/out) object from which the error string is to be fetched. -// Returns: -// NULL if 'enc' is NULL. Otherwise, returns the error string if the last call -// to 'enc' had an error, or an empty string if the last call was a success. -WEBP_EXTERN(const char*) WebPAnimEncoderGetError(WebPAnimEncoder* enc); - -// Deletes the WebPAnimEncoder object. -// Parameters: -// enc - (in/out) object to be deleted -WEBP_EXTERN(void) WebPAnimEncoderDelete(WebPAnimEncoder* enc); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_WEBP_MUX_H_ */ diff --git a/Example/Pods/libwebp/src/webp/mux_types.h b/Example/Pods/libwebp/src/webp/mux_types.h deleted file mode 100644 index c94043a3..00000000 --- a/Example/Pods/libwebp/src/webp/mux_types.h +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Data-types common to the mux and demux libraries. -// -// Author: Urvang (urvang@google.com) - -#ifndef WEBP_WEBP_MUX_TYPES_H_ -#define WEBP_WEBP_MUX_TYPES_H_ - -#include // free() -#include // memset() -#include "./types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Note: forward declaring enumerations is not allowed in (strict) C and C++, -// the types are left here for reference. -// typedef enum WebPFeatureFlags WebPFeatureFlags; -// typedef enum WebPMuxAnimDispose WebPMuxAnimDispose; -// typedef enum WebPMuxAnimBlend WebPMuxAnimBlend; -typedef struct WebPData WebPData; - -// VP8X Feature Flags. -typedef enum WebPFeatureFlags { - FRAGMENTS_FLAG = 0x00000001, - ANIMATION_FLAG = 0x00000002, - XMP_FLAG = 0x00000004, - EXIF_FLAG = 0x00000008, - ALPHA_FLAG = 0x00000010, - ICCP_FLAG = 0x00000020 -} WebPFeatureFlags; - -// Dispose method (animation only). Indicates how the area used by the current -// frame is to be treated before rendering the next frame on the canvas. -typedef enum WebPMuxAnimDispose { - WEBP_MUX_DISPOSE_NONE, // Do not dispose. - WEBP_MUX_DISPOSE_BACKGROUND // Dispose to background color. -} WebPMuxAnimDispose; - -// Blend operation (animation only). Indicates how transparent pixels of the -// current frame are blended with those of the previous canvas. -typedef enum WebPMuxAnimBlend { - WEBP_MUX_BLEND, // Blend. - WEBP_MUX_NO_BLEND // Do not blend. -} WebPMuxAnimBlend; - -// Data type used to describe 'raw' data, e.g., chunk data -// (ICC profile, metadata) and WebP compressed image data. -struct WebPData { - const uint8_t* bytes; - size_t size; -}; - -// Initializes the contents of the 'webp_data' object with default values. -static WEBP_INLINE void WebPDataInit(WebPData* webp_data) { - if (webp_data != NULL) { - memset(webp_data, 0, sizeof(*webp_data)); - } -} - -// Clears the contents of the 'webp_data' object by calling free(). Does not -// deallocate the object itself. -static WEBP_INLINE void WebPDataClear(WebPData* webp_data) { - if (webp_data != NULL) { - free((void*)webp_data->bytes); - WebPDataInit(webp_data); - } -} - -// Allocates necessary storage for 'dst' and copies the contents of 'src'. -// Returns true on success. -static WEBP_INLINE int WebPDataCopy(const WebPData* src, WebPData* dst) { - if (src == NULL || dst == NULL) return 0; - WebPDataInit(dst); - if (src->bytes != NULL && src->size != 0) { - dst->bytes = (uint8_t*)malloc(src->size); - if (dst->bytes == NULL) return 0; - memcpy((void*)dst->bytes, src->bytes, src->size); - dst->size = src->size; - } - return 1; -} - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_WEBP_MUX_TYPES_H_ */ diff --git a/Example/Pods/libwebp/src/webp/types.h b/Example/Pods/libwebp/src/webp/types.h deleted file mode 100644 index 98fff35a..00000000 --- a/Example/Pods/libwebp/src/webp/types.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Common types -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_WEBP_TYPES_H_ -#define WEBP_WEBP_TYPES_H_ - -#include // for size_t - -#ifndef _MSC_VER -#include -#if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \ - (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) -#define WEBP_INLINE inline -#else -#define WEBP_INLINE -#endif -#else -typedef signed char int8_t; -typedef unsigned char uint8_t; -typedef signed short int16_t; -typedef unsigned short uint16_t; -typedef signed int int32_t; -typedef unsigned int uint32_t; -typedef unsigned long long int uint64_t; -typedef long long int int64_t; -#define WEBP_INLINE __forceinline -#endif /* _MSC_VER */ - -#ifndef WEBP_EXTERN -// This explicitly marks library functions and allows for changing the -// signature for e.g., Windows DLL builds. -# if defined(__GNUC__) && __GNUC__ >= 4 -# define WEBP_EXTERN(type) extern __attribute__ ((visibility ("default"))) type -# else -# define WEBP_EXTERN(type) extern type -# endif /* __GNUC__ >= 4 */ -#endif /* WEBP_EXTERN */ - -// Macro to check ABI compatibility (same major revision number) -#define WEBP_ABI_IS_INCOMPATIBLE(a, b) (((a) >> 8) != ((b) >> 8)) - -#endif /* WEBP_WEBP_TYPES_H_ */ diff --git a/Examples/Example-Mac/Example-Mac.xcodeproj/project.pbxproj b/Examples/Example-Mac/Example-Mac.xcodeproj/project.pbxproj new file mode 100644 index 00000000..45ca4a25 --- /dev/null +++ b/Examples/Example-Mac/Example-Mac.xcodeproj/project.pbxproj @@ -0,0 +1,489 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 0C353DF727BB3E7B00422709 /* APNGViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0C353DF427BB3E7B00422709 /* APNGViewController.xib */; }; + 0C353DF827BB3E7B00422709 /* APNGViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C353DF527BB3E7B00422709 /* APNGViewController.m */; }; + 447F70872BF5022600C5C956 /* AnimatedWebPViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 447F70852BF5022600C5C956 /* AnimatedWebPViewController.m */; }; + 447F70882BF5022600C5C956 /* AnimatedWebPViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 447F70862BF5022600C5C956 /* AnimatedWebPViewController.xib */; }; + 689613C6208EA95800D2095C /* GIFViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 689613C4208EA95800D2095C /* GIFViewController.m */; }; + 689613C7208EA95800D2095C /* GIFViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 689613C5208EA95800D2095C /* GIFViewController.xib */; }; + 9C8BAA38D285DF744BB7A18E /* libPods-Example-Mac.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 30CF2F690D5332945E2257CA /* libPods-Example-Mac.a */; }; + 9D9328C51C3C60E700E1F1D3 /* PINViewWithBackgroundColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9328C41C3C60E700E1F1D3 /* PINViewWithBackgroundColor.m */; }; + 9D9328C91C3D09BB00E1F1D3 /* WebPViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9328C71C3D09BB00E1F1D3 /* WebPViewController.m */; }; + 9D9328CA1C3D09BB00E1F1D3 /* WebPViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9D9328C81C3D09BB00E1F1D3 /* WebPViewController.xib */; }; + 9D9328CF1C3D0C0D00E1F1D3 /* ScrollViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9328CD1C3D0C0D00E1F1D3 /* ScrollViewController.m */; }; + 9D9328D01C3D0C0D00E1F1D3 /* ScrollViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9D9328CE1C3D0C0D00E1F1D3 /* ScrollViewController.xib */; }; + 9D9328D41C3D131900E1F1D3 /* ProcessingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9328D21C3D131900E1F1D3 /* ProcessingViewController.m */; }; + 9D9328D51C3D131900E1F1D3 /* ProcessingViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9D9328D31C3D131900E1F1D3 /* ProcessingViewController.xib */; }; + 9D9328D91C3D243A00E1F1D3 /* ProgressiveViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9328D71C3D243A00E1F1D3 /* ProgressiveViewController.m */; }; + 9D9328DA1C3D243A00E1F1D3 /* ProgressiveViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9D9328D81C3D243A00E1F1D3 /* ProgressiveViewController.xib */; }; + 9D9328DE1C3D275D00E1F1D3 /* DegradedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9328DC1C3D275D00E1F1D3 /* DegradedViewController.m */; }; + 9D9328DF1C3D275D00E1F1D3 /* DegradedViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9D9328DD1C3D275D00E1F1D3 /* DegradedViewController.xib */; }; + 9D9328E21C3D489400E1F1D3 /* Kitten.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9328E11C3D489400E1F1D3 /* Kitten.m */; }; + 9D97D09D1C3C4D960006C115 /* PINImageCollectionViewItemView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9D97D09B1C3C4D960006C115 /* PINImageCollectionViewItemView.xib */; }; + 9DC09DB81C39AB0D00C6451E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DC09DB71C39AB0D00C6451E /* AppDelegate.m */; }; + 9DC09DBB1C39AB0D00C6451E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DC09DBA1C39AB0D00C6451E /* main.m */; }; + 9DC09DBD1C39AB0D00C6451E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9DC09DBC1C39AB0D00C6451E /* Assets.xcassets */; }; + 9DC09DC01C39AB0D00C6451E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9DC09DBE1C39AB0D00C6451E /* MainMenu.xib */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 0C353DF427BB3E7B00422709 /* APNGViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = APNGViewController.xib; sourceTree = ""; }; + 0C353DF527BB3E7B00422709 /* APNGViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = APNGViewController.m; sourceTree = ""; }; + 0C353DF627BB3E7B00422709 /* APNGViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APNGViewController.h; sourceTree = ""; }; + 0C7B3B480ECE116693899B73 /* Pods-PINRemoteImage.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PINRemoteImage.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage.debug.xcconfig"; sourceTree = ""; }; + 30CF2F690D5332945E2257CA /* libPods-Example-Mac.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Example-Mac.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 447F70842BF5022600C5C956 /* AnimatedWebPViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AnimatedWebPViewController.h; sourceTree = ""; }; + 447F70852BF5022600C5C956 /* AnimatedWebPViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AnimatedWebPViewController.m; sourceTree = ""; }; + 447F70862BF5022600C5C956 /* AnimatedWebPViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AnimatedWebPViewController.xib; sourceTree = ""; }; + 689613C3208EA95800D2095C /* GIFViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GIFViewController.h; sourceTree = ""; }; + 689613C4208EA95800D2095C /* GIFViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GIFViewController.m; sourceTree = ""; }; + 689613C5208EA95800D2095C /* GIFViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = GIFViewController.xib; sourceTree = ""; }; + 7C5CAA5957692DE0A6EC6CF9 /* Pods-Example-Mac.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example-Mac.release.xcconfig"; path = "Pods/Target Support Files/Pods-Example-Mac/Pods-Example-Mac.release.xcconfig"; sourceTree = ""; }; + 92BC66B6FF2EEFA71D678DDF /* Pods-Example-Mac.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example-Mac.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Example-Mac/Pods-Example-Mac.debug.xcconfig"; sourceTree = ""; }; + 9D9328C31C3C60E700E1F1D3 /* PINViewWithBackgroundColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINViewWithBackgroundColor.h; sourceTree = ""; }; + 9D9328C41C3C60E700E1F1D3 /* PINViewWithBackgroundColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINViewWithBackgroundColor.m; sourceTree = ""; }; + 9D9328C61C3D09BB00E1F1D3 /* WebPViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPViewController.h; sourceTree = ""; }; + 9D9328C71C3D09BB00E1F1D3 /* WebPViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebPViewController.m; sourceTree = ""; }; + 9D9328C81C3D09BB00E1F1D3 /* WebPViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = WebPViewController.xib; sourceTree = ""; }; + 9D9328CC1C3D0C0D00E1F1D3 /* ScrollViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollViewController.h; sourceTree = ""; }; + 9D9328CD1C3D0C0D00E1F1D3 /* ScrollViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScrollViewController.m; sourceTree = ""; }; + 9D9328CE1C3D0C0D00E1F1D3 /* ScrollViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ScrollViewController.xib; sourceTree = ""; }; + 9D9328D11C3D131900E1F1D3 /* ProcessingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessingViewController.h; sourceTree = ""; }; + 9D9328D21C3D131900E1F1D3 /* ProcessingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProcessingViewController.m; sourceTree = ""; }; + 9D9328D31C3D131900E1F1D3 /* ProcessingViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ProcessingViewController.xib; sourceTree = ""; }; + 9D9328D61C3D243A00E1F1D3 /* ProgressiveViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProgressiveViewController.h; sourceTree = ""; }; + 9D9328D71C3D243A00E1F1D3 /* ProgressiveViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProgressiveViewController.m; sourceTree = ""; }; + 9D9328D81C3D243A00E1F1D3 /* ProgressiveViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ProgressiveViewController.xib; sourceTree = ""; }; + 9D9328DB1C3D275D00E1F1D3 /* DegradedViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DegradedViewController.h; sourceTree = ""; }; + 9D9328DC1C3D275D00E1F1D3 /* DegradedViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DegradedViewController.m; sourceTree = ""; }; + 9D9328DD1C3D275D00E1F1D3 /* DegradedViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = DegradedViewController.xib; sourceTree = ""; }; + 9D9328E01C3D489400E1F1D3 /* Kitten.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Kitten.h; path = "../../Example-Shared/Kitten.h"; sourceTree = ""; }; + 9D9328E11C3D489400E1F1D3 /* Kitten.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Kitten.m; path = "../../Example-Shared/Kitten.m"; sourceTree = ""; }; + 9D97D09C1C3C4D960006C115 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/PINImageCollectionViewItemView.xib; sourceTree = ""; }; + 9DC09DB31C39AB0D00C6451E /* Example-Mac.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Example-Mac.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 9DC09DB61C39AB0D00C6451E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 9DC09DB71C39AB0D00C6451E /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 9DC09DBA1C39AB0D00C6451E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 9DC09DBC1C39AB0D00C6451E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 9DC09DBF1C39AB0D00C6451E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 9DC09DC11C39AB0D00C6451E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 9DC09DCA1C39AB0D00C6451E /* PINRemoteImageTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageTests.m; sourceTree = ""; }; + 9DC09DCC1C39AB0D00C6451E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A560E2F6800411CCF5086206 /* Pods-PINRemoteImage.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PINRemoteImage.release.xcconfig"; path = "Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage.release.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 9DC09DB01C39AB0D00C6451E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9C8BAA38D285DF744BB7A18E /* libPods-Example-Mac.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 19057E8A9A6779B7C486AF2B /* Frameworks */ = { + isa = PBXGroup; + children = ( + 30CF2F690D5332945E2257CA /* libPods-Example-Mac.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9D9328CB1C3D09BE00E1F1D3 /* Views */ = { + isa = PBXGroup; + children = ( + 9D97D09B1C3C4D960006C115 /* PINImageCollectionViewItemView.xib */, + 9D9328C31C3C60E700E1F1D3 /* PINViewWithBackgroundColor.h */, + 9D9328C41C3C60E700E1F1D3 /* PINViewWithBackgroundColor.m */, + ); + name = Views; + sourceTree = ""; + }; + 9DC09DAA1C39AB0D00C6451E = { + isa = PBXGroup; + children = ( + 9DC09DB51C39AB0D00C6451E /* PINRemoteImage */, + 9DC09DC91C39AB0D00C6451E /* PINRemoteImageTests */, + 9DC09DB41C39AB0D00C6451E /* Products */, + D8AD56B80C0F0D90F37F7BC5 /* Pods */, + 19057E8A9A6779B7C486AF2B /* Frameworks */, + ); + sourceTree = ""; + }; + 9DC09DB41C39AB0D00C6451E /* Products */ = { + isa = PBXGroup; + children = ( + 9DC09DB31C39AB0D00C6451E /* Example-Mac.app */, + ); + name = Products; + sourceTree = ""; + }; + 9DC09DB51C39AB0D00C6451E /* PINRemoteImage */ = { + isa = PBXGroup; + children = ( + 9DC09DB91C39AB0D00C6451E /* Supporting Files */, + 9D9328CB1C3D09BE00E1F1D3 /* Views */, + 9D9328E01C3D489400E1F1D3 /* Kitten.h */, + 9D9328E11C3D489400E1F1D3 /* Kitten.m */, + 9DC09DB61C39AB0D00C6451E /* AppDelegate.h */, + 9DC09DB71C39AB0D00C6451E /* AppDelegate.m */, + 9DC09DBE1C39AB0D00C6451E /* MainMenu.xib */, + 9DC09DC11C39AB0D00C6451E /* Info.plist */, + 9D9328CC1C3D0C0D00E1F1D3 /* ScrollViewController.h */, + 9D9328CD1C3D0C0D00E1F1D3 /* ScrollViewController.m */, + 9D9328CE1C3D0C0D00E1F1D3 /* ScrollViewController.xib */, + 9D9328C61C3D09BB00E1F1D3 /* WebPViewController.h */, + 9D9328C71C3D09BB00E1F1D3 /* WebPViewController.m */, + 9D9328C81C3D09BB00E1F1D3 /* WebPViewController.xib */, + 9D9328D61C3D243A00E1F1D3 /* ProgressiveViewController.h */, + 9D9328D71C3D243A00E1F1D3 /* ProgressiveViewController.m */, + 9D9328D81C3D243A00E1F1D3 /* ProgressiveViewController.xib */, + 9D9328DB1C3D275D00E1F1D3 /* DegradedViewController.h */, + 9D9328DC1C3D275D00E1F1D3 /* DegradedViewController.m */, + 9D9328DD1C3D275D00E1F1D3 /* DegradedViewController.xib */, + 9D9328D11C3D131900E1F1D3 /* ProcessingViewController.h */, + 9D9328D21C3D131900E1F1D3 /* ProcessingViewController.m */, + 9D9328D31C3D131900E1F1D3 /* ProcessingViewController.xib */, + 689613C3208EA95800D2095C /* GIFViewController.h */, + 689613C4208EA95800D2095C /* GIFViewController.m */, + 689613C5208EA95800D2095C /* GIFViewController.xib */, + 0C353DF627BB3E7B00422709 /* APNGViewController.h */, + 0C353DF527BB3E7B00422709 /* APNGViewController.m */, + 0C353DF427BB3E7B00422709 /* APNGViewController.xib */, + 447F70842BF5022600C5C956 /* AnimatedWebPViewController.h */, + 447F70852BF5022600C5C956 /* AnimatedWebPViewController.m */, + 447F70862BF5022600C5C956 /* AnimatedWebPViewController.xib */, + ); + path = PINRemoteImage; + sourceTree = ""; + }; + 9DC09DB91C39AB0D00C6451E /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 9DC09DBC1C39AB0D00C6451E /* Assets.xcassets */, + 9DC09DBA1C39AB0D00C6451E /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 9DC09DC91C39AB0D00C6451E /* PINRemoteImageTests */ = { + isa = PBXGroup; + children = ( + 9DC09DCA1C39AB0D00C6451E /* PINRemoteImageTests.m */, + 9DC09DCC1C39AB0D00C6451E /* Info.plist */, + ); + path = PINRemoteImageTests; + sourceTree = ""; + }; + D8AD56B80C0F0D90F37F7BC5 /* Pods */ = { + isa = PBXGroup; + children = ( + 0C7B3B480ECE116693899B73 /* Pods-PINRemoteImage.debug.xcconfig */, + A560E2F6800411CCF5086206 /* Pods-PINRemoteImage.release.xcconfig */, + 92BC66B6FF2EEFA71D678DDF /* Pods-Example-Mac.debug.xcconfig */, + 7C5CAA5957692DE0A6EC6CF9 /* Pods-Example-Mac.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 9DC09DB21C39AB0D00C6451E /* Example-Mac */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9DC09DCF1C39AB0D00C6451E /* Build configuration list for PBXNativeTarget "Example-Mac" */; + buildPhases = ( + 8CFB37DD63603884BA1E041F /* [CP] Check Pods Manifest.lock */, + 9DC09DAF1C39AB0D00C6451E /* Sources */, + 9DC09DB01C39AB0D00C6451E /* Frameworks */, + 9DC09DB11C39AB0D00C6451E /* Resources */, + 0A5F6E29FAACC9894DA1E108 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Example-Mac"; + productName = PINRemoteImage; + productReference = 9DC09DB31C39AB0D00C6451E /* Example-Mac.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 9DC09DAB1C39AB0D00C6451E /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = mischneider; + TargetAttributes = { + 9DC09DB21C39AB0D00C6451E = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 9DC09DAE1C39AB0D00C6451E /* Build configuration list for PBXProject "Example-Mac" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + English, + en, + Base, + ); + mainGroup = 9DC09DAA1C39AB0D00C6451E; + productRefGroup = 9DC09DB41C39AB0D00C6451E /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 9DC09DB21C39AB0D00C6451E /* Example-Mac */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 9DC09DB11C39AB0D00C6451E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9DC09DBD1C39AB0D00C6451E /* Assets.xcassets in Resources */, + 9D9328DA1C3D243A00E1F1D3 /* ProgressiveViewController.xib in Resources */, + 9D9328DF1C3D275D00E1F1D3 /* DegradedViewController.xib in Resources */, + 9D9328CA1C3D09BB00E1F1D3 /* WebPViewController.xib in Resources */, + 9D9328D01C3D0C0D00E1F1D3 /* ScrollViewController.xib in Resources */, + 447F70882BF5022600C5C956 /* AnimatedWebPViewController.xib in Resources */, + 9D97D09D1C3C4D960006C115 /* PINImageCollectionViewItemView.xib in Resources */, + 0C353DF727BB3E7B00422709 /* APNGViewController.xib in Resources */, + 689613C7208EA95800D2095C /* GIFViewController.xib in Resources */, + 9DC09DC01C39AB0D00C6451E /* MainMenu.xib in Resources */, + 9D9328D51C3D131900E1F1D3 /* ProcessingViewController.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 0A5F6E29FAACC9894DA1E108 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Example-Mac/Pods-Example-Mac-resources.sh", + "${PODS_CONFIGURATION_BUILD_DIR}/PINCache/PINCache.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/PINOperation/PINOperation.bundle", + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/PINCache.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/PINOperation.bundle", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Example-Mac/Pods-Example-Mac-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + 8CFB37DD63603884BA1E041F /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Example-Mac-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 9DC09DAF1C39AB0D00C6451E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9D9328CF1C3D0C0D00E1F1D3 /* ScrollViewController.m in Sources */, + 689613C6208EA95800D2095C /* GIFViewController.m in Sources */, + 9D9328C91C3D09BB00E1F1D3 /* WebPViewController.m in Sources */, + 9D9328E21C3D489400E1F1D3 /* Kitten.m in Sources */, + 9D9328DE1C3D275D00E1F1D3 /* DegradedViewController.m in Sources */, + 9DC09DBB1C39AB0D00C6451E /* main.m in Sources */, + 9D9328D41C3D131900E1F1D3 /* ProcessingViewController.m in Sources */, + 0C353DF827BB3E7B00422709 /* APNGViewController.m in Sources */, + 9D9328D91C3D243A00E1F1D3 /* ProgressiveViewController.m in Sources */, + 9DC09DB81C39AB0D00C6451E /* AppDelegate.m in Sources */, + 9D9328C51C3C60E700E1F1D3 /* PINViewWithBackgroundColor.m in Sources */, + 447F70872BF5022600C5C956 /* AnimatedWebPViewController.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 9D97D09B1C3C4D960006C115 /* PINImageCollectionViewItemView.xib */ = { + isa = PBXVariantGroup; + children = ( + 9D97D09C1C3C4D960006C115 /* Base */, + ); + name = PINImageCollectionViewItemView.xib; + sourceTree = ""; + }; + 9DC09DBE1C39AB0D00C6451E /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 9DC09DBF1C39AB0D00C6451E /* Base */, + ); + name = MainMenu.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 9DC09DCD1C39AB0D00C6451E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 9DC09DCE1C39AB0D00C6451E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 9DC09DD01C39AB0D00C6451E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 92BC66B6FF2EEFA71D678DDF /* Pods-Example-Mac.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = PINRemoteImage/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 11.0; + PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.demo.Example; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 9DC09DD11C39AB0D00C6451E /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7C5CAA5957692DE0A6EC6CF9 /* Pods-Example-Mac.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = PINRemoteImage/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 11.0; + PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.demo.Example; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 9DC09DAE1C39AB0D00C6451E /* Build configuration list for PBXProject "Example-Mac" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9DC09DCD1C39AB0D00C6451E /* Debug */, + 9DC09DCE1C39AB0D00C6451E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 9DC09DCF1C39AB0D00C6451E /* Build configuration list for PBXNativeTarget "Example-Mac" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9DC09DD01C39AB0D00C6451E /* Debug */, + 9DC09DD11C39AB0D00C6451E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 9DC09DAB1C39AB0D00C6451E /* Project object */; +} diff --git a/Examples/Example-Mac/Example-Mac.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/Example-Mac/Example-Mac.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/Examples/Example-Mac/Example-Mac.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Examples/Example-Mac/Example-Mac.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Examples/Example-Mac/Example-Mac.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Examples/Example-Mac/Example-Mac.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Examples/Example-Mac/Example-Mac.xcworkspace/contents.xcworkspacedata b/Examples/Example-Mac/Example-Mac.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..8bdc4ee6 --- /dev/null +++ b/Examples/Example-Mac/Example-Mac.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Examples/Example-Mac/Example-Mac.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Examples/Example-Mac/Example-Mac.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Examples/Example-Mac/Example-Mac.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Examples/Example-Mac/PINRemoteImage/APNGViewController.h b/Examples/Example-Mac/PINRemoteImage/APNGViewController.h new file mode 100644 index 00000000..2b3f052b --- /dev/null +++ b/Examples/Example-Mac/PINRemoteImage/APNGViewController.h @@ -0,0 +1,13 @@ +// +// APNGViewController.h +// PINRemoteImage +// +// Created by Garrett Moon on 4/23/18. +// Copyright © 2018 mischneider. All rights reserved. +// + +#import + +@interface APNGViewController : NSViewController + +@end diff --git a/Examples/Example-Mac/PINRemoteImage/APNGViewController.m b/Examples/Example-Mac/PINRemoteImage/APNGViewController.m new file mode 100644 index 00000000..441ae52b --- /dev/null +++ b/Examples/Example-Mac/PINRemoteImage/APNGViewController.m @@ -0,0 +1,26 @@ +// +// APNGViewController.m +// PINRemoteImage +// +// Created by Garrett Moon on 4/23/18. +// Copyright © 2018 mischneider. All rights reserved. +// + +#import "APNGViewController.h" + +#import + +@interface APNGViewController () + +@property (weak) IBOutlet PINAnimatedImageView *animatedImageView; + +@end + +@implementation APNGViewController + +- (void)viewWillAppear { + [super viewWillAppear]; + [self.animatedImageView pin_setImageFromURL:[NSURL URLWithString:@"https://upload.wikimedia.org/wikipedia/commons/1/14/Animated_PNG_example_bouncing_beach_ball.png"]]; +} + +@end diff --git a/Examples/Example-Mac/PINRemoteImage/APNGViewController.xib b/Examples/Example-Mac/PINRemoteImage/APNGViewController.xib new file mode 100644 index 00000000..c0c006cd --- /dev/null +++ b/Examples/Example-Mac/PINRemoteImage/APNGViewController.xib @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/Example-Mac/PINRemoteImage/AnimatedWebPViewController.h b/Examples/Example-Mac/PINRemoteImage/AnimatedWebPViewController.h new file mode 100644 index 00000000..b3d83c9d --- /dev/null +++ b/Examples/Example-Mac/PINRemoteImage/AnimatedWebPViewController.h @@ -0,0 +1,17 @@ +// +// AnimatedWebPViewController.h +// Example-Mac +// +// Created by Andy Finnell on 5/15/24. +// Copyright © 2024 mischneider. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface AnimatedWebPViewController : NSViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/Examples/Example-Mac/PINRemoteImage/AnimatedWebPViewController.m b/Examples/Example-Mac/PINRemoteImage/AnimatedWebPViewController.m new file mode 100644 index 00000000..d323fc87 --- /dev/null +++ b/Examples/Example-Mac/PINRemoteImage/AnimatedWebPViewController.m @@ -0,0 +1,23 @@ +// +// AnimatedWebPViewController.m +// Example-Mac +// +// Created by Andy Finnell on 5/15/24. +// Copyright © 2024 mischneider. All rights reserved. +// + +#import "AnimatedWebPViewController.h" +#import + +@interface AnimatedWebPViewController () +@property (weak) IBOutlet PINAnimatedImageView *animatedImageView; +@end + +@implementation AnimatedWebPViewController + +- (void)viewWillAppear { + [super viewWillAppear]; + [self.animatedImageView pin_setImageFromURL:[NSURL URLWithString:@"https://mathiasbynens.be/demo/animated-webp-supported.webp"]]; +} + +@end diff --git a/Examples/Example-Mac/PINRemoteImage/AnimatedWebPViewController.xib b/Examples/Example-Mac/PINRemoteImage/AnimatedWebPViewController.xib new file mode 100644 index 00000000..51ab2121 --- /dev/null +++ b/Examples/Example-Mac/PINRemoteImage/AnimatedWebPViewController.xib @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example-Mac/PINRemoteImage/AppDelegate.h b/Examples/Example-Mac/PINRemoteImage/AppDelegate.h similarity index 100% rename from Example-Mac/PINRemoteImage/AppDelegate.h rename to Examples/Example-Mac/PINRemoteImage/AppDelegate.h diff --git a/Example-Mac/PINRemoteImage/AppDelegate.m b/Examples/Example-Mac/PINRemoteImage/AppDelegate.m similarity index 86% rename from Example-Mac/PINRemoteImage/AppDelegate.m rename to Examples/Example-Mac/PINRemoteImage/AppDelegate.m index a1e14174..328d6447 100644 --- a/Example-Mac/PINRemoteImage/AppDelegate.m +++ b/Examples/Example-Mac/PINRemoteImage/AppDelegate.m @@ -15,6 +15,9 @@ #import "DegradedViewController.h" #import "ProgressiveViewController.h" #import "ProcessingViewController.h" +#import "GIFViewController.h" +#import "APNGViewController.h" +#import "AnimatedWebPViewController.h" enum : NSUInteger { kScrollViewControllerSegment = 0, @@ -22,6 +25,9 @@ kProgressiveViewControllerSegment, kDegradedViewControllerSegment, kProcessingViewControllerSegment, + kGIFViewControllerSegment, + kAPNGViewControllerSegment, + kAnimatedWebPViewControllerSegment, }; @interface AppDelegate () @@ -69,7 +75,10 @@ - (NSDictionary *)viewControllerMapping @(kWebPViewControllerSegment) : [WebPViewController class], @(kProgressiveViewControllerSegment) : [ProgressiveViewController class], @(kDegradedViewControllerSegment) : [DegradedViewController class], - @(kProcessingViewControllerSegment) : [ProcessingViewController class] + @(kProcessingViewControllerSegment) : [ProcessingViewController class], + @(kGIFViewControllerSegment) : [GIFViewController class], + @(kAPNGViewControllerSegment) : [APNGViewController class], + @(kAnimatedWebPViewControllerSegment) : [AnimatedWebPViewController class], }; } @@ -97,4 +106,4 @@ - (IBAction)segmentedControlChanged:(NSSegmentedControl *)segmentedControl [self.window.contentView addSubview:self.currentViewController.view]; } -@end \ No newline at end of file +@end diff --git a/Example-Mac/PINRemoteImage/Assets.xcassets/AppIcon.appiconset/Contents.json b/Examples/Example-Mac/PINRemoteImage/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from Example-Mac/PINRemoteImage/Assets.xcassets/AppIcon.appiconset/Contents.json rename to Examples/Example-Mac/PINRemoteImage/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/Example-Mac/PINRemoteImage/Assets.xcassets/Contents.json b/Examples/Example-Mac/PINRemoteImage/Assets.xcassets/Contents.json similarity index 100% rename from Example-Mac/PINRemoteImage/Assets.xcassets/Contents.json rename to Examples/Example-Mac/PINRemoteImage/Assets.xcassets/Contents.json diff --git a/Example-Mac/PINRemoteImage/Assets.xcassets/white-pinterest-logo.imageset/Contents.json b/Examples/Example-Mac/PINRemoteImage/Assets.xcassets/white-pinterest-logo.imageset/Contents.json similarity index 100% rename from Example-Mac/PINRemoteImage/Assets.xcassets/white-pinterest-logo.imageset/Contents.json rename to Examples/Example-Mac/PINRemoteImage/Assets.xcassets/white-pinterest-logo.imageset/Contents.json diff --git a/Example-Mac/PINRemoteImage/Assets.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@1x.png b/Examples/Example-Mac/PINRemoteImage/Assets.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@1x.png similarity index 100% rename from Example-Mac/PINRemoteImage/Assets.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@1x.png rename to Examples/Example-Mac/PINRemoteImage/Assets.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@1x.png diff --git a/Example-Mac/PINRemoteImage/Assets.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@2x.png b/Examples/Example-Mac/PINRemoteImage/Assets.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@2x.png similarity index 100% rename from Example-Mac/PINRemoteImage/Assets.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@2x.png rename to Examples/Example-Mac/PINRemoteImage/Assets.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@2x.png diff --git a/Example-Mac/PINRemoteImage/Base.lproj/MainMenu.xib b/Examples/Example-Mac/PINRemoteImage/Base.lproj/MainMenu.xib similarity index 97% rename from Example-Mac/PINRemoteImage/Base.lproj/MainMenu.xib rename to Examples/Example-Mac/PINRemoteImage/Base.lproj/MainMenu.xib index ed9bf949..1171d648 100644 --- a/Example-Mac/PINRemoteImage/Base.lproj/MainMenu.xib +++ b/Examples/Example-Mac/PINRemoteImage/Base.lproj/MainMenu.xib @@ -1,8 +1,9 @@ - - + + - + + @@ -667,15 +668,16 @@ + - + - - + + - - + + @@ -686,10 +688,10 @@ - - + + - + @@ -699,6 +701,9 @@ + + + @@ -716,7 +721,14 @@ - + + + + + + + + diff --git a/Example-Mac/PINRemoteImage/Base.lproj/PINImageCollectionViewItemView.xib b/Examples/Example-Mac/PINRemoteImage/Base.lproj/PINImageCollectionViewItemView.xib similarity index 100% rename from Example-Mac/PINRemoteImage/Base.lproj/PINImageCollectionViewItemView.xib rename to Examples/Example-Mac/PINRemoteImage/Base.lproj/PINImageCollectionViewItemView.xib diff --git a/Example-Mac/PINRemoteImage/DegradedViewController.h b/Examples/Example-Mac/PINRemoteImage/DegradedViewController.h similarity index 100% rename from Example-Mac/PINRemoteImage/DegradedViewController.h rename to Examples/Example-Mac/PINRemoteImage/DegradedViewController.h diff --git a/Example-Mac/PINRemoteImage/DegradedViewController.m b/Examples/Example-Mac/PINRemoteImage/DegradedViewController.m similarity index 100% rename from Example-Mac/PINRemoteImage/DegradedViewController.m rename to Examples/Example-Mac/PINRemoteImage/DegradedViewController.m diff --git a/Example-Mac/PINRemoteImage/DegradedViewController.xib b/Examples/Example-Mac/PINRemoteImage/DegradedViewController.xib similarity index 100% rename from Example-Mac/PINRemoteImage/DegradedViewController.xib rename to Examples/Example-Mac/PINRemoteImage/DegradedViewController.xib diff --git a/Examples/Example-Mac/PINRemoteImage/GIFViewController.h b/Examples/Example-Mac/PINRemoteImage/GIFViewController.h new file mode 100644 index 00000000..0a5fe687 --- /dev/null +++ b/Examples/Example-Mac/PINRemoteImage/GIFViewController.h @@ -0,0 +1,13 @@ +// +// GIFViewController.h +// PINRemoteImage +// +// Created by Garrett Moon on 4/23/18. +// Copyright © 2018 mischneider. All rights reserved. +// + +#import + +@interface GIFViewController : NSViewController + +@end diff --git a/Examples/Example-Mac/PINRemoteImage/GIFViewController.m b/Examples/Example-Mac/PINRemoteImage/GIFViewController.m new file mode 100644 index 00000000..87b09c08 --- /dev/null +++ b/Examples/Example-Mac/PINRemoteImage/GIFViewController.m @@ -0,0 +1,26 @@ +// +// GIFViewController.m +// PINRemoteImage +// +// Created by Garrett Moon on 4/23/18. +// Copyright © 2018 mischneider. All rights reserved. +// + +#import "GIFViewController.h" + +#import + +@interface GIFViewController () + +@property (weak) IBOutlet PINAnimatedImageView *animatedImageView; + +@end + +@implementation GIFViewController + +- (void)viewWillAppear { + [super viewWillAppear]; + [self.animatedImageView pin_setImageFromURL:[NSURL URLWithString:@"https://i.pinimg.com/originals/f5/23/f1/f523f141646b613f78566ba964208990.gif"]]; +} + +@end diff --git a/Examples/Example-Mac/PINRemoteImage/GIFViewController.xib b/Examples/Example-Mac/PINRemoteImage/GIFViewController.xib new file mode 100644 index 00000000..91e68321 --- /dev/null +++ b/Examples/Example-Mac/PINRemoteImage/GIFViewController.xib @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example-Mac/PINRemoteImage/Info.plist b/Examples/Example-Mac/PINRemoteImage/Info.plist similarity index 100% rename from Example-Mac/PINRemoteImage/Info.plist rename to Examples/Example-Mac/PINRemoteImage/Info.plist diff --git a/Example-Mac/PINRemoteImage/PINViewWithBackgroundColor.h b/Examples/Example-Mac/PINRemoteImage/PINViewWithBackgroundColor.h similarity index 100% rename from Example-Mac/PINRemoteImage/PINViewWithBackgroundColor.h rename to Examples/Example-Mac/PINRemoteImage/PINViewWithBackgroundColor.h diff --git a/Example-Mac/PINRemoteImage/PINViewWithBackgroundColor.m b/Examples/Example-Mac/PINRemoteImage/PINViewWithBackgroundColor.m similarity index 100% rename from Example-Mac/PINRemoteImage/PINViewWithBackgroundColor.m rename to Examples/Example-Mac/PINRemoteImage/PINViewWithBackgroundColor.m diff --git a/Example-Mac/PINRemoteImage/ProcessingViewController.h b/Examples/Example-Mac/PINRemoteImage/ProcessingViewController.h similarity index 100% rename from Example-Mac/PINRemoteImage/ProcessingViewController.h rename to Examples/Example-Mac/PINRemoteImage/ProcessingViewController.h diff --git a/Examples/Example-Mac/PINRemoteImage/ProcessingViewController.m b/Examples/Example-Mac/PINRemoteImage/ProcessingViewController.m new file mode 100644 index 00000000..0203be39 --- /dev/null +++ b/Examples/Example-Mac/PINRemoteImage/ProcessingViewController.m @@ -0,0 +1,79 @@ +// +// ProcessingViewController.m +// PINRemoteImage +// +// Created by Michael Schneider on 1/6/16. +// Copyright © 2016 mischneider. All rights reserved. +// + +#import "ProcessingViewController.h" + +#import + +@interface ProcessingViewController () +@property (weak) IBOutlet NSImageView *imageView; + +@end + +@implementation ProcessingViewController + +#pragma mark - Lifecycle + +- (instancetype)init +{ + self = [super initWithNibName:NSStringFromClass(self.class) bundle:nil]; + if (self == nil) { return self; } + return self; +} + + +#pragma mark - NSViewController + +- (void)viewWillAppear +{ + [super viewWillAppear]; + + [self.imageView pin_setImageFromURL:[NSURL URLWithString:@"https://i.pinimg.com/736x/5b/c6/c5/5bc6c5387ff6f104fd642f2b375efba3.jpg"] processorKey:@"rounded" processor:^NSImage *(PINRemoteImageManagerResult *result, NSUInteger *cost) + { + NSImage *image = result.image; + CGFloat radius = 7.0f; + CGSize targetSize = CGSizeMake(200, 300); + CGRect imageRect = CGRectMake(0, 0, targetSize.width, targetSize.height); + + NSImage *processedImage = [[NSImage alloc] initWithSize:targetSize]; + [processedImage lockFocus]; + + NSBezierPath *bezierPath = [NSBezierPath bezierPathWithRoundedRect:imageRect xRadius:radius yRadius:radius]; + [bezierPath addClip]; + + CGFloat widthMultiplier = targetSize.width / image.size.width; + CGFloat heightMultiplier = targetSize.height / image.size.height; + CGFloat sizeMultiplier = MAX(widthMultiplier, heightMultiplier); + + CGRect drawRect = CGRectMake(0, 0, image.size.width * sizeMultiplier, image.size.height * sizeMultiplier); + if (CGRectGetMaxX(drawRect) > CGRectGetMaxX(imageRect)) { + drawRect.origin.x -= (CGRectGetMaxX(drawRect) - CGRectGetMaxX(imageRect)) / 2.0; + } + if (CGRectGetMaxY(drawRect) > CGRectGetMaxY(imageRect)) { + drawRect.origin.y -= (CGRectGetMaxY(drawRect) - CGRectGetMaxY(imageRect)) / 2.0; + } + + [image drawInRect:drawRect]; + + [[NSColor redColor] setStroke]; + [bezierPath setLineWidth:5.0]; + [bezierPath stroke]; + + NSImage *logo = [NSImage imageNamed:@"white-pinterest-logo"]; + CGContextRef ctx = [[NSGraphicsContext currentContext] CGContext]; + CGContextSetBlendMode(ctx, kCGBlendModeOverlay); + CGContextSetAlpha(ctx, 0.5); + CGContextDrawImage(ctx, CGRectMake(90, 10, logo.size.width, logo.size.height), [logo CGImage]); + + [processedImage unlockFocus]; + + return processedImage; + }]; +} + +@end diff --git a/Example-Mac/PINRemoteImage/ProcessingViewController.xib b/Examples/Example-Mac/PINRemoteImage/ProcessingViewController.xib similarity index 100% rename from Example-Mac/PINRemoteImage/ProcessingViewController.xib rename to Examples/Example-Mac/PINRemoteImage/ProcessingViewController.xib diff --git a/Example-Mac/PINRemoteImage/ProgressiveViewController.h b/Examples/Example-Mac/PINRemoteImage/ProgressiveViewController.h similarity index 100% rename from Example-Mac/PINRemoteImage/ProgressiveViewController.h rename to Examples/Example-Mac/PINRemoteImage/ProgressiveViewController.h diff --git a/Examples/Example-Mac/PINRemoteImage/ProgressiveViewController.m b/Examples/Example-Mac/PINRemoteImage/ProgressiveViewController.m new file mode 100644 index 00000000..518298bd --- /dev/null +++ b/Examples/Example-Mac/PINRemoteImage/ProgressiveViewController.m @@ -0,0 +1,60 @@ +// +// ProgressiveViewController.m +// PINRemoteImage +// +// Created by Michael Schneider on 1/6/16. +// Copyright © 2016 mischneider. All rights reserved. +// + +#import "ProgressiveViewController.h" + +#import +#import + +@interface ProgressiveViewController () +@property (weak) IBOutlet NSImageView *imageView; + +@end + +@implementation ProgressiveViewController + +#pragma mark - Lifecycle + +- (instancetype)init +{ + self = [super initWithNibName:NSStringFromClass(self.class) bundle:nil]; + if (self == nil) { return self; } + return self; +} + + +#pragma mark - NSViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + // MUST BE SET ON IMAGE VIEW TO GET PROGRESS UPDATES! + self.imageView.pin_updateWithProgress = YES; +} + +- (void)viewWillAppear +{ + [super viewWillAppear]; + + NSURL *progressiveURL = [NSURL URLWithString:@"https://i.pinimg.com/1200x/2e/0c/c5/2e0cc5d86e7b7cd42af225c29f21c37f.jpg"]; + [[PINRemoteImageManager sharedImageManager] setProgressThresholds:@[@(0.1), @(0.2), @(0.3), @(0.4), @(0.5), @(0.6), @(0.7), @(0.8), @(0.9)] completion:nil]; + [[[PINRemoteImageManager sharedImageManager] cache] removeObjectForKey:[[PINRemoteImageManager sharedImageManager] cacheKeyForURL:progressiveURL processorKey:nil]]; + [self.imageView pin_setImageFromURL:progressiveURL]; + + NSMutableArray *progress = [[NSMutableArray alloc] init]; + [[PINRemoteImageManager sharedImageManager] + downloadImageWithURL:progressiveURL + options:PINRemoteImageManagerDownloadOptionsNone progressImage:^(PINRemoteImageManagerResult *result) { + [progress addObject:result.image]; + } completion:^(PINRemoteImageManagerResult *result) { + [progress addObject:result.image]; + }]; +} + +@end diff --git a/Example-Mac/PINRemoteImage/ProgressiveViewController.xib b/Examples/Example-Mac/PINRemoteImage/ProgressiveViewController.xib similarity index 100% rename from Example-Mac/PINRemoteImage/ProgressiveViewController.xib rename to Examples/Example-Mac/PINRemoteImage/ProgressiveViewController.xib diff --git a/Example-Mac/PINRemoteImage/ScrollViewController.h b/Examples/Example-Mac/PINRemoteImage/ScrollViewController.h similarity index 100% rename from Example-Mac/PINRemoteImage/ScrollViewController.h rename to Examples/Example-Mac/PINRemoteImage/ScrollViewController.h diff --git a/Example-Mac/PINRemoteImage/ScrollViewController.m b/Examples/Example-Mac/PINRemoteImage/ScrollViewController.m similarity index 98% rename from Example-Mac/PINRemoteImage/ScrollViewController.m rename to Examples/Example-Mac/PINRemoteImage/ScrollViewController.m index 63e2d350..770ff6f8 100644 --- a/Example-Mac/PINRemoteImage/ScrollViewController.m +++ b/Examples/Example-Mac/PINRemoteImage/ScrollViewController.m @@ -11,7 +11,7 @@ #import #import #import -#import +#import #import "PINViewWithBackgroundColor.h" #import "Kitten.h" diff --git a/Example-Mac/PINRemoteImage/ScrollViewController.xib b/Examples/Example-Mac/PINRemoteImage/ScrollViewController.xib similarity index 100% rename from Example-Mac/PINRemoteImage/ScrollViewController.xib rename to Examples/Example-Mac/PINRemoteImage/ScrollViewController.xib diff --git a/Example-Mac/PINRemoteImage/WebPViewController.h b/Examples/Example-Mac/PINRemoteImage/WebPViewController.h similarity index 100% rename from Example-Mac/PINRemoteImage/WebPViewController.h rename to Examples/Example-Mac/PINRemoteImage/WebPViewController.h diff --git a/Examples/Example-Mac/PINRemoteImage/WebPViewController.m b/Examples/Example-Mac/PINRemoteImage/WebPViewController.m new file mode 100644 index 00000000..185bddbe --- /dev/null +++ b/Examples/Example-Mac/PINRemoteImage/WebPViewController.m @@ -0,0 +1,38 @@ +// +// WebPViewController.m +// PINRemoteImage +// +// Created by Michael Schneider on 1/6/16. +// Copyright © 2016 mischneider. All rights reserved. +// + +#import "WebPViewController.h" + +#import + +@interface WebPViewController () +@property (weak) IBOutlet NSImageView *imageView; +@end + +@implementation WebPViewController + +#pragma mark - Lifecycle + +- (instancetype)init +{ + self = [super initWithNibName:NSStringFromClass(self.class) bundle:nil]; + if (self == nil) { return self; } + return self; +} + + +#pragma mark - NSViewController + +- (void)viewWillAppear +{ + [super viewWillAppear]; + + [self.imageView pin_setImageFromURL:[NSURL URLWithString:@"https://raw.githubusercontent.com/samdutton/simpl/main/picturetype/kittens.webp"]]; +} + +@end diff --git a/Example-Mac/PINRemoteImage/WebPViewController.xib b/Examples/Example-Mac/PINRemoteImage/WebPViewController.xib similarity index 100% rename from Example-Mac/PINRemoteImage/WebPViewController.xib rename to Examples/Example-Mac/PINRemoteImage/WebPViewController.xib diff --git a/Example-Mac/PINRemoteImage/main.m b/Examples/Example-Mac/PINRemoteImage/main.m similarity index 100% rename from Example-Mac/PINRemoteImage/main.m rename to Examples/Example-Mac/PINRemoteImage/main.m diff --git a/Examples/Example-Mac/Podfile b/Examples/Example-Mac/Podfile new file mode 100644 index 00000000..2f8b32f4 --- /dev/null +++ b/Examples/Example-Mac/Podfile @@ -0,0 +1,7 @@ +platform :macos, 11.0 + +target 'Example-Mac' do + pod "PINRemoteImage/OSX", :path => "../../" + pod "PINRemoteImage/PINCache", :path => "../../" + pod "PINCache" +end diff --git a/Examples/Example-Mac/Podfile.lock b/Examples/Example-Mac/Podfile.lock new file mode 100644 index 00000000..33c15802 --- /dev/null +++ b/Examples/Example-Mac/Podfile.lock @@ -0,0 +1,39 @@ +PODS: + - PINCache (3.0.4): + - PINCache/Arc-exception-safe (= 3.0.4) + - PINCache/Core (= 3.0.4) + - PINCache/Arc-exception-safe (3.0.4): + - PINCache/Core + - PINCache/Core (3.0.4): + - PINOperation (~> 1.2.3) + - PINOperation (1.2.3) + - PINRemoteImage/Core (3.0.4): + - PINOperation + - PINRemoteImage/OSX (3.0.4): + - PINRemoteImage/Core + - PINRemoteImage/PINCache (3.0.4): + - PINCache (~> 3.0.4) + - PINRemoteImage/Core + +DEPENDENCIES: + - PINCache + - PINRemoteImage/OSX (from `../../`) + - PINRemoteImage/PINCache (from `../../`) + +SPEC REPOS: + trunk: + - PINCache + - PINOperation + +EXTERNAL SOURCES: + PINRemoteImage: + :path: "../../" + +SPEC CHECKSUMS: + PINCache: d9a87a0ff397acffe9e2f0db972ac14680441158 + PINOperation: fb563bcc9c32c26d6c78aaff967d405aa2ee74a7 + PINRemoteImage: 6256a644f4996991f124811763c7286b2a63ff94 + +PODFILE CHECKSUM: a04c05adb7772d865f0951358a8d41d8a62f76f4 + +COCOAPODS: 1.15.2 diff --git a/Example-Shared/Kitten.h b/Examples/Example-Shared/Kitten.h similarity index 93% rename from Example-Shared/Kitten.h rename to Examples/Example-Shared/Kitten.h index e35b2e7a..5428710c 100644 --- a/Example-Shared/Kitten.h +++ b/Examples/Example-Shared/Kitten.h @@ -5,6 +5,7 @@ // Created by Michael Schneider on 1/6/16. // Copyright © 2016 mischneider. All rights reserved. // +#import #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED #import diff --git a/Examples/Example-Shared/Kitten.m b/Examples/Example-Shared/Kitten.m new file mode 100644 index 00000000..f2a48cb3 --- /dev/null +++ b/Examples/Example-Shared/Kitten.m @@ -0,0 +1,132 @@ +// +// Kitten.m +// PINRemoteImage +// +// Created by Michael Schneider on 1/6/16. +// Copyright © 2016 mischneider. All rights reserved. +// + +#import "Kitten.h" + +#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED + +@interface NSValue (PINiOSMapping) ++ (NSValue *)valueWithCGSize:(CGSize)size; +- (CGSize)CGSizeValue; +@end + +@implementation NSValue (PINiOSMapping) + ++ (NSValue *)valueWithCGSize:(CGSize)size +{ + return [self valueWithSize:size]; +} + +- (CGSize)CGSizeValue +{ + return self.sizeValue; +} + +@end + +#endif + + +@implementation Kitten + ++ (void)fetchKittenForWidth:(CGFloat)width completion:(void (^)(NSArray *kittens))completion +{ + NSArray *kittenURLs = @[[NSURL URLWithString:@"https://i.pinimg.com/736x/92/5d/5a/925d5ac74db0dcfabc238e1686e31d16.jpg"], + [NSURL URLWithString:@"https://i.pinimg.com/736x/ff/b3/ae/ffb3ae40533b7f9463cf1c04d7ab69d1.jpg"], + [NSURL URLWithString:@"https://i.pinimg.com/736x/e4/b7/7c/e4b77ca06e1d4a401b1a49d7fadd90d9.jpg"], + [NSURL URLWithString:@"https://i.pinimg.com/736x/46/e1/59/46e159d76b167ed9211d662f95e7bf6f.jpg"], + [NSURL URLWithString:@"https://i.pinimg.com/736x/7a/72/77/7a72779329942c06f888c148eb8d7e34.jpg"], + [NSURL URLWithString:@"https://i.pinimg.com/736x/60/21/8f/60218ff43257fb3b6d7c5b888f74a5bf.jpg"], + [NSURL URLWithString:@"https://i.pinimg.com/736x/90/e8/e4/90e8e47d53e71e0d97691dd13a5617fb.jpg"], + [NSURL URLWithString:@"https://i.pinimg.com/736x/96/ae/31/96ae31fbc52d96dd3308d2754a6ca37e.jpg"], + [NSURL URLWithString:@"https://i.pinimg.com/736x/9b/7b/99/9b7b99ff63be31bba8f9863724b3ebbc.jpg"], + [NSURL URLWithString:@"https://i.pinimg.com/736x/80/23/51/802351d953dd2a8b232d0da1c7ca6880.jpg"], + [NSURL URLWithString:@"https://i.pinimg.com/736x/f5/c4/f0/f5c4f04fa2686338dc3b08420d198484.jpg"], + [NSURL URLWithString:@"https://i.pinimg.com/736x/2b/06/4f/2b064f3e0af984a556ac94b251ff7060.jpg"], + [NSURL URLWithString:@"https://i.pinimg.com/736x/17/1f/c0/171fc02398143269d8a507a15563166a.jpg"], + [NSURL URLWithString:@"https://i.pinimg.com/736x/8a/35/33/8a35338bbf67c86a198ba2dd926edd82.jpg"], + [NSURL URLWithString:@"https://i.pinimg.com/736x/4d/6e/3c/4d6e3cf970031116c57486e85c2a4cab.jpg"], + [NSURL URLWithString:@"https://i.pinimg.com/736x/54/25/ee/5425eeccba78731cf7be70f0b8808bd2.jpg"], + [NSURL URLWithString:@"https://i.pinimg.com/736x/04/f1/3f/04f13fdb7580dcbe8c4d6b7d5a0a5ec2.jpg"], + [NSURL URLWithString:@"https://i.pinimg.com/736x/dc/16/4e/dc164ed33af9d899e5ed188e642f00e9.jpg"], + [NSURL URLWithString:@"https://i.pinimg.com/736x/c1/06/13/c106132936189b6cb654671f2a2183ed.jpg"], + [NSURL URLWithString:@"https://i.pinimg.com/736x/46/43/ed/4643eda4e1be4273721a76a370b90346.jpg"], + ]; + + NSArray *kittenSizes = @[[NSValue valueWithCGSize:CGSizeMake(503, 992)], + [NSValue valueWithCGSize:CGSizeMake(500, 337)], + [NSValue valueWithCGSize:CGSizeMake(522, 695)], + [NSValue valueWithCGSize:CGSizeMake(557, 749)], + [NSValue valueWithCGSize:CGSizeMake(710, 1069)], + [NSValue valueWithCGSize:CGSizeMake(522, 676)], + [NSValue valueWithCGSize:CGSizeMake(500, 688)], + [NSValue valueWithCGSize:CGSizeMake(377, 700)], + [NSValue valueWithCGSize:CGSizeMake(334, 494)], + [NSValue valueWithCGSize:CGSizeMake(625, 469)], + [NSValue valueWithCGSize:CGSizeMake(625, 833)], + [NSValue valueWithCGSize:CGSizeMake(625, 469)], + [NSValue valueWithCGSize:CGSizeMake(625, 469)], + [NSValue valueWithCGSize:CGSizeMake(625, 791)], + [NSValue valueWithCGSize:CGSizeMake(625, 833)], + [NSValue valueWithCGSize:CGSizeMake(605, 605)], + [NSValue valueWithCGSize:CGSizeMake(504, 750)], + [NSValue valueWithCGSize:CGSizeMake(500, 500)], + [NSValue valueWithCGSize:CGSizeMake(640, 640)], + [NSValue valueWithCGSize:CGSizeMake(500, 473)], + ]; + + dispatch_group_t group = dispatch_group_create(); + NSMutableArray *kittens = [[NSMutableArray alloc] init]; + + CGFloat scale = 1; +#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED + scale = [[UIScreen mainScreen] scale]; +#else + scale = [[NSScreen mainScreen] backingScaleFactor]; +#endif + dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + NSInteger count = 0; + for (NSInteger idx = 0; idx < 500; idx++) { + Kitten *kitten = [[Kitten alloc] init]; + CGFloat r = (rand() % 255) / 255.0f; + CGFloat g = (rand() % 255) / 255.0f; + CGFloat b = (rand() % 255) / 255.0f; +#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED + kitten.dominantColor = [UIColor colorWithRed:r green:g blue:b alpha:1.0f]; +#else + kitten.dominantColor = [NSColor colorWithRed:r green:g blue:b alpha:1.0f]; +#endif + + NSUInteger kittenIdx = rand() % 20; + + CGSize kittenSize = [kittenSizes[kittenIdx] CGSizeValue]; + NSInteger kittenSizeWidth = kittenSize.width; + NSInteger kittenSizeHeight = kittenSize.height; + + if (kittenSizeWidth > (width * scale)) { + kittenSizeHeight = ((width * scale) / kittenSizeWidth) * kittenSizeHeight; + kittenSizeWidth = (width * scale); + } + + kitten.imageURL = kittenURLs[kittenIdx]; + kitten.imageSize = CGSizeMake(kittenSizeWidth / scale, kittenSizeHeight / scale); + + dispatch_sync(dispatch_get_main_queue(), ^{ + [kittens addObject:kitten]; + }); + count++; + } + }); + dispatch_group_notify(group, dispatch_get_main_queue(), ^{ + if (completion) { + completion(kittens); + } + }); +} + +@end diff --git a/Examples/Example-Xcode-SPM/Example-Xcode-SPM.xcodeproj/project.pbxproj b/Examples/Example-Xcode-SPM/Example-Xcode-SPM.xcodeproj/project.pbxproj new file mode 100644 index 00000000..83456512 --- /dev/null +++ b/Examples/Example-Xcode-SPM/Example-Xcode-SPM.xcodeproj/project.pbxproj @@ -0,0 +1,370 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 843037332A01C67500914266 /* PINRemoteImage in Resources */ = {isa = PBXBuildFile; fileRef = FB3894EB2577F8960025252E /* PINRemoteImage */; }; + FB3894CD2577F22F0025252E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB3894CC2577F22F0025252E /* AppDelegate.swift */; }; + FB3894CF2577F22F0025252E /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB3894CE2577F22F0025252E /* SceneDelegate.swift */; }; + FB3894D12577F22F0025252E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB3894D02577F22F0025252E /* ViewController.swift */; }; + FB3894D42577F22F0025252E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FB3894D22577F22F0025252E /* Main.storyboard */; }; + FB3894D62577F2300025252E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FB3894D52577F2300025252E /* Assets.xcassets */; }; + FB3894D92577F2300025252E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FB3894D72577F2300025252E /* LaunchScreen.storyboard */; }; + FB3894EE2577F8B40025252E /* PINRemoteImage in Frameworks */ = {isa = PBXBuildFile; productRef = FB3894ED2577F8B40025252E /* PINRemoteImage */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + FB3894C92577F22F0025252E /* Example-Xcode-SPM.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Example-Xcode-SPM.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + FB3894CC2577F22F0025252E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + FB3894CE2577F22F0025252E /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + FB3894D02577F22F0025252E /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + FB3894D32577F22F0025252E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + FB3894D52577F2300025252E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + FB3894D82577F2300025252E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + FB3894DA2577F2300025252E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + FB3894EB2577F8960025252E /* PINRemoteImage */ = {isa = PBXFileReference; lastKnownFileType = folder; name = PINRemoteImage; path = ../../..; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + FB3894C62577F22F0025252E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + FB3894EE2577F8B40025252E /* PINRemoteImage in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + FB3894C02577F22F0025252E = { + isa = PBXGroup; + children = ( + FB3894CB2577F22F0025252E /* Example-Xcode-SPM */, + FB3894CA2577F22F0025252E /* Products */, + FB3894E42577F4490025252E /* Frameworks */, + ); + sourceTree = ""; + }; + FB3894CA2577F22F0025252E /* Products */ = { + isa = PBXGroup; + children = ( + FB3894C92577F22F0025252E /* Example-Xcode-SPM.app */, + ); + name = Products; + sourceTree = ""; + }; + FB3894CB2577F22F0025252E /* Example-Xcode-SPM */ = { + isa = PBXGroup; + children = ( + FB3894EB2577F8960025252E /* PINRemoteImage */, + FB3894CC2577F22F0025252E /* AppDelegate.swift */, + FB3894CE2577F22F0025252E /* SceneDelegate.swift */, + FB3894D02577F22F0025252E /* ViewController.swift */, + FB3894D22577F22F0025252E /* Main.storyboard */, + FB3894D52577F2300025252E /* Assets.xcassets */, + FB3894D72577F2300025252E /* LaunchScreen.storyboard */, + FB3894DA2577F2300025252E /* Info.plist */, + ); + path = "Example-Xcode-SPM"; + sourceTree = ""; + }; + FB3894E42577F4490025252E /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + FB3894C82577F22F0025252E /* Example-Xcode-SPM */ = { + isa = PBXNativeTarget; + buildConfigurationList = FB3894DD2577F2300025252E /* Build configuration list for PBXNativeTarget "Example-Xcode-SPM" */; + buildPhases = ( + FB3894C52577F22F0025252E /* Sources */, + FB3894C62577F22F0025252E /* Frameworks */, + FB3894C72577F22F0025252E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Example-Xcode-SPM"; + packageProductDependencies = ( + FB3894ED2577F8B40025252E /* PINRemoteImage */, + ); + productName = "Example-Xcode-SPM"; + productReference = FB3894C92577F22F0025252E /* Example-Xcode-SPM.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + FB3894C12577F22F0025252E /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1220; + LastUpgradeCheck = 1220; + TargetAttributes = { + FB3894C82577F22F0025252E = { + CreatedOnToolsVersion = 12.2; + }; + }; + }; + buildConfigurationList = FB3894C42577F22F0025252E /* Build configuration list for PBXProject "Example-Xcode-SPM" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = FB3894C02577F22F0025252E; + productRefGroup = FB3894CA2577F22F0025252E /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + FB3894C82577F22F0025252E /* Example-Xcode-SPM */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + FB3894C72577F22F0025252E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 843037332A01C67500914266 /* PINRemoteImage in Resources */, + FB3894D92577F2300025252E /* LaunchScreen.storyboard in Resources */, + FB3894D62577F2300025252E /* Assets.xcassets in Resources */, + FB3894D42577F22F0025252E /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + FB3894C52577F22F0025252E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FB3894D12577F22F0025252E /* ViewController.swift in Sources */, + FB3894CD2577F22F0025252E /* AppDelegate.swift in Sources */, + FB3894CF2577F22F0025252E /* SceneDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + FB3894D22577F22F0025252E /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + FB3894D32577F22F0025252E /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + FB3894D72577F2300025252E /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + FB3894D82577F2300025252E /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + FB3894DB2577F2300025252E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.2; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + FB3894DC2577F2300025252E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.2; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + FB3894DE2577F2300025252E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = "Example-Xcode-SPM/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "pinterest.Example-Xcode-SPM"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + FB3894DF2577F2300025252E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = "Example-Xcode-SPM/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "pinterest.Example-Xcode-SPM"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + FB3894C42577F22F0025252E /* Build configuration list for PBXProject "Example-Xcode-SPM" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FB3894DB2577F2300025252E /* Debug */, + FB3894DC2577F2300025252E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FB3894DD2577F2300025252E /* Build configuration list for PBXNativeTarget "Example-Xcode-SPM" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FB3894DE2577F2300025252E /* Debug */, + FB3894DF2577F2300025252E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCSwiftPackageProductDependency section */ + FB3894ED2577F8B40025252E /* PINRemoteImage */ = { + isa = XCSwiftPackageProductDependency; + productName = PINRemoteImage; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = FB3894C12577F22F0025252E /* Project object */; +} diff --git a/Examples/Example-Xcode-SPM/Example-Xcode-SPM.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/Example-Xcode-SPM/Example-Xcode-SPM.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/Examples/Example-Xcode-SPM/Example-Xcode-SPM.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Examples/Example-Xcode-SPM/Example-Xcode-SPM.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Examples/Example-Xcode-SPM/Example-Xcode-SPM.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Examples/Example-Xcode-SPM/Example-Xcode-SPM.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Examples/Example-Xcode-SPM/Example-Xcode-SPM/AppDelegate.swift b/Examples/Example-Xcode-SPM/Example-Xcode-SPM/AppDelegate.swift new file mode 100644 index 00000000..911aa4ea --- /dev/null +++ b/Examples/Example-Xcode-SPM/Example-Xcode-SPM/AppDelegate.swift @@ -0,0 +1,36 @@ +// +// AppDelegate.swift +// Example-Xcode-SPM +// +// Created by Petro Rovenskyy on 02.12.2020. +// + +import UIKit + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + return true + } + + // MARK: UISceneSession Lifecycle + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } + + func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they will not return. + } + + +} + diff --git a/Examples/Example-Xcode-SPM/Example-Xcode-SPM/Assets.xcassets/AccentColor.colorset/Contents.json b/Examples/Example-Xcode-SPM/Example-Xcode-SPM/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/Examples/Example-Xcode-SPM/Example-Xcode-SPM/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Examples/Example-Xcode-SPM/Example-Xcode-SPM/Assets.xcassets/AppIcon.appiconset/Contents.json b/Examples/Example-Xcode-SPM/Example-Xcode-SPM/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..9221b9bb --- /dev/null +++ b/Examples/Example-Xcode-SPM/Example-Xcode-SPM/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Examples/Example-Xcode-SPM/Example-Xcode-SPM/Assets.xcassets/Contents.json b/Examples/Example-Xcode-SPM/Example-Xcode-SPM/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/Examples/Example-Xcode-SPM/Example-Xcode-SPM/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Examples/Example-Xcode-SPM/Example-Xcode-SPM/Base.lproj/LaunchScreen.storyboard b/Examples/Example-Xcode-SPM/Example-Xcode-SPM/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000..865e9329 --- /dev/null +++ b/Examples/Example-Xcode-SPM/Example-Xcode-SPM/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/Example-Xcode-SPM/Example-Xcode-SPM/Base.lproj/Main.storyboard b/Examples/Example-Xcode-SPM/Example-Xcode-SPM/Base.lproj/Main.storyboard new file mode 100644 index 00000000..17984893 --- /dev/null +++ b/Examples/Example-Xcode-SPM/Example-Xcode-SPM/Base.lproj/Main.storyboard @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/Example-Xcode-SPM/Example-Xcode-SPM/Info.plist b/Examples/Example-Xcode-SPM/Example-Xcode-SPM/Info.plist new file mode 100644 index 00000000..5b531f7b --- /dev/null +++ b/Examples/Example-Xcode-SPM/Example-Xcode-SPM/Info.plist @@ -0,0 +1,66 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + + UIApplicationSupportsIndirectInputEvents + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Examples/Example-Xcode-SPM/Example-Xcode-SPM/SceneDelegate.swift b/Examples/Example-Xcode-SPM/Example-Xcode-SPM/SceneDelegate.swift new file mode 100644 index 00000000..e25f3342 --- /dev/null +++ b/Examples/Example-Xcode-SPM/Example-Xcode-SPM/SceneDelegate.swift @@ -0,0 +1,52 @@ +// +// SceneDelegate.swift +// Example-Xcode-SPM +// +// Created by Petro Rovenskyy on 02.12.2020. +// + +import UIKit + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. + // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. + // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). + guard let _ = (scene as? UIWindowScene) else { return } + } + + func sceneDidDisconnect(_ scene: UIScene) { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + // Release any resources associated with this scene that can be re-created the next time the scene connects. + // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). + } + + func sceneDidBecomeActive(_ scene: UIScene) { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + } + + func sceneWillResignActive(_ scene: UIScene) { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + } + + func sceneWillEnterForeground(_ scene: UIScene) { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. + } + + func sceneDidEnterBackground(_ scene: UIScene) { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // to restore the scene back to its current state. + } + + +} + diff --git a/Examples/Example-Xcode-SPM/Example-Xcode-SPM/ViewController.swift b/Examples/Example-Xcode-SPM/Example-Xcode-SPM/ViewController.swift new file mode 100644 index 00000000..d548ce53 --- /dev/null +++ b/Examples/Example-Xcode-SPM/Example-Xcode-SPM/ViewController.swift @@ -0,0 +1,31 @@ +// +// ViewController.swift +// Example-Xcode-SPM +// +// Created by Petro Rovenskyy on 02.12.2020. +// + +import UIKit +import PINRemoteImage + +class ViewController: UIViewController { + @IBOutlet weak var info: UILabel! + @IBOutlet weak var imgView: PINAnimatedImageView! + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view. + self.info.text = "PINRemoteImage+SPM+Xcode=🥰" + self.imgView.pin_updateWithProgress = true + } + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + guard let imageURL = URL(string: "https://i.pinimg.com/originals/f5/23/f1/f523f141646b613f78566ba964208990.gif") else { + return + } + self.imgView.pin_setImage(from: imageURL) + } + + +} + diff --git a/Examples/Example-tvOS/Example-tvOS.xcodeproj/project.pbxproj b/Examples/Example-tvOS/Example-tvOS.xcodeproj/project.pbxproj new file mode 100644 index 00000000..b4859100 --- /dev/null +++ b/Examples/Example-tvOS/Example-tvOS.xcodeproj/project.pbxproj @@ -0,0 +1,403 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 689613C9208FBC6B00D2095C /* GIFViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 689613C8208FBC6B00D2095C /* GIFViewController.swift */; }; + 689613CB208FBE3100D2095C /* WebPViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 689613CA208FBE3100D2095C /* WebPViewController.swift */; }; + 78699F481C668C8E0044C9E9 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78699F471C668C8E0044C9E9 /* AppDelegate.swift */; }; + 78699F4C1C668C8E0044C9E9 /* ProgressiveViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78699F4B1C668C8E0044C9E9 /* ProgressiveViewController.swift */; }; + 78699F4F1C668C8E0044C9E9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 78699F4D1C668C8E0044C9E9 /* Main.storyboard */; }; + 78699F511C668C8E0044C9E9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 78699F501C668C8E0044C9E9 /* Assets.xcassets */; }; + 78699F591C669AC70044C9E9 /* ProcessingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78699F581C669AC70044C9E9 /* ProcessingViewController.swift */; }; + 78699F5B1C66A5A90044C9E9 /* DegradedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78699F5A1C66A5A90044C9E9 /* DegradedViewController.swift */; }; + 78699F5D1C66A7E20044C9E9 /* CollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78699F5C1C66A7E20044C9E9 /* CollectionViewController.swift */; }; + 78699F5F1C66A8610044C9E9 /* CollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78699F5E1C66A8610044C9E9 /* CollectionViewCell.swift */; }; + C0AB4733C23AA355900F09E9 /* Pods_Example_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC3CA13FB1BD9E2682A1CCEF /* Pods_Example_tvOS.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 092ED8B731DCCEB16C919D24 /* Pods-Example-tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example-tvOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-Example-tvOS/Pods-Example-tvOS.release.xcconfig"; sourceTree = ""; }; + 093C3E4AE850337BCD0D2FE6 /* Pods-PINRemoteImage.tvOSExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PINRemoteImage.tvOSExample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample.debug.xcconfig"; sourceTree = ""; }; + 689613C8208FBC6B00D2095C /* GIFViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GIFViewController.swift; sourceTree = ""; }; + 689613CA208FBE3100D2095C /* WebPViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebPViewController.swift; sourceTree = ""; }; + 78699F441C668C8E0044C9E9 /* Example-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Example-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 78699F471C668C8E0044C9E9 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 78699F4B1C668C8E0044C9E9 /* ProgressiveViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressiveViewController.swift; sourceTree = ""; }; + 78699F4E1C668C8E0044C9E9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 78699F501C668C8E0044C9E9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 78699F521C668C8E0044C9E9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 78699F581C669AC70044C9E9 /* ProcessingViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProcessingViewController.swift; sourceTree = ""; }; + 78699F5A1C66A5A90044C9E9 /* DegradedViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DegradedViewController.swift; sourceTree = ""; }; + 78699F5C1C66A7E20044C9E9 /* CollectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionViewController.swift; sourceTree = ""; }; + 78699F5E1C66A8610044C9E9 /* CollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionViewCell.swift; sourceTree = ""; }; + AAF1AB8C026DF61369E568CC /* Pods-PINRemoteImage.tvOSExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PINRemoteImage.tvOSExample.release.xcconfig"; path = "Pods/Target Support Files/Pods-PINRemoteImage.tvOSExample/Pods-PINRemoteImage.tvOSExample.release.xcconfig"; sourceTree = ""; }; + AB405D54A079CA1CF3D77696 /* Pods-Example-tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example-tvOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Example-tvOS/Pods-Example-tvOS.debug.xcconfig"; sourceTree = ""; }; + BC3CA13FB1BD9E2682A1CCEF /* Pods_Example_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Example_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 78699F411C668C8E0044C9E9 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C0AB4733C23AA355900F09E9 /* Pods_Example_tvOS.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 717A14585C13E19AFD257717 /* Frameworks */ = { + isa = PBXGroup; + children = ( + BC3CA13FB1BD9E2682A1CCEF /* Pods_Example_tvOS.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 78699F3B1C668C8E0044C9E9 = { + isa = PBXGroup; + children = ( + 78699F461C668C8E0044C9E9 /* PINRemoteImage.tvOSExample */, + 78699F451C668C8E0044C9E9 /* Products */, + 91B09A3FE05D54DA24016146 /* Pods */, + 717A14585C13E19AFD257717 /* Frameworks */, + ); + sourceTree = ""; + }; + 78699F451C668C8E0044C9E9 /* Products */ = { + isa = PBXGroup; + children = ( + 78699F441C668C8E0044C9E9 /* Example-tvOS.app */, + ); + name = Products; + sourceTree = ""; + }; + 78699F461C668C8E0044C9E9 /* PINRemoteImage.tvOSExample */ = { + isa = PBXGroup; + children = ( + 78699F501C668C8E0044C9E9 /* Assets.xcassets */, + 78699F521C668C8E0044C9E9 /* Info.plist */, + 78699F471C668C8E0044C9E9 /* AppDelegate.swift */, + 78699F4D1C668C8E0044C9E9 /* Main.storyboard */, + 78699F4B1C668C8E0044C9E9 /* ProgressiveViewController.swift */, + 78699F581C669AC70044C9E9 /* ProcessingViewController.swift */, + 78699F5A1C66A5A90044C9E9 /* DegradedViewController.swift */, + 78699F5C1C66A7E20044C9E9 /* CollectionViewController.swift */, + 78699F5E1C66A8610044C9E9 /* CollectionViewCell.swift */, + 689613C8208FBC6B00D2095C /* GIFViewController.swift */, + 689613CA208FBE3100D2095C /* WebPViewController.swift */, + ); + path = PINRemoteImage.tvOSExample; + sourceTree = ""; + }; + 91B09A3FE05D54DA24016146 /* Pods */ = { + isa = PBXGroup; + children = ( + 093C3E4AE850337BCD0D2FE6 /* Pods-PINRemoteImage.tvOSExample.debug.xcconfig */, + AAF1AB8C026DF61369E568CC /* Pods-PINRemoteImage.tvOSExample.release.xcconfig */, + AB405D54A079CA1CF3D77696 /* Pods-Example-tvOS.debug.xcconfig */, + 092ED8B731DCCEB16C919D24 /* Pods-Example-tvOS.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 78699F431C668C8E0044C9E9 /* Example-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 78699F551C668C8E0044C9E9 /* Build configuration list for PBXNativeTarget "Example-tvOS" */; + buildPhases = ( + FA9E035135C48FB08841B4A3 /* [CP] Check Pods Manifest.lock */, + 78699F401C668C8E0044C9E9 /* Sources */, + 78699F411C668C8E0044C9E9 /* Frameworks */, + 78699F421C668C8E0044C9E9 /* Resources */, + 8B150830C60182EB93A19C74 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Example-tvOS"; + productName = PINRemoteImage.tvOSExample; + productReference = 78699F441C668C8E0044C9E9 /* Example-tvOS.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 78699F3C1C668C8E0044C9E9 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0910; + TargetAttributes = { + 78699F431C668C8E0044C9E9 = { + CreatedOnToolsVersion = 7.2.1; + LastSwiftMigration = 0910; + }; + }; + }; + buildConfigurationList = 78699F3F1C668C8E0044C9E9 /* Build configuration list for PBXProject "Example-tvOS" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + English, + en, + Base, + ); + mainGroup = 78699F3B1C668C8E0044C9E9; + productRefGroup = 78699F451C668C8E0044C9E9 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 78699F431C668C8E0044C9E9 /* Example-tvOS */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 78699F421C668C8E0044C9E9 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 78699F511C668C8E0044C9E9 /* Assets.xcassets in Resources */, + 78699F4F1C668C8E0044C9E9 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 8B150830C60182EB93A19C74 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Example-tvOS/Pods-Example-tvOS-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/PINOperation/PINOperation.framework", + "${BUILT_PRODUCTS_DIR}/PINRemoteImage/PINRemoteImage.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PINOperation.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PINRemoteImage.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Example-tvOS/Pods-Example-tvOS-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + FA9E035135C48FB08841B4A3 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Example-tvOS-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 78699F401C668C8E0044C9E9 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 689613CB208FBE3100D2095C /* WebPViewController.swift in Sources */, + 78699F5D1C66A7E20044C9E9 /* CollectionViewController.swift in Sources */, + 78699F4C1C668C8E0044C9E9 /* ProgressiveViewController.swift in Sources */, + 78699F591C669AC70044C9E9 /* ProcessingViewController.swift in Sources */, + 78699F5F1C66A8610044C9E9 /* CollectionViewCell.swift in Sources */, + 689613C9208FBC6B00D2095C /* GIFViewController.swift in Sources */, + 78699F481C668C8E0044C9E9 /* AppDelegate.swift in Sources */, + 78699F5B1C66A5A90044C9E9 /* DegradedViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 78699F4D1C668C8E0044C9E9 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 78699F4E1C668C8E0044C9E9 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 78699F531C668C8E0044C9E9 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = appletvos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 9.1; + }; + name = Debug; + }; + 78699F541C668C8E0044C9E9 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = appletvos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 9.1; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 78699F561C668C8E0044C9E9 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AB405D54A079CA1CF3D77696 /* Pods-Example-tvOS.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + INFOPLIST_FILE = PINRemoteImage.tvOSExample/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.PINRemoteImage-tvOSExample"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; + TVOS_DEPLOYMENT_TARGET = 14.0; + }; + name = Debug; + }; + 78699F571C668C8E0044C9E9 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 092ED8B731DCCEB16C919D24 /* Pods-Example-tvOS.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + INFOPLIST_FILE = PINRemoteImage.tvOSExample/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.PINRemoteImage-tvOSExample"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; + TVOS_DEPLOYMENT_TARGET = 14.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 78699F3F1C668C8E0044C9E9 /* Build configuration list for PBXProject "Example-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 78699F531C668C8E0044C9E9 /* Debug */, + 78699F541C668C8E0044C9E9 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 78699F551C668C8E0044C9E9 /* Build configuration list for PBXNativeTarget "Example-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 78699F561C668C8E0044C9E9 /* Debug */, + 78699F571C668C8E0044C9E9 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 78699F3C1C668C8E0044C9E9 /* Project object */; +} diff --git a/Example-tvOS/PINRemoteImage.tvOSExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/Example-tvOS/Example-tvOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to Examples/Example-tvOS/Example-tvOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/Examples/Example-tvOS/Example-tvOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Examples/Example-tvOS/Example-tvOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Examples/Example-tvOS/Example-tvOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Examples/Example-tvOS/Example-tvOS.xcworkspace/contents.xcworkspacedata b/Examples/Example-tvOS/Example-tvOS.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..72403e9e --- /dev/null +++ b/Examples/Example-tvOS/Example-tvOS.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Examples/Example-tvOS/Example-tvOS.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Examples/Example-tvOS/Example-tvOS.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Examples/Example-tvOS/Example-tvOS.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Examples/Example-tvOS/PINRemoteImage.tvOSExample/AppDelegate.swift b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/AppDelegate.swift new file mode 100644 index 00000000..843bb0a1 --- /dev/null +++ b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/AppDelegate.swift @@ -0,0 +1,43 @@ +// +// AppDelegate.swift +// PINRemoteImage.tvOSExample +// +// Created by Isaac Overacker on 2/6/16. +// +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool { + // Override point for customization after application launch. + return true + } + func applicationWillResignActive(_ application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(_ application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(_ application: UIApplication) { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(_ application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(_ application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + +} + diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json rename to Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Contents.json b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Contents.json similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Contents.json rename to Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Contents.json diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Contents.json b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Contents.json similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Contents.json rename to Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Contents.json diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json rename to Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Contents.json b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Contents.json similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Contents.json rename to Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Contents.json diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json rename to Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Contents.json b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Contents.json similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Contents.json rename to Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Contents.json diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json rename to Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Contents.json b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Contents.json similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Contents.json rename to Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Contents.json diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Contents.json b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Contents.json similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Contents.json rename to Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Contents.json diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json rename to Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Contents.json b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Contents.json similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Contents.json rename to Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Contents.json diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json rename to Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Contents.json b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Contents.json similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Contents.json rename to Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Contents.json diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json rename to Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json rename to Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/Contents.json b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/Contents.json similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/Contents.json rename to Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/Contents.json diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/LaunchImage.launchimage/Contents.json b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/LaunchImage.launchimage/Contents.json similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/LaunchImage.launchimage/Contents.json rename to Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/LaunchImage.launchimage/Contents.json diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/white-pinterest-logo.imageset/Contents.json b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/white-pinterest-logo.imageset/Contents.json similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/white-pinterest-logo.imageset/Contents.json rename to Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/white-pinterest-logo.imageset/Contents.json diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@1x.png b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@1x.png similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@1x.png rename to Examples/Example-tvOS/PINRemoteImage.tvOSExample/Assets.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@1x.png diff --git a/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Base.lproj/Main.storyboard b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Base.lproj/Main.storyboard new file mode 100644 index 00000000..90039622 --- /dev/null +++ b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Base.lproj/Main.storyboard @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/CollectionViewCell.swift b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/CollectionViewCell.swift similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample/CollectionViewCell.swift rename to Examples/Example-tvOS/PINRemoteImage.tvOSExample/CollectionViewCell.swift diff --git a/Examples/Example-tvOS/PINRemoteImage.tvOSExample/CollectionViewController.swift b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/CollectionViewController.swift new file mode 100644 index 00000000..7c56fbe2 --- /dev/null +++ b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/CollectionViewController.swift @@ -0,0 +1,65 @@ +// +// CollectionViewController.swift +// PINRemoteImage.tvOSExample +// +// Created by Isaac Overacker on 2/6/16. +// +// + +import UIKit +import PINRemoteImage + +private let reuseIdentifier = "Cell" + +class CollectionViewController: UICollectionViewController { + + let kittenURLs = [ + URL(string: "https://i.pinimg.com/736x/92/5d/5a/925d5ac74db0dcfabc238e1686e31d16.jpg"), + URL(string: "https://i.pinimg.com/736x/ff/b3/ae/ffb3ae40533b7f9463cf1c04d7ab69d1.jpg"), + URL(string: "https://i.pinimg.com/736x/e4/b7/7c/e4b77ca06e1d4a401b1a49d7fadd90d9.jpg"), + URL(string: "https://i.pinimg.com/736x/46/e1/59/46e159d76b167ed9211d662f95e7bf6f.jpg"), + URL(string: "https://i.pinimg.com/736x/7a/72/77/7a72779329942c06f888c148eb8d7e34.jpg"), + URL(string: "https://i.pinimg.com/736x/60/21/8f/60218ff43257fb3b6d7c5b888f74a5bf.jpg"), + URL(string: "https://i.pinimg.com/736x/90/e8/e4/90e8e47d53e71e0d97691dd13a5617fb.jpg"), + URL(string: "https://i.pinimg.com/736x/96/ae/31/96ae31fbc52d96dd3308d2754a6ca37e.jpg"), + URL(string: "https://i.pinimg.com/736x/9b/7b/99/9b7b99ff63be31bba8f9863724b3ebbc.jpg"), + URL(string: "https://i.pinimg.com/736x/80/23/51/802351d953dd2a8b232d0da1c7ca6880.jpg"), + URL(string: "https://i.pinimg.com/736x/f5/c4/f0/f5c4f04fa2686338dc3b08420d198484.jpg"), + URL(string: "https://i.pinimg.com/736x/2b/06/4f/2b064f3e0af984a556ac94b251ff7060.jpg"), + URL(string: "https://i.pinimg.com/736x/17/1f/c0/171fc02398143269d8a507a15563166a.jpg"), + URL(string: "https://i.pinimg.com/736x/8a/35/33/8a35338bbf67c86a198ba2dd926edd82.jpg"), + URL(string: "https://i.pinimg.com/736x/4d/6e/3c/4d6e3cf970031116c57486e85c2a4cab.jpg"), + URL(string: "https://i.pinimg.com/736x/54/25/ee/5425eeccba78731cf7be70f0b8808bd2.jpg"), + URL(string: "https://i.pinimg.com/736x/04/f1/3f/04f13fdb7580dcbe8c4d6b7d5a0a5ec2.jpg"), + URL(string: "https://i.pinimg.com/736x/dc/16/4e/dc164ed33af9d899e5ed188e642f00e9.jpg"), + URL(string: "https://i.pinimg.com/736x/c1/06/13/c106132936189b6cb654671f2a2183ed.jpg"), + URL(string: "https://i.pinimg.com/736x/46/43/ed/4643eda4e1be4273721a76a370b90346.jpg") + ] + + override func viewDidLoad() { + super.viewDidLoad() + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + // MARK: UICollectionViewDataSource + + override func numberOfSections(in collectionView: UICollectionView) -> Int { + return 1 + } + + + override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return kittenURLs.count + } + + override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! CollectionViewCell + cell.imageView.pin_setImage(from: kittenURLs[indexPath.row]) + return cell + } + +} diff --git a/Examples/Example-tvOS/PINRemoteImage.tvOSExample/DegradedViewController.swift b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/DegradedViewController.swift new file mode 100644 index 00000000..aceb5e80 --- /dev/null +++ b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/DegradedViewController.swift @@ -0,0 +1,35 @@ +// +// DegradedViewController.swift +// PINRemoteImage.tvOSExample +// +// Created by Isaac Overacker on 2/6/16. +// +// + +import UIKit +import PINRemoteImage + +class DegradedViewController: UIViewController { + + @IBOutlet weak var imageView: UIImageView! + + override func viewDidLoad() { + super.viewDidLoad() + PINRemoteImageManager.shared().setShouldUpgradeLowQualityImages(true, completion: nil) + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + imageView.pin_setImage(from: [ + URL(string: "https://loremflickr.com/101/101")!, + URL(string: "https://loremflickr.com/401/401")!, + URL(string: "https://loremflickr.com/801/801")! + ]) + } +} diff --git a/Examples/Example-tvOS/PINRemoteImage.tvOSExample/GIFViewController.swift b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/GIFViewController.swift new file mode 100644 index 00000000..cf6e10ee --- /dev/null +++ b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/GIFViewController.swift @@ -0,0 +1,20 @@ +// +// GIFViewController.swift +// PINRemoteImage.tvOSExample +// +// Created by Garrett Moon on 4/24/18. +// + +import UIKit +import PINRemoteImage + +class GIFViewController: UIViewController { + + @IBOutlet weak var imageView: PINAnimatedImageView! + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + imageView.pin_setImage(from: URL(string: "https://i.pinimg.com/originals/f5/23/f1/f523f141646b613f78566ba964208990.gif")) + } +} diff --git a/Example-tvOS/PINRemoteImage.tvOSExample/Info.plist b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/Info.plist similarity index 100% rename from Example-tvOS/PINRemoteImage.tvOSExample/Info.plist rename to Examples/Example-tvOS/PINRemoteImage.tvOSExample/Info.plist diff --git a/Examples/Example-tvOS/PINRemoteImage.tvOSExample/ProcessingViewController.swift b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/ProcessingViewController.swift new file mode 100644 index 00000000..5e7cc147 --- /dev/null +++ b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/ProcessingViewController.swift @@ -0,0 +1,75 @@ +// +// ProcessingViewController.swift +// PINRemoteImage.tvOSExample +// +// Created by Isaac Overacker on 2/6/16. +// +// + +import UIKit +import PINRemoteImage + +class ProcessingViewController: UIViewController { + + @IBOutlet weak var imageView: UIImageView! + + override func viewDidLoad() { + super.viewDidLoad() + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + if let url = URL(string: "https://i.pinimg.com/1200x/2e/0c/c5/2e0cc5d86e7b7cd42af225c29f21c37f.jpg") { + imageView.pin_setImage(from: url, + processorKey: "rounded", + processor: { (result, cost) -> UIImage? in + if let image = result.image { + let radius = CGFloat(7.0) + let targetSize = CGSize(width: 200, height: 300) + let imageRect = CGRect(x: 0, y: 0, width: targetSize.width, height: targetSize.height) + UIGraphicsBeginImageContext(imageRect.size) + let bezierPath = UIBezierPath(roundedRect: imageRect, cornerRadius: radius) + bezierPath.addClip() + + let widthMultiplier = CGFloat(targetSize.width / image.size.width) + let heightMultiplier = CGFloat(targetSize.height / image.size.height) + let sizeMultiplier = max(widthMultiplier, heightMultiplier) + + var drawRect = CGRect(x: 0, y: 0, width: image.size.width * sizeMultiplier, height: image.size.height * sizeMultiplier) + if drawRect.maxX > imageRect.maxX { + drawRect.origin.x -= (drawRect.maxX - imageRect.maxX) / 2.0 + } + if drawRect.maxY > imageRect.maxY { + drawRect.origin.y -= (drawRect.maxY - imageRect.maxY) / 2.0 + } + + image.draw(in: drawRect) + + UIColor.red.setStroke() + bezierPath.lineWidth = 5.0 + bezierPath.stroke() + + let ctx = UIGraphicsGetCurrentContext()! + ctx.setBlendMode(.overlay) + ctx.setAlpha(0.5) + + if let logo = UIImage(named: "white-pinterest-logo") { + logo.draw(in: CGRect(x: 0, y: drawRect.size.height - logo.size.height, width: logo.size.width, height: logo.size.height)) + } + + let processedImage = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + return processedImage + } + + return nil + }) + } + } +} diff --git a/Examples/Example-tvOS/PINRemoteImage.tvOSExample/ProgressiveViewController.swift b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/ProgressiveViewController.swift new file mode 100644 index 00000000..0d2d2334 --- /dev/null +++ b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/ProgressiveViewController.swift @@ -0,0 +1,50 @@ +// +// ProgressiveViewController.swift +// PINRemoteImage.tvOSExample +// +// Created by Isaac Overacker on 2/6/16. +// +// + +import UIKit +import PINRemoteImage + +class ProgressiveViewController: UIViewController { + + @IBOutlet weak var imageView: UIImageView! + + override func viewDidLoad() { + super.viewDidLoad() + imageView.pin_updateWithProgress = true + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + if let url = URL(string: "https://i.pinimg.com/1200x/2e/0c/c5/2e0cc5d86e7b7cd42af225c29f21c37f.jpg") { + PINRemoteImageManager.shared().setProgressThresholds([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9], completion: nil) + + imageView.pin_setImage(from: url) + + var progress = [UIImage]() + PINRemoteImageManager.shared().downloadImage(with: url, + options: [], + progressImage: { result in + if let image = result.image { + progress.append(image) + } + }, completion: { result in + if let image = result.image { + progress.append(image) + } + }) + } + } + +} + diff --git a/Examples/Example-tvOS/PINRemoteImage.tvOSExample/WebPViewController.swift b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/WebPViewController.swift new file mode 100644 index 00000000..0b8c1bea --- /dev/null +++ b/Examples/Example-tvOS/PINRemoteImage.tvOSExample/WebPViewController.swift @@ -0,0 +1,20 @@ +// +// WebPViewController.swift +// PINRemoteImage.tvOSExample +// +// Created by Garrett Moon on 4/24/18. +// + +import UIKit +import PINRemoteImage + +class WebPViewController: UIViewController { + + @IBOutlet weak var imageView: UIImageView! + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + imageView.pin_setImage(from: URL(string: "https://raw.githubusercontent.com/samdutton/simpl/main/picturetype/kittens.webp")) + } +} diff --git a/Examples/Example-tvOS/Podfile b/Examples/Example-tvOS/Podfile new file mode 100644 index 00000000..39241db4 --- /dev/null +++ b/Examples/Example-tvOS/Podfile @@ -0,0 +1,7 @@ +use_frameworks! + +platform :tvos, 14.0 + +target 'Example-tvOS' do + pod "PINRemoteImage/iOS", :path => "../../" +end diff --git a/Examples/Example-tvOS/Podfile.lock b/Examples/Example-tvOS/Podfile.lock new file mode 100644 index 00000000..4994a9b0 --- /dev/null +++ b/Examples/Example-tvOS/Podfile.lock @@ -0,0 +1,25 @@ +PODS: + - PINOperation (1.2.3) + - PINRemoteImage/Core (3.0.4): + - PINOperation + - PINRemoteImage/iOS (3.0.4): + - PINRemoteImage/Core + +DEPENDENCIES: + - PINRemoteImage/iOS (from `../../`) + +SPEC REPOS: + trunk: + - PINOperation + +EXTERNAL SOURCES: + PINRemoteImage: + :path: "../../" + +SPEC CHECKSUMS: + PINOperation: fb563bcc9c32c26d6c78aaff967d405aa2ee74a7 + PINRemoteImage: 6256a644f4996991f124811763c7286b2a63ff94 + +PODFILE CHECKSUM: 92fdbb41115684253472b196b5b53ee177e9f4b9 + +COCOAPODS: 1.15.2 diff --git a/Examples/Example/Example.xcodeproj/project.pbxproj b/Examples/Example/Example.xcodeproj/project.pbxproj new file mode 100644 index 00000000..2339aafd --- /dev/null +++ b/Examples/Example/Example.xcodeproj/project.pbxproj @@ -0,0 +1,491 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 0CF0743224093090008F126B /* APNGViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF0743124093090008F126B /* APNGViewController.m */; }; + 2B38B1CD5C8E405102293255 /* libPods-Example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3FA9AA7E6E87DBD4CB132A1F /* libPods-Example.a */; }; + 447F707A2BF4F80900C5C956 /* AnimatedWebPViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 447F70792BF4F80900C5C956 /* AnimatedWebPViewController.m */; }; + 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; + 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58F195388D20070C39A /* CoreGraphics.framework */; }; + 6003F592195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; + 6003F598195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F596195388D20070C39A /* InfoPlist.strings */; }; + 6003F59A195388D20070C39A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F599195388D20070C39A /* main.m */; }; + 6003F59E195388D20070C39A /* PINAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F59D195388D20070C39A /* PINAppDelegate.m */; }; + 6003F5A1195388D20070C39A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6003F59F195388D20070C39A /* Main.storyboard */; }; + 6003F5A7195388D20070C39A /* PINViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5A6195388D20070C39A /* PINViewController.m */; }; + 6003F5A9195388D20070C39A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5A8195388D20070C39A /* Images.xcassets */; }; + 682C52611B584DD300B3B813 /* ProcessingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 682C52601B584DD300B3B813 /* ProcessingViewController.m */; }; + 682C52671B58515D00B3B813 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 682C52661B58515D00B3B813 /* Media.xcassets */; }; + 687666B920869C82001E825C /* GIFViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 687666B820869C82001E825C /* GIFViewController.m */; }; + 68B385081B557116004EB26F /* WebPViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 68B385071B557116004EB26F /* WebPViewController.m */; }; + 68B3850B1B5572BF004EB26F /* ProgressiveViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 68B3850A1B5572BF004EB26F /* ProgressiveViewController.m */; }; + 68B3850E1B5577D4004EB26F /* DegradedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 68B3850D1B5577D4004EB26F /* DegradedViewController.m */; }; + 9D9328E51C3D4CC200E1F1D3 /* Kitten.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9328E41C3D4CC200E1F1D3 /* Kitten.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 063FF605A6CC8884BB10EE35 /* Pods-PINRemoteImage Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PINRemoteImage Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests.debug.xcconfig"; sourceTree = ""; }; + 0CF0743024093090008F126B /* APNGViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APNGViewController.h; sourceTree = ""; }; + 0CF0743124093090008F126B /* APNGViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = APNGViewController.m; sourceTree = ""; }; + 25CF9DB8CF954119BAA63004 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; + 32A377E2A670E405B928B26E /* Pods-Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Example/Pods-Example.debug.xcconfig"; sourceTree = ""; }; + 3FA9AA7E6E87DBD4CB132A1F /* libPods-Example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Example.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 447F70782BF4F80900C5C956 /* AnimatedWebPViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AnimatedWebPViewController.h; sourceTree = ""; }; + 447F70792BF4F80900C5C956 /* AnimatedWebPViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AnimatedWebPViewController.m; sourceTree = ""; }; + 500C3EFB07D23E183AC04C5D /* Pods-Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-Example/Pods-Example.release.xcconfig"; sourceTree = ""; }; + 5A85B7779305DF163437777D /* libPods-PINRemoteImage Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PINRemoteImage Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6003F58A195388D20070C39A /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 6003F591195388D20070C39A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 6003F595195388D20070C39A /* PINRemoteImage-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "PINRemoteImage-Info.plist"; sourceTree = ""; }; + 6003F597195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 6003F599195388D20070C39A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6003F59C195388D20070C39A /* PINAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PINAppDelegate.h; sourceTree = ""; }; + 6003F59D195388D20070C39A /* PINAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PINAppDelegate.m; sourceTree = ""; }; + 6003F5A0195388D20070C39A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6003F5A5195388D20070C39A /* PINViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PINViewController.h; sourceTree = ""; }; + 6003F5A6195388D20070C39A /* PINViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PINViewController.m; sourceTree = ""; }; + 6003F5A8195388D20070C39A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6003F5AF195388D20070C39A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + 6008DA13D004B38845BA74EC /* Pods-PINRemoteImage Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PINRemoteImage Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-PINRemoteImage Tests/Pods-PINRemoteImage Tests.release.xcconfig"; sourceTree = ""; }; + 682C525F1B584DD300B3B813 /* ProcessingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessingViewController.h; sourceTree = ""; }; + 682C52601B584DD300B3B813 /* ProcessingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProcessingViewController.m; sourceTree = ""; }; + 682C52661B58515D00B3B813 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Media.xcassets; path = PINRemoteImage/Media.xcassets; sourceTree = SOURCE_ROOT; }; + 687666B720869C82001E825C /* GIFViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GIFViewController.h; sourceTree = ""; }; + 687666B820869C82001E825C /* GIFViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GIFViewController.m; sourceTree = ""; }; + 68B385061B557116004EB26F /* WebPViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPViewController.h; sourceTree = ""; }; + 68B385071B557116004EB26F /* WebPViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebPViewController.m; sourceTree = ""; }; + 68B385091B5572BF004EB26F /* ProgressiveViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProgressiveViewController.h; sourceTree = ""; }; + 68B3850A1B5572BF004EB26F /* ProgressiveViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProgressiveViewController.m; sourceTree = ""; }; + 68B3850C1B5577D4004EB26F /* DegradedViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DegradedViewController.h; sourceTree = ""; }; + 68B3850D1B5577D4004EB26F /* DegradedViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DegradedViewController.m; sourceTree = ""; }; + 68B5CDF01A0BEC8C00A4BAAC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 68B5CDF11A0BEC8C00A4BAAC /* PINRemoteImage_Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImage_Tests.m; sourceTree = ""; }; + 8D571FD9970F7A64A2B80EE0 /* Pods-PINRemoteImage.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PINRemoteImage.release.xcconfig"; path = "Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage.release.xcconfig"; sourceTree = ""; }; + 95043F8A31505C02E51C4D2F /* Pods-PINRemoteImage.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PINRemoteImage.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PINRemoteImage/Pods-PINRemoteImage.debug.xcconfig"; sourceTree = ""; }; + 9D9328E31C3D4CC200E1F1D3 /* Kitten.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Kitten.h; path = "../../Example-Shared/Kitten.h"; sourceTree = ""; }; + 9D9328E41C3D4CC200E1F1D3 /* Kitten.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Kitten.m; path = "../../Example-Shared/Kitten.m"; sourceTree = ""; }; + A5DEC9B706184109844D57E2 /* PINRemoteImage.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = PINRemoteImage.podspec; path = ../PINRemoteImage.podspec; sourceTree = ""; }; + E2B84DF860DF48B5B22537B6 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; + F30E394524AE56850067A777 /* PINRemoteImage copy-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "PINRemoteImage copy-Info.plist"; path = "/Users/garrettmoon/code/PINRemoteImage/Examples/Example/PINRemoteImage copy-Info.plist"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 6003F587195388D20070C39A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */, + 6003F592195388D20070C39A /* UIKit.framework in Frameworks */, + 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */, + 2B38B1CD5C8E405102293255 /* libPods-Example.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 6003F581195388D10070C39A = { + isa = PBXGroup; + children = ( + 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */, + 6003F593195388D20070C39A /* PINRemoteImage */, + 68B5CDEE1A0BEC8C00A4BAAC /* PINRemoteImage Tests */, + 6003F58C195388D20070C39A /* Frameworks */, + 6003F58B195388D20070C39A /* Products */, + F5A6BFF7672C3055495CF245 /* Pods */, + F30E394524AE56850067A777 /* PINRemoteImage copy-Info.plist */, + ); + sourceTree = ""; + }; + 6003F58B195388D20070C39A /* Products */ = { + isa = PBXGroup; + children = ( + 6003F58A195388D20070C39A /* Example.app */, + ); + name = Products; + sourceTree = ""; + }; + 6003F58C195388D20070C39A /* Frameworks */ = { + isa = PBXGroup; + children = ( + 6003F58D195388D20070C39A /* Foundation.framework */, + 6003F58F195388D20070C39A /* CoreGraphics.framework */, + 6003F591195388D20070C39A /* UIKit.framework */, + 6003F5AF195388D20070C39A /* XCTest.framework */, + 5A85B7779305DF163437777D /* libPods-PINRemoteImage Tests.a */, + 3FA9AA7E6E87DBD4CB132A1F /* libPods-Example.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + 6003F593195388D20070C39A /* PINRemoteImage */ = { + isa = PBXGroup; + children = ( + 9D9328E31C3D4CC200E1F1D3 /* Kitten.h */, + 9D9328E41C3D4CC200E1F1D3 /* Kitten.m */, + 6003F59C195388D20070C39A /* PINAppDelegate.h */, + 6003F59D195388D20070C39A /* PINAppDelegate.m */, + 6003F59F195388D20070C39A /* Main.storyboard */, + 6003F5A5195388D20070C39A /* PINViewController.h */, + 6003F5A6195388D20070C39A /* PINViewController.m */, + 6003F5A8195388D20070C39A /* Images.xcassets */, + 6003F594195388D20070C39A /* Supporting Files */, + 68B385061B557116004EB26F /* WebPViewController.h */, + 68B385071B557116004EB26F /* WebPViewController.m */, + 68B385091B5572BF004EB26F /* ProgressiveViewController.h */, + 682C52661B58515D00B3B813 /* Media.xcassets */, + 68B3850A1B5572BF004EB26F /* ProgressiveViewController.m */, + 68B3850C1B5577D4004EB26F /* DegradedViewController.h */, + 68B3850D1B5577D4004EB26F /* DegradedViewController.m */, + 682C525F1B584DD300B3B813 /* ProcessingViewController.h */, + 682C52601B584DD300B3B813 /* ProcessingViewController.m */, + 687666B720869C82001E825C /* GIFViewController.h */, + 687666B820869C82001E825C /* GIFViewController.m */, + 0CF0743024093090008F126B /* APNGViewController.h */, + 0CF0743124093090008F126B /* APNGViewController.m */, + 447F70782BF4F80900C5C956 /* AnimatedWebPViewController.h */, + 447F70792BF4F80900C5C956 /* AnimatedWebPViewController.m */, + ); + path = PINRemoteImage; + sourceTree = ""; + }; + 6003F594195388D20070C39A /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6003F595195388D20070C39A /* PINRemoteImage-Info.plist */, + 6003F596195388D20070C39A /* InfoPlist.strings */, + 6003F599195388D20070C39A /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */ = { + isa = PBXGroup; + children = ( + A5DEC9B706184109844D57E2 /* PINRemoteImage.podspec */, + E2B84DF860DF48B5B22537B6 /* README.md */, + 25CF9DB8CF954119BAA63004 /* LICENSE */, + ); + name = "Podspec Metadata"; + sourceTree = ""; + }; + 68B5CDEE1A0BEC8C00A4BAAC /* PINRemoteImage Tests */ = { + isa = PBXGroup; + children = ( + 68B5CDF11A0BEC8C00A4BAAC /* PINRemoteImage_Tests.m */, + 68B5CDEF1A0BEC8C00A4BAAC /* Supporting Files */, + ); + path = "PINRemoteImage Tests"; + sourceTree = ""; + }; + 68B5CDEF1A0BEC8C00A4BAAC /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 68B5CDF01A0BEC8C00A4BAAC /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + F5A6BFF7672C3055495CF245 /* Pods */ = { + isa = PBXGroup; + children = ( + 95043F8A31505C02E51C4D2F /* Pods-PINRemoteImage.debug.xcconfig */, + 8D571FD9970F7A64A2B80EE0 /* Pods-PINRemoteImage.release.xcconfig */, + 063FF605A6CC8884BB10EE35 /* Pods-PINRemoteImage Tests.debug.xcconfig */, + 6008DA13D004B38845BA74EC /* Pods-PINRemoteImage Tests.release.xcconfig */, + 32A377E2A670E405B928B26E /* Pods-Example.debug.xcconfig */, + 500C3EFB07D23E183AC04C5D /* Pods-Example.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 6003F589195388D20070C39A /* Example */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "Example" */; + buildPhases = ( + D2E4FE25FDCE1E36A864F521 /* [CP] Check Pods Manifest.lock */, + 6003F586195388D20070C39A /* Sources */, + 6003F587195388D20070C39A /* Frameworks */, + 6003F588195388D20070C39A /* Resources */, + 80872930FA6F2284B32F00DB /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Example; + productName = PIRemoteImage; + productReference = 6003F58A195388D20070C39A /* Example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6003F582195388D10070C39A /* Project object */ = { + isa = PBXProject; + attributes = { + CLASSPREFIX = PI; + LastUpgradeCheck = 0730; + ORGANIZATIONNAME = "Garrett Moon"; + }; + buildConfigurationList = 6003F585195388D10070C39A /* Build configuration list for PBXProject "Example" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + English, + en, + Base, + ); + mainGroup = 6003F581195388D10070C39A; + productRefGroup = 6003F58B195388D20070C39A /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6003F589195388D20070C39A /* Example */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 6003F588195388D20070C39A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 682C52671B58515D00B3B813 /* Media.xcassets in Resources */, + 6003F5A9195388D20070C39A /* Images.xcassets in Resources */, + 6003F5A1195388D20070C39A /* Main.storyboard in Resources */, + 6003F598195388D20070C39A /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 80872930FA6F2284B32F00DB /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Example/Pods-Example-resources.sh", + "${PODS_CONFIGURATION_BUILD_DIR}/PINCache/PINCache.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/PINOperation/PINOperation.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/PINRemoteImage/PINRemoteImage.bundle", + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/PINCache.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/PINOperation.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/PINRemoteImage.bundle", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Example/Pods-Example-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + D2E4FE25FDCE1E36A864F521 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Example-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 6003F586195388D20070C39A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 68B385081B557116004EB26F /* WebPViewController.m in Sources */, + 68B3850B1B5572BF004EB26F /* ProgressiveViewController.m in Sources */, + 9D9328E51C3D4CC200E1F1D3 /* Kitten.m in Sources */, + 6003F59E195388D20070C39A /* PINAppDelegate.m in Sources */, + 447F707A2BF4F80900C5C956 /* AnimatedWebPViewController.m in Sources */, + 682C52611B584DD300B3B813 /* ProcessingViewController.m in Sources */, + 687666B920869C82001E825C /* GIFViewController.m in Sources */, + 0CF0743224093090008F126B /* APNGViewController.m in Sources */, + 6003F5A7195388D20070C39A /* PINViewController.m in Sources */, + 68B3850E1B5577D4004EB26F /* DegradedViewController.m in Sources */, + 6003F59A195388D20070C39A /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6003F596195388D20070C39A /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 6003F597195388D20070C39A /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 6003F59F195388D20070C39A /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6003F5A0195388D20070C39A /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 6003F5BD195388D20070C39A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 7.1; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 6003F5BE195388D20070C39A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 7.1; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6003F5C0195388D20070C39A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 32A377E2A670E405B928B26E /* Pods-Example.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + INFOPLIST_FILE = "PINRemoteImage/PINRemoteImage-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = Example; + PROVISIONING_PROFILE = ""; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 6003F5C1195388D20070C39A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 500C3EFB07D23E183AC04C5D /* Pods-Example.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + INFOPLIST_FILE = "PINRemoteImage/PINRemoteImage-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = Example; + PROVISIONING_PROFILE = ""; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 6003F585195388D10070C39A /* Build configuration list for PBXProject "Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6003F5BD195388D20070C39A /* Debug */, + 6003F5BE195388D20070C39A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6003F5C0195388D20070C39A /* Debug */, + 6003F5C1195388D20070C39A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6003F582195388D10070C39A /* Project object */; +} diff --git a/Example/PINRemoteImage.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from Example/PINRemoteImage.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to Examples/Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/Examples/Example/Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Examples/Example/Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Examples/Example/Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Examples/Example/Example.xcworkspace/contents.xcworkspacedata b/Examples/Example/Example.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..a37cf193 --- /dev/null +++ b/Examples/Example/Example.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Examples/Example/Example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Examples/Example/Example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Examples/Example/Example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Examples/Example/PINRemoteImage/APNGViewController.h b/Examples/Example/PINRemoteImage/APNGViewController.h new file mode 100644 index 00000000..100fbea7 --- /dev/null +++ b/Examples/Example/PINRemoteImage/APNGViewController.h @@ -0,0 +1,17 @@ +// +// APNGViewController.h +// PINRemoteImage +// +// Created by SAGESSE on 2020/2/28. +// Copyright © 2020 Garrett Moon. All rights reserved. +// + +#import + +#import + +@interface APNGViewController : UIViewController + +@property (nonatomic, weak) IBOutlet PINAnimatedImageView *animatedImageView; + +@end diff --git a/Examples/Example/PINRemoteImage/APNGViewController.m b/Examples/Example/PINRemoteImage/APNGViewController.m new file mode 100644 index 00000000..0a1a6920 --- /dev/null +++ b/Examples/Example/PINRemoteImage/APNGViewController.m @@ -0,0 +1,45 @@ +// +// APNGViewController.m +// PINRemoteImage +// +// Created by SAGESSE on 2020/2/28. +// Copyright © 2020 Garrett Moon. All rights reserved. +// + +#import "APNGViewController.h" + +#import + +@interface APNGViewController () + +@end + +@implementation APNGViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +- (void)viewWillAppear:(BOOL)animated +{ + [super viewWillAppear:animated]; + [self.animatedImageView pin_setImageFromURL:[NSURL URLWithString:@"https://upload.wikimedia.org/wikipedia/commons/1/14/Animated_PNG_example_bouncing_beach_ball.png"]]; +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/Examples/Example/PINRemoteImage/AnimatedWebPViewController.h b/Examples/Example/PINRemoteImage/AnimatedWebPViewController.h new file mode 100644 index 00000000..67eb4e02 --- /dev/null +++ b/Examples/Example/PINRemoteImage/AnimatedWebPViewController.h @@ -0,0 +1,21 @@ +// +// AnimatedWebPViewController.h +// Example +// +// Created by Andy Finnell on 5/15/24. +// Copyright © 2024 Garrett Moon. All rights reserved. +// + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface AnimatedWebPViewController : UIViewController + +@property (nonatomic, weak) IBOutlet PINAnimatedImageView *animatedImageView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Examples/Example/PINRemoteImage/AnimatedWebPViewController.m b/Examples/Example/PINRemoteImage/AnimatedWebPViewController.m new file mode 100644 index 00000000..8b466941 --- /dev/null +++ b/Examples/Example/PINRemoteImage/AnimatedWebPViewController.m @@ -0,0 +1,24 @@ +// +// AnimatedWebPViewController.m +// Example +// +// Created by Andy Finnell on 5/15/24. +// Copyright © 2024 Garrett Moon. All rights reserved. +// + +#import "AnimatedWebPViewController.h" +#import + +@interface AnimatedWebPViewController () + +@end + +@implementation AnimatedWebPViewController + +- (void)viewWillAppear:(BOOL)animated +{ + [super viewWillAppear:animated]; + [self.animatedImageView pin_setImageFromURL:[NSURL URLWithString:@"https://mathiasbynens.be/demo/animated-webp-supported.webp"]]; +} + +@end diff --git a/Examples/Example/PINRemoteImage/Base.lproj/Main.storyboard b/Examples/Example/PINRemoteImage/Base.lproj/Main.storyboard new file mode 100644 index 00000000..4acffaa0 --- /dev/null +++ b/Examples/Example/PINRemoteImage/Base.lproj/Main.storyboard @@ -0,0 +1,296 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example/PINRemoteImage/DegradedViewController.h b/Examples/Example/PINRemoteImage/DegradedViewController.h similarity index 100% rename from Example/PINRemoteImage/DegradedViewController.h rename to Examples/Example/PINRemoteImage/DegradedViewController.h diff --git a/Example/PINRemoteImage/DegradedViewController.m b/Examples/Example/PINRemoteImage/DegradedViewController.m similarity index 91% rename from Example/PINRemoteImage/DegradedViewController.m rename to Examples/Example/PINRemoteImage/DegradedViewController.m index 560d3ec2..42dfad67 100644 --- a/Example/PINRemoteImage/DegradedViewController.m +++ b/Examples/Example/PINRemoteImage/DegradedViewController.m @@ -32,9 +32,9 @@ - (void)didReceiveMemoryWarning - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - [self.imageView pin_setImageFromURLs:@[[NSURL URLWithString:@"https://placekitten.com/101/101"], - [NSURL URLWithString:@"https://placekitten.com/401/401"], - [NSURL URLWithString:@"https://placekitten.com/801/801"]]]; + [self.imageView pin_setImageFromURLs:@[[NSURL URLWithString:@"https://loremflickr.com/101/101"], + [NSURL URLWithString:@"https://loremflickr.com/401/401"], + [NSURL URLWithString:@"https://loremflickr.com/801/801"]]]; } /* diff --git a/Examples/Example/PINRemoteImage/GIFViewController.h b/Examples/Example/PINRemoteImage/GIFViewController.h new file mode 100644 index 00000000..8dc074bd --- /dev/null +++ b/Examples/Example/PINRemoteImage/GIFViewController.h @@ -0,0 +1,17 @@ +// +// GIFViewController.h +// PINRemoteImage +// +// Created by Garrett Moon on 4/17/18. +// Copyright © 2018 Garrett Moon. All rights reserved. +// + +#import + +#import + +@interface GIFViewController : UIViewController + +@property (nonatomic, weak) IBOutlet PINAnimatedImageView *animatedImageView; + +@end diff --git a/Examples/Example/PINRemoteImage/GIFViewController.m b/Examples/Example/PINRemoteImage/GIFViewController.m new file mode 100644 index 00000000..215799c6 --- /dev/null +++ b/Examples/Example/PINRemoteImage/GIFViewController.m @@ -0,0 +1,45 @@ +// +// GIFViewController.m +// PINRemoteImage +// +// Created by Garrett Moon on 4/17/18. +// Copyright © 2018 Garrett Moon. All rights reserved. +// + +#import "GIFViewController.h" + +#import + +@interface GIFViewController () + +@end + +@implementation GIFViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +- (void)viewWillAppear:(BOOL)animated +{ + [super viewWillAppear:animated]; + [self.animatedImageView pin_setImageFromURL:[NSURL URLWithString:@"https://i.pinimg.com/originals/f5/23/f1/f523f141646b613f78566ba964208990.gif"]]; +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/Examples/Example/PINRemoteImage/Images.xcassets/AppIcon.appiconset/Contents.json b/Examples/Example/PINRemoteImage/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..9221b9bb --- /dev/null +++ b/Examples/Example/PINRemoteImage/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Example/PINRemoteImage/Images.xcassets/LaunchImage.launchimage/Contents.json b/Examples/Example/PINRemoteImage/Images.xcassets/LaunchImage.launchimage/Contents.json similarity index 100% rename from Example/PINRemoteImage/Images.xcassets/LaunchImage.launchimage/Contents.json rename to Examples/Example/PINRemoteImage/Images.xcassets/LaunchImage.launchimage/Contents.json diff --git a/Example/PINRemoteImage/Media.xcassets/white-pinterest-logo.imageset/Contents.json b/Examples/Example/PINRemoteImage/Media.xcassets/white-pinterest-logo.imageset/Contents.json similarity index 100% rename from Example/PINRemoteImage/Media.xcassets/white-pinterest-logo.imageset/Contents.json rename to Examples/Example/PINRemoteImage/Media.xcassets/white-pinterest-logo.imageset/Contents.json diff --git a/Example/PINRemoteImage/Media.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@1x.png b/Examples/Example/PINRemoteImage/Media.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@1x.png similarity index 100% rename from Example/PINRemoteImage/Media.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@1x.png rename to Examples/Example/PINRemoteImage/Media.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@1x.png diff --git a/Example/PINRemoteImage/Media.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@2x.png b/Examples/Example/PINRemoteImage/Media.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@2x.png similarity index 100% rename from Example/PINRemoteImage/Media.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@2x.png rename to Examples/Example/PINRemoteImage/Media.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@2x.png diff --git a/Example/PINRemoteImage/PINAppDelegate.h b/Examples/Example/PINRemoteImage/PINAppDelegate.h similarity index 100% rename from Example/PINRemoteImage/PINAppDelegate.h rename to Examples/Example/PINRemoteImage/PINAppDelegate.h diff --git a/Example/PINRemoteImage/PINAppDelegate.m b/Examples/Example/PINRemoteImage/PINAppDelegate.m similarity index 100% rename from Example/PINRemoteImage/PINAppDelegate.m rename to Examples/Example/PINRemoteImage/PINAppDelegate.m diff --git a/Example/PINRemoteImage/PINRemoteImage-Info.plist b/Examples/Example/PINRemoteImage/PINRemoteImage-Info.plist similarity index 88% rename from Example/PINRemoteImage/PINRemoteImage-Info.plist rename to Examples/Example/PINRemoteImage/PINRemoteImage-Info.plist index b06b79c0..3272b56e 100644 --- a/Example/PINRemoteImage/PINRemoteImage-Info.plist +++ b/Examples/Example/PINRemoteImage/PINRemoteImage-Info.plist @@ -5,7 +5,7 @@ CFBundleDevelopmentRegion en CFBundleDisplayName - ${PRODUCT_NAME} + $(PRODUCT_NAME) CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier @@ -24,6 +24,13 @@ 1.0 LSRequiresIPhoneOS + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + NSExceptionAllowsInsecureHTTPLoads + + UIMainStoryboardFile Main UIRequiredDeviceCapabilities diff --git a/Example/PINRemoteImage/PINViewController.h b/Examples/Example/PINRemoteImage/PINViewController.h similarity index 100% rename from Example/PINRemoteImage/PINViewController.h rename to Examples/Example/PINRemoteImage/PINViewController.h diff --git a/Example/PINRemoteImage/PINViewController.m b/Examples/Example/PINRemoteImage/PINViewController.m similarity index 97% rename from Example/PINRemoteImage/PINViewController.m rename to Examples/Example/PINRemoteImage/PINViewController.m index 77317f85..853afbe1 100644 --- a/Example/PINRemoteImage/PINViewController.m +++ b/Examples/Example/PINRemoteImage/PINViewController.m @@ -11,9 +11,6 @@ #import #import #import -#if USE_FLANIMATED_IMAGE -#import -#endif #import "Kitten.h" @@ -36,7 +33,7 @@ - (instancetype)initWithCoder:(NSCoder *)aDecoder { srand([[NSDate date] timeIntervalSince1970]); if (self = [super initWithCoder:aDecoder]) { - [[[PINRemoteImageManager sharedImageManager] cache] removeAllCachedObjects]; + [[[PINRemoteImageManager sharedImageManager] cache] removeAllObjects]; } return self; } @@ -120,6 +117,7 @@ - (instancetype)initWithFrame:(CGRect)frame - (void)prepareForReuse { + [super prepareForReuse]; self.imageView.image = nil; } diff --git a/Example/PINRemoteImage/ProcessingViewController.h b/Examples/Example/PINRemoteImage/ProcessingViewController.h similarity index 100% rename from Example/PINRemoteImage/ProcessingViewController.h rename to Examples/Example/PINRemoteImage/ProcessingViewController.h diff --git a/Examples/Example/PINRemoteImage/ProcessingViewController.m b/Examples/Example/PINRemoteImage/ProcessingViewController.m new file mode 100644 index 00000000..833a3b8c --- /dev/null +++ b/Examples/Example/PINRemoteImage/ProcessingViewController.m @@ -0,0 +1,88 @@ +// +// ProcessingViewController.m +// PINRemoteImage +// +// Created by Garrett Moon on 7/16/15. +// Copyright (c) 2015 Garrett Moon. All rights reserved. +// + +#import "ProcessingViewController.h" + +#import + +@interface ProcessingViewController () + +@end + +@implementation ProcessingViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +- (void)viewWillAppear:(BOOL)animated +{ + [super viewWillAppear:animated]; + + [self.imageView pin_setImageFromURL:[NSURL URLWithString:@"https://i.pinimg.com/736x/5b/c6/c5/5bc6c5387ff6f104fd642f2b375efba3.jpg"] processorKey:@"rounded" processor:^UIImage *(PINRemoteImageManagerResult *result, NSUInteger *cost) + { + UIImage *image = result.image; + CGFloat radius = 7.0f; + CGSize targetSize = CGSizeMake(200, 300); + CGRect imageRect = CGRectMake(0, 0, targetSize.width, targetSize.height); + UIGraphicsBeginImageContext(imageRect.size); + UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:imageRect cornerRadius:radius]; + [bezierPath addClip]; + + CGFloat widthMultiplier = targetSize.width / image.size.width; + CGFloat heightMultiplier = targetSize.height / image.size.height; + CGFloat sizeMultiplier = MAX(widthMultiplier, heightMultiplier); + + CGRect drawRect = CGRectMake(0, 0, image.size.width * sizeMultiplier, image.size.height * sizeMultiplier); + if (CGRectGetMaxX(drawRect) > CGRectGetMaxX(imageRect)) { + drawRect.origin.x -= (CGRectGetMaxX(drawRect) - CGRectGetMaxX(imageRect)) / 2.0; + } + if (CGRectGetMaxY(drawRect) > CGRectGetMaxY(imageRect)) { + drawRect.origin.y -= (CGRectGetMaxY(drawRect) - CGRectGetMaxY(imageRect)) / 2.0; + } + + [image drawInRect:drawRect]; + + [[UIColor redColor] setStroke]; + [bezierPath setLineWidth:5.0]; + [bezierPath stroke]; + + CGContextRef ctx = UIGraphicsGetCurrentContext(); + CGContextSetBlendMode(ctx, kCGBlendModeOverlay); + CGContextSetAlpha(ctx, 0.5); + + UIImage *logo = [UIImage imageNamed:@"white-pinterest-logo"]; + CGContextScaleCTM(ctx, 1.0, -1.0); + CGContextTranslateCTM(ctx, 0.0, -drawRect.size.height); + CGContextDrawImage(ctx, CGRectMake(90, 10, logo.size.width, logo.size.height), [logo CGImage]); + + UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return processedImage; + }]; +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/Example/PINRemoteImage/ProgressiveViewController.h b/Examples/Example/PINRemoteImage/ProgressiveViewController.h similarity index 100% rename from Example/PINRemoteImage/ProgressiveViewController.h rename to Examples/Example/PINRemoteImage/ProgressiveViewController.h diff --git a/Examples/Example/PINRemoteImage/ProgressiveViewController.m b/Examples/Example/PINRemoteImage/ProgressiveViewController.m new file mode 100644 index 00000000..efac02ee --- /dev/null +++ b/Examples/Example/PINRemoteImage/ProgressiveViewController.m @@ -0,0 +1,64 @@ +// +// ProgressiveViewController.m +// PINRemoteImage +// +// Created by Garrett Moon on 7/14/15. +// Copyright (c) 2015 Garrett Moon. All rights reserved. +// + +#import "ProgressiveViewController.h" + +#import +#import + + +@interface ProgressiveViewController () + +@end + +@implementation ProgressiveViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + // MUST BE SET ON IMAGE VIEW TO GET PROGRESS UPDATES! + self.imageView.pin_updateWithProgress = YES; + // Do any additional setup after loading the view. +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +- (void)viewWillAppear:(BOOL)animated +{ + [super viewWillAppear:animated]; + self.imageView.image = nil; + NSURL *progressiveURL = [NSURL URLWithString:@"https://i.pinimg.com/1200x/2e/0c/c5/2e0cc5d86e7b7cd42af225c29f21c37f.jpg"]; + [[PINRemoteImageManager sharedImageManager] setProgressThresholds:@[@(0.1), @(0.2), @(0.3), @(0.4), @(0.5), @(0.6), @(0.7), @(0.8), @(0.9)] completion:nil]; + [[[PINRemoteImageManager sharedImageManager] cache] removeObjectForKey:[[PINRemoteImageManager sharedImageManager] cacheKeyForURL:progressiveURL processorKey:nil]]; + [self.imageView pin_setImageFromURL:progressiveURL]; + + NSMutableArray *progress = [[NSMutableArray alloc] init]; + [[PINRemoteImageManager sharedImageManager] + downloadImageWithURL:progressiveURL + options:PINRemoteImageManagerDownloadOptionsNone progressImage:^(PINRemoteImageManagerResult *result) { + [progress addObject:result.image]; + } completion:^(PINRemoteImageManagerResult *result) { + [progress addObject:result.image]; + }]; +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/Example/PINRemoteImage/WebPViewController.h b/Examples/Example/PINRemoteImage/WebPViewController.h similarity index 100% rename from Example/PINRemoteImage/WebPViewController.h rename to Examples/Example/PINRemoteImage/WebPViewController.h diff --git a/Examples/Example/PINRemoteImage/WebPViewController.m b/Examples/Example/PINRemoteImage/WebPViewController.m new file mode 100644 index 00000000..7038183f --- /dev/null +++ b/Examples/Example/PINRemoteImage/WebPViewController.m @@ -0,0 +1,47 @@ +// +// WebPViewController.m +// PINRemoteImage +// +// Created by Garrett Moon on 7/14/15. +// Copyright (c) 2015 Garrett Moon. All rights reserved. +// + +#import "WebPViewController.h" + +#import + +@interface WebPViewController () + +@end + +@implementation WebPViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +- (void)viewWillAppear:(BOOL)animated +{ + [super viewWillAppear:animated]; + [self.imageView pin_setImageFromURL:[NSURL URLWithString:@"https://raw.githubusercontent.com/samdutton/simpl/main/picturetype/kittens.webp"]]; +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/Example/PINRemoteImage/en.lproj/InfoPlist.strings b/Examples/Example/PINRemoteImage/en.lproj/InfoPlist.strings similarity index 100% rename from Example/PINRemoteImage/en.lproj/InfoPlist.strings rename to Examples/Example/PINRemoteImage/en.lproj/InfoPlist.strings diff --git a/Example/PINRemoteImage/main.m b/Examples/Example/PINRemoteImage/main.m similarity index 100% rename from Example/PINRemoteImage/main.m rename to Examples/Example/PINRemoteImage/main.m diff --git a/Examples/Example/Podfile b/Examples/Example/Podfile new file mode 100644 index 00000000..59cb239b --- /dev/null +++ b/Examples/Example/Podfile @@ -0,0 +1,10 @@ +platform :ios, 14.0 + +def shared_pods + pod "PINRemoteImage", :path => "../../" + pod "PINRemoteImage/PINCache", :path => "../../" +end + +target 'Example' do + shared_pods +end diff --git a/Examples/Example/Podfile.lock b/Examples/Example/Podfile.lock new file mode 100644 index 00000000..6f020fdc --- /dev/null +++ b/Examples/Example/Podfile.lock @@ -0,0 +1,38 @@ +PODS: + - PINCache (3.0.4): + - PINCache/Arc-exception-safe (= 3.0.4) + - PINCache/Core (= 3.0.4) + - PINCache/Arc-exception-safe (3.0.4): + - PINCache/Core + - PINCache/Core (3.0.4): + - PINOperation (~> 1.2.3) + - PINOperation (1.2.3) + - PINRemoteImage (3.0.4): + - PINRemoteImage/PINCache (= 3.0.4) + - PINRemoteImage/Core (3.0.4): + - PINOperation + - PINRemoteImage/PINCache (3.0.4): + - PINCache (~> 3.0.4) + - PINRemoteImage/Core + +DEPENDENCIES: + - PINRemoteImage (from `../../`) + - PINRemoteImage/PINCache (from `../../`) + +SPEC REPOS: + trunk: + - PINCache + - PINOperation + +EXTERNAL SOURCES: + PINRemoteImage: + :path: "../../" + +SPEC CHECKSUMS: + PINCache: d9a87a0ff397acffe9e2f0db972ac14680441158 + PINOperation: fb563bcc9c32c26d6c78aaff967d405aa2ee74a7 + PINRemoteImage: 6256a644f4996991f124811763c7286b2a63ff94 + +PODFILE CHECKSUM: b542b3c8c29f4086253ffdf2139d599970e1c2cb + +COCOAPODS: 1.15.2 diff --git a/Examples/Swift-Example/Podfile b/Examples/Swift-Example/Podfile new file mode 100644 index 00000000..8d9685b4 --- /dev/null +++ b/Examples/Swift-Example/Podfile @@ -0,0 +1,9 @@ +# Uncomment this line to define a global platform for your project +platform :ios, '14.0' +# Uncomment this line if you're using Swift +use_frameworks! + +target 'Swift-Example' do + pod 'PINRemoteImage', :path => '../../' +end + diff --git a/Examples/Swift-Example/Podfile.lock b/Examples/Swift-Example/Podfile.lock new file mode 100644 index 00000000..47ceab6f --- /dev/null +++ b/Examples/Swift-Example/Podfile.lock @@ -0,0 +1,37 @@ +PODS: + - PINCache (3.0.4): + - PINCache/Arc-exception-safe (= 3.0.4) + - PINCache/Core (= 3.0.4) + - PINCache/Arc-exception-safe (3.0.4): + - PINCache/Core + - PINCache/Core (3.0.4): + - PINOperation (~> 1.2.3) + - PINOperation (1.2.3) + - PINRemoteImage (3.0.4): + - PINRemoteImage/PINCache (= 3.0.4) + - PINRemoteImage/Core (3.0.4): + - PINOperation + - PINRemoteImage/PINCache (3.0.4): + - PINCache (~> 3.0.4) + - PINRemoteImage/Core + +DEPENDENCIES: + - PINRemoteImage (from `../../`) + +SPEC REPOS: + trunk: + - PINCache + - PINOperation + +EXTERNAL SOURCES: + PINRemoteImage: + :path: "../../" + +SPEC CHECKSUMS: + PINCache: d9a87a0ff397acffe9e2f0db972ac14680441158 + PINOperation: fb563bcc9c32c26d6c78aaff967d405aa2ee74a7 + PINRemoteImage: 6256a644f4996991f124811763c7286b2a63ff94 + +PODFILE CHECKSUM: 493be0577869744e7a142367f13f9f5aa0e6fb4c + +COCOAPODS: 1.15.2 diff --git a/Examples/Swift-Example/Swift-Example.xcodeproj/project.pbxproj b/Examples/Swift-Example/Swift-Example.xcodeproj/project.pbxproj new file mode 100644 index 00000000..abe82b7f --- /dev/null +++ b/Examples/Swift-Example/Swift-Example.xcodeproj/project.pbxproj @@ -0,0 +1,410 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 0C353DFA27BB468600422709 /* APNGViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C353DF927BB468600422709 /* APNGViewController.swift */; }; + 689613CD208FC26400D2095C /* GIFViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 689613CC208FC26400D2095C /* GIFViewController.swift */; }; + 8E0F3C501C542A25006C0777 /* ScrollViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E0F3C4F1C542A25006C0777 /* ScrollViewController.swift */; }; + 8E0F3C521C542A31006C0777 /* WebPViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E0F3C511C542A31006C0777 /* WebPViewController.swift */; }; + 8E0F3C541C542A55006C0777 /* ProgressiveViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E0F3C531C542A55006C0777 /* ProgressiveViewController.swift */; }; + 8E0F3C561C542A63006C0777 /* DegradedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E0F3C551C542A63006C0777 /* DegradedViewController.swift */; }; + 8E0F3C581C542A6F006C0777 /* ProcessingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E0F3C571C542A6F006C0777 /* ProcessingViewController.swift */; }; + 8E161F221C78910D0047D3C9 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8E161F211C78910D0047D3C9 /* Media.xcassets */; }; + 8E50054A1C4F62EB0095AD0F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E5005491C4F62EB0095AD0F /* AppDelegate.swift */; }; + 8E50054F1C4F62EB0095AD0F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8E50054D1C4F62EB0095AD0F /* Main.storyboard */; }; + 8E5005511C4F62EB0095AD0F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8E5005501C4F62EB0095AD0F /* Assets.xcassets */; }; + 8E5005541C4F62EB0095AD0F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8E5005521C4F62EB0095AD0F /* LaunchScreen.storyboard */; }; + C413DCAD48C05B093777B96B /* Pods_Swift_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3498E59FF2DC090C0259B157 /* Pods_Swift_Example.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 0C353DF927BB468600422709 /* APNGViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = APNGViewController.swift; sourceTree = ""; }; + 3498E59FF2DC090C0259B157 /* Pods_Swift_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Swift_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 39E0C8A2598DAAD2294FF9F4 /* Pods-Swift-Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Swift-Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Swift-Example/Pods-Swift-Example.debug.xcconfig"; sourceTree = ""; }; + 689613CC208FC26400D2095C /* GIFViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GIFViewController.swift; sourceTree = ""; }; + 7184321E1DE18C231C8323FF /* Pods-Swift-Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Swift-Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-Swift-Example/Pods-Swift-Example.release.xcconfig"; sourceTree = ""; }; + 8E0F3C4F1C542A25006C0777 /* ScrollViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScrollViewController.swift; sourceTree = ""; }; + 8E0F3C511C542A31006C0777 /* WebPViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebPViewController.swift; sourceTree = ""; }; + 8E0F3C531C542A55006C0777 /* ProgressiveViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProgressiveViewController.swift; sourceTree = ""; }; + 8E0F3C551C542A63006C0777 /* DegradedViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DegradedViewController.swift; sourceTree = ""; }; + 8E0F3C571C542A6F006C0777 /* ProcessingViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProcessingViewController.swift; sourceTree = ""; }; + 8E161F211C78910D0047D3C9 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = ""; }; + 8E5005461C4F62EB0095AD0F /* Swift-Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Swift-Example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 8E5005491C4F62EB0095AD0F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 8E50054E1C4F62EB0095AD0F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 8E5005501C4F62EB0095AD0F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 8E5005531C4F62EB0095AD0F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 8E5005551C4F62EB0095AD0F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8E5005431C4F62EB0095AD0F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C413DCAD48C05B093777B96B /* Pods_Swift_Example.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 24730C1B70695DF45A582B9E /* Frameworks */ = { + isa = PBXGroup; + children = ( + 3498E59FF2DC090C0259B157 /* Pods_Swift_Example.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 7ED1DD6CD3BBE6638F979D61 /* Pods */ = { + isa = PBXGroup; + children = ( + 39E0C8A2598DAAD2294FF9F4 /* Pods-Swift-Example.debug.xcconfig */, + 7184321E1DE18C231C8323FF /* Pods-Swift-Example.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; + 8E0F3C5A1C542A84006C0777 /* Controllers */ = { + isa = PBXGroup; + children = ( + 0C353DF927BB468600422709 /* APNGViewController.swift */, + 8E0F3C4F1C542A25006C0777 /* ScrollViewController.swift */, + 8E0F3C531C542A55006C0777 /* ProgressiveViewController.swift */, + 8E0F3C511C542A31006C0777 /* WebPViewController.swift */, + 8E0F3C571C542A6F006C0777 /* ProcessingViewController.swift */, + 8E0F3C551C542A63006C0777 /* DegradedViewController.swift */, + 689613CC208FC26400D2095C /* GIFViewController.swift */, + ); + name = Controllers; + sourceTree = ""; + }; + 8E50053D1C4F62EB0095AD0F = { + isa = PBXGroup; + children = ( + 8E5005481C4F62EB0095AD0F /* Swift-Example */, + 8E5005471C4F62EB0095AD0F /* Products */, + 7ED1DD6CD3BBE6638F979D61 /* Pods */, + 24730C1B70695DF45A582B9E /* Frameworks */, + ); + sourceTree = ""; + }; + 8E5005471C4F62EB0095AD0F /* Products */ = { + isa = PBXGroup; + children = ( + 8E5005461C4F62EB0095AD0F /* Swift-Example.app */, + ); + name = Products; + sourceTree = ""; + }; + 8E5005481C4F62EB0095AD0F /* Swift-Example */ = { + isa = PBXGroup; + children = ( + 8E5005491C4F62EB0095AD0F /* AppDelegate.swift */, + 8E0F3C5A1C542A84006C0777 /* Controllers */, + 8E50054D1C4F62EB0095AD0F /* Main.storyboard */, + 8E161F211C78910D0047D3C9 /* Media.xcassets */, + 8E5005501C4F62EB0095AD0F /* Assets.xcassets */, + 8E5005521C4F62EB0095AD0F /* LaunchScreen.storyboard */, + 8E5005551C4F62EB0095AD0F /* Info.plist */, + ); + path = "Swift-Example"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8E5005451C4F62EB0095AD0F /* Swift-Example */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8E5005581C4F62EB0095AD0F /* Build configuration list for PBXNativeTarget "Swift-Example" */; + buildPhases = ( + DF334D262862F883DC0191BF /* [CP] Check Pods Manifest.lock */, + 8E5005421C4F62EB0095AD0F /* Sources */, + 8E5005431C4F62EB0095AD0F /* Frameworks */, + 8E5005441C4F62EB0095AD0F /* Resources */, + 4D54DBF73842B0F913D42C98 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Swift-Example"; + productName = "Swift-Example"; + productReference = 8E5005461C4F62EB0095AD0F /* Swift-Example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 8E50053E1C4F62EB0095AD0F /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0710; + LastUpgradeCheck = 0810; + ORGANIZATIONNAME = "Marius Landwehr"; + TargetAttributes = { + 8E5005451C4F62EB0095AD0F = { + CreatedOnToolsVersion = 7.1.1; + LastSwiftMigration = 1020; + }; + }; + }; + buildConfigurationList = 8E5005411C4F62EB0095AD0F /* Build configuration list for PBXProject "Swift-Example" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + English, + en, + Base, + ); + mainGroup = 8E50053D1C4F62EB0095AD0F; + productRefGroup = 8E5005471C4F62EB0095AD0F /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8E5005451C4F62EB0095AD0F /* Swift-Example */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 8E5005441C4F62EB0095AD0F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8E5005541C4F62EB0095AD0F /* LaunchScreen.storyboard in Resources */, + 8E5005511C4F62EB0095AD0F /* Assets.xcassets in Resources */, + 8E161F221C78910D0047D3C9 /* Media.xcassets in Resources */, + 8E50054F1C4F62EB0095AD0F /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 4D54DBF73842B0F913D42C98 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Swift-Example/Pods-Swift-Example-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/PINCache/PINCache.framework", + "${BUILT_PRODUCTS_DIR}/PINOperation/PINOperation.framework", + "${BUILT_PRODUCTS_DIR}/PINRemoteImage/PINRemoteImage.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PINCache.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PINOperation.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PINRemoteImage.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Swift-Example/Pods-Swift-Example-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + DF334D262862F883DC0191BF /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Swift-Example-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8E5005421C4F62EB0095AD0F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C353DFA27BB468600422709 /* APNGViewController.swift in Sources */, + 8E50054A1C4F62EB0095AD0F /* AppDelegate.swift in Sources */, + 8E0F3C501C542A25006C0777 /* ScrollViewController.swift in Sources */, + 8E0F3C541C542A55006C0777 /* ProgressiveViewController.swift in Sources */, + 8E0F3C581C542A6F006C0777 /* ProcessingViewController.swift in Sources */, + 689613CD208FC26400D2095C /* GIFViewController.swift in Sources */, + 8E0F3C521C542A31006C0777 /* WebPViewController.swift in Sources */, + 8E0F3C561C542A63006C0777 /* DegradedViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 8E50054D1C4F62EB0095AD0F /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 8E50054E1C4F62EB0095AD0F /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 8E5005521C4F62EB0095AD0F /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 8E5005531C4F62EB0095AD0F /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 8E5005561C4F62EB0095AD0F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.1; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 8E5005571C4F62EB0095AD0F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.1; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 8E5005591C4F62EB0095AD0F /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 39E0C8A2598DAAD2294FF9F4 /* Pods-Swift-Example.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "Swift-Example/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.pintereset.Swift-Example"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 8E50055A1C4F62EB0095AD0F /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7184321E1DE18C231C8323FF /* Pods-Swift-Example.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "Swift-Example/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.pintereset.Swift-Example"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 8E5005411C4F62EB0095AD0F /* Build configuration list for PBXProject "Swift-Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8E5005561C4F62EB0095AD0F /* Debug */, + 8E5005571C4F62EB0095AD0F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8E5005581C4F62EB0095AD0F /* Build configuration list for PBXNativeTarget "Swift-Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8E5005591C4F62EB0095AD0F /* Debug */, + 8E50055A1C4F62EB0095AD0F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 8E50053E1C4F62EB0095AD0F /* Project object */; +} diff --git a/Examples/Swift-Example/Swift-Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/Swift-Example/Swift-Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/Examples/Swift-Example/Swift-Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Examples/Swift-Example/Swift-Example.xcworkspace/contents.xcworkspacedata b/Examples/Swift-Example/Swift-Example.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..3c22eb94 --- /dev/null +++ b/Examples/Swift-Example/Swift-Example.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Examples/Swift-Example/Swift-Example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Examples/Swift-Example/Swift-Example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Examples/Swift-Example/Swift-Example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Examples/Swift-Example/Swift-Example/APNGViewController.swift b/Examples/Swift-Example/Swift-Example/APNGViewController.swift new file mode 100644 index 00000000..1dfc4556 --- /dev/null +++ b/Examples/Swift-Example/Swift-Example/APNGViewController.swift @@ -0,0 +1,21 @@ +// +// APNGViewController.swift +// Swift-Example +// +// Created by Garrett Moon on 4/24/18. +// Copyright © 2018 Marius Landwehr. All rights reserved. +// + +import UIKit +import PINRemoteImage + +class APNGViewController: UIViewController { + + @IBOutlet weak var imageView: PINAnimatedImageView! + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + imageView.pin_setImage(from: URL(string: "https://upload.wikimedia.org/wikipedia/commons/1/14/Animated_PNG_example_bouncing_beach_ball.png")) + } +} diff --git a/Examples/Swift-Example/Swift-Example/AppDelegate.swift b/Examples/Swift-Example/Swift-Example/AppDelegate.swift new file mode 100644 index 00000000..79c5c824 --- /dev/null +++ b/Examples/Swift-Example/Swift-Example/AppDelegate.swift @@ -0,0 +1,47 @@ +// +// AppDelegate.swift +// Swift-Example +// +// Created by Marius Landwehr on 20.01.16. +// Copyright © 2016 Marius Landwehr. All rights reserved. +// + +import UIKit +import PINRemoteImage + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + PINRemoteImageManager.shared().setProgressiveRendersMaxProgressiveRenderSize(CGSize.init(width: 2048, height: 2048), completion: nil) + return true + } + + func applicationWillResignActive(_ application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(_ application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(_ application: UIApplication) { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(_ application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(_ application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + +} + diff --git a/Examples/Swift-Example/Swift-Example/Assets.xcassets/AppIcon.appiconset/Contents.json b/Examples/Swift-Example/Swift-Example/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..118c98f7 --- /dev/null +++ b/Examples/Swift-Example/Swift-Example/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,38 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Examples/Swift-Example/Swift-Example/Base.lproj/LaunchScreen.storyboard b/Examples/Swift-Example/Swift-Example/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000..f70f059c --- /dev/null +++ b/Examples/Swift-Example/Swift-Example/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/Swift-Example/Swift-Example/Base.lproj/Main.storyboard b/Examples/Swift-Example/Swift-Example/Base.lproj/Main.storyboard new file mode 100644 index 00000000..893e1aab --- /dev/null +++ b/Examples/Swift-Example/Swift-Example/Base.lproj/Main.storyboard @@ -0,0 +1,241 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/Swift-Example/Swift-Example/DegradedViewController.swift b/Examples/Swift-Example/Swift-Example/DegradedViewController.swift new file mode 100644 index 00000000..5de78610 --- /dev/null +++ b/Examples/Swift-Example/Swift-Example/DegradedViewController.swift @@ -0,0 +1,30 @@ +// +// DegradedViewController.swift +// Swift-Example +// +// Created by Marius Landwehr on 23.01.16. +// Copyright © 2016 Marius Landwehr. All rights reserved. +// + +import UIKit +import PINRemoteImage + +class DegradedViewController: UIViewController { + + @IBOutlet weak var imageView: UIImageView! + + override func viewDidLoad() { + super.viewDidLoad() + + PINRemoteImageManager.shared().setShouldUpgradeLowQualityImages(true, completion: nil) + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + imageView.pin_setImage(from: [ + URL(string: "https://loremflickr.com/101/101")!, + URL(string: "https://loremflickr.com/401/401")!, + URL(string: "https://loremflickr.com/801/801")!]) + } +} diff --git a/Examples/Swift-Example/Swift-Example/GIFViewController.swift b/Examples/Swift-Example/Swift-Example/GIFViewController.swift new file mode 100644 index 00000000..04582bb9 --- /dev/null +++ b/Examples/Swift-Example/Swift-Example/GIFViewController.swift @@ -0,0 +1,21 @@ +// +// GIFViewController.swift +// Swift-Example +// +// Created by Garrett Moon on 4/24/18. +// Copyright © 2018 Marius Landwehr. All rights reserved. +// + +import UIKit +import PINRemoteImage + +class GIFViewController: UIViewController { + + @IBOutlet weak var imageView: PINAnimatedImageView! + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + imageView.pin_setImage(from: URL(string: "https://i.pinimg.com/originals/f5/23/f1/f523f141646b613f78566ba964208990.gif")) + } +} diff --git a/Examples/Swift-Example/Swift-Example/Info.plist b/Examples/Swift-Example/Swift-Example/Info.plist new file mode 100644 index 00000000..6905cc67 --- /dev/null +++ b/Examples/Swift-Example/Swift-Example/Info.plist @@ -0,0 +1,40 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Examples/Swift-Example/Swift-Example/Media.xcassets/white-pinterest-logo.imageset/Contents.json b/Examples/Swift-Example/Swift-Example/Media.xcassets/white-pinterest-logo.imageset/Contents.json new file mode 100644 index 00000000..5c589373 --- /dev/null +++ b/Examples/Swift-Example/Swift-Example/Media.xcassets/white-pinterest-logo.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "white-pinterest-logo@1x.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "white-pinterest-logo@2x.png" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Examples/Swift-Example/Swift-Example/Media.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@1x.png b/Examples/Swift-Example/Swift-Example/Media.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@1x.png new file mode 100644 index 00000000..2c882a9b Binary files /dev/null and b/Examples/Swift-Example/Swift-Example/Media.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@1x.png differ diff --git a/Examples/Swift-Example/Swift-Example/Media.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@2x.png b/Examples/Swift-Example/Swift-Example/Media.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@2x.png new file mode 100644 index 00000000..53546558 Binary files /dev/null and b/Examples/Swift-Example/Swift-Example/Media.xcassets/white-pinterest-logo.imageset/white-pinterest-logo@2x.png differ diff --git a/Examples/Swift-Example/Swift-Example/ProcessingViewController.swift b/Examples/Swift-Example/Swift-Example/ProcessingViewController.swift new file mode 100644 index 00000000..6022f358 --- /dev/null +++ b/Examples/Swift-Example/Swift-Example/ProcessingViewController.swift @@ -0,0 +1,71 @@ +// +// ProcessingViewController.swift +// Swift-Example +// +// Created by Marius Landwehr on 23.01.16. +// Copyright © 2016 Marius Landwehr. All rights reserved. +// + +import UIKit +import PINRemoteImage + +class ProcessingViewController: UIViewController { + + @IBOutlet weak var imageView: UIImageView! + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + let url = URL(string: "https://i.pinimg.com/736x/5b/c6/c5/5bc6c5387ff6f104fd642f2b375efba3.jpg") + + imageView.pin_setImage(from: url, processorKey: "rounded") { (result, unsafePointer) -> UIImage? in + + guard let image = result.image else { return nil } + + let radius : CGFloat = 7.0 + let targetSize = CGSize(width: 200, height: 300) + let imageRect = CGRect(x: 0, y: 0, width: targetSize.width, height: targetSize.height) + + UIGraphicsBeginImageContext(imageRect.size) + + let bezierPath = UIBezierPath(roundedRect: imageRect, cornerRadius: radius) + bezierPath.addClip() + + let widthMultiplier : CGFloat = targetSize.width / image.size.width + let heightMultiplier : CGFloat = targetSize.height / image.size.height + let sizeMultiplier = max(widthMultiplier, heightMultiplier) + + var drawRect = CGRect(x: 0, y: 0, width: image.size.width * sizeMultiplier, height: image.size.height * sizeMultiplier) + if (drawRect.maxX > imageRect.maxX) { + drawRect.origin.x -= (drawRect.maxX - imageRect.maxX) / 2 + } + if (drawRect.maxY > imageRect.maxY) { + drawRect.origin.y -= (drawRect.maxY - imageRect.maxY) / 2 + } + + image.draw(in: drawRect) + + UIColor.red.setStroke() + bezierPath.lineWidth = 5.0 + bezierPath.stroke() + + let ctx = UIGraphicsGetCurrentContext() + ctx?.setBlendMode(CGBlendMode.overlay) + ctx?.setAlpha(0.5) + + let logo = UIImage(named: "white-pinterest-logo") + ctx?.scaleBy(x: 1.0, y: -1.0) + ctx?.translateBy(x: 0.0, y: -drawRect.size.height) + + if let coreGraphicsImage = logo?.cgImage { + ctx?.draw(coreGraphicsImage, in: CGRect(x: 90, y: 10, width: logo!.size.width, height: logo!.size.height)) + } + + let processedImage = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + + return processedImage + + } + } +} diff --git a/Examples/Swift-Example/Swift-Example/ProgressiveViewController.swift b/Examples/Swift-Example/Swift-Example/ProgressiveViewController.swift new file mode 100644 index 00000000..07161517 --- /dev/null +++ b/Examples/Swift-Example/Swift-Example/ProgressiveViewController.swift @@ -0,0 +1,36 @@ +// +// ProgressiveViewController.swift +// Swift-Example +// +// Created by Marius Landwehr on 23.01.16. +// Copyright © 2016 Marius Landwehr. All rights reserved. +// + +import UIKit +import PINRemoteImage +import PINCache + +class ProgressiveViewController: UIViewController { + + @IBOutlet weak var imageView: UIImageView! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + imageView.pin_updateWithProgress = true + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + guard let imageURL = URL(string: "https://i.pinimg.com/1200x/2e/0c/c5/2e0cc5d86e7b7cd42af225c29f21c37f.jpg") else { + return + } + + PINRemoteImageManager.shared().setProgressThresholds([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0], completion: nil) + PINRemoteImageManager.shared().cache.removeObject(forKey: PINRemoteImageManager.shared().cacheKey(for: imageURL, processorKey: nil)) + + imageView.pin_setImage(from: imageURL) + } +} diff --git a/Examples/Swift-Example/Swift-Example/ScrollViewController.swift b/Examples/Swift-Example/Swift-Example/ScrollViewController.swift new file mode 100644 index 00000000..4c9b506a --- /dev/null +++ b/Examples/Swift-Example/Swift-Example/ScrollViewController.swift @@ -0,0 +1,190 @@ +// +// ScrollViewController.swift +// Swift-Example +// +// Created by Marius Landwehr on 23.01.16. +// Copyright © 2016 Marius Landwehr. All rights reserved. +// + +import UIKit +import PINRemoteImage +import PINCache + +struct Kitten { + + let imageUrl : URL + let size : CGSize + var dominantColor : UIColor? + + init(urlString : String, size : CGSize) { + self.imageUrl = URL(string: urlString)! + self.size = size + } +} + +class PinImageCell : UICollectionViewCell { + + let imageView : UIImageView + + override init(frame: CGRect) { + imageView = UIImageView() + + super.init(frame: frame) + + imageView.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(imageView) + + let view = ["imageView" : imageView] + + let constraintsH = NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[imageView]-0-|", options: [], metrics: nil, views: view) + let constraintsV = NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[imageView]-0-|", options: [], metrics: nil, views: view) + contentView.addConstraints(constraintsH) + contentView.addConstraints(constraintsV) + + layer.cornerRadius = 7 + layer.masksToBounds = true + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func prepareForReuse() { + super.prepareForReuse() + imageView.image = nil + } +} + +class ScrollViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout { + + let kittens = [ + Kitten(urlString: "https://i.pinimg.com/736x/92/5d/5a/925d5ac74db0dcfabc238e1686e31d16.jpg", size: CGSize(width: 503, height: 992)), + Kitten(urlString: "https://i.pinimg.com/736x/ff/b3/ae/ffb3ae40533b7f9463cf1c04d7ab69d1.jpg", size: CGSize(width: 500, height: 337)), + Kitten(urlString: "https://i.pinimg.com/736x/e4/b7/7c/e4b77ca06e1d4a401b1a49d7fadd90d9.jpg", size: CGSize(width: 522, height: 695)), + Kitten(urlString: "https://i.pinimg.com/736x/46/e1/59/46e159d76b167ed9211d662f95e7bf6f.jpg", size: CGSize(width: 557, height: 749)), + Kitten(urlString: "https://i.pinimg.com/736x/7a/72/77/7a72779329942c06f888c148eb8d7e34.jpg", size: CGSize(width: 710, height: 1069)), + Kitten(urlString: "https://i.pinimg.com/736x/60/21/8f/60218ff43257fb3b6d7c5b888f74a5bf.jpg", size: CGSize(width: 522, height: 676)), + Kitten(urlString: "https://i.pinimg.com/736x/90/e8/e4/90e8e47d53e71e0d97691dd13a5617fb.jpg", size: CGSize(width: 500, height: 688)), + Kitten(urlString: "https://i.pinimg.com/736x/96/ae/31/96ae31fbc52d96dd3308d2754a6ca37e.jpg", size: CGSize(width: 377, height: 700)), + Kitten(urlString: "https://i.pinimg.com/736x/9b/7b/99/9b7b99ff63be31bba8f9863724b3ebbc.jpg", size: CGSize(width: 334, height: 494)), + Kitten(urlString: "https://i.pinimg.com/736x/80/23/51/802351d953dd2a8b232d0da1c7ca6880.jpg", size: CGSize(width: 625, height: 469)), + Kitten(urlString: "https://i.pinimg.com/736x/f5/c4/f0/f5c4f04fa2686338dc3b08420d198484.jpg", size: CGSize(width: 625, height: 833)), + Kitten(urlString: "https://i.pinimg.com/736x/2b/06/4f/2b064f3e0af984a556ac94b251ff7060.jpg", size: CGSize(width: 625, height: 469)), + Kitten(urlString: "https://i.pinimg.com/736x/17/1f/c0/171fc02398143269d8a507a15563166a.jpg", size: CGSize(width: 625, height: 469)), + Kitten(urlString: "https://i.pinimg.com/736x/8a/35/33/8a35338bbf67c86a198ba2dd926edd82.jpg", size: CGSize(width: 625, height: 791)), + Kitten(urlString: "https://i.pinimg.com/736x/4d/6e/3c/4d6e3cf970031116c57486e85c2a4cab.jpg", size: CGSize(width: 625, height: 833)), + Kitten(urlString: "https://i.pinimg.com/736x/54/25/ee/5425eeccba78731cf7be70f0b8808bd2.jpg", size: CGSize(width: 605, height: 605)), + Kitten(urlString: "https://i.pinimg.com/736x/04/f1/3f/04f13fdb7580dcbe8c4d6b7d5a0a5ec2.jpg", size: CGSize(width: 504, height: 750)), + Kitten(urlString: "https://i.pinimg.com/736x/dc/16/4e/dc164ed33af9d899e5ed188e642f00e9.jpg", size: CGSize(width: 500, height: 500)), + Kitten(urlString: "https://i.pinimg.com/736x/c1/06/13/c106132936189b6cb654671f2a2183ed.jpg", size: CGSize(width: 640, height: 640)), + Kitten(urlString: "https://i.pinimg.com/736x/46/43/ed/4643eda4e1be4273721a76a370b90346.jpg", size: CGSize(width: 500, height: 473)), + ] + + var collectionKittens = [Kitten]() + + var collectionView : UICollectionView? + + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { + super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) + PINRemoteImageManager.shared().cache.removeAllObjects() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + PINRemoteImageManager.shared().cache.removeAllObjects() + } + + override func viewDidLoad() { + super.viewDidLoad() + + collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: UICollectionViewFlowLayout()) + collectionView?.register(PinImageCell.self, forCellWithReuseIdentifier: String(describing: PinImageCell.self)) + collectionView?.delegate = self + collectionView?.dataSource = self + + if let cView = collectionView { + view.addSubview(cView) + } + + createRandomKittens() + } + + func createRandomKittens() { + let dispatchGroup = DispatchGroup() + if let bounds = collectionView?.bounds { + var tmpKittens = [Kitten]() + + DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async(group: dispatchGroup) { () -> Void in + + for _ in 1...500 { + let randGreen : CGFloat = CGFloat(drand48()) + let randBlue : CGFloat = CGFloat(drand48()) + let randRed : CGFloat = CGFloat(drand48()) + + let randomColor = UIColor(red: randRed, green: randGreen, blue: randBlue, alpha: 1) + let kittenIndex : Int = Int(arc4random() % 20) + let randKitten = self.kittens[kittenIndex] + + var width = randKitten.size.width + var height = randKitten.size.height + + if width > (bounds.size.width) { + height = height / (width / bounds.size.width) + width = bounds.size.width + } + + var newKitten = Kitten(urlString: randKitten.imageUrl.absoluteString, size: CGSize(width: width, height: height)) + newKitten.dominantColor = randomColor + + DispatchQueue.main.sync(execute: { () -> Void in + tmpKittens.append(newKitten) + }) + } + } + + dispatchGroup.notify(queue: DispatchQueue.main, execute: { () -> Void in + self.collectionKittens += tmpKittens + self.collectionView?.reloadData() + }) + } + } + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + let kitten = collectionKittens[indexPath.row] + return kitten.size + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: PinImageCell.self), for: indexPath) + + if let pinCell = cell as? PinImageCell { + + let kitten = collectionKittens[indexPath.row] + pinCell.backgroundColor = kitten.dominantColor + pinCell.alpha = 0 + + weak var weakPinCell = pinCell + + pinCell.imageView.pin_setImage(from: kitten.imageUrl, completion: { (result) in + if result.requestDuration > 0.25 { + UIView.animate(withDuration: 0.3, animations: { + weakPinCell?.alpha = 1 + }) + } else { + weakPinCell?.alpha = 1 + } + }) + } + + return cell + } + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return collectionKittens.count + } + + func numberOfSections(in collectionView: UICollectionView) -> Int { + return 1 + } +} diff --git a/Examples/Swift-Example/Swift-Example/WebPViewController.swift b/Examples/Swift-Example/Swift-Example/WebPViewController.swift new file mode 100644 index 00000000..de22700a --- /dev/null +++ b/Examples/Swift-Example/Swift-Example/WebPViewController.swift @@ -0,0 +1,21 @@ +// +// WebPViewController.swift +// Swift-Example +// +// Created by Marius Landwehr on 23.01.16. +// Copyright © 2016 Marius Landwehr. All rights reserved. +// + +import UIKit +import PINRemoteImage + +class WebPViewController: UIViewController { + + @IBOutlet weak var imageView: UIImageView! + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + imageView.pin_setImage(from: URL(string: "https://raw.githubusercontent.com/samdutton/simpl/main/picturetype/kittens.webp")) + } +} diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..cf21392a --- /dev/null +++ b/Makefile @@ -0,0 +1,41 @@ +PLATFORM="platform=iOS Simulator,name=iPhone 16,OS=18.5" +SDK="iphonesimulator18.5" +SHELL=/bin/bash -o pipefail +XCODE_MAJOR_VERSION=$(shell xcodebuild -version | HEAD -n 1 | sed -E 's/Xcode ([0-9]+).*/\1/') +IOS_EXAMPLE_PROJECT="Examples/Example-Xcode-SPM/Example-Xcode-SPM.xcodeproj" +EXAMPLE_SCHEME="Example-Xcode-SPM" + +.PHONY: all webp cocoapods test carthage analyze spm example + +cocoapods: + pod lib lint --allow-warnings + +analyze: + xcodebuild clean analyze -destination ${PLATFORM} -sdk ${SDK} -workspace PINRemoteImage.xcworkspace -scheme PINRemoteImage \ + CODE_SIGNING_REQUIRED=NO \ + CLANG_ANALYZER_OUTPUT=plist-html \ + CLANG_ANALYZER_OUTPUT_DIR="$(shell pwd)/clang" | xcpretty + if [[ -n `find $(shell pwd)/clang -name "*.html"` ]] ; then rm -rf `pwd`/clang; exit 1; fi + rm -rf $(shell pwd)/clang + +test: + xcodebuild clean test -destination ${PLATFORM} -sdk ${SDK} -workspace PINRemoteImage.xcworkspace -scheme PINRemoteImage \ + CODE_SIGNING_REQUIRED=NO | xcpretty + +carthage: + carthage update --no-use-binaries --no-build + carthage build --no-skip-current --use-xcframeworks + +spm: + swift build + +example: + if [ ${XCODE_MAJOR_VERSION} -lt 16 ] ; then \ + echo "Xcode 16 and Swift 5.9 required to build example project"; \ + exit 1; \ + fi + xcodebuild clean build -project ${IOS_EXAMPLE_PROJECT} -scheme ${EXAMPLE_SCHEME} -destination ${PLATFORM} -sdk ${SDK} \ + ONLY_ACTIVE_ARCH=NO \ + CODE_SIGNING_REQUIRED=NO | xcpretty + +all: carthage test cocoapods analyze spm example \ No newline at end of file diff --git a/PINRemoteImage.podspec b/PINRemoteImage.podspec index 6dc9079f..74dd6450 100644 --- a/PINRemoteImage.podspec +++ b/PINRemoteImage.podspec @@ -9,41 +9,49 @@ Pod::Spec.new do |s| s.name = "PINRemoteImage" - s.version = "3.0.0-beta.3" + s.version = '3.0.4' s.summary = "A thread safe, performant, feature rich image fetcher" s.homepage = "https://github.com/pinterest/PINRemoteImage" s.license = 'Apache 2.0' s.author = { "Garrett Moon" => "garrett@pinterest.com" } s.source = { :git => "https://github.com/pinterest/PINRemoteImage.git", :tag => s.version.to_s } - s.social_media_url = 'https://twitter.com/garrettmoon' + s.prefix_header_file = false + # s.social_media_url = 'https://twitter.com/garrettmoon' - s.ios.deployment_target = "7.0" - s.tvos.deployment_target = "9.0" + ios_deployment = "14.0" + tvos_deployment = "14.0" + osx_deployment = "11.0" + s.cocoapods_version = '>= 1.13.0' + s.ios.deployment_target = ios_deployment + s.tvos.deployment_target = tvos_deployment s.requires_arc = true - # Include optional FLAnimatedImage module - s.default_subspecs = 'FLAnimatedImage','PINCache' + s.default_subspecs = 'PINCache' ### Subspecs s.subspec 'Core' do |cs| - cs.ios.deployment_target = "7.0" - cs.tvos.deployment_target = "9.0" - cs.osx.deployment_target = "10.9" - cs.source_files = 'Pod/Classes/**/*.{h,m}' - cs.exclude_files = 'Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.h', 'Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.m','Pod/Classes/PINCache/**/*.{h,m}' - cs.public_header_files = 'Pod/Classes/**/*.h' + cs.dependency 'PINOperation' + cs.ios.deployment_target = ios_deployment + cs.tvos.deployment_target = tvos_deployment + cs.osx.deployment_target = osx_deployment + cs.source_files = 'Source/Classes/**/*.{h,m}' + cs.public_header_files = 'Source/Classes/include/**/*.h' + cs.exclude_files = 'Source/Classes/PINCache/*.{h,m}', 'Source/Classes/include/PINRemoteImage/PINCache+PINRemoteImageCaching.h' cs.frameworks = 'ImageIO', 'Accelerate' + cs.xcconfig = { + 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) PIN_WEBP=1', + } end s.subspec 'iOS' do |ios| - ios.ios.deployment_target = "7.0" - ios.tvos.deployment_target = "9.0" + ios.ios.deployment_target = ios_deployment + ios.tvos.deployment_target = tvos_deployment ios.dependency 'PINRemoteImage/Core' ios.frameworks = 'UIKit' end s.subspec 'OSX' do |cs| - cs.osx.deployment_target = "10.9" + cs.osx.deployment_target = osx_deployment cs.dependency 'PINRemoteImage/Core' cs.frameworks = 'Cocoa', 'CoreServices' end @@ -52,27 +60,15 @@ Pod::Spec.new do |s| s.subspec 'tvOS' do |tvos| tvos.dependency 'PINRemoteImage/iOS' end - - s.subspec "FLAnimatedImage" do |fs| - fs.platforms = "ios" - fs.dependency 'PINRemoteImage/Core' - fs.source_files = 'Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.h', 'Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.m' - fs.dependency 'FLAnimatedImage', '>= 1.0' - end - - s.subspec 'WebP' do |webp| - webp.xcconfig = { - 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) PIN_WEBP=1', - 'USER_HEADER_SEARCH_PATHS' => '$(inherited) $(SRCROOT)/libwebp/src' - } - webp.dependency 'PINRemoteImage/Core' - webp.dependency 'libwebp' - end s.subspec "PINCache" do |pc| - pc.dependency 'PINRemoteImage/Core' - pc.dependency 'PINCache', '>=3.0.1-beta' - pc.source_files = 'Pod/Classes/PINCache/**/*.{h,m}' + pc.dependency 'PINRemoteImage/Core' + pc.ios.deployment_target = ios_deployment + pc.tvos.deployment_target = tvos_deployment + pc.osx.deployment_target = osx_deployment + pc.dependency 'PINCache', '~> 3.0.4' + pc.source_files = 'Source/Classes/PINCache/*.{h,m}', 'Source/Classes/include/PINRemoteImage/PINCache+PINRemoteImageCaching.h' end + s.resource_bundles = { 'PINRemoteImage' => ['Source/PrivacyInfo.xcprivacy'] } end diff --git a/PINRemoteImage.xcodeproj/project.pbxproj b/PINRemoteImage.xcodeproj/project.pbxproj new file mode 100644 index 00000000..cac0ba98 --- /dev/null +++ b/PINRemoteImage.xcodeproj/project.pbxproj @@ -0,0 +1,1425 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 0CF0743B24093139008F126B /* PINAPNGAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF0743524093139008F126B /* PINAPNGAnimatedImage.m */; }; + 0CF0743C24093139008F126B /* PINAPNGAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF0743524093139008F126B /* PINAPNGAnimatedImage.m */; }; + 0E71BE2A22E94C7200FC5B99 /* fireworks.gif in Resources */ = {isa = PBXBuildFile; fileRef = 0E71BE2522E94C7200FC5B99 /* fireworks.gif */; }; + 139D3A631F67284400F82935 /* PINRemoteImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 139D3A5A1F67284400F82935 /* PINRemoteImage.framework */; }; + 139D4FCA1F672B0D00DE64E0 /* PINButton+PINRemoteImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DD47F991C699F4B00F12CA0 /* PINButton+PINRemoteImage.m */; }; + 139D4FCB1F672B0D00DE64E0 /* PINImageView+PINRemoteImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DD47F9B1C699F4B00F12CA0 /* PINImageView+PINRemoteImage.m */; }; + 139D4FCC1F672B0D00DE64E0 /* NSData+ImageDetectors.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918DF1BCF23C800710963 /* NSData+ImageDetectors.m */; }; + 139D4FCD1F672B0D00DE64E0 /* PINCache+PINRemoteImageCaching.m in Sources */ = {isa = PBXBuildFile; fileRef = 68CA92821DB19C20008BECE2 /* PINCache+PINRemoteImageCaching.m */; }; + 139D4FCE1F672B0D00DE64E0 /* PINAlternateRepresentationProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 68F0EA8F1CB32EC900F1FD41 /* PINAlternateRepresentationProvider.m */; }; + 139D4FD01F672B0D00DE64E0 /* PINProgressiveImage.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918EE1BCF23C800710963 /* PINProgressiveImage.m */; }; + 139D4FD11F672B0D00DE64E0 /* PINRemoteImageCategoryManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918DC1BCF23C800710963 /* PINRemoteImageCategoryManager.m */; }; + 139D4FD21F672B0D00DE64E0 /* PINRemoteImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918F61BCF23C800710963 /* PINRemoteImageManager.m */; }; + 139D4FD31F672B0D00DE64E0 /* PINRemoteImageManagerResult.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918F81BCF23C800710963 /* PINRemoteImageManagerResult.m */; }; + 139D4FD41F672B0D00DE64E0 /* PINURLSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918FE1BCF23C900710963 /* PINURLSessionManager.m */; }; + 139D4FD51F672B0D00DE64E0 /* PINRequestRetryStrategy.m in Sources */ = {isa = PBXBuildFile; fileRef = 926E015D1F0DFCAE00874D01 /* PINRequestRetryStrategy.m */; }; + 139D4FD61F672B0D00DE64E0 /* PINImage+ScaledImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 68A6B1D91E5248BF003A92D1 /* PINImage+ScaledImage.m */; }; + 139D4FD71F672B0D00DE64E0 /* PINImage+DecodedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DD47FA11C699FDC00F12CA0 /* PINImage+DecodedImage.m */; }; + 139D4FDB1F672B0D00DE64E0 /* PINRemoteImageCallbacks.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918F11BCF23C800710963 /* PINRemoteImageCallbacks.m */; }; + 139D4FDC1F672B0D00DE64E0 /* PINRemoteImageDownloadTask.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918F41BCF23C800710963 /* PINRemoteImageDownloadTask.m */; }; + 139D4FDD1F672B0D00DE64E0 /* PINRemoteImageProcessorTask.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918FA1BCF23C800710963 /* PINRemoteImageProcessorTask.m */; }; + 139D4FDE1F672B0D00DE64E0 /* PINRemoteImageTask.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918FC1BCF23C800710963 /* PINRemoteImageTask.m */; }; + 139D4FDF1F672B0D00DE64E0 /* PINRemoteLock.m in Sources */ = {isa = PBXBuildFile; fileRef = 6858C0741C9CC5BA00E420EB /* PINRemoteLock.m */; }; + 139D4FE01F672B0D00DE64E0 /* PINRemoteImageMemoryContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 68F0EA911CB32EC900F1FD41 /* PINRemoteImageMemoryContainer.m */; }; + 139D4FE11F672B0D00DE64E0 /* PINRemoteImageBasicCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 68CA927A1DAEFF93008BECE2 /* PINRemoteImageBasicCache.m */; }; + 139D4FE21F672B0D00DE64E0 /* PINRemoteImageDownloadQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 68B1F2801E679D7A00ED87C4 /* PINRemoteImageDownloadQueue.m */; }; + 139D4FE31F672B0D00DE64E0 /* PINResume.m in Sources */ = {isa = PBXBuildFile; fileRef = 68B7E3B11E736C73000FC887 /* PINResume.m */; }; + 139D4FE41F672B0D00DE64E0 /* PINSpeedRecorder.m in Sources */ = {isa = PBXBuildFile; fileRef = 6860CB071F578287005E886E /* PINSpeedRecorder.m */; }; + 139D50A91F672BBF00DE64E0 /* PINRemoteImageCallbacks.h in Headers */ = {isa = PBXBuildFile; fileRef = F1B918F01BCF23C800710963 /* PINRemoteImageCallbacks.h */; }; + 139D50AA1F672BBF00DE64E0 /* PINRemoteImageDownloadTask.h in Headers */ = {isa = PBXBuildFile; fileRef = F1B918F31BCF23C800710963 /* PINRemoteImageDownloadTask.h */; }; + 139D50AB1F672BBF00DE64E0 /* PINRemoteImageProcessorTask.h in Headers */ = {isa = PBXBuildFile; fileRef = F1B918F91BCF23C800710963 /* PINRemoteImageProcessorTask.h */; }; + 139D50AC1F672BBF00DE64E0 /* PINRemoteImageTask.h in Headers */ = {isa = PBXBuildFile; fileRef = F1B918FB1BCF23C800710963 /* PINRemoteImageTask.h */; }; + 139D50AD1F672BBF00DE64E0 /* PINRemoteLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 6858C0731C9CC5BA00E420EB /* PINRemoteLock.h */; }; + 139D50AE1F672BBF00DE64E0 /* PINRemoteImageMemoryContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 68F0EA901CB32EC900F1FD41 /* PINRemoteImageMemoryContainer.h */; }; + 139D50AF1F672BBF00DE64E0 /* PINRemoteImageBasicCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 68CA92791DAEFF93008BECE2 /* PINRemoteImageBasicCache.h */; }; + 139D50B01F672BBF00DE64E0 /* PINRemoteImageDownloadQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 68B1F27F1E679D7A00ED87C4 /* PINRemoteImageDownloadQueue.h */; }; + 139D50B11F672BBF00DE64E0 /* PINResume.h in Headers */ = {isa = PBXBuildFile; fileRef = 68B7E3B01E736C73000FC887 /* PINResume.h */; }; + 139D50B21F672BBF00DE64E0 /* PINSpeedRecorder.h in Headers */ = {isa = PBXBuildFile; fileRef = 6860CB061F578287005E886E /* PINSpeedRecorder.h */; }; + 440872302BFFC55700C053C2 /* PINRemoteImageDataConvertible.h in Headers */ = {isa = PBXBuildFile; fileRef = 4408722F2BFFC4AF00C053C2 /* PINRemoteImageDataConvertible.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 440872312BFFC55B00C053C2 /* PINRemoteImageDataConvertible.h in Headers */ = {isa = PBXBuildFile; fileRef = 4408722F2BFFC4AF00C053C2 /* PINRemoteImageDataConvertible.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57202BF26B6A0005D70F /* NSData+ImageDetectors.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C570A2BF26B6A0005D70F /* NSData+ImageDetectors.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57212BF26B6A0005D70F /* PINAlternateRepresentationProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C570B2BF26B6A0005D70F /* PINAlternateRepresentationProvider.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57222BF26B6A0005D70F /* PINAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C570C2BF26B6A0005D70F /* PINAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57232BF26B6A0005D70F /* PINAnimatedImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C570D2BF26B6A0005D70F /* PINAnimatedImageView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57242BF26B6A0005D70F /* PINAnimatedImageView+PINRemoteImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C570E2BF26B6A0005D70F /* PINAnimatedImageView+PINRemoteImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57252BF26B6A0005D70F /* PINAPNGAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C570F2BF26B6A0005D70F /* PINAPNGAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57262BF26B6A0005D70F /* PINButton+PINRemoteImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C57102BF26B6A0005D70F /* PINButton+PINRemoteImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57272BF26B6A0005D70F /* PINCache+PINRemoteImageCaching.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C57112BF26B6A0005D70F /* PINCache+PINRemoteImageCaching.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57282BF26B6A0005D70F /* PINCachedAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C57122BF26B6A0005D70F /* PINCachedAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57292BF26B6A0005D70F /* PINGIFAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C57132BF26B6A0005D70F /* PINGIFAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C572A2BF26B6A0005D70F /* PINImageView+PINRemoteImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C57142BF26B6A0005D70F /* PINImageView+PINRemoteImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C572B2BF26B6A0005D70F /* PINProgressiveImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C57152BF26B6A0005D70F /* PINProgressiveImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C572C2BF26B6A0005D70F /* PINRemoteImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C57162BF26B6A0005D70F /* PINRemoteImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C572D2BF26B6A0005D70F /* PINRemoteImageCaching.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C57172BF26B6A0005D70F /* PINRemoteImageCaching.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C572E2BF26B6A0005D70F /* PINRemoteImageCategoryManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C57182BF26B6A0005D70F /* PINRemoteImageCategoryManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C572F2BF26B6A0005D70F /* PINRemoteImageMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C57192BF26B6A0005D70F /* PINRemoteImageMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57302BF26B6A0005D70F /* PINRemoteImageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C571A2BF26B6A0005D70F /* PINRemoteImageManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57312BF26B6A0005D70F /* PINRemoteImageManagerResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C571B2BF26B6A0005D70F /* PINRemoteImageManagerResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57322BF26B6A0005D70F /* PINRequestRetryStrategy.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C571C2BF26B6A0005D70F /* PINRequestRetryStrategy.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57332BF26B6A0005D70F /* PINURLSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C571D2BF26B6A0005D70F /* PINURLSessionManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57342BF26B6A0005D70F /* PINWebPAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C571E2BF26B6A0005D70F /* PINWebPAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57392BF280280005D70F /* PINRemoteImageManager+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 680B83C71ECE5F9D00210A55 /* PINRemoteImageManager+Private.h */; }; + 445C574F2BF294410005D70F /* PINRemoteImageCaching.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C57172BF26B6A0005D70F /* PINRemoteImageCaching.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57502BF294410005D70F /* NSData+ImageDetectors.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C570A2BF26B6A0005D70F /* NSData+ImageDetectors.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57512BF294410005D70F /* PINAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C570C2BF26B6A0005D70F /* PINAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57522BF294410005D70F /* PINAnimatedImageView+PINRemoteImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C570E2BF26B6A0005D70F /* PINAnimatedImageView+PINRemoteImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57532BF294410005D70F /* PINRemoteImageManagerResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C571B2BF26B6A0005D70F /* PINRemoteImageManagerResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57542BF294410005D70F /* PINAlternateRepresentationProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C570B2BF26B6A0005D70F /* PINAlternateRepresentationProvider.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57552BF294410005D70F /* PINRemoteImageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C571A2BF26B6A0005D70F /* PINRemoteImageManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57562BF294410005D70F /* PINWebPAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C571E2BF26B6A0005D70F /* PINWebPAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57572BF294410005D70F /* PINAPNGAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C570F2BF26B6A0005D70F /* PINAPNGAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57582BF294410005D70F /* PINImageView+PINRemoteImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C57142BF26B6A0005D70F /* PINImageView+PINRemoteImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57592BF294410005D70F /* PINURLSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C571D2BF26B6A0005D70F /* PINURLSessionManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C575A2BF294410005D70F /* PINButton+PINRemoteImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C57102BF26B6A0005D70F /* PINButton+PINRemoteImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C575B2BF294410005D70F /* PINGIFAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C57132BF26B6A0005D70F /* PINGIFAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C575C2BF294410005D70F /* PINCachedAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C57122BF26B6A0005D70F /* PINCachedAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C575D2BF294410005D70F /* PINCache+PINRemoteImageCaching.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C57112BF26B6A0005D70F /* PINCache+PINRemoteImageCaching.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C575E2BF294410005D70F /* PINRemoteImageMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C57192BF26B6A0005D70F /* PINRemoteImageMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C575F2BF294410005D70F /* PINRequestRetryStrategy.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C571C2BF26B6A0005D70F /* PINRequestRetryStrategy.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57602BF294410005D70F /* PINRemoteImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C57162BF26B6A0005D70F /* PINRemoteImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57612BF294410005D70F /* PINAnimatedImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C570D2BF26B6A0005D70F /* PINAnimatedImageView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57622BF294410005D70F /* PINRemoteImageCategoryManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C57182BF26B6A0005D70F /* PINRemoteImageCategoryManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 445C57632BF294410005D70F /* PINProgressiveImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 445C57152BF26B6A0005D70F /* PINProgressiveImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 447F707E2BF4FD1300C5C956 /* PINImage+ScaledImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 447F707B2BF4FD1300C5C956 /* PINImage+ScaledImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 447F707F2BF4FD1300C5C956 /* PINImage+ScaledImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 447F707B2BF4FD1300C5C956 /* PINImage+ScaledImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 447F70802BF4FD1300C5C956 /* NSHTTPURLResponse+MaxAge.h in Headers */ = {isa = PBXBuildFile; fileRef = 447F707C2BF4FD1300C5C956 /* NSHTTPURLResponse+MaxAge.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 447F70812BF4FD1300C5C956 /* NSHTTPURLResponse+MaxAge.h in Headers */ = {isa = PBXBuildFile; fileRef = 447F707C2BF4FD1300C5C956 /* NSHTTPURLResponse+MaxAge.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 447F70822BF4FD1300C5C956 /* PINImage+DecodedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 447F707D2BF4FD1300C5C956 /* PINImage+DecodedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 447F70832BF4FD1300C5C956 /* PINImage+DecodedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 447F707D2BF4FD1300C5C956 /* PINImage+DecodedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 683128F51F95045200D5B4A8 /* PINAnimatedImage+PINAnimatedImageTesting.m in Sources */ = {isa = PBXBuildFile; fileRef = 683128F41F95045200D5B4A8 /* PINAnimatedImage+PINAnimatedImageTesting.m */; }; + 6858C0751C9CC5BA00E420EB /* PINRemoteLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 6858C0731C9CC5BA00E420EB /* PINRemoteLock.h */; }; + 6858C0761C9CC5BA00E420EB /* PINRemoteLock.m in Sources */ = {isa = PBXBuildFile; fileRef = 6858C0741C9CC5BA00E420EB /* PINRemoteLock.m */; }; + 6860CB081F578287005E886E /* PINSpeedRecorder.h in Headers */ = {isa = PBXBuildFile; fileRef = 6860CB061F578287005E886E /* PINSpeedRecorder.h */; }; + 6860CB091F578287005E886E /* PINSpeedRecorder.m in Sources */ = {isa = PBXBuildFile; fileRef = 6860CB071F578287005E886E /* PINSpeedRecorder.m */; }; + 6864A9221F6D94AF007BB848 /* PINAnimatedImageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6864A9211F6D94AF007BB848 /* PINAnimatedImageTests.swift */; }; + 687750281F6B2305008748B0 /* PINWebPAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 687750261F6B2305008748B0 /* PINWebPAnimatedImage.m */; }; + 68837707252F9D5300B9C290 /* PINCache.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 68837706252F9D5300B9C290 /* PINCache.framework */; }; + 68837709252F9D5300B9C290 /* PINOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 68837708252F9D5300B9C290 /* PINOperation.framework */; }; + 6883770B252F9D7800B9C290 /* PINCache.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6883770A252F9D7800B9C290 /* PINCache.framework */; }; + 6883770D252F9D7800B9C290 /* PINOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6883770C252F9D7800B9C290 /* PINOperation.framework */; }; + 68912D86208FDB4900F5FE0E /* PINRemoteWeakProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 68912D84208FDB4900F5FE0E /* PINRemoteWeakProxy.h */; }; + 68912D87208FDB4900F5FE0E /* PINRemoteWeakProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 68912D84208FDB4900F5FE0E /* PINRemoteWeakProxy.h */; }; + 68912D88208FDB4900F5FE0E /* PINRemoteWeakProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 68912D85208FDB4900F5FE0E /* PINRemoteWeakProxy.m */; }; + 68912D89208FDB4900F5FE0E /* PINRemoteWeakProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 68912D85208FDB4900F5FE0E /* PINRemoteWeakProxy.m */; }; + 689613D8208FD89900D2095C /* PINAnimatedImageView+PINRemoteImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 689613D2208FD89900D2095C /* PINAnimatedImageView+PINRemoteImage.m */; }; + 689613D9208FD89900D2095C /* PINAnimatedImageView+PINRemoteImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 689613D2208FD89900D2095C /* PINAnimatedImageView+PINRemoteImage.m */; }; + 689613DE208FD8B700D2095C /* PINAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 689613DC208FD8B600D2095C /* PINAnimatedImageView.m */; }; + 689613DF208FD8B700D2095C /* PINAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 689613DC208FD8B600D2095C /* PINAnimatedImageView.m */; }; + 689613E4208FD90B00D2095C /* PINDisplayLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 689613E2208FD90A00D2095C /* PINDisplayLink.h */; }; + 689613E5208FD90B00D2095C /* PINDisplayLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 689613E2208FD90A00D2095C /* PINDisplayLink.h */; }; + 689613E6208FD90B00D2095C /* PINDisplayLink.m in Sources */ = {isa = PBXBuildFile; fileRef = 689613E3208FD90B00D2095C /* PINDisplayLink.m */; }; + 689613E7208FD90B00D2095C /* PINDisplayLink.m in Sources */ = {isa = PBXBuildFile; fileRef = 689613E3208FD90B00D2095C /* PINDisplayLink.m */; }; + 68A0FC1C1E523434000B552D /* PINRemoteImageTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 68A0FC1B1E523434000B552D /* PINRemoteImageTests.m */; }; + 68A0FC1E1E523434000B552D /* PINRemoteImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F1B918D11BCF239200710963 /* PINRemoteImage.framework */; }; + 68A6B1DB1E5248BF003A92D1 /* PINImage+ScaledImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 68A6B1D91E5248BF003A92D1 /* PINImage+ScaledImage.m */; }; + 68B1F2811E679D7A00ED87C4 /* PINRemoteImageDownloadQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 68B1F27F1E679D7A00ED87C4 /* PINRemoteImageDownloadQueue.h */; }; + 68B1F2821E679D7A00ED87C4 /* PINRemoteImageDownloadQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 68B1F2801E679D7A00ED87C4 /* PINRemoteImageDownloadQueue.m */; }; + 68B7E3B21E736C73000FC887 /* PINResume.h in Headers */ = {isa = PBXBuildFile; fileRef = 68B7E3B01E736C73000FC887 /* PINResume.h */; }; + 68B7E3B31E736C73000FC887 /* PINResume.m in Sources */ = {isa = PBXBuildFile; fileRef = 68B7E3B11E736C73000FC887 /* PINResume.m */; }; + 68C155CC1F6EE0A20075EE40 /* PINCachedAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 68C155CA1F6EE0A20075EE40 /* PINCachedAnimatedImage.m */; }; + 68C155D71F6EE8890075EE40 /* PINAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 68C155D51F6EE8890075EE40 /* PINAnimatedImage.m */; }; + 68C155DD1F6F202F0075EE40 /* PINGIFAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 68C155DB1F6F202F0075EE40 /* PINGIFAnimatedImage.m */; }; + 68CA927C1DAEFF93008BECE2 /* PINRemoteImageBasicCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 68CA92791DAEFF93008BECE2 /* PINRemoteImageBasicCache.h */; }; + 68CA927D1DAEFF93008BECE2 /* PINRemoteImageBasicCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 68CA927A1DAEFF93008BECE2 /* PINRemoteImageBasicCache.m */; }; + 68CA92841DB19C20008BECE2 /* PINCache+PINRemoteImageCaching.m in Sources */ = {isa = PBXBuildFile; fileRef = 68CA92821DB19C20008BECE2 /* PINCache+PINRemoteImageCaching.m */; }; + 68D7344C1F75FDCF00B9C95D /* PINAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 68C155D51F6EE8890075EE40 /* PINAnimatedImage.m */; }; + 68D7344E1F75FDDB00B9C95D /* PINCachedAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 68C155CA1F6EE0A20075EE40 /* PINCachedAnimatedImage.m */; }; + 68D734521F75FDEA00B9C95D /* PINGIFAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 68C155DB1F6F202F0075EE40 /* PINGIFAnimatedImage.m */; }; + 68F0EA931CB32EC900F1FD41 /* PINAlternateRepresentationProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 68F0EA8F1CB32EC900F1FD41 /* PINAlternateRepresentationProvider.m */; }; + 68F0EA941CB32EC900F1FD41 /* PINRemoteImageMemoryContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 68F0EA901CB32EC900F1FD41 /* PINRemoteImageMemoryContainer.h */; }; + 68F0EA951CB32EC900F1FD41 /* PINRemoteImageMemoryContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 68F0EA911CB32EC900F1FD41 /* PINRemoteImageMemoryContainer.m */; }; + 84CA25F929FB269F0038CFA1 /* PINRemoteImageManager+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 680B83C71ECE5F9D00210A55 /* PINRemoteImageManager+Private.h */; }; + 926E01641F0DFEE800874D01 /* PINRequestRetryStrategy.m in Sources */ = {isa = PBXBuildFile; fileRef = 926E015D1F0DFCAE00874D01 /* PINRequestRetryStrategy.m */; }; + 938E98D52224775600029E4D /* PINRemoteImageManagerConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 939546BE2220AF84006031BB /* PINRemoteImageManagerConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 938E98DA2224775B00029E4D /* PINRemoteImageManagerConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 939546BF2220AF84006031BB /* PINRemoteImageManagerConfiguration.m */; }; + 939546C02220AF84006031BB /* PINRemoteImageManagerConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 939546BE2220AF84006031BB /* PINRemoteImageManagerConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 939546C12220AF84006031BB /* PINRemoteImageManagerConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 939546BF2220AF84006031BB /* PINRemoteImageManagerConfiguration.m */; }; + 9DD47F9D1C699F4B00F12CA0 /* PINButton+PINRemoteImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DD47F991C699F4B00F12CA0 /* PINButton+PINRemoteImage.m */; }; + 9DD47F9F1C699F4B00F12CA0 /* PINImageView+PINRemoteImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DD47F9B1C699F4B00F12CA0 /* PINImageView+PINRemoteImage.m */; }; + 9DD47FA51C699FDC00F12CA0 /* PINImage+DecodedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DD47FA11C699FDC00F12CA0 /* PINImage+DecodedImage.m */; }; + A7343C5B228993D100972894 /* NSHTTPURLResponse+MaxAge.m in Sources */ = {isa = PBXBuildFile; fileRef = ACD28EAE81695DDF84BB76B8 /* NSHTTPURLResponse+MaxAge.m */; }; + A7343C60228993F400972894 /* NSHTTPURLResponse+MaxAge.m in Sources */ = {isa = PBXBuildFile; fileRef = ACD28EAE81695DDF84BB76B8 /* NSHTTPURLResponse+MaxAge.m */; }; + ACD28AB87FABF6BA3B9BF4E4 /* NSDate+PINCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = ACD28D963D79EEC14EE071CE /* NSDate+PINCacheTests.m */; }; + B5BB4023274DB69F0042AE1D /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B5BB4022274DB69F0042AE1D /* Media.xcassets */; }; + B5BB4024274DB69F0042AE1D /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B5BB4022274DB69F0042AE1D /* Media.xcassets */; }; + D93A340224182D46005EB15E /* TestAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D93A340124182D46005EB15E /* TestAnimatedImage.m */; }; + D93A340324182D46005EB15E /* TestAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D93A340124182D46005EB15E /* TestAnimatedImage.m */; }; + F1B918FF1BCF23C900710963 /* PINRemoteImageCategoryManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918DC1BCF23C800710963 /* PINRemoteImageCategoryManager.m */; }; + F1B919011BCF23C900710963 /* NSData+ImageDetectors.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918DF1BCF23C800710963 /* NSData+ImageDetectors.m */; }; + F1B9190F1BCF23C900710963 /* PINProgressiveImage.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918EE1BCF23C800710963 /* PINProgressiveImage.m */; }; + F1B919111BCF23C900710963 /* PINRemoteImageCallbacks.h in Headers */ = {isa = PBXBuildFile; fileRef = F1B918F01BCF23C800710963 /* PINRemoteImageCallbacks.h */; }; + F1B919121BCF23C900710963 /* PINRemoteImageCallbacks.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918F11BCF23C800710963 /* PINRemoteImageCallbacks.m */; }; + F1B919141BCF23C900710963 /* PINRemoteImageDownloadTask.h in Headers */ = {isa = PBXBuildFile; fileRef = F1B918F31BCF23C800710963 /* PINRemoteImageDownloadTask.h */; }; + F1B919151BCF23C900710963 /* PINRemoteImageDownloadTask.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918F41BCF23C800710963 /* PINRemoteImageDownloadTask.m */; }; + F1B919171BCF23C900710963 /* PINRemoteImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918F61BCF23C800710963 /* PINRemoteImageManager.m */; }; + F1B919191BCF23C900710963 /* PINRemoteImageManagerResult.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918F81BCF23C800710963 /* PINRemoteImageManagerResult.m */; }; + F1B9191A1BCF23C900710963 /* PINRemoteImageProcessorTask.h in Headers */ = {isa = PBXBuildFile; fileRef = F1B918F91BCF23C800710963 /* PINRemoteImageProcessorTask.h */; }; + F1B9191B1BCF23C900710963 /* PINRemoteImageProcessorTask.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918FA1BCF23C800710963 /* PINRemoteImageProcessorTask.m */; }; + F1B9191C1BCF23C900710963 /* PINRemoteImageTask.h in Headers */ = {isa = PBXBuildFile; fileRef = F1B918FB1BCF23C800710963 /* PINRemoteImageTask.h */; }; + F1B9191D1BCF23C900710963 /* PINRemoteImageTask.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918FC1BCF23C800710963 /* PINRemoteImageTask.m */; }; + F1B9191F1BCF23C900710963 /* PINURLSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918FE1BCF23C900710963 /* PINURLSessionManager.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 139D3A641F67284400F82935 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = F1B918C81BCF239200710963 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 139D3A591F67284400F82935; + remoteInfo = "PINRemoteImage-tvOS"; + }; + 68A0FC1F1E523434000B552D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = F1B918C81BCF239200710963 /* Project object */; + proxyType = 1; + remoteGlobalIDString = F1B918D01BCF239200710963; + remoteInfo = "PINRemoteImage-iOS"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 687BB0B11E527EBC005D70C6 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0CF0743524093139008F126B /* PINAPNGAnimatedImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINAPNGAnimatedImage.m; sourceTree = ""; }; + 0E71BE2522E94C7200FC5B99 /* fireworks.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = fireworks.gif; sourceTree = ""; }; + 139D3A5A1F67284400F82935 /* PINRemoteImage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PINRemoteImage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 139D3A621F67284400F82935 /* PINRemoteImage-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "PINRemoteImage-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 4408722F2BFFC4AF00C053C2 /* PINRemoteImageDataConvertible.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageDataConvertible.h; sourceTree = ""; }; + 4419469E2BF3AAF100E7A59C /* WebP.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = WebP.xcframework; path = webp/WebP.xcframework; sourceTree = ""; }; + 441946A12BF3AB6500E7A59C /* WebPDemux.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = WebPDemux.xcframework; path = webp/WebPDemux.xcframework; sourceTree = ""; }; + 445C570A2BF26B6A0005D70F /* NSData+ImageDetectors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+ImageDetectors.h"; sourceTree = ""; }; + 445C570B2BF26B6A0005D70F /* PINAlternateRepresentationProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINAlternateRepresentationProvider.h; sourceTree = ""; }; + 445C570C2BF26B6A0005D70F /* PINAnimatedImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINAnimatedImage.h; sourceTree = ""; }; + 445C570D2BF26B6A0005D70F /* PINAnimatedImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINAnimatedImageView.h; sourceTree = ""; }; + 445C570E2BF26B6A0005D70F /* PINAnimatedImageView+PINRemoteImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PINAnimatedImageView+PINRemoteImage.h"; sourceTree = ""; }; + 445C570F2BF26B6A0005D70F /* PINAPNGAnimatedImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINAPNGAnimatedImage.h; sourceTree = ""; }; + 445C57102BF26B6A0005D70F /* PINButton+PINRemoteImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PINButton+PINRemoteImage.h"; sourceTree = ""; }; + 445C57112BF26B6A0005D70F /* PINCache+PINRemoteImageCaching.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PINCache+PINRemoteImageCaching.h"; sourceTree = ""; }; + 445C57122BF26B6A0005D70F /* PINCachedAnimatedImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINCachedAnimatedImage.h; sourceTree = ""; }; + 445C57132BF26B6A0005D70F /* PINGIFAnimatedImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINGIFAnimatedImage.h; sourceTree = ""; }; + 445C57142BF26B6A0005D70F /* PINImageView+PINRemoteImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PINImageView+PINRemoteImage.h"; sourceTree = ""; }; + 445C57152BF26B6A0005D70F /* PINProgressiveImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINProgressiveImage.h; sourceTree = ""; }; + 445C57162BF26B6A0005D70F /* PINRemoteImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINRemoteImage.h; sourceTree = ""; }; + 445C57172BF26B6A0005D70F /* PINRemoteImageCaching.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageCaching.h; sourceTree = ""; }; + 445C57182BF26B6A0005D70F /* PINRemoteImageCategoryManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageCategoryManager.h; sourceTree = ""; }; + 445C57192BF26B6A0005D70F /* PINRemoteImageMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageMacros.h; sourceTree = ""; }; + 445C571A2BF26B6A0005D70F /* PINRemoteImageManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageManager.h; sourceTree = ""; }; + 445C571B2BF26B6A0005D70F /* PINRemoteImageManagerResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageManagerResult.h; sourceTree = ""; }; + 445C571C2BF26B6A0005D70F /* PINRequestRetryStrategy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINRequestRetryStrategy.h; sourceTree = ""; }; + 445C571D2BF26B6A0005D70F /* PINURLSessionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINURLSessionManager.h; sourceTree = ""; }; + 445C571E2BF26B6A0005D70F /* PINWebPAnimatedImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINWebPAnimatedImage.h; sourceTree = ""; }; + 445C574C2BF285D70005D70F /* libwebp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = libwebp.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 447F707B2BF4FD1300C5C956 /* PINImage+ScaledImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PINImage+ScaledImage.h"; sourceTree = ""; }; + 447F707C2BF4FD1300C5C956 /* NSHTTPURLResponse+MaxAge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSHTTPURLResponse+MaxAge.h"; sourceTree = ""; }; + 447F707D2BF4FD1300C5C956 /* PINImage+DecodedImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PINImage+DecodedImage.h"; sourceTree = ""; }; + 680B83C71ECE5F9D00210A55 /* PINRemoteImageManager+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "PINRemoteImageManager+Private.h"; path = "../PINRemoteImageManager+Private.h"; sourceTree = ""; }; + 6818C1541E551B5A00875DB7 /* PINCache.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PINCache.framework; path = "Carthage/Checkouts/PINCache/build/Debug-iphoneos/PINCache.framework"; sourceTree = ""; }; + 6818C1561E551BAB00875DB7 /* PINOperation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PINOperation.framework; path = "Carthage/Checkouts/PINOperation/build/Debug-iphoneos/PINOperation.framework"; sourceTree = ""; }; + 683128F31F95045200D5B4A8 /* PINAnimatedImage+PINAnimatedImageTesting.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PINAnimatedImage+PINAnimatedImageTesting.h"; sourceTree = ""; }; + 683128F41F95045200D5B4A8 /* PINAnimatedImage+PINAnimatedImageTesting.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "PINAnimatedImage+PINAnimatedImageTesting.m"; sourceTree = ""; }; + 6858C0731C9CC5BA00E420EB /* PINRemoteLock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINRemoteLock.h; sourceTree = ""; }; + 6858C0741C9CC5BA00E420EB /* PINRemoteLock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINRemoteLock.m; sourceTree = ""; }; + 6860CB061F578287005E886E /* PINSpeedRecorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINSpeedRecorder.h; sourceTree = ""; }; + 6860CB071F578287005E886E /* PINSpeedRecorder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINSpeedRecorder.m; sourceTree = ""; }; + 6864A9201F6D94AF007BB848 /* PINRemoteImageTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PINRemoteImageTests-Bridging-Header.h"; sourceTree = ""; }; + 6864A9211F6D94AF007BB848 /* PINAnimatedImageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PINAnimatedImageTests.swift; sourceTree = ""; }; + 687750261F6B2305008748B0 /* PINWebPAnimatedImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINWebPAnimatedImage.m; sourceTree = ""; }; + 687D3FC81E5650790027B131 /* PINOperation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PINOperation.framework; path = "Carthage/Checkouts/PINCache/Carthage/Checkouts/PINOperation/build/Debug-iphoneos/PINOperation.framework"; sourceTree = ""; }; + 68837706252F9D5300B9C290 /* PINCache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PINCache.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 68837708252F9D5300B9C290 /* PINOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PINOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 6883770A252F9D7800B9C290 /* PINCache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PINCache.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 6883770C252F9D7800B9C290 /* PINOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PINOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 68912D84208FDB4900F5FE0E /* PINRemoteWeakProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PINRemoteWeakProxy.h; sourceTree = ""; }; + 68912D85208FDB4900F5FE0E /* PINRemoteWeakProxy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PINRemoteWeakProxy.m; sourceTree = ""; }; + 689613D2208FD89900D2095C /* PINAnimatedImageView+PINRemoteImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "PINAnimatedImageView+PINRemoteImage.m"; sourceTree = ""; }; + 689613DC208FD8B600D2095C /* PINAnimatedImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINAnimatedImageView.m; sourceTree = ""; }; + 689613E2208FD90A00D2095C /* PINDisplayLink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINDisplayLink.h; sourceTree = ""; }; + 689613E3208FD90B00D2095C /* PINDisplayLink.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINDisplayLink.m; sourceTree = ""; }; + 68A0FC191E523434000B552D /* PINRemoteImageTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PINRemoteImageTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 68A0FC1B1E523434000B552D /* PINRemoteImageTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageTests.m; sourceTree = ""; }; + 68A0FC1D1E523434000B552D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 68A6B1D91E5248BF003A92D1 /* PINImage+ScaledImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "PINImage+ScaledImage.m"; sourceTree = ""; }; + 68B1F27F1E679D7A00ED87C4 /* PINRemoteImageDownloadQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageDownloadQueue.h; sourceTree = ""; }; + 68B1F2801E679D7A00ED87C4 /* PINRemoteImageDownloadQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageDownloadQueue.m; sourceTree = ""; }; + 68B7E3B01E736C73000FC887 /* PINResume.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINResume.h; sourceTree = ""; }; + 68B7E3B11E736C73000FC887 /* PINResume.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINResume.m; sourceTree = ""; }; + 68C155CA1F6EE0A20075EE40 /* PINCachedAnimatedImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PINCachedAnimatedImage.m; sourceTree = ""; }; + 68C155D51F6EE8890075EE40 /* PINAnimatedImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PINAnimatedImage.m; sourceTree = ""; }; + 68C155DB1F6F202F0075EE40 /* PINGIFAnimatedImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PINGIFAnimatedImage.m; sourceTree = ""; }; + 68CA92791DAEFF93008BECE2 /* PINRemoteImageBasicCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageBasicCache.h; sourceTree = ""; }; + 68CA927A1DAEFF93008BECE2 /* PINRemoteImageBasicCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageBasicCache.m; sourceTree = ""; }; + 68CA92821DB19C20008BECE2 /* PINCache+PINRemoteImageCaching.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "PINCache+PINRemoteImageCaching.m"; path = "PINCache/PINCache+PINRemoteImageCaching.m"; sourceTree = ""; }; + 68F0EA8F1CB32EC900F1FD41 /* PINAlternateRepresentationProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINAlternateRepresentationProvider.m; sourceTree = ""; }; + 68F0EA901CB32EC900F1FD41 /* PINRemoteImageMemoryContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageMemoryContainer.h; sourceTree = ""; }; + 68F0EA911CB32EC900F1FD41 /* PINRemoteImageMemoryContainer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageMemoryContainer.m; sourceTree = ""; }; + 926E015D1F0DFCAE00874D01 /* PINRequestRetryStrategy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PINRequestRetryStrategy.m; sourceTree = ""; }; + 939546BE2220AF84006031BB /* PINRemoteImageManagerConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageManagerConfiguration.h; sourceTree = ""; }; + 939546BF2220AF84006031BB /* PINRemoteImageManagerConfiguration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageManagerConfiguration.m; sourceTree = ""; }; + 9DD47F991C699F4B00F12CA0 /* PINButton+PINRemoteImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "PINButton+PINRemoteImage.m"; sourceTree = ""; }; + 9DD47F9B1C699F4B00F12CA0 /* PINImageView+PINRemoteImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "PINImageView+PINRemoteImage.m"; sourceTree = ""; }; + 9DD47FA11C699FDC00F12CA0 /* PINImage+DecodedImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "PINImage+DecodedImage.m"; sourceTree = ""; }; + ACD288C6E6B13E6DA226D252 /* NSDate+PINCacheTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+PINCacheTests.h"; sourceTree = ""; }; + ACD28D963D79EEC14EE071CE /* NSDate+PINCacheTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDate+PINCacheTests.m"; sourceTree = ""; }; + ACD28EAE81695DDF84BB76B8 /* NSHTTPURLResponse+MaxAge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSHTTPURLResponse+MaxAge.m"; sourceTree = ""; }; + B5BB4022274DB69F0042AE1D /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = ""; }; + D93A340024182D46005EB15E /* TestAnimatedImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestAnimatedImage.h; sourceTree = ""; }; + D93A340124182D46005EB15E /* TestAnimatedImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestAnimatedImage.m; sourceTree = ""; }; + F1B918D11BCF239200710963 /* PINRemoteImage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PINRemoteImage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F1B918D61BCF239200710963 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + F1B918DC1BCF23C800710963 /* PINRemoteImageCategoryManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageCategoryManager.m; sourceTree = ""; }; + F1B918DF1BCF23C800710963 /* NSData+ImageDetectors.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+ImageDetectors.m"; sourceTree = ""; }; + F1B918EE1BCF23C800710963 /* PINProgressiveImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINProgressiveImage.m; sourceTree = ""; }; + F1B918F01BCF23C800710963 /* PINRemoteImageCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageCallbacks.h; sourceTree = ""; }; + F1B918F11BCF23C800710963 /* PINRemoteImageCallbacks.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageCallbacks.m; sourceTree = ""; }; + F1B918F31BCF23C800710963 /* PINRemoteImageDownloadTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageDownloadTask.h; sourceTree = ""; }; + F1B918F41BCF23C800710963 /* PINRemoteImageDownloadTask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageDownloadTask.m; sourceTree = ""; }; + F1B918F61BCF23C800710963 /* PINRemoteImageManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageManager.m; sourceTree = ""; }; + F1B918F81BCF23C800710963 /* PINRemoteImageManagerResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageManagerResult.m; sourceTree = ""; }; + F1B918F91BCF23C800710963 /* PINRemoteImageProcessorTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageProcessorTask.h; sourceTree = ""; }; + F1B918FA1BCF23C800710963 /* PINRemoteImageProcessorTask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageProcessorTask.m; sourceTree = ""; }; + F1B918FB1BCF23C800710963 /* PINRemoteImageTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINRemoteImageTask.h; sourceTree = ""; }; + F1B918FC1BCF23C800710963 /* PINRemoteImageTask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINRemoteImageTask.m; sourceTree = ""; }; + F1B918FE1BCF23C900710963 /* PINURLSessionManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINURLSessionManager.m; sourceTree = ""; }; + F1E3658B1BE04112003BF022 /* PINRemoteImage.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = PINRemoteImage.modulemap; sourceTree = ""; }; + F370FD6524AD0F6D0026A9D9 /* WebPDemux.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebPDemux.framework; path = webp/WebPDemux.framework; sourceTree = ""; }; + F370FD6824AD0F920026A9D9 /* WebPDecoder.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebPDecoder.framework; path = webp/WebPDecoder.framework; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 139D3A561F67284400F82935 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6883770B252F9D7800B9C290 /* PINCache.framework in Frameworks */, + 6883770D252F9D7800B9C290 /* PINOperation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 139D3A5F1F67284400F82935 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 139D3A631F67284400F82935 /* PINRemoteImage.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 68A0FC161E523434000B552D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 68A0FC1E1E523434000B552D /* PINRemoteImage.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F1B918CD1BCF239200710963 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 68837709252F9D5300B9C290 /* PINOperation.framework in Frameworks */, + 68837707252F9D5300B9C290 /* PINCache.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 445C571F2BF26B6A0005D70F /* PINRemoteImage */ = { + isa = PBXGroup; + children = ( + 445C570A2BF26B6A0005D70F /* NSData+ImageDetectors.h */, + 445C570B2BF26B6A0005D70F /* PINAlternateRepresentationProvider.h */, + 445C570C2BF26B6A0005D70F /* PINAnimatedImage.h */, + 445C570D2BF26B6A0005D70F /* PINAnimatedImageView.h */, + 445C570E2BF26B6A0005D70F /* PINAnimatedImageView+PINRemoteImage.h */, + 445C570F2BF26B6A0005D70F /* PINAPNGAnimatedImage.h */, + 445C57102BF26B6A0005D70F /* PINButton+PINRemoteImage.h */, + 445C57112BF26B6A0005D70F /* PINCache+PINRemoteImageCaching.h */, + 445C57122BF26B6A0005D70F /* PINCachedAnimatedImage.h */, + 445C57132BF26B6A0005D70F /* PINGIFAnimatedImage.h */, + 445C57142BF26B6A0005D70F /* PINImageView+PINRemoteImage.h */, + 445C57152BF26B6A0005D70F /* PINProgressiveImage.h */, + 445C57162BF26B6A0005D70F /* PINRemoteImage.h */, + 445C57172BF26B6A0005D70F /* PINRemoteImageCaching.h */, + 445C57182BF26B6A0005D70F /* PINRemoteImageCategoryManager.h */, + 445C57192BF26B6A0005D70F /* PINRemoteImageMacros.h */, + 445C571A2BF26B6A0005D70F /* PINRemoteImageManager.h */, + 445C571B2BF26B6A0005D70F /* PINRemoteImageManagerResult.h */, + 4408722F2BFFC4AF00C053C2 /* PINRemoteImageDataConvertible.h */, + 445C571C2BF26B6A0005D70F /* PINRequestRetryStrategy.h */, + 445C571D2BF26B6A0005D70F /* PINURLSessionManager.h */, + 445C571E2BF26B6A0005D70F /* PINWebPAnimatedImage.h */, + 447F707C2BF4FD1300C5C956 /* NSHTTPURLResponse+MaxAge.h */, + 939546BE2220AF84006031BB /* PINRemoteImageManagerConfiguration.h */, + 447F707D2BF4FD1300C5C956 /* PINImage+DecodedImage.h */, + 447F707B2BF4FD1300C5C956 /* PINImage+ScaledImage.h */, + ); + path = PINRemoteImage; + sourceTree = ""; + }; + 6818C1531E551B5900875DB7 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 441946A12BF3AB6500E7A59C /* WebPDemux.xcframework */, + 4419469E2BF3AAF100E7A59C /* WebP.xcframework */, + 445C574C2BF285D70005D70F /* libwebp.framework */, + 6883770A252F9D7800B9C290 /* PINCache.framework */, + 6883770C252F9D7800B9C290 /* PINOperation.framework */, + 68837706252F9D5300B9C290 /* PINCache.framework */, + 68837708252F9D5300B9C290 /* PINOperation.framework */, + F370FD6824AD0F920026A9D9 /* WebPDecoder.framework */, + F370FD6524AD0F6D0026A9D9 /* WebPDemux.framework */, + 687D3FC81E5650790027B131 /* PINOperation.framework */, + 6818C1561E551BAB00875DB7 /* PINOperation.framework */, + 6818C1541E551B5A00875DB7 /* PINCache.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 68A0FC1A1E523434000B552D /* Tests */ = { + isa = PBXGroup; + children = ( + 0E71BE2522E94C7200FC5B99 /* fireworks.gif */, + 68A0FC1B1E523434000B552D /* PINRemoteImageTests.m */, + 6864A9211F6D94AF007BB848 /* PINAnimatedImageTests.swift */, + D93A340024182D46005EB15E /* TestAnimatedImage.h */, + D93A340124182D46005EB15E /* TestAnimatedImage.m */, + 68A0FC1D1E523434000B552D /* Info.plist */, + 6864A9201F6D94AF007BB848 /* PINRemoteImageTests-Bridging-Header.h */, + 683128F31F95045200D5B4A8 /* PINAnimatedImage+PINAnimatedImageTesting.h */, + 683128F41F95045200D5B4A8 /* PINAnimatedImage+PINAnimatedImageTesting.m */, + ACD288C6E6B13E6DA226D252 /* NSDate+PINCacheTests.h */, + ACD28D963D79EEC14EE071CE /* NSDate+PINCacheTests.m */, + B5BB4022274DB69F0042AE1D /* Media.xcassets */, + ); + path = Tests; + sourceTree = ""; + }; + 68C155D21F6EE3450075EE40 /* AnimatedImages */ = { + isa = PBXGroup; + children = ( + 68C155D51F6EE8890075EE40 /* PINAnimatedImage.m */, + 689613DC208FD8B600D2095C /* PINAnimatedImageView.m */, + 68C155CA1F6EE0A20075EE40 /* PINCachedAnimatedImage.m */, + 687750261F6B2305008748B0 /* PINWebPAnimatedImage.m */, + 68C155DB1F6F202F0075EE40 /* PINGIFAnimatedImage.m */, + 0CF0743524093139008F126B /* PINAPNGAnimatedImage.m */, + ); + path = AnimatedImages; + sourceTree = ""; + }; + 68C155D31F6EE3BE0075EE40 /* AnimatedImages */ = { + isa = PBXGroup; + children = ( + ); + path = AnimatedImages; + sourceTree = ""; + }; + 68CA92801DB19C06008BECE2 /* PINCache */ = { + isa = PBXGroup; + children = ( + 68CA92821DB19C20008BECE2 /* PINCache+PINRemoteImageCaching.m */, + ); + name = PINCache; + sourceTree = ""; + }; + 68EB25221C6A64BE002501A3 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + F1B918D61BCF239200710963 /* Info.plist */, + F1E3658B1BE04112003BF022 /* PINRemoteImage.modulemap */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + CC4243F61E62051900FD6517 /* Categories */ = { + isa = PBXGroup; + children = ( + F1B918DF1BCF23C800710963 /* NSData+ImageDetectors.m */, + ); + path = Categories; + sourceTree = ""; + }; + F165DFD61BD021E30008C6E8 /* Public */ = { + isa = PBXGroup; + children = ( + FBC820802526277E007FD40D /* include */, + 68C155D21F6EE3450075EE40 /* AnimatedImages */, + F1B918E41BCF23C800710963 /* ImageCategories */, + CC4243F61E62051900FD6517 /* Categories */, + 68CA92801DB19C06008BECE2 /* PINCache */, + 68F0EA8F1CB32EC900F1FD41 /* PINAlternateRepresentationProvider.m */, + F1B918EE1BCF23C800710963 /* PINProgressiveImage.m */, + F1B918DC1BCF23C800710963 /* PINRemoteImageCategoryManager.m */, + F1B918F61BCF23C800710963 /* PINRemoteImageManager.m */, + 939546BF2220AF84006031BB /* PINRemoteImageManagerConfiguration.m */, + F1B918F81BCF23C800710963 /* PINRemoteImageManagerResult.m */, + F1B918FE1BCF23C900710963 /* PINURLSessionManager.m */, + 926E015D1F0DFCAE00874D01 /* PINRequestRetryStrategy.m */, + ); + name = Public; + path = Classes; + sourceTree = ""; + }; + F165DFD71BD021EE0008C6E8 /* Project */ = { + isa = PBXGroup; + children = ( + 68C155D31F6EE3BE0075EE40 /* AnimatedImages */, + F1B918DD1BCF23C800710963 /* Categories */, + 689613E2208FD90A00D2095C /* PINDisplayLink.h */, + 689613E3208FD90B00D2095C /* PINDisplayLink.m */, + F1B918F01BCF23C800710963 /* PINRemoteImageCallbacks.h */, + F1B918F11BCF23C800710963 /* PINRemoteImageCallbacks.m */, + F1B918F31BCF23C800710963 /* PINRemoteImageDownloadTask.h */, + F1B918F41BCF23C800710963 /* PINRemoteImageDownloadTask.m */, + F1B918F91BCF23C800710963 /* PINRemoteImageProcessorTask.h */, + F1B918FA1BCF23C800710963 /* PINRemoteImageProcessorTask.m */, + F1B918FB1BCF23C800710963 /* PINRemoteImageTask.h */, + F1B918FC1BCF23C800710963 /* PINRemoteImageTask.m */, + 6858C0731C9CC5BA00E420EB /* PINRemoteLock.h */, + 6858C0741C9CC5BA00E420EB /* PINRemoteLock.m */, + 68F0EA901CB32EC900F1FD41 /* PINRemoteImageMemoryContainer.h */, + 68F0EA911CB32EC900F1FD41 /* PINRemoteImageMemoryContainer.m */, + 68CA92791DAEFF93008BECE2 /* PINRemoteImageBasicCache.h */, + 68CA927A1DAEFF93008BECE2 /* PINRemoteImageBasicCache.m */, + 68B1F27F1E679D7A00ED87C4 /* PINRemoteImageDownloadQueue.h */, + 68B1F2801E679D7A00ED87C4 /* PINRemoteImageDownloadQueue.m */, + 68912D84208FDB4900F5FE0E /* PINRemoteWeakProxy.h */, + 68912D85208FDB4900F5FE0E /* PINRemoteWeakProxy.m */, + 68B7E3B01E736C73000FC887 /* PINResume.h */, + 68B7E3B11E736C73000FC887 /* PINResume.m */, + 6860CB061F578287005E886E /* PINSpeedRecorder.h */, + 6860CB071F578287005E886E /* PINSpeedRecorder.m */, + ); + name = Project; + path = Classes; + sourceTree = ""; + }; + F1B918C71BCF239200710963 = { + isa = PBXGroup; + children = ( + F1B918D31BCF239200710963 /* PINRemoteImage */, + 68A0FC1A1E523434000B552D /* Tests */, + F1B918D21BCF239200710963 /* Products */, + 6818C1531E551B5900875DB7 /* Frameworks */, + ); + sourceTree = ""; + usesTabs = 0; + }; + F1B918D21BCF239200710963 /* Products */ = { + isa = PBXGroup; + children = ( + F1B918D11BCF239200710963 /* PINRemoteImage.framework */, + 68A0FC191E523434000B552D /* PINRemoteImageTests.xctest */, + 139D3A5A1F67284400F82935 /* PINRemoteImage.framework */, + 139D3A621F67284400F82935 /* PINRemoteImage-tvOSTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + F1B918D31BCF239200710963 /* PINRemoteImage */ = { + isa = PBXGroup; + children = ( + F165DFD61BD021E30008C6E8 /* Public */, + F165DFD71BD021EE0008C6E8 /* Project */, + 68EB25221C6A64BE002501A3 /* Supporting Files */, + ); + name = PINRemoteImage; + path = Source; + sourceTree = ""; + }; + F1B918DD1BCF23C800710963 /* Categories */ = { + isa = PBXGroup; + children = ( + 680B83C71ECE5F9D00210A55 /* PINRemoteImageManager+Private.h */, + 68A6B1D91E5248BF003A92D1 /* PINImage+ScaledImage.m */, + 9DD47FA11C699FDC00F12CA0 /* PINImage+DecodedImage.m */, + ACD28EAE81695DDF84BB76B8 /* NSHTTPURLResponse+MaxAge.m */, + ); + path = Categories; + sourceTree = ""; + }; + F1B918E41BCF23C800710963 /* ImageCategories */ = { + isa = PBXGroup; + children = ( + 689613D2208FD89900D2095C /* PINAnimatedImageView+PINRemoteImage.m */, + 9DD47F991C699F4B00F12CA0 /* PINButton+PINRemoteImage.m */, + 9DD47F9B1C699F4B00F12CA0 /* PINImageView+PINRemoteImage.m */, + ); + path = ImageCategories; + sourceTree = ""; + }; + FBC820802526277E007FD40D /* include */ = { + isa = PBXGroup; + children = ( + 445C571F2BF26B6A0005D70F /* PINRemoteImage */, + ); + path = include; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 139D3A571F67284400F82935 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 139D50A91F672BBF00DE64E0 /* PINRemoteImageCallbacks.h in Headers */, + 938E98D52224775600029E4D /* PINRemoteImageManagerConfiguration.h in Headers */, + 445C574F2BF294410005D70F /* PINRemoteImageCaching.h in Headers */, + 445C57502BF294410005D70F /* NSData+ImageDetectors.h in Headers */, + 445C57512BF294410005D70F /* PINAnimatedImage.h in Headers */, + 445C57522BF294410005D70F /* PINAnimatedImageView+PINRemoteImage.h in Headers */, + 445C57532BF294410005D70F /* PINRemoteImageManagerResult.h in Headers */, + 445C57542BF294410005D70F /* PINAlternateRepresentationProvider.h in Headers */, + 440872312BFFC55B00C053C2 /* PINRemoteImageDataConvertible.h in Headers */, + 445C57552BF294410005D70F /* PINRemoteImageManager.h in Headers */, + 445C57562BF294410005D70F /* PINWebPAnimatedImage.h in Headers */, + 445C57572BF294410005D70F /* PINAPNGAnimatedImage.h in Headers */, + 445C57582BF294410005D70F /* PINImageView+PINRemoteImage.h in Headers */, + 445C57592BF294410005D70F /* PINURLSessionManager.h in Headers */, + 447F70812BF4FD1300C5C956 /* NSHTTPURLResponse+MaxAge.h in Headers */, + 445C575A2BF294410005D70F /* PINButton+PINRemoteImage.h in Headers */, + 445C575B2BF294410005D70F /* PINGIFAnimatedImage.h in Headers */, + 445C575C2BF294410005D70F /* PINCachedAnimatedImage.h in Headers */, + 445C575D2BF294410005D70F /* PINCache+PINRemoteImageCaching.h in Headers */, + 445C575E2BF294410005D70F /* PINRemoteImageMacros.h in Headers */, + 445C575F2BF294410005D70F /* PINRequestRetryStrategy.h in Headers */, + 445C57602BF294410005D70F /* PINRemoteImage.h in Headers */, + 445C57612BF294410005D70F /* PINAnimatedImageView.h in Headers */, + 445C57622BF294410005D70F /* PINRemoteImageCategoryManager.h in Headers */, + 445C57632BF294410005D70F /* PINProgressiveImage.h in Headers */, + 139D50AA1F672BBF00DE64E0 /* PINRemoteImageDownloadTask.h in Headers */, + 445C57392BF280280005D70F /* PINRemoteImageManager+Private.h in Headers */, + 139D50AB1F672BBF00DE64E0 /* PINRemoteImageProcessorTask.h in Headers */, + 139D50AC1F672BBF00DE64E0 /* PINRemoteImageTask.h in Headers */, + 139D50AD1F672BBF00DE64E0 /* PINRemoteLock.h in Headers */, + 139D50AE1F672BBF00DE64E0 /* PINRemoteImageMemoryContainer.h in Headers */, + 139D50AF1F672BBF00DE64E0 /* PINRemoteImageBasicCache.h in Headers */, + 139D50B01F672BBF00DE64E0 /* PINRemoteImageDownloadQueue.h in Headers */, + 447F70832BF4FD1300C5C956 /* PINImage+DecodedImage.h in Headers */, + 447F707F2BF4FD1300C5C956 /* PINImage+ScaledImage.h in Headers */, + 139D50B11F672BBF00DE64E0 /* PINResume.h in Headers */, + 139D50B21F672BBF00DE64E0 /* PINSpeedRecorder.h in Headers */, + 68912D87208FDB4900F5FE0E /* PINRemoteWeakProxy.h in Headers */, + 689613E5208FD90B00D2095C /* PINDisplayLink.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F1B918CE1BCF239200710963 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 445C57272BF26B6A0005D70F /* PINCache+PINRemoteImageCaching.h in Headers */, + F1B919111BCF23C900710963 /* PINRemoteImageCallbacks.h in Headers */, + 939546C02220AF84006031BB /* PINRemoteImageManagerConfiguration.h in Headers */, + 445C572F2BF26B6A0005D70F /* PINRemoteImageMacros.h in Headers */, + 84CA25F929FB269F0038CFA1 /* PINRemoteImageManager+Private.h in Headers */, + 689613E4208FD90B00D2095C /* PINDisplayLink.h in Headers */, + 445C57242BF26B6A0005D70F /* PINAnimatedImageView+PINRemoteImage.h in Headers */, + F1B919141BCF23C900710963 /* PINRemoteImageDownloadTask.h in Headers */, + 440872302BFFC55700C053C2 /* PINRemoteImageDataConvertible.h in Headers */, + F1B9191C1BCF23C900710963 /* PINRemoteImageTask.h in Headers */, + 68912D86208FDB4900F5FE0E /* PINRemoteWeakProxy.h in Headers */, + 68F0EA941CB32EC900F1FD41 /* PINRemoteImageMemoryContainer.h in Headers */, + 445C57212BF26B6A0005D70F /* PINAlternateRepresentationProvider.h in Headers */, + F1B9191A1BCF23C900710963 /* PINRemoteImageProcessorTask.h in Headers */, + 6858C0751C9CC5BA00E420EB /* PINRemoteLock.h in Headers */, + 445C57302BF26B6A0005D70F /* PINRemoteImageManager.h in Headers */, + 6860CB081F578287005E886E /* PINSpeedRecorder.h in Headers */, + 447F70802BF4FD1300C5C956 /* NSHTTPURLResponse+MaxAge.h in Headers */, + 445C57232BF26B6A0005D70F /* PINAnimatedImageView.h in Headers */, + 445C57282BF26B6A0005D70F /* PINCachedAnimatedImage.h in Headers */, + 445C57312BF26B6A0005D70F /* PINRemoteImageManagerResult.h in Headers */, + 445C57252BF26B6A0005D70F /* PINAPNGAnimatedImage.h in Headers */, + 445C57322BF26B6A0005D70F /* PINRequestRetryStrategy.h in Headers */, + 68B7E3B21E736C73000FC887 /* PINResume.h in Headers */, + 68CA927C1DAEFF93008BECE2 /* PINRemoteImageBasicCache.h in Headers */, + 445C572B2BF26B6A0005D70F /* PINProgressiveImage.h in Headers */, + 445C572E2BF26B6A0005D70F /* PINRemoteImageCategoryManager.h in Headers */, + 445C572A2BF26B6A0005D70F /* PINImageView+PINRemoteImage.h in Headers */, + 445C57292BF26B6A0005D70F /* PINGIFAnimatedImage.h in Headers */, + 445C57332BF26B6A0005D70F /* PINURLSessionManager.h in Headers */, + 68B1F2811E679D7A00ED87C4 /* PINRemoteImageDownloadQueue.h in Headers */, + 445C57342BF26B6A0005D70F /* PINWebPAnimatedImage.h in Headers */, + 445C57262BF26B6A0005D70F /* PINButton+PINRemoteImage.h in Headers */, + 445C572D2BF26B6A0005D70F /* PINRemoteImageCaching.h in Headers */, + 447F70822BF4FD1300C5C956 /* PINImage+DecodedImage.h in Headers */, + 447F707E2BF4FD1300C5C956 /* PINImage+ScaledImage.h in Headers */, + 445C572C2BF26B6A0005D70F /* PINRemoteImage.h in Headers */, + 445C57202BF26B6A0005D70F /* NSData+ImageDetectors.h in Headers */, + 445C57222BF26B6A0005D70F /* PINAnimatedImage.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 139D3A591F67284400F82935 /* PINRemoteImage-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 139D3A741F67284400F82935 /* Build configuration list for PBXNativeTarget "PINRemoteImage-tvOS" */; + buildPhases = ( + 139D3A551F67284400F82935 /* Sources */, + 139D3A561F67284400F82935 /* Frameworks */, + 139D3A571F67284400F82935 /* Headers */, + 139D3A581F67284400F82935 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "PINRemoteImage-tvOS"; + productName = "PINRemoteImage-tvOS"; + productReference = 139D3A5A1F67284400F82935 /* PINRemoteImage.framework */; + productType = "com.apple.product-type.framework"; + }; + 139D3A611F67284400F82935 /* PINRemoteImage-tvOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 139D3A751F67284400F82935 /* Build configuration list for PBXNativeTarget "PINRemoteImage-tvOSTests" */; + buildPhases = ( + 139D3A5E1F67284400F82935 /* Sources */, + 139D3A5F1F67284400F82935 /* Frameworks */, + 139D3A601F67284400F82935 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 139D3A651F67284400F82935 /* PBXTargetDependency */, + ); + name = "PINRemoteImage-tvOSTests"; + productName = "PINRemoteImage-tvOSTests"; + productReference = 139D3A621F67284400F82935 /* PINRemoteImage-tvOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 68A0FC181E523434000B552D /* PINRemoteImageTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 68A0FC231E523434000B552D /* Build configuration list for PBXNativeTarget "PINRemoteImageTests" */; + buildPhases = ( + 68A0FC151E523434000B552D /* Sources */, + 687BB0B11E527EBC005D70C6 /* CopyFiles */, + 68A0FC161E523434000B552D /* Frameworks */, + 68A0FC171E523434000B552D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 68A0FC201E523434000B552D /* PBXTargetDependency */, + ); + name = PINRemoteImageTests; + productName = PINRemoteImageTests; + productReference = 68A0FC191E523434000B552D /* PINRemoteImageTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + F1B918D01BCF239200710963 /* PINRemoteImage */ = { + isa = PBXNativeTarget; + buildConfigurationList = F1B918D91BCF239200710963 /* Build configuration list for PBXNativeTarget "PINRemoteImage" */; + buildPhases = ( + F1B918CC1BCF239200710963 /* Sources */, + F1B918CD1BCF239200710963 /* Frameworks */, + F1B918CE1BCF239200710963 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PINRemoteImage; + productName = PINRemoteImage; + productReference = F1B918D11BCF239200710963 /* PINRemoteImage.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + F1B918C81BCF239200710963 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1530; + ORGANIZATIONNAME = Pinterest; + TargetAttributes = { + 139D3A591F67284400F82935 = { + CreatedOnToolsVersion = 9.0; + ProvisioningStyle = Automatic; + }; + 139D3A611F67284400F82935 = { + CreatedOnToolsVersion = 9.0; + ProvisioningStyle = Automatic; + }; + 68A0FC181E523434000B552D = { + CreatedOnToolsVersion = 8.2.1; + LastSwiftMigration = 1020; + ProvisioningStyle = Automatic; + }; + F1B918D01BCF239200710963 = { + CreatedOnToolsVersion = 7.0; + }; + }; + }; + buildConfigurationList = F1B918CB1BCF239200710963 /* Build configuration list for PBXProject "PINRemoteImage" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = F1B918C71BCF239200710963; + productRefGroup = F1B918D21BCF239200710963 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + F1B918D01BCF239200710963 /* PINRemoteImage */, + 68A0FC181E523434000B552D /* PINRemoteImageTests */, + 139D3A591F67284400F82935 /* PINRemoteImage-tvOS */, + 139D3A611F67284400F82935 /* PINRemoteImage-tvOSTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 139D3A581F67284400F82935 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 139D3A601F67284400F82935 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B5BB4024274DB69F0042AE1D /* Media.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 68A0FC171E523434000B552D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B5BB4023274DB69F0042AE1D /* Media.xcassets in Resources */, + 0E71BE2A22E94C7200FC5B99 /* fireworks.gif in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 139D3A551F67284400F82935 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 139D4FCA1F672B0D00DE64E0 /* PINButton+PINRemoteImage.m in Sources */, + 139D4FCB1F672B0D00DE64E0 /* PINImageView+PINRemoteImage.m in Sources */, + 139D4FCC1F672B0D00DE64E0 /* NSData+ImageDetectors.m in Sources */, + 139D4FCD1F672B0D00DE64E0 /* PINCache+PINRemoteImageCaching.m in Sources */, + 0CF0743C24093139008F126B /* PINAPNGAnimatedImage.m in Sources */, + 139D4FCE1F672B0D00DE64E0 /* PINAlternateRepresentationProvider.m in Sources */, + 139D4FD01F672B0D00DE64E0 /* PINProgressiveImage.m in Sources */, + 139D4FD11F672B0D00DE64E0 /* PINRemoteImageCategoryManager.m in Sources */, + 139D4FD21F672B0D00DE64E0 /* PINRemoteImageManager.m in Sources */, + 139D4FD31F672B0D00DE64E0 /* PINRemoteImageManagerResult.m in Sources */, + 139D4FD41F672B0D00DE64E0 /* PINURLSessionManager.m in Sources */, + 139D4FD51F672B0D00DE64E0 /* PINRequestRetryStrategy.m in Sources */, + 139D4FD61F672B0D00DE64E0 /* PINImage+ScaledImage.m in Sources */, + 139D4FD71F672B0D00DE64E0 /* PINImage+DecodedImage.m in Sources */, + 139D4FDB1F672B0D00DE64E0 /* PINRemoteImageCallbacks.m in Sources */, + 139D4FDC1F672B0D00DE64E0 /* PINRemoteImageDownloadTask.m in Sources */, + 139D4FDD1F672B0D00DE64E0 /* PINRemoteImageProcessorTask.m in Sources */, + 139D4FDE1F672B0D00DE64E0 /* PINRemoteImageTask.m in Sources */, + 139D4FDF1F672B0D00DE64E0 /* PINRemoteLock.m in Sources */, + 139D4FE01F672B0D00DE64E0 /* PINRemoteImageMemoryContainer.m in Sources */, + 139D4FE11F672B0D00DE64E0 /* PINRemoteImageBasicCache.m in Sources */, + 139D4FE21F672B0D00DE64E0 /* PINRemoteImageDownloadQueue.m in Sources */, + 139D4FE31F672B0D00DE64E0 /* PINResume.m in Sources */, + 68D734521F75FDEA00B9C95D /* PINGIFAnimatedImage.m in Sources */, + 139D4FE41F672B0D00DE64E0 /* PINSpeedRecorder.m in Sources */, + 68D7344C1F75FDCF00B9C95D /* PINAnimatedImage.m in Sources */, + 938E98DA2224775B00029E4D /* PINRemoteImageManagerConfiguration.m in Sources */, + A7343C60228993F400972894 /* NSHTTPURLResponse+MaxAge.m in Sources */, + 689613E7208FD90B00D2095C /* PINDisplayLink.m in Sources */, + 68D7344E1F75FDDB00B9C95D /* PINCachedAnimatedImage.m in Sources */, + 689613D9208FD89900D2095C /* PINAnimatedImageView+PINRemoteImage.m in Sources */, + 68912D89208FDB4900F5FE0E /* PINRemoteWeakProxy.m in Sources */, + 689613DF208FD8B700D2095C /* PINAnimatedImageView.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 139D3A5E1F67284400F82935 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D93A340324182D46005EB15E /* TestAnimatedImage.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 68A0FC151E523434000B552D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6864A9221F6D94AF007BB848 /* PINAnimatedImageTests.swift in Sources */, + 68A0FC1C1E523434000B552D /* PINRemoteImageTests.m in Sources */, + 683128F51F95045200D5B4A8 /* PINAnimatedImage+PINAnimatedImageTesting.m in Sources */, + D93A340224182D46005EB15E /* TestAnimatedImage.m in Sources */, + ACD28AB87FABF6BA3B9BF4E4 /* NSDate+PINCacheTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F1B918CC1BCF239200710963 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 68F0EA931CB32EC900F1FD41 /* PINAlternateRepresentationProvider.m in Sources */, + 0CF0743B24093139008F126B /* PINAPNGAnimatedImage.m in Sources */, + 926E01641F0DFEE800874D01 /* PINRequestRetryStrategy.m in Sources */, + F1B9190F1BCF23C900710963 /* PINProgressiveImage.m in Sources */, + F1B919121BCF23C900710963 /* PINRemoteImageCallbacks.m in Sources */, + 68C155CC1F6EE0A20075EE40 /* PINCachedAnimatedImage.m in Sources */, + 9DD47F9D1C699F4B00F12CA0 /* PINButton+PINRemoteImage.m in Sources */, + 6858C0761C9CC5BA00E420EB /* PINRemoteLock.m in Sources */, + F1B919191BCF23C900710963 /* PINRemoteImageManagerResult.m in Sources */, + F1B9191D1BCF23C900710963 /* PINRemoteImageTask.m in Sources */, + 68B1F2821E679D7A00ED87C4 /* PINRemoteImageDownloadQueue.m in Sources */, + F1B919011BCF23C900710963 /* NSData+ImageDetectors.m in Sources */, + 939546C12220AF84006031BB /* PINRemoteImageManagerConfiguration.m in Sources */, + A7343C5B228993D100972894 /* NSHTTPURLResponse+MaxAge.m in Sources */, + 689613E6208FD90B00D2095C /* PINDisplayLink.m in Sources */, + F1B918FF1BCF23C900710963 /* PINRemoteImageCategoryManager.m in Sources */, + 9DD47FA51C699FDC00F12CA0 /* PINImage+DecodedImage.m in Sources */, + 68F0EA951CB32EC900F1FD41 /* PINRemoteImageMemoryContainer.m in Sources */, + F1B919151BCF23C900710963 /* PINRemoteImageDownloadTask.m in Sources */, + 68CA92841DB19C20008BECE2 /* PINCache+PINRemoteImageCaching.m in Sources */, + 68CA927D1DAEFF93008BECE2 /* PINRemoteImageBasicCache.m in Sources */, + 68C155DD1F6F202F0075EE40 /* PINGIFAnimatedImage.m in Sources */, + F1B9191F1BCF23C900710963 /* PINURLSessionManager.m in Sources */, + 689613D8208FD89900D2095C /* PINAnimatedImageView+PINRemoteImage.m in Sources */, + 687750281F6B2305008748B0 /* PINWebPAnimatedImage.m in Sources */, + F1B9191B1BCF23C900710963 /* PINRemoteImageProcessorTask.m in Sources */, + 68A6B1DB1E5248BF003A92D1 /* PINImage+ScaledImage.m in Sources */, + 68C155D71F6EE8890075EE40 /* PINAnimatedImage.m in Sources */, + 68912D88208FDB4900F5FE0E /* PINRemoteWeakProxy.m in Sources */, + 6860CB091F578287005E886E /* PINSpeedRecorder.m in Sources */, + 689613DE208FD8B700D2095C /* PINAnimatedImageView.m in Sources */, + 9DD47F9F1C699F4B00F12CA0 /* PINImageView+PINRemoteImage.m in Sources */, + 68B7E3B31E736C73000FC887 /* PINResume.m in Sources */, + F1B919171BCF23C900710963 /* PINRemoteImageManager.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 139D3A651F67284400F82935 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 139D3A591F67284400F82935 /* PINRemoteImage-tvOS */; + targetProxy = 139D3A641F67284400F82935 /* PBXContainerItemProxy */; + }; + 68A0FC201E523434000B552D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = F1B918D01BCF239200710963 /* PINRemoteImage */; + targetProxy = 68A0FC1F1E523434000B552D /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 139D3A6B1F67284400F82935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/webp", + ); + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_PREPROCESSOR_DEFINITIONS = ( + "PIN_WEBP=0", + "$(inherited)", + ); + INFOPLIST_FILE = Source/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = Source/PINRemoteImage.modulemap; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINRemoteImage; + PRODUCT_NAME = PINRemoteImage; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + 139D3A6C1F67284400F82935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/webp", + ); + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "PIN_WEBP=0", + ); + INFOPLIST_FILE = Source/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = Source/PINRemoteImage.modulemap; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINRemoteImage; + PRODUCT_NAME = PINRemoteImage; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + 139D3A6D1F67284400F82935 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_PREPROCESSOR_DEFINITIONS = ( + "PINWEBP=0", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.pinterest.PINRemoteImage-tvOSTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + }; + name = Debug; + }; + 139D3A6E1F67284400F82935 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = ""; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = Tests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.pinterest.PINRemoteImage-tvOSTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + }; + name = Release; + }; + 68A0FC211E523434000B552D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "PIN_WEBP=1", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = test.PINRemoteImageTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Tests/PINRemoteImageTests-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 68A0FC221E523434000B552D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + INFOPLIST_FILE = Tests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = test.PINRemoteImageTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Tests/PINRemoteImageTests-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + F1B918D71BCF239200710963 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + FRAMEWORK_SEARCH_PATHS = Carthage/Build/iOS; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = "Carthage/Checkouts/libwebp/**"; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_CFLAGS = ""; + PRODUCT_NAME = PINRemoteImage; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 14.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + F1B918D81BCF239200710963 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + FRAMEWORK_SEARCH_PATHS = Carthage/Build/iOS; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ""; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = "Carthage/Checkouts/libwebp/**"; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_CFLAGS = ""; + PRODUCT_NAME = PINRemoteImage; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 14.0; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + F1B918DA1BCF239200710963 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + "$(PROJECT_DIR)/Carthage/Build/Mac", + "$(PROJECT_DIR)/Carthage/Build/tvOS", + "$(PROJECT_DIR)/Carthage/Checkouts/libwebp/Carthage/Build/iOS", + "$(PROJECT_DIR)/Carthage/Checkouts/libwebp/Carthage/Build/Mac", + "$(PROJECT_DIR)/Carthage/Checkouts/libwebp/Carthage/Build/tvOS", + "$(PROJECT_DIR)/Carthage/Checkouts/PINCache/Carthage/Build/iOS", + "$(PROJECT_DIR)/Carthage/Checkouts/PINCache/Carthage/Build/Mac", + "$(PROJECT_DIR)/Carthage/Checkouts/PINCache/Carthage/Build/tvOS", + "$(PROJECT_DIR)/webp", + ); + GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; + INFOPLIST_FILE = Source/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = Source/PINRemoteImage.modulemap; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINRemoteImage; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + F1B918DB1BCF239200710963 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + "$(PROJECT_DIR)/Carthage/Build/Mac", + "$(PROJECT_DIR)/Carthage/Build/tvOS", + "$(PROJECT_DIR)/Carthage/Checkouts/libwebp/Carthage/Build/iOS", + "$(PROJECT_DIR)/Carthage/Checkouts/libwebp/Carthage/Build/Mac", + "$(PROJECT_DIR)/Carthage/Checkouts/libwebp/Carthage/Build/tvOS", + "$(PROJECT_DIR)/Carthage/Checkouts/PINCache/Carthage/Build/iOS", + "$(PROJECT_DIR)/Carthage/Checkouts/PINCache/Carthage/Build/Mac", + "$(PROJECT_DIR)/Carthage/Checkouts/PINCache/Carthage/Build/tvOS", + "$(PROJECT_DIR)/webp", + ); + GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; + INFOPLIST_FILE = Source/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = Source/PINRemoteImage.modulemap; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11"; + PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINRemoteImage; + SKIP_INSTALL = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 139D3A741F67284400F82935 /* Build configuration list for PBXNativeTarget "PINRemoteImage-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 139D3A6B1F67284400F82935 /* Debug */, + 139D3A6C1F67284400F82935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 139D3A751F67284400F82935 /* Build configuration list for PBXNativeTarget "PINRemoteImage-tvOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 139D3A6D1F67284400F82935 /* Debug */, + 139D3A6E1F67284400F82935 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 68A0FC231E523434000B552D /* Build configuration list for PBXNativeTarget "PINRemoteImageTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 68A0FC211E523434000B552D /* Debug */, + 68A0FC221E523434000B552D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F1B918CB1BCF239200710963 /* Build configuration list for PBXProject "PINRemoteImage" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F1B918D71BCF239200710963 /* Debug */, + F1B918D81BCF239200710963 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F1B918D91BCF239200710963 /* Build configuration list for PBXNativeTarget "PINRemoteImage" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F1B918DA1BCF239200710963 /* Debug */, + F1B918DB1BCF239200710963 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = F1B918C81BCF239200710963 /* Project object */; +} diff --git a/PINRemoteImage/PINRemoteImage.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/PINRemoteImage.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from PINRemoteImage/PINRemoteImage.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to PINRemoteImage.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/PINRemoteImage.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/PINRemoteImage.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/PINRemoteImage.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/PINRemoteImage.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/PINRemoteImage.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..3ddf867a --- /dev/null +++ b/PINRemoteImage.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + BuildSystemType + Latest + + diff --git a/PINRemoteImage.xcodeproj/xcshareddata/xcschemes/PINRemoteImage-tvOS.xcscheme b/PINRemoteImage.xcodeproj/xcshareddata/xcschemes/PINRemoteImage-tvOS.xcscheme new file mode 100644 index 00000000..879fdc5b --- /dev/null +++ b/PINRemoteImage.xcodeproj/xcshareddata/xcschemes/PINRemoteImage-tvOS.xcscheme @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PINRemoteImage.xcodeproj/xcshareddata/xcschemes/PINRemoteImage.xcscheme b/PINRemoteImage.xcodeproj/xcshareddata/xcschemes/PINRemoteImage.xcscheme new file mode 100644 index 00000000..6a77f6c1 --- /dev/null +++ b/PINRemoteImage.xcodeproj/xcshareddata/xcschemes/PINRemoteImage.xcscheme @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PINRemoteImage.xcworkspace/contents.xcworkspacedata b/PINRemoteImage.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..5b1b2725 --- /dev/null +++ b/PINRemoteImage.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/PINRemoteImage.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/PINRemoteImage.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/PINRemoteImage.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/PINRemoteImage/PINRemoteImage.xcodeproj/project.pbxproj b/PINRemoteImage/PINRemoteImage.xcodeproj/project.pbxproj deleted file mode 100644 index 0ad1afea..00000000 --- a/PINRemoteImage/PINRemoteImage.xcodeproj/project.pbxproj +++ /dev/null @@ -1,496 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 6858C0751C9CC5BA00E420EB /* PINRemoteLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 6858C0731C9CC5BA00E420EB /* PINRemoteLock.h */; }; - 6858C0761C9CC5BA00E420EB /* PINRemoteLock.m in Sources */ = {isa = PBXBuildFile; fileRef = 6858C0741C9CC5BA00E420EB /* PINRemoteLock.m */; }; - 68F0EA921CB32EC900F1FD41 /* PINAlternateRepresentationProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 68F0EA8E1CB32EC900F1FD41 /* PINAlternateRepresentationProvider.h */; }; - 68F0EA931CB32EC900F1FD41 /* PINAlternateRepresentationProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 68F0EA8F1CB32EC900F1FD41 /* PINAlternateRepresentationProvider.m */; }; - 68F0EA941CB32EC900F1FD41 /* PINRemoteImageMemoryContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 68F0EA901CB32EC900F1FD41 /* PINRemoteImageMemoryContainer.h */; }; - 68F0EA951CB32EC900F1FD41 /* PINRemoteImageMemoryContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 68F0EA911CB32EC900F1FD41 /* PINRemoteImageMemoryContainer.m */; }; - 9DD47F9C1C699F4B00F12CA0 /* PINButton+PINRemoteImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 9DD47F981C699F4B00F12CA0 /* PINButton+PINRemoteImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9DD47F9D1C699F4B00F12CA0 /* PINButton+PINRemoteImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DD47F991C699F4B00F12CA0 /* PINButton+PINRemoteImage.m */; }; - 9DD47F9E1C699F4B00F12CA0 /* PINImageView+PINRemoteImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 9DD47F9A1C699F4B00F12CA0 /* PINImageView+PINRemoteImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9DD47F9F1C699F4B00F12CA0 /* PINImageView+PINRemoteImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DD47F9B1C699F4B00F12CA0 /* PINImageView+PINRemoteImage.m */; }; - 9DD47FA41C699FDC00F12CA0 /* PINImage+DecodedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 9DD47FA01C699FDC00F12CA0 /* PINImage+DecodedImage.h */; }; - 9DD47FA51C699FDC00F12CA0 /* PINImage+DecodedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DD47FA11C699FDC00F12CA0 /* PINImage+DecodedImage.m */; }; - 9DD47FA61C699FDC00F12CA0 /* PINImage+WebP.h in Headers */ = {isa = PBXBuildFile; fileRef = 9DD47FA21C699FDC00F12CA0 /* PINImage+WebP.h */; }; - 9DD47FA71C699FDC00F12CA0 /* PINImage+WebP.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DD47FA31C699FDC00F12CA0 /* PINImage+WebP.m */; }; - F165DFD91BD0504A0008C6E8 /* PINRemoteImageMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = F165DFD81BD0504A0008C6E8 /* PINRemoteImageMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F1B918FF1BCF23C900710963 /* PINRemoteImageCategoryManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918DC1BCF23C800710963 /* PINRemoteImageCategoryManager.m */; }; - F1B919001BCF23C900710963 /* NSData+ImageDetectors.h in Headers */ = {isa = PBXBuildFile; fileRef = F1B918DE1BCF23C800710963 /* NSData+ImageDetectors.h */; }; - F1B919011BCF23C900710963 /* NSData+ImageDetectors.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918DF1BCF23C800710963 /* NSData+ImageDetectors.m */; }; - F1B919061BCF23C900710963 /* FLAnimatedImageView+PINRemoteImage.h in Headers */ = {isa = PBXBuildFile; fileRef = F1B918E51BCF23C800710963 /* FLAnimatedImageView+PINRemoteImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F1B919071BCF23C900710963 /* FLAnimatedImageView+PINRemoteImage.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918E61BCF23C800710963 /* FLAnimatedImageView+PINRemoteImage.m */; }; - F1B9190C1BCF23C900710963 /* PINDataTaskOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = F1B918EB1BCF23C800710963 /* PINDataTaskOperation.h */; }; - F1B9190D1BCF23C900710963 /* PINDataTaskOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918EC1BCF23C800710963 /* PINDataTaskOperation.m */; }; - F1B9190E1BCF23C900710963 /* PINProgressiveImage.h in Headers */ = {isa = PBXBuildFile; fileRef = F1B918ED1BCF23C800710963 /* PINProgressiveImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F1B9190F1BCF23C900710963 /* PINProgressiveImage.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918EE1BCF23C800710963 /* PINProgressiveImage.m */; }; - F1B919101BCF23C900710963 /* PINRemoteImage.h in Headers */ = {isa = PBXBuildFile; fileRef = F1B918EF1BCF23C800710963 /* PINRemoteImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F1B919111BCF23C900710963 /* PINRemoteImageCallbacks.h in Headers */ = {isa = PBXBuildFile; fileRef = F1B918F01BCF23C800710963 /* PINRemoteImageCallbacks.h */; }; - F1B919121BCF23C900710963 /* PINRemoteImageCallbacks.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918F11BCF23C800710963 /* PINRemoteImageCallbacks.m */; }; - F1B919131BCF23C900710963 /* PINRemoteImageCategoryManager.h in Headers */ = {isa = PBXBuildFile; fileRef = F1B918F21BCF23C800710963 /* PINRemoteImageCategoryManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F1B919141BCF23C900710963 /* PINRemoteImageDownloadTask.h in Headers */ = {isa = PBXBuildFile; fileRef = F1B918F31BCF23C800710963 /* PINRemoteImageDownloadTask.h */; }; - F1B919151BCF23C900710963 /* PINRemoteImageDownloadTask.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918F41BCF23C800710963 /* PINRemoteImageDownloadTask.m */; }; - F1B919161BCF23C900710963 /* PINRemoteImageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = F1B918F51BCF23C800710963 /* PINRemoteImageManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F1B919171BCF23C900710963 /* PINRemoteImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918F61BCF23C800710963 /* PINRemoteImageManager.m */; }; - F1B919181BCF23C900710963 /* PINRemoteImageManagerResult.h in Headers */ = {isa = PBXBuildFile; fileRef = F1B918F71BCF23C800710963 /* PINRemoteImageManagerResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F1B919191BCF23C900710963 /* PINRemoteImageManagerResult.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918F81BCF23C800710963 /* PINRemoteImageManagerResult.m */; }; - F1B9191A1BCF23C900710963 /* PINRemoteImageProcessorTask.h in Headers */ = {isa = PBXBuildFile; fileRef = F1B918F91BCF23C800710963 /* PINRemoteImageProcessorTask.h */; }; - F1B9191B1BCF23C900710963 /* PINRemoteImageProcessorTask.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918FA1BCF23C800710963 /* PINRemoteImageProcessorTask.m */; }; - F1B9191C1BCF23C900710963 /* PINRemoteImageTask.h in Headers */ = {isa = PBXBuildFile; fileRef = F1B918FB1BCF23C800710963 /* PINRemoteImageTask.h */; }; - F1B9191D1BCF23C900710963 /* PINRemoteImageTask.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918FC1BCF23C800710963 /* PINRemoteImageTask.m */; }; - F1B9191E1BCF23C900710963 /* PINURLSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = F1B918FD1BCF23C800710963 /* PINURLSessionManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F1B9191F1BCF23C900710963 /* PINURLSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F1B918FE1BCF23C900710963 /* PINURLSessionManager.m */; }; - F1B919231BCF273F00710963 /* PINCache.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F1B919221BCF273F00710963 /* PINCache.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 6858C0731C9CC5BA00E420EB /* PINRemoteLock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PINRemoteLock.h; path = ../../Pod/Classes/PINRemoteLock.h; sourceTree = ""; }; - 6858C0741C9CC5BA00E420EB /* PINRemoteLock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PINRemoteLock.m; path = ../../Pod/Classes/PINRemoteLock.m; sourceTree = ""; }; - 68EB25231C6A64E4002501A3 /* PINRemoteImage-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PINRemoteImage-Prefix.pch"; sourceTree = ""; }; - 68F0EA8E1CB32EC900F1FD41 /* PINAlternateRepresentationProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PINAlternateRepresentationProvider.h; path = ../../Pod/Classes/PINAlternateRepresentationProvider.h; sourceTree = ""; }; - 68F0EA8F1CB32EC900F1FD41 /* PINAlternateRepresentationProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PINAlternateRepresentationProvider.m; path = ../../Pod/Classes/PINAlternateRepresentationProvider.m; sourceTree = ""; }; - 68F0EA901CB32EC900F1FD41 /* PINRemoteImageMemoryContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PINRemoteImageMemoryContainer.h; path = ../../Pod/Classes/PINRemoteImageMemoryContainer.h; sourceTree = ""; }; - 68F0EA911CB32EC900F1FD41 /* PINRemoteImageMemoryContainer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PINRemoteImageMemoryContainer.m; path = ../../Pod/Classes/PINRemoteImageMemoryContainer.m; sourceTree = ""; }; - 9DD47F981C699F4B00F12CA0 /* PINButton+PINRemoteImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PINButton+PINRemoteImage.h"; sourceTree = ""; }; - 9DD47F991C699F4B00F12CA0 /* PINButton+PINRemoteImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "PINButton+PINRemoteImage.m"; sourceTree = ""; }; - 9DD47F9A1C699F4B00F12CA0 /* PINImageView+PINRemoteImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PINImageView+PINRemoteImage.h"; sourceTree = ""; }; - 9DD47F9B1C699F4B00F12CA0 /* PINImageView+PINRemoteImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "PINImageView+PINRemoteImage.m"; sourceTree = ""; }; - 9DD47FA01C699FDC00F12CA0 /* PINImage+DecodedImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PINImage+DecodedImage.h"; sourceTree = ""; }; - 9DD47FA11C699FDC00F12CA0 /* PINImage+DecodedImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "PINImage+DecodedImage.m"; sourceTree = ""; }; - 9DD47FA21C699FDC00F12CA0 /* PINImage+WebP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PINImage+WebP.h"; sourceTree = ""; }; - 9DD47FA31C699FDC00F12CA0 /* PINImage+WebP.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "PINImage+WebP.m"; sourceTree = ""; }; - F165DFD81BD0504A0008C6E8 /* PINRemoteImageMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PINRemoteImageMacros.h; path = ../../Pod/Classes/PINRemoteImageMacros.h; sourceTree = ""; }; - F1B918D11BCF239200710963 /* PINRemoteImage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PINRemoteImage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - F1B918D61BCF239200710963 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - F1B918DC1BCF23C800710963 /* PINRemoteImageCategoryManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PINRemoteImageCategoryManager.m; path = ../../Pod/Classes/PINRemoteImageCategoryManager.m; sourceTree = ""; }; - F1B918DE1BCF23C800710963 /* NSData+ImageDetectors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+ImageDetectors.h"; sourceTree = ""; }; - F1B918DF1BCF23C800710963 /* NSData+ImageDetectors.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+ImageDetectors.m"; sourceTree = ""; }; - F1B918E51BCF23C800710963 /* FLAnimatedImageView+PINRemoteImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FLAnimatedImageView+PINRemoteImage.h"; sourceTree = ""; }; - F1B918E61BCF23C800710963 /* FLAnimatedImageView+PINRemoteImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "FLAnimatedImageView+PINRemoteImage.m"; sourceTree = ""; }; - F1B918EB1BCF23C800710963 /* PINDataTaskOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PINDataTaskOperation.h; path = ../../Pod/Classes/PINDataTaskOperation.h; sourceTree = ""; }; - F1B918EC1BCF23C800710963 /* PINDataTaskOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PINDataTaskOperation.m; path = ../../Pod/Classes/PINDataTaskOperation.m; sourceTree = ""; }; - F1B918ED1BCF23C800710963 /* PINProgressiveImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PINProgressiveImage.h; path = ../../Pod/Classes/PINProgressiveImage.h; sourceTree = ""; }; - F1B918EE1BCF23C800710963 /* PINProgressiveImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PINProgressiveImage.m; path = ../../Pod/Classes/PINProgressiveImage.m; sourceTree = ""; }; - F1B918EF1BCF23C800710963 /* PINRemoteImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PINRemoteImage.h; path = ../../Pod/Classes/PINRemoteImage.h; sourceTree = ""; }; - F1B918F01BCF23C800710963 /* PINRemoteImageCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PINRemoteImageCallbacks.h; path = ../../Pod/Classes/PINRemoteImageCallbacks.h; sourceTree = ""; }; - F1B918F11BCF23C800710963 /* PINRemoteImageCallbacks.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PINRemoteImageCallbacks.m; path = ../../Pod/Classes/PINRemoteImageCallbacks.m; sourceTree = ""; }; - F1B918F21BCF23C800710963 /* PINRemoteImageCategoryManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PINRemoteImageCategoryManager.h; path = ../../Pod/Classes/PINRemoteImageCategoryManager.h; sourceTree = ""; }; - F1B918F31BCF23C800710963 /* PINRemoteImageDownloadTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PINRemoteImageDownloadTask.h; path = ../../Pod/Classes/PINRemoteImageDownloadTask.h; sourceTree = ""; }; - F1B918F41BCF23C800710963 /* PINRemoteImageDownloadTask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PINRemoteImageDownloadTask.m; path = ../../Pod/Classes/PINRemoteImageDownloadTask.m; sourceTree = ""; }; - F1B918F51BCF23C800710963 /* PINRemoteImageManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PINRemoteImageManager.h; path = ../../Pod/Classes/PINRemoteImageManager.h; sourceTree = ""; }; - F1B918F61BCF23C800710963 /* PINRemoteImageManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PINRemoteImageManager.m; path = ../../Pod/Classes/PINRemoteImageManager.m; sourceTree = ""; }; - F1B918F71BCF23C800710963 /* PINRemoteImageManagerResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PINRemoteImageManagerResult.h; path = ../../Pod/Classes/PINRemoteImageManagerResult.h; sourceTree = ""; }; - F1B918F81BCF23C800710963 /* PINRemoteImageManagerResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PINRemoteImageManagerResult.m; path = ../../Pod/Classes/PINRemoteImageManagerResult.m; sourceTree = ""; }; - F1B918F91BCF23C800710963 /* PINRemoteImageProcessorTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PINRemoteImageProcessorTask.h; path = ../../Pod/Classes/PINRemoteImageProcessorTask.h; sourceTree = ""; }; - F1B918FA1BCF23C800710963 /* PINRemoteImageProcessorTask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PINRemoteImageProcessorTask.m; path = ../../Pod/Classes/PINRemoteImageProcessorTask.m; sourceTree = ""; }; - F1B918FB1BCF23C800710963 /* PINRemoteImageTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PINRemoteImageTask.h; path = ../../Pod/Classes/PINRemoteImageTask.h; sourceTree = ""; }; - F1B918FC1BCF23C800710963 /* PINRemoteImageTask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PINRemoteImageTask.m; path = ../../Pod/Classes/PINRemoteImageTask.m; sourceTree = ""; }; - F1B918FD1BCF23C800710963 /* PINURLSessionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PINURLSessionManager.h; path = ../../Pod/Classes/PINURLSessionManager.h; sourceTree = ""; }; - F1B918FE1BCF23C900710963 /* PINURLSessionManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PINURLSessionManager.m; path = ../../Pod/Classes/PINURLSessionManager.m; sourceTree = ""; }; - F1B919221BCF273F00710963 /* PINCache.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PINCache.framework; path = ../Carthage/Build/iOS/PINCache.framework; sourceTree = ""; }; - F1E3658B1BE04112003BF022 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - F1B918CD1BCF239200710963 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - F1B919231BCF273F00710963 /* PINCache.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 68EB25221C6A64BE002501A3 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 68EB25231C6A64E4002501A3 /* PINRemoteImage-Prefix.pch */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - F165DFD61BD021E30008C6E8 /* Public */ = { - isa = PBXGroup; - children = ( - F1B918EF1BCF23C800710963 /* PINRemoteImage.h */, - F165DFD81BD0504A0008C6E8 /* PINRemoteImageMacros.h */, - F1B918E41BCF23C800710963 /* Image Categories */, - F1B918ED1BCF23C800710963 /* PINProgressiveImage.h */, - F1B918EE1BCF23C800710963 /* PINProgressiveImage.m */, - F1B918F21BCF23C800710963 /* PINRemoteImageCategoryManager.h */, - F1B918DC1BCF23C800710963 /* PINRemoteImageCategoryManager.m */, - F1B918F51BCF23C800710963 /* PINRemoteImageManager.h */, - F1B918F61BCF23C800710963 /* PINRemoteImageManager.m */, - F1B918F71BCF23C800710963 /* PINRemoteImageManagerResult.h */, - F1B918F81BCF23C800710963 /* PINRemoteImageManagerResult.m */, - F1B918FD1BCF23C800710963 /* PINURLSessionManager.h */, - F1B918FE1BCF23C900710963 /* PINURLSessionManager.m */, - ); - name = Public; - sourceTree = ""; - }; - F165DFD71BD021EE0008C6E8 /* Project */ = { - isa = PBXGroup; - children = ( - F1B918DD1BCF23C800710963 /* Categories */, - F1B918EB1BCF23C800710963 /* PINDataTaskOperation.h */, - F1B918EC1BCF23C800710963 /* PINDataTaskOperation.m */, - F1B918F01BCF23C800710963 /* PINRemoteImageCallbacks.h */, - F1B918F11BCF23C800710963 /* PINRemoteImageCallbacks.m */, - F1B918F31BCF23C800710963 /* PINRemoteImageDownloadTask.h */, - F1B918F41BCF23C800710963 /* PINRemoteImageDownloadTask.m */, - F1B918F91BCF23C800710963 /* PINRemoteImageProcessorTask.h */, - F1B918FA1BCF23C800710963 /* PINRemoteImageProcessorTask.m */, - F1B918FB1BCF23C800710963 /* PINRemoteImageTask.h */, - F1B918FC1BCF23C800710963 /* PINRemoteImageTask.m */, - 6858C0731C9CC5BA00E420EB /* PINRemoteLock.h */, - 6858C0741C9CC5BA00E420EB /* PINRemoteLock.m */, - 68F0EA8E1CB32EC900F1FD41 /* PINAlternateRepresentationProvider.h */, - 68F0EA8F1CB32EC900F1FD41 /* PINAlternateRepresentationProvider.m */, - 68F0EA901CB32EC900F1FD41 /* PINRemoteImageMemoryContainer.h */, - 68F0EA911CB32EC900F1FD41 /* PINRemoteImageMemoryContainer.m */, - ); - name = Project; - sourceTree = ""; - }; - F1B918C71BCF239200710963 = { - isa = PBXGroup; - children = ( - F1B918D31BCF239200710963 /* PINRemoteImage */, - F1B919221BCF273F00710963 /* PINCache.framework */, - F1B918D21BCF239200710963 /* Products */, - ); - sourceTree = ""; - usesTabs = 0; - }; - F1B918D21BCF239200710963 /* Products */ = { - isa = PBXGroup; - children = ( - F1B918D11BCF239200710963 /* PINRemoteImage.framework */, - ); - name = Products; - sourceTree = ""; - }; - F1B918D31BCF239200710963 /* PINRemoteImage */ = { - isa = PBXGroup; - children = ( - F165DFD61BD021E30008C6E8 /* Public */, - F165DFD71BD021EE0008C6E8 /* Project */, - 68EB25221C6A64BE002501A3 /* Supporting Files */, - F1B918D61BCF239200710963 /* Info.plist */, - F1E3658B1BE04112003BF022 /* module.modulemap */, - ); - path = PINRemoteImage; - sourceTree = ""; - }; - F1B918DD1BCF23C800710963 /* Categories */ = { - isa = PBXGroup; - children = ( - F1B918DE1BCF23C800710963 /* NSData+ImageDetectors.h */, - F1B918DF1BCF23C800710963 /* NSData+ImageDetectors.m */, - 9DD47FA01C699FDC00F12CA0 /* PINImage+DecodedImage.h */, - 9DD47FA11C699FDC00F12CA0 /* PINImage+DecodedImage.m */, - 9DD47FA21C699FDC00F12CA0 /* PINImage+WebP.h */, - 9DD47FA31C699FDC00F12CA0 /* PINImage+WebP.m */, - ); - name = Categories; - path = ../../Pod/Classes/Categories; - sourceTree = ""; - }; - F1B918E41BCF23C800710963 /* Image Categories */ = { - isa = PBXGroup; - children = ( - F1B918E51BCF23C800710963 /* FLAnimatedImageView+PINRemoteImage.h */, - F1B918E61BCF23C800710963 /* FLAnimatedImageView+PINRemoteImage.m */, - 9DD47F981C699F4B00F12CA0 /* PINButton+PINRemoteImage.h */, - 9DD47F991C699F4B00F12CA0 /* PINButton+PINRemoteImage.m */, - 9DD47F9A1C699F4B00F12CA0 /* PINImageView+PINRemoteImage.h */, - 9DD47F9B1C699F4B00F12CA0 /* PINImageView+PINRemoteImage.m */, - ); - name = "Image Categories"; - path = "../../Pod/Classes/Image Categories"; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - F1B918CE1BCF239200710963 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 9DD47FA61C699FDC00F12CA0 /* PINImage+WebP.h in Headers */, - F1B919131BCF23C900710963 /* PINRemoteImageCategoryManager.h in Headers */, - F1B919161BCF23C900710963 /* PINRemoteImageManager.h in Headers */, - F1B9190C1BCF23C900710963 /* PINDataTaskOperation.h in Headers */, - 9DD47F9E1C699F4B00F12CA0 /* PINImageView+PINRemoteImage.h in Headers */, - 9DD47F9C1C699F4B00F12CA0 /* PINButton+PINRemoteImage.h in Headers */, - F165DFD91BD0504A0008C6E8 /* PINRemoteImageMacros.h in Headers */, - 68F0EA941CB32EC900F1FD41 /* PINRemoteImageMemoryContainer.h in Headers */, - 68F0EA921CB32EC900F1FD41 /* PINAlternateRepresentationProvider.h in Headers */, - F1B9191C1BCF23C900710963 /* PINRemoteImageTask.h in Headers */, - F1B919101BCF23C900710963 /* PINRemoteImage.h in Headers */, - F1B919001BCF23C900710963 /* NSData+ImageDetectors.h in Headers */, - F1B9191E1BCF23C900710963 /* PINURLSessionManager.h in Headers */, - F1B919061BCF23C900710963 /* FLAnimatedImageView+PINRemoteImage.h in Headers */, - F1B919111BCF23C900710963 /* PINRemoteImageCallbacks.h in Headers */, - F1B9190E1BCF23C900710963 /* PINProgressiveImage.h in Headers */, - 6858C0751C9CC5BA00E420EB /* PINRemoteLock.h in Headers */, - F1B919181BCF23C900710963 /* PINRemoteImageManagerResult.h in Headers */, - F1B9191A1BCF23C900710963 /* PINRemoteImageProcessorTask.h in Headers */, - 9DD47FA41C699FDC00F12CA0 /* PINImage+DecodedImage.h in Headers */, - F1B919141BCF23C900710963 /* PINRemoteImageDownloadTask.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - F1B918D01BCF239200710963 /* PINRemoteImage-iOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = F1B918D91BCF239200710963 /* Build configuration list for PBXNativeTarget "PINRemoteImage-iOS" */; - buildPhases = ( - F1B918CC1BCF239200710963 /* Sources */, - F1B918CD1BCF239200710963 /* Frameworks */, - F1B918CE1BCF239200710963 /* Headers */, - F1B918CF1BCF239200710963 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "PINRemoteImage-iOS"; - productName = PINRemoteImage; - productReference = F1B918D11BCF239200710963 /* PINRemoteImage.framework */; - productType = "com.apple.product-type.framework"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - F1B918C81BCF239200710963 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0700; - ORGANIZATIONNAME = Pinterest; - TargetAttributes = { - F1B918D01BCF239200710963 = { - CreatedOnToolsVersion = 7.0; - }; - }; - }; - buildConfigurationList = F1B918CB1BCF239200710963 /* Build configuration list for PBXProject "PINRemoteImage" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = F1B918C71BCF239200710963; - productRefGroup = F1B918D21BCF239200710963 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - F1B918D01BCF239200710963 /* PINRemoteImage-iOS */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - F1B918CF1BCF239200710963 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - F1B918CC1BCF239200710963 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 68F0EA931CB32EC900F1FD41 /* PINAlternateRepresentationProvider.m in Sources */, - F1B919071BCF23C900710963 /* FLAnimatedImageView+PINRemoteImage.m in Sources */, - F1B9190F1BCF23C900710963 /* PINProgressiveImage.m in Sources */, - F1B919121BCF23C900710963 /* PINRemoteImageCallbacks.m in Sources */, - 9DD47F9D1C699F4B00F12CA0 /* PINButton+PINRemoteImage.m in Sources */, - 6858C0761C9CC5BA00E420EB /* PINRemoteLock.m in Sources */, - F1B919191BCF23C900710963 /* PINRemoteImageManagerResult.m in Sources */, - F1B9191D1BCF23C900710963 /* PINRemoteImageTask.m in Sources */, - F1B919011BCF23C900710963 /* NSData+ImageDetectors.m in Sources */, - F1B918FF1BCF23C900710963 /* PINRemoteImageCategoryManager.m in Sources */, - 9DD47FA51C699FDC00F12CA0 /* PINImage+DecodedImage.m in Sources */, - 68F0EA951CB32EC900F1FD41 /* PINRemoteImageMemoryContainer.m in Sources */, - F1B919151BCF23C900710963 /* PINRemoteImageDownloadTask.m in Sources */, - F1B9191F1BCF23C900710963 /* PINURLSessionManager.m in Sources */, - F1B9191B1BCF23C900710963 /* PINRemoteImageProcessorTask.m in Sources */, - F1B9190D1BCF23C900710963 /* PINDataTaskOperation.m in Sources */, - 9DD47FA71C699FDC00F12CA0 /* PINImage+WebP.m in Sources */, - 9DD47F9F1C699F4B00F12CA0 /* PINImageView+PINRemoteImage.m in Sources */, - F1B919171BCF23C900710963 /* PINRemoteImageManager.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - F1B918D71BCF239200710963 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ../Carthage/Build/iOS; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_NAME = PINRemoteImage; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - F1B918D81BCF239200710963 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = ../Carthage/Build/iOS; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = PINRemoteImage; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - F1B918DA1BCF239200710963 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "PINRemoteImage/PINRemoteImage-Prefix.pch"; - INFOPLIST_FILE = PINRemoteImage/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = PINRemoteImage/module.modulemap; - PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINRemoteImage; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - F1B918DB1BCF239200710963 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "PINRemoteImage/PINRemoteImage-Prefix.pch"; - INFOPLIST_FILE = PINRemoteImage/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = PINRemoteImage/module.modulemap; - PRODUCT_BUNDLE_IDENTIFIER = com.pinterest.PINRemoteImage; - SKIP_INSTALL = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - F1B918CB1BCF239200710963 /* Build configuration list for PBXProject "PINRemoteImage" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - F1B918D71BCF239200710963 /* Debug */, - F1B918D81BCF239200710963 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - F1B918D91BCF239200710963 /* Build configuration list for PBXNativeTarget "PINRemoteImage-iOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - F1B918DA1BCF239200710963 /* Debug */, - F1B918DB1BCF239200710963 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = F1B918C81BCF239200710963 /* Project object */; -} diff --git a/PINRemoteImage/PINRemoteImage.xcodeproj/xcshareddata/xcschemes/PINRemoteImage.xcscheme b/PINRemoteImage/PINRemoteImage.xcodeproj/xcshareddata/xcschemes/PINRemoteImage.xcscheme deleted file mode 100644 index 6fcd32b9..00000000 --- a/PINRemoteImage/PINRemoteImage.xcodeproj/xcshareddata/xcschemes/PINRemoteImage.xcscheme +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/PINRemoteImage/PINRemoteImage/PINRemoteImage-Prefix.pch b/PINRemoteImage/PINRemoteImage/PINRemoteImage-Prefix.pch deleted file mode 100644 index 6dccedc2..00000000 --- a/PINRemoteImage/PINRemoteImage/PINRemoteImage-Prefix.pch +++ /dev/null @@ -1,10 +0,0 @@ -// -// PINRemoteImage-Prefix.pch -// PINRemoteImage -// -// Created by Garrett Moon on 2/9/16. -// Copyright © 2016 Pinterest. All rights reserved. -// - -#import -#import "PINRemoteImageMacros.h" diff --git a/PINRemoteImage/PINRemoteImage/module.modulemap b/PINRemoteImage/PINRemoteImage/module.modulemap deleted file mode 100644 index 2c43df54..00000000 --- a/PINRemoteImage/PINRemoteImage/module.modulemap +++ /dev/null @@ -1,10 +0,0 @@ -framework module PINRemoteImage { - umbrella header "PINRemoteImage.h" - - textual header "PINRemoteImageMacros.h" - header "FLAnimatedImageView+PINRemoteImage.h" - header "PINButton+PINRemoteImage.h" - header "PINImageView+PINRemoteImage.h" - - export * -} \ No newline at end of file diff --git a/PINRemoteImage/PINRemoteImageTests/Info.plist b/PINRemoteImage/PINRemoteImageTests/Info.plist new file mode 100644 index 00000000..6c6c23c4 --- /dev/null +++ b/PINRemoteImage/PINRemoteImageTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/PINRemoteImage/PINRemoteImageTests/PINRemoteImageTests.m b/PINRemoteImage/PINRemoteImageTests/PINRemoteImageTests.m new file mode 100644 index 00000000..bfd6f5c7 --- /dev/null +++ b/PINRemoteImage/PINRemoteImageTests/PINRemoteImageTests.m @@ -0,0 +1,39 @@ +// +// PINRemoteImageTests.m +// PINRemoteImageTests +// +// Created by Garrett Moon on 2/13/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import + +@interface PINRemoteImageTests : XCTestCase + +@end + +@implementation PINRemoteImageTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testExample { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. +} + +- (void)testPerformanceExample { + // This is an example of a performance test case. + [self measureBlock:^{ + // Put the code you want to measure the time of here. + }]; +} + +@end diff --git a/Package.swift b/Package.swift new file mode 100644 index 00000000..c04e6e4f --- /dev/null +++ b/Package.swift @@ -0,0 +1,41 @@ +// swift-tools-version:5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "PINRemoteImage", + platforms: [ + .iOS(.v14), + .macOS(.v11), + .tvOS(.v14), + ], + products: [ + .library( + name: "PINRemoteImage", + type: .static, + targets: ["PINRemoteImage"]), + ], + dependencies: [ + .package(url: "https://github.com/pinterest/PINCache.git", from: "3.0.4"), + ], + targets: [ + .target( + name: "PINRemoteImage", + dependencies: ["PINCache"], + path: "Source/Classes", + resources: [.process("../PrivacyInfo.xcprivacy")], + publicHeadersPath: "include", + cSettings: [ + .headerSearchPath("."), + .headerSearchPath("Categories"), + .headerSearchPath("AnimatedImages"), + .headerSearchPath("ImageCategories"), + .headerSearchPath("PinCache"), + + .define("NS_BLOCK_ASSERTIONS", to: "1", .when(configuration: .release)), + .define("USE_PINCACHE", to: "1"), + .define("PIN_WEBP", to: "1"), + ]), + ] +) diff --git a/Pod/Classes/Categories/NSData+ImageDetectors.h b/Pod/Classes/Categories/NSData+ImageDetectors.h deleted file mode 100644 index 95cd2a48..00000000 --- a/Pod/Classes/Categories/NSData+ImageDetectors.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// NSData+ImageDetectors.h -// Pods -// -// Created by Garrett Moon on 11/19/14. -// -// - -#import - -@interface NSData (PINImageDetectors) - -- (BOOL)pin_isGIF; -#ifdef PIN_WEBP -- (BOOL)pin_isWebP; -#endif - -@end diff --git a/Pod/Classes/Categories/NSData+ImageDetectors.m b/Pod/Classes/Categories/NSData+ImageDetectors.m deleted file mode 100644 index 91811325..00000000 --- a/Pod/Classes/Categories/NSData+ImageDetectors.m +++ /dev/null @@ -1,43 +0,0 @@ -// -// NSData+ImageDetectors.m -// Pods -// -// Created by Garrett Moon on 11/19/14. -// -// - -#import "NSData+ImageDetectors.h" - -@implementation NSData (PINImageDetectors) - -- (BOOL)pin_isGIF -{ - const NSInteger length = 3; - Byte firstBytes[length]; - if ([self length] >= length) { - [self getBytes:&firstBytes length:length]; - //G, I, F - if (firstBytes[0] == 0x47 && firstBytes[1] == 0x49 && firstBytes[2] == 0x46) { - return YES; - } - } - return NO; -} - -#ifdef PIN_WEBP -- (BOOL)pin_isWebP -{ - const NSInteger length = 12; - Byte firstBytes[length]; - if ([self length] >= length) { - [self getBytes:&firstBytes length:length]; - //R, I, F, F, -, -, -, -, W, E, B, P - if (firstBytes[0] == 0x52 && firstBytes[1] == 0x49 && firstBytes[2] == 0x46 && firstBytes[3] == 0x46 && firstBytes[8] == 0x57 && firstBytes[9] == 0x45 && firstBytes[10] == 0x42 && firstBytes[11] == 0x50) { - return YES; - } - } - return NO; -} -#endif - -@end diff --git a/Pod/Classes/Categories/PINImage+DecodedImage.h b/Pod/Classes/Categories/PINImage+DecodedImage.h deleted file mode 100644 index 48afb8a6..00000000 --- a/Pod/Classes/Categories/PINImage+DecodedImage.h +++ /dev/null @@ -1,43 +0,0 @@ -// -// UIImage+DecodedImage.h -// Pods -// -// Created by Garrett Moon on 11/19/14. -// -// - -#import - -#if PIN_TARGET_IOS -#import -#elif PIN_TARGET_MAC -#import -#endif - -#import "PINRemoteImageMacros.h" - -#if !PIN_TARGET_IOS -@interface NSImage (PINiOSMapping) - -@property(nonatomic, readonly, nullable) CGImageRef CGImage; - -+ (nullable NSImage *)imageWithData:(nonnull NSData *)imageData; -+ (nullable NSImage *)imageWithContentsOfFile:(nonnull NSString *)path; -+ (nonnull NSImage *)imageWithCGImage:(nonnull CGImageRef)imageRef; - -@end -#endif - -NSData * __nullable PINImageJPEGRepresentation(PINImage * __nonnull image, CGFloat compressionQuality); -NSData * __nullable PINImagePNGRepresentation(PINImage * __nonnull image); - -@interface PINImage (PINDecodedImage) - -+ (nullable PINImage *)pin_decodedImageWithData:(nonnull NSData *)data; -+ (nullable PINImage *)pin_decodedImageWithData:(nonnull NSData *)data skipDecodeIfPossible:(BOOL)skipDecodeIfPossible; -+ (nullable PINImage *)pin_decodedImageWithCGImageRef:(nonnull CGImageRef)imageRef; -#if PIN_TARGET_IOS -+ (nullable PINImage *)pin_decodedImageWithCGImageRef:(nonnull CGImageRef)imageRef orientation:(UIImageOrientation) orientation; -#endif - -@end diff --git a/Pod/Classes/Categories/PINImage+DecodedImage.m b/Pod/Classes/Categories/PINImage+DecodedImage.m deleted file mode 100644 index 63febb78..00000000 --- a/Pod/Classes/Categories/PINImage+DecodedImage.m +++ /dev/null @@ -1,233 +0,0 @@ -// -// UIImage+DecodedImage.m -// Pods -// -// Created by Garrett Moon on 11/19/14. -// -// - -#import "PINImage+DecodedImage.h" - -#import - -#ifdef PIN_WEBP -#import "PINImage+WebP.h" -#endif - -#import "NSData+ImageDetectors.h" - -#if !PIN_TARGET_IOS -@implementation NSImage (PINiOSMapping) - -- (CGImageRef)CGImage -{ - NSGraphicsContext *context = [NSGraphicsContext currentContext]; - NSRect rect = NSMakeRect(0.0, 0.0, self.size.width, self.size.height); - return [self CGImageForProposedRect:&rect context:context hints:NULL]; -} - -+ (NSImage *)imageWithData:(NSData *)imageData; -{ - return [[self alloc] initWithData:imageData]; -} - -+ (NSImage *)imageWithContentsOfFile:(NSString *)path -{ - return path ? [[self alloc] initWithContentsOfFile:path] : nil; -} - -+ (NSImage *)imageWithCGImage:(CGImageRef)imageRef -{ - return [[self alloc] initWithCGImage:imageRef size:CGSizeZero]; -} - -@end -#endif - -NSData * __nullable PINImageJPEGRepresentation(PINImage * __nonnull image, CGFloat compressionQuality) -{ -#if PIN_TARGET_IOS - return UIImageJPEGRepresentation(image, compressionQuality); -#elif PIN_TARGET_MAC - NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:[image TIFFRepresentation]]; - NSDictionary *imageProperties = @{NSImageCompressionFactor : @(compressionQuality)}; - return [imageRep representationUsingType:NSJPEGFileType properties:imageProperties]; -#endif -} - -NSData * __nullable PINImagePNGRepresentation(PINImage * __nonnull image) { -#if PIN_TARGET_IOS - return UIImagePNGRepresentation(image); -#elif PIN_TARGET_MAC - NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:[image TIFFRepresentation]]; - NSDictionary *imageProperties = @{NSImageCompressionFactor : @1}; - return [imageRep representationUsingType:NSPNGFileType properties:imageProperties]; -#endif -} - - -@implementation PINImage (PINDecodedImage) - -+ (PINImage *)pin_decodedImageWithData:(NSData *)data -{ - return [self pin_decodedImageWithData:data skipDecodeIfPossible:NO]; -} - -+ (PINImage *)pin_decodedImageWithData:(NSData *)data skipDecodeIfPossible:(BOOL)skipDecodeIfPossible -{ - if (data == nil) { - return nil; - } - - if ([data pin_isGIF]) { - return [PINImage imageWithData:data]; - } -#ifdef PIN_WEBP - if ([data pin_isWebP]) { - return [PINImage pin_imageWithWebPData:data]; - } -#endif - - PINImage *decodedImage = nil; - - CGImageSourceRef imageSourceRef = CGImageSourceCreateWithData((CFDataRef)data, NULL); - - if (imageSourceRef) { - CGImageRef imageRef = CGImageSourceCreateImageAtIndex(imageSourceRef, 0, (CFDictionaryRef)@{(NSString *)kCGImageSourceShouldCache : (NSNumber *)kCFBooleanFalse}); - if (imageRef) { -#if PIN_TARGET_IOS - UIImageOrientation orientation = pin_UIImageOrientationFromImageSource(imageSourceRef); - if (skipDecodeIfPossible) { - decodedImage = [PINImage imageWithCGImage:imageRef scale:1.0 orientation:orientation]; - } else { - decodedImage = [self pin_decodedImageWithCGImageRef:imageRef orientation:orientation]; - } -#elif PIN_TARGET_MAC - if (skipDecodeIfPossible) { - CGSize imageSize = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)); - decodedImage = [[NSImage alloc] initWithCGImage:imageRef size:imageSize]; - } else { - decodedImage = [self pin_decodedImageWithCGImageRef:imageRef]; - } -#endif - CGImageRelease(imageRef); - } - - CFRelease(imageSourceRef); - } - - return decodedImage; -} - -+ (PINImage *)pin_decodedImageWithCGImageRef:(CGImageRef)imageRef -{ -#if PIN_TARGET_IOS - return [self pin_decodedImageWithCGImageRef:imageRef orientation:UIImageOrientationUp]; -} - -+ (PINImage *)pin_decodedImageWithCGImageRef:(CGImageRef)imageRef orientation:(UIImageOrientation)orientation -{ -#endif - BOOL opaque = YES; - CGImageAlphaInfo alpha = CGImageGetAlphaInfo(imageRef); - if (alpha == kCGImageAlphaFirst || alpha == kCGImageAlphaLast || alpha == kCGImageAlphaOnly || alpha == kCGImageAlphaPremultipliedFirst || alpha == kCGImageAlphaPremultipliedLast) { - opaque = NO; - } - - CGSize imageSize = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)); - - CGBitmapInfo info = opaque ? (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host) : (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host); - CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); - - //Use UIGraphicsBeginImageContext parameters from docs: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIKitFunctionReference/#//apple_ref/c/func/UIGraphicsBeginImageContextWithOptions - CGContextRef ctx = CGBitmapContextCreate(NULL, imageSize.width, imageSize.height, - 8, - 0, - colorspace, - info); - - CGColorSpaceRelease(colorspace); - - PINImage *decodedImage = nil; - if (ctx) { - CGContextSetBlendMode(ctx, kCGBlendModeCopy); - CGContextDrawImage(ctx, CGRectMake(0, 0, imageSize.width, imageSize.height), imageRef); - - CGImageRef newImage = CGBitmapContextCreateImage(ctx); - -#if PIN_TARGET_IOS - decodedImage = [UIImage imageWithCGImage:newImage scale:1.0 orientation:orientation]; -#elif PIN_TARGET_MAC - decodedImage = [[NSImage alloc] initWithCGImage:newImage size:imageSize]; -#endif - CGImageRelease(newImage); - CGContextRelease(ctx); - - } else { -#if PIN_TARGET_IOS - decodedImage = [UIImage imageWithCGImage:imageRef scale:1.0 orientation:orientation]; -#elif PIN_TARGET_MAC - decodedImage = [[NSImage alloc] initWithCGImage:imageRef size:imageSize]; -#endif - } - - return decodedImage; -} - -#if PIN_TARGET_IOS -UIImageOrientation pin_UIImageOrientationFromImageSource(CGImageSourceRef imageSourceRef) { - UIImageOrientation orientation = UIImageOrientationUp; - - if (imageSourceRef != nil) { - NSDictionary *dict = (NSDictionary *)CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(imageSourceRef, 0, NULL)); - - if (dict != nil) { - - NSNumber* exifOrientation = dict[(id)kCGImagePropertyOrientation]; - if (exifOrientation != nil) { - - switch (exifOrientation.intValue) { - case 1: /*kCGImagePropertyOrientationUp*/ - orientation = UIImageOrientationUp; - break; - - case 2: /*kCGImagePropertyOrientationUpMirrored*/ - orientation = UIImageOrientationUpMirrored; - break; - - case 3: /*kCGImagePropertyOrientationDown*/ - orientation = UIImageOrientationDown; - break; - - case 4: /*kCGImagePropertyOrientationDownMirrored*/ - orientation = UIImageOrientationDownMirrored; - break; - case 5: /*kCGImagePropertyOrientationLeftMirrored*/ - orientation = UIImageOrientationLeftMirrored; - break; - - case 6: /*kCGImagePropertyOrientationRight*/ - orientation = UIImageOrientationRight; - break; - - case 7: /*kCGImagePropertyOrientationRightMirrored*/ - orientation = UIImageOrientationRightMirrored; - break; - - case 8: /*kCGImagePropertyOrientationLeft*/ - orientation = UIImageOrientationLeft; - break; - - default: - break; - } - } - } - } - - return orientation; -} - -#endif - -@end diff --git a/Pod/Classes/Categories/PINImage+WebP.h b/Pod/Classes/Categories/PINImage+WebP.h deleted file mode 100644 index d999736e..00000000 --- a/Pod/Classes/Categories/PINImage+WebP.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// UIImage+WebP.h -// Pods -// -// Created by Garrett Moon on 11/18/14. -// -// - -#ifdef PIN_WEBP - -#if PIN_TARGET_IOS -#import -#elif PIN_TARGET_MAC -#import -#endif - -#import "PINRemoteImageMacros.h" - -@interface PINImage (PINWebP) - -+ (PINImage *)pin_imageWithWebPData:(NSData *)webPData; - -@end - -#endif diff --git a/Pod/Classes/Categories/PINImage+WebP.m b/Pod/Classes/Categories/PINImage+WebP.m deleted file mode 100644 index 4e99898b..00000000 --- a/Pod/Classes/Categories/PINImage+WebP.m +++ /dev/null @@ -1,82 +0,0 @@ -// -// UIImage+WebP.m -// Pods -// -// Created by Garrett Moon on 11/18/14. -// -// - -#import "PINImage+WebP.h" - -#ifdef PIN_WEBP -#import "webp/decode.h" - -static void releaseData(void *info, const void *data, size_t size) -{ - free((void *)data); -} - -@implementation PINImage (PINWebP) - -+ (PINImage *)pin_imageWithWebPData:(NSData *)webPData -{ - WebPBitstreamFeatures features; - if (WebPGetFeatures([webPData bytes], [webPData length], &features) == VP8_STATUS_OK) { - // Decode the WebP image data into a RGBA value array - int height, width; - uint8_t *data = NULL; - int pixelLength = 0; - - if (features.has_alpha) { - data = WebPDecodeRGBA([webPData bytes], [webPData length], &width, &height); - pixelLength = 4; - } else { - data = WebPDecodeRGB([webPData bytes], [webPData length], &width, &height); - pixelLength = 3; - } - - if (data) { - CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, data, width * height * pixelLength, releaseData); - - CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); - CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; - - if (features.has_alpha) { - bitmapInfo |= kCGImageAlphaLast; - } else { - bitmapInfo |= kCGImageAlphaNone; - } - - CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; - CGImageRef imageRef = CGImageCreate(width, - height, - 8, - 8 * pixelLength, - pixelLength * width, - colorSpaceRef, - bitmapInfo, - provider, - NULL, - NO, - renderingIntent); - - PINImage *image = nil; -#if PIN_TARGET_IOS - image = [UIImage imageWithCGImage:imageRef]; -#elif PIN_TARGET_MAC - image = [[self alloc] initWithCGImage:imageRef size:CGSizeZero]; -#endif - - CGImageRelease(imageRef); - CGColorSpaceRelease(colorSpaceRef); - CGDataProviderRelease(provider); - - return image; - } - } - return nil; -} - -@end - -#endif diff --git a/Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.h b/Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.h deleted file mode 100644 index 12cc7184..00000000 --- a/Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// FLAnimatedImageView+PINRemoteImage.h -// Pods -// -// Created by Garrett Moon on 8/17/14. -// -// - -#import "PINRemoteImageMacros.h" -#if USE_FLANIMATED_IMAGE -#import - -#import "PINRemoteImageCategoryManager.h" - -@interface FLAnimatedImageView (PINRemoteImage) - -@end - -#endif \ No newline at end of file diff --git a/Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.m b/Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.m deleted file mode 100644 index f7e40333..00000000 --- a/Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.m +++ /dev/null @@ -1,124 +0,0 @@ -// -// FLAnimatedImageView+PINRemoteImage.m -// Pods -// -// Created by Garrett Moon on 8/17/14. -// -// - -#import "FLAnimatedImageView+PINRemoteImage.h" - -#if USE_FLANIMATED_IMAGE -@implementation FLAnimatedImageView (PINRemoteImage) - -- (void)pin_setImageFromURL:(NSURL *)url -{ - [PINRemoteImageCategoryManager setImageOnView:self fromURL:url]; -} - -- (void)pin_setImageFromURL:(NSURL *)url placeholderImage:(UIImage *)placeholderImage -{ - [PINRemoteImageCategoryManager setImageOnView:self fromURL:url placeholderImage:placeholderImage]; -} - -- (void)pin_setImageFromURL:(NSURL *)url completion:(PINRemoteImageManagerImageCompletion)completion -{ - [PINRemoteImageCategoryManager setImageOnView:self fromURL:url completion:completion]; -} - -- (void)pin_setImageFromURL:(NSURL *)url placeholderImage:(UIImage *)placeholderImage completion:(PINRemoteImageManagerImageCompletion)completion -{ - [PINRemoteImageCategoryManager setImageOnView:self fromURL:url placeholderImage:placeholderImage completion:completion]; -} - -- (void)pin_setImageFromURL:(NSURL *)url processorKey:(NSString *)processorKey processor:(PINRemoteImageManagerImageProcessor)processor -{ - [PINRemoteImageCategoryManager setImageOnView:self fromURL:url processorKey:processorKey processor:processor]; -} - -- (void)pin_setImageFromURL:(NSURL *)url placeholderImage:(UIImage *)placeholderImage processorKey:(NSString *)processorKey processor:(PINRemoteImageManagerImageProcessor)processor -{ - [PINRemoteImageCategoryManager setImageOnView:self fromURL:url placeholderImage:placeholderImage processorKey:processorKey processor:processor]; -} - -- (void)pin_setImageFromURL:(NSURL *)url processorKey:(NSString *)processorKey processor:(PINRemoteImageManagerImageProcessor)processor completion:(PINRemoteImageManagerImageCompletion)completion -{ - [PINRemoteImageCategoryManager setImageOnView:self fromURL:url processorKey:processorKey processor:processor completion:completion]; -} - -- (void)pin_setImageFromURL:(NSURL *)url placeholderImage:(UIImage *)placeholderImage processorKey:(NSString *)processorKey processor:(PINRemoteImageManagerImageProcessor)processor completion:(PINRemoteImageManagerImageCompletion)completion -{ - [PINRemoteImageCategoryManager setImageOnView:self fromURLs:@[url] placeholderImage:placeholderImage processorKey:processorKey processor:processor completion:completion]; -} - -- (void)pin_setImageFromURLs:(NSArray *)urls -{ - [PINRemoteImageCategoryManager setImageOnView:self fromURLs:urls]; -} - -- (void)pin_setImageFromURLs:(NSArray *)urls placeholderImage:(UIImage *)placeholderImage -{ - [PINRemoteImageCategoryManager setImageOnView:self fromURLs:urls placeholderImage:placeholderImage]; -} - -- (void)pin_setImageFromURLs:(NSArray *)urls placeholderImage:(UIImage *)placeholderImage completion:(PINRemoteImageManagerImageCompletion)completion -{ - [PINRemoteImageCategoryManager setImageOnView:self fromURLs:urls placeholderImage:placeholderImage completion:completion]; -} - -- (void)pin_cancelImageDownload -{ - [PINRemoteImageCategoryManager cancelImageDownloadOnView:self]; -} - -- (NSUUID *)pin_downloadImageOperationUUID -{ - return [PINRemoteImageCategoryManager downloadImageOperationUUIDOnView:self]; -} - -- (void)pin_setDownloadImageOperationUUID:(NSUUID *)downloadImageOperationUUID -{ - [PINRemoteImageCategoryManager setDownloadImageOperationUUID:downloadImageOperationUUID onView:self]; -} - -- (BOOL)pin_updateWithProgress -{ - return [PINRemoteImageCategoryManager updateWithProgressOnView:self]; -} - -- (void)setPin_updateWithProgress:(BOOL)updateWithProgress -{ - [PINRemoteImageCategoryManager setUpdateWithProgressOnView:updateWithProgress onView:self]; -} - -- (void)pin_setPlaceholderWithImage:(UIImage *)image -{ - self.image = image; -} - -- (void)pin_updateUIWithRemoteImageManagerResult:(PINRemoteImageManagerResult *)result -{ - if (result.alternativeRepresentation && [result.alternativeRepresentation isKindOfClass:[FLAnimatedImage class]]) { - self.animatedImage = (FLAnimatedImage *)result.alternativeRepresentation; - [self setNeedsLayout]; - } else if (result.image) { - self.image = result.image; - [self setNeedsLayout]; - } -} - -- (void)pin_clearImages -{ - self.animatedImage = nil; - self.image = nil; - [self setNeedsLayout]; -} - -- (BOOL)pin_ignoreGIFs -{ - return NO; -} - -@end - -#endif \ No newline at end of file diff --git a/Pod/Classes/Image Categories/PINButton+PINRemoteImage.h b/Pod/Classes/Image Categories/PINButton+PINRemoteImage.h deleted file mode 100644 index 95964b19..00000000 --- a/Pod/Classes/Image Categories/PINButton+PINRemoteImage.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// UIButton+PINRemoteImage.h -// Pods -// -// Created by Garrett Moon on 8/18/14. -// -// - -#if PIN_TARGET_IOS -#import -#elif PIN_TARGET_MAC -#import -#endif - -#import "PINRemoteImageManager.h" -#import "PINRemoteImageCategoryManager.h" - -@interface PINButton (PINRemoteImage) - -@end diff --git a/Pod/Classes/Image Categories/PINImageView+PINRemoteImage.h b/Pod/Classes/Image Categories/PINImageView+PINRemoteImage.h deleted file mode 100644 index f2b262b2..00000000 --- a/Pod/Classes/Image Categories/PINImageView+PINRemoteImage.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// UIImageView+PINRemoteImage.h -// Pods -// -// Created by Garrett Moon on 8/17/14. -// -// - -#if PIN_TARGET_IOS -#import -#elif PIN_TARGET_MAC -#import -#endif - -#import "PINRemoteImageManager.h" -#import "PINRemoteImageCategoryManager.h" - -@interface PINImageView (PINRemoteImage) - -@end diff --git a/Pod/Classes/PINAlternateRepresentationProvider.h b/Pod/Classes/PINAlternateRepresentationProvider.h deleted file mode 100644 index d3506096..00000000 --- a/Pod/Classes/PINAlternateRepresentationProvider.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// PINAlternateRepresentationProvider.h -// Pods -// -// Created by Garrett Moon on 3/17/16. -// -// - -#import - -#import "PINRemoteImageManager.h" - -@protocol PINRemoteImageManagerAlternateRepresentationProvider -@required - -/** - @discussion This method will be called with data off the wire or stored in the cache. Return an object to have it returned as the alternativeRepresentation object in the PINRemoteImageManagerResult. @warning this method can be called on the main thread, be careful of doing expensive work. - */ -- (id)alternateRepresentationWithData:(NSData *)data options:(PINRemoteImageManagerDownloadOptions)options; - -@end - -@interface PINAlternateRepresentationProvider : NSObject - -@end diff --git a/Pod/Classes/PINAlternateRepresentationProvider.m b/Pod/Classes/PINAlternateRepresentationProvider.m deleted file mode 100644 index 99c03ce2..00000000 --- a/Pod/Classes/PINAlternateRepresentationProvider.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// PINAlternateRepresentationProvider.m -// Pods -// -// Created by Garrett Moon on 3/17/16. -// -// - -#import "PINAlternateRepresentationProvider.h" - -#import "NSData+ImageDetectors.h" -#if USE_FLANIMATED_IMAGE -#import -#endif - -@implementation PINAlternateRepresentationProvider - -- (id)alternateRepresentationWithData:(NSData *)data options:(PINRemoteImageManagerDownloadOptions)options -{ -#if USE_FLANIMATED_IMAGE - if ([data pin_isGIF]) { - return [FLAnimatedImage animatedImageWithGIFData:data]; - } -#endif - return nil; -} - -@end diff --git a/Pod/Classes/PINAnimatedImage.h b/Pod/Classes/PINAnimatedImage.h deleted file mode 100644 index 644a072f..00000000 --- a/Pod/Classes/PINAnimatedImage.h +++ /dev/null @@ -1,157 +0,0 @@ -// -// PINAnimatedImage.h -// Pods -// -// Created by Garrett Moon on 3/18/16. -// -// - -#import - -#import "PINRemoteImageMacros.h" - -#define PINAnimatedImageDebug 0 - -extern NSString *kPINAnimatedImageErrorDomain; - -/** - PINAnimatedImage decoding and processing errors. - */ -typedef NS_ENUM(NSUInteger, PINAnimatedImageError) { - /** No error, yay! */ - PINAnimatedImageErrorNoError = 0, - /** Could not create a necessary file. */ - PINAnimatedImageErrorFileCreationError, - /** Could not get a file handle to the necessary file. */ - PINAnimatedImageErrorFileHandleError, - /** Could not decode the image. */ - PINAnimatedImageErrorImageFrameError, - /** Could not memory map the file. */ - PINAnimatedImageErrorMappingError, - /** File write error */ - PINAnimatedImageErrorFileWrite, -}; - -/** - The processing status of the animated image. - */ -typedef NS_ENUM(NSUInteger, PINAnimatedImageStatus) { - /** No work has been done. */ - PINAnimatedImageStatusUnprocessed = 0, - /** Info about the animated image and the cover image are available. */ - PINAnimatedImageStatusInfoProcessed, - /** At least one set of frames has been decoded to a file. It's safe to start playback. */ - PINAnimatedImageStatusFirstFileProcessed, - /** The entire animated image has been processed. */ - PINAnimatedImageStatusProcessed, - /** Processing was canceled. */ - PINAnimatedImageStatusCanceled, - /** There was an error in processing. */ - PINAnimatedImageStatusError, -}; - -extern const Float32 kPINAnimatedImageDefaultDuration; -extern const Float32 kPINAnimatedImageMinimumDuration; -extern const NSTimeInterval kPINAnimatedImageDisplayRefreshRate; - -/** - Called when the cover image of an animatedImage is ready. - */ -typedef void(^PINAnimatedImageInfoReady)(PINImage *coverImage); - - -/** - PINAnimatedImage is a class which decodes GIFs to memory mapped files on disk. Like PINRemoteImageManager, - it will only decode a GIF one time, regardless of the number of the number of PINAnimatedImages created with - the same NSData. - - PINAnimatedImage's are also decoded chunks at a time, writing each chunk to a separate file. This allows callback - and playback to start before the GIF is completely decoded. If a frame is requested beyond what has been processed, - nil will be returned. Because a fileReady is called on each chunk completion, you can pause playback if you hit a nil - frame until you receive another fileReady call. - - Internally, PINAnimatedImage attempts to keep only the files it needs open – the last file associated with the requested - frame and the one after (to prime). - - It's important to note that until infoCompletion is called, it is unsafe to access many of the methods on PINAnimatedImage. - */ -@interface PINAnimatedImage : NSObject - -- (instancetype)initWithAnimatedImageData:(NSData *)animatedImageData NS_DESIGNATED_INITIALIZER; - -/** - A block to be called on when GIF info has been processed. Status will == PINAnimatedImageStatusInfoProcessed - */ -@property (nonatomic, strong, readwrite) PINAnimatedImageInfoReady infoCompletion; -/** - A block to be called whenever a new file is done being processed. You can start (or resume) playback when you - get this callback, though it's possible for playback to catch up to the decoding and you'll need to pause. - */ -@property (nonatomic, strong, readwrite) dispatch_block_t fileReady; -/** - A block to be called when the animated image is fully decoded and written to disk. - */ -@property (nonatomic, strong, readwrite) dispatch_block_t animatedImageReady; - -/** - The current status of the animated image. - */ -@property (nonatomic, assign, readwrite) PINAnimatedImageStatus status; - -/** - A helper function which references status to check if the coverImage is ready. - */ -@property (nonatomic, readonly) BOOL coverImageReady; -/** - A helper function which references status to check if playback is ready. - */ -@property (nonatomic, readonly) BOOL playbackReady; -/** - The first frame / cover image of the animated image. - @warning Access to this property before status == PINAnimatedImageStatusInfoProcessed is undefined. You can check coverImageReady too. - */ -@property (nonatomic, readonly) PINImage *coverImage; -/** - The total duration of one loop of playback. - @warning Access to this property before status == PINAnimatedImageStatusInfoProcessed is undefined. - */ -@property (nonatomic, readonly) CFTimeInterval totalDuration; -/** - The number of frames to play per second * display refresh rate (defined as 60 which appears to be true on iOS). You probably want to - set this value on a displayLink. - @warning Access to this property before status == PINAnimatedImageStatusInfoProcessed is undefined. - */ -@property (nonatomic, readonly) NSUInteger frameInterval; -/** - The number of times to loop the animated image. Returns 0 if looping should occur infinitely. - @warning Access to this property before status == PINAnimatedImageStatusInfoProcessed is undefined. - */ -@property (nonatomic, readonly) size_t loopCount; -/** - The total number of frames in the animated image. - @warning Access to this property before status == PINAnimatedImageStatusInfoProcessed is undefined. - */ -@property (nonatomic, readonly) size_t frameCount; -/** - Any processing error that may have occured. - */ -@property (nonatomic, readonly) NSError *error; - -/** - The image at the frame index passed in. - @param index The index of the frame to retrieve. - @warning Access to this property before status == PINAnimatedImageStatusInfoProcessed is undefined. - */ -- (CGImageRef)imageAtIndex:(NSUInteger)index; -/** - The duration of the frame of the passed in index. - @param index The index of the frame to retrieve the duration it should be shown for. - @warning Access to this property before status == PINAnimatedImageStatusInfoProcessed is undefined. - */ -- (CFTimeInterval)durationAtIndex:(NSUInteger)index; -/** - Clears out the strong references to any memory maps that are being held. - */ -- (void)clearAnimatedImageCache; - -@end diff --git a/Pod/Classes/PINAnimatedImage.m b/Pod/Classes/PINAnimatedImage.m deleted file mode 100644 index 8f9837ee..00000000 --- a/Pod/Classes/PINAnimatedImage.m +++ /dev/null @@ -1,531 +0,0 @@ -// -// PINAnimatedImage.m -// Pods -// -// Created by Garrett Moon on 3/18/16. -// -// - -#import "PINAnimatedImage.h" - -#import "PINRemoteLock.h" -#import "PINAnimatedImageManager.h" - -NSString *kPINAnimatedImageErrorDomain = @"kPINAnimatedImageErrorDomain"; - -const Float32 kPINAnimatedImageDefaultDuration = 0.1; - -static const size_t kPINAnimatedImageBitsPerComponent = 8; - -const NSTimeInterval kPINAnimatedImageDisplayRefreshRate = 60.0; -//http://nullsleep.tumblr.com/post/16524517190/animated-gif-minimum-frame-delay-browser -const Float32 kPINAnimatedImageMinimumDuration = 1 / kPINAnimatedImageDisplayRefreshRate; - -@class PINSharedAnimatedImage; - -@interface PINAnimatedImage () -{ - PINRemoteLock *_completionLock; - PINRemoteLock *_dataLock; - - NSData *_currentData; - NSData *_nextData; -} - -@property (atomic, strong, readwrite) PINSharedAnimatedImage *sharedAnimatedImage; -@property (atomic, assign, readwrite) BOOL infoCompleted; - -@end - -@implementation PINAnimatedImage - -- (instancetype)init -{ - return [self initWithAnimatedImageData:nil]; -} - -- (instancetype)initWithAnimatedImageData:(NSData *)animatedImageData -{ - if (self = [super init]) { - _completionLock = [[PINRemoteLock alloc] initWithName:@"PINAnimatedImage completion lock"]; - _dataLock = [[PINRemoteLock alloc] initWithName:@"PINAnimatedImage data lock"]; - - NSAssert(animatedImageData != nil, @"animatedImageData must not be nil."); - - [[PINAnimatedImageManager sharedManager] animatedPathForImageData:animatedImageData infoCompletion:^(PINImage *coverImage, PINSharedAnimatedImage *shared) { - self.sharedAnimatedImage = shared; - self.infoCompleted = YES; - - [_completionLock lockWithBlock:^{ - if (_infoCompletion) { - _infoCompletion(coverImage); - _infoCompletion = nil; - } - }]; - } completion:^(BOOL completed, NSString *path, NSError *error) { - BOOL success = NO; - - if (completed && error == nil) { - success = YES; - } - - [_completionLock lockWithBlock:^{ - if (_fileReady) { - _fileReady(); - } - }]; - - if (success) { - [_completionLock lockWithBlock:^{ - if (_animatedImageReady) { - _animatedImageReady(); - _fileReady = nil; - _animatedImageReady = nil; - } - }]; - } - }]; - } - return self; -} - -- (void)setInfoCompletion:(PINAnimatedImageInfoReady)infoCompletion -{ - [_completionLock lockWithBlock:^{ - _infoCompletion = infoCompletion; - }]; -} - -- (void)setAnimatedImageReady:(dispatch_block_t)animatedImageReady -{ - [_completionLock lockWithBlock:^{ - _animatedImageReady = animatedImageReady; - }]; -} - -- (void)setFileReady:(dispatch_block_t)fileReady -{ - [_completionLock lockWithBlock:^{ - _fileReady = fileReady; - }]; -} - -- (PINImage *)coverImageWithMemoryMap:(NSData *)memoryMap width:(UInt32)width height:(UInt32)height bitsPerPixel:(UInt32)bitsPerPixel bitmapInfo:(CGBitmapInfo)bitmapInfo -{ - CGImageRef imageRef = [[self class] imageAtIndex:0 inMemoryMap:memoryMap width:width height:height bitsPerPixel:bitsPerPixel bitmapInfo:bitmapInfo]; -#if PIN_TARGET_IOS - return [UIImage imageWithCGImage:imageRef]; -#elif PIN_TARGET_MAC - return [[NSImage alloc] initWithCGImage:imageRef size:CGSizeMake(width, height)]; -#endif -} - -void releaseData(void *data, const void *imageData, size_t size); - -void releaseData(void *data, const void *imageData, size_t size) -{ - CFRelease(data); -} - -- (CGImageRef)imageAtIndex:(NSUInteger)index inSharedImageFiles:(NSArray *)imageFiles width:(UInt32)width height:(UInt32)height bitsPerPixel:(UInt32)bitsPerPixel bitmapInfo:(CGBitmapInfo)bitmapInfo -{ - if (self.status == PINAnimatedImageStatusError) { - return nil; - } - - for (NSUInteger fileIdx = 0; fileIdx < imageFiles.count; fileIdx++) { - PINSharedAnimatedImageFile *imageFile = imageFiles[fileIdx]; - if (index < imageFile.frameCount) { - __block NSData *memoryMappedData = nil; - [_dataLock lockWithBlock:^{ - memoryMappedData = imageFile.memoryMappedData; - _currentData = memoryMappedData; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - [_dataLock lockWithBlock:^{ - _nextData = (fileIdx + 1 < imageFiles.count) ? imageFiles[fileIdx + 1].memoryMappedData : imageFiles[0].memoryMappedData; - }]; - }); - }]; - return [[self class] imageAtIndex:index inMemoryMap:memoryMappedData width:width height:height bitsPerPixel:bitsPerPixel bitmapInfo:bitmapInfo]; - } else { - index -= imageFile.frameCount; - } - } - //image file not done yet :( - return nil; -} - -- (CFTimeInterval)durationAtIndex:(NSUInteger)index -{ - return self.durations[index]; -} - -+ (CGImageRef)imageAtIndex:(NSUInteger)index inMemoryMap:(NSData *)memoryMap width:(UInt32)width height:(UInt32)height bitsPerPixel:(UInt32)bitsPerPixel bitmapInfo:(CGBitmapInfo)bitmapInfo -{ - if (memoryMap == nil) { - return nil; - } - - Float32 outDuration; - - const size_t imageLength = width * height * bitsPerPixel / 8; - - //frame duration + previous images - NSUInteger offset = sizeof(UInt32) + (index * (imageLength + sizeof(outDuration))); - - [memoryMap getBytes:&outDuration range:NSMakeRange(offset, sizeof(outDuration))]; - - BytePtr imageData = (BytePtr)[memoryMap bytes]; - imageData += offset + sizeof(outDuration); - - NSAssert(offset + sizeof(outDuration) + imageLength <= memoryMap.length, @"Requesting frame beyond data bounds"); - - //retain the memory map, it will be released when releaseData is called - CFRetain((CFDataRef)memoryMap); - CGDataProviderRef dataProvider = CGDataProviderCreateWithData((void *)memoryMap, imageData, imageLength, releaseData); - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - CGImageRef imageRef = CGImageCreate(width, - height, - kPINAnimatedImageBitsPerComponent, - bitsPerPixel, - bitsPerPixel / 8 * width, - colorSpace, - bitmapInfo, - dataProvider, - NULL, - NO, - kCGRenderingIntentDefault); - if (imageRef) { - CFAutorelease(imageRef); - } - - CGColorSpaceRelease(colorSpace); - CGDataProviderRelease(dataProvider); - - return imageRef; -} - -// Although the following methods are unused, they could be in the future for restoring decoded images off disk (they're cleared currently). -+ (UInt32)widthFromMemoryMap:(NSData *)memoryMap -{ - UInt32 width; - [memoryMap getBytes:&width range:NSMakeRange(2, sizeof(width))]; - return width; -} - -+ (UInt32)heightFromMemoryMap:(NSData *)memoryMap -{ - UInt32 height; - [memoryMap getBytes:&height range:NSMakeRange(6, sizeof(height))]; - return height; -} - -+ (UInt32)bitsPerPixelFromMemoryMap:(NSData *)memoryMap -{ - UInt32 bitsPerPixel; - [memoryMap getBytes:&bitsPerPixel range:NSMakeRange(10, sizeof(bitsPerPixel))]; - return bitsPerPixel; -} - -+ (UInt32)loopCountFromMemoryMap:(NSData *)memoryMap -{ - UInt32 loopCount; - [memoryMap getBytes:&loopCount range:NSMakeRange(14, sizeof(loopCount))]; - return loopCount; -} - -+ (UInt32)frameCountFromMemoryMap:(NSData *)memoryMap -{ - UInt32 frameCount; - [memoryMap getBytes:&frameCount range:NSMakeRange(18, sizeof(frameCount))]; - return frameCount; -} - -//durations should be a buffer of size Float32 * frameCount -+ (Float32 *)createDurations:(Float32 *)durations fromMemoryMap:(NSData *)memoryMap frameCount:(UInt32)frameCount frameSize:(NSUInteger)frameSize totalDuration:(nonnull CFTimeInterval *)totalDuration -{ - *totalDuration = 0; - [memoryMap getBytes:&durations range:NSMakeRange(22, sizeof(Float32) * frameCount)]; - - for (NSUInteger idx = 0; idx < frameCount; idx++) { - *totalDuration += durations[idx]; - } - - return durations; -} - -- (Float32 *)durations -{ - NSAssert([self infoReady], @"info must be ready"); - return self.sharedAnimatedImage.durations; -} - -- (CFTimeInterval)totalDuration -{ - NSAssert([self infoReady], @"info must be ready"); - return self.sharedAnimatedImage.totalDuration; -} - -- (size_t)loopCount -{ - NSAssert([self infoReady], @"info must be ready"); - return self.sharedAnimatedImage.loopCount; -} - -- (size_t)frameCount -{ - NSAssert([self infoReady], @"info must be ready"); - return self.sharedAnimatedImage.frameCount; -} - -- (size_t)width -{ - NSAssert([self infoReady], @"info must be ready"); - return self.sharedAnimatedImage.width; -} - -- (size_t)height -{ - NSAssert([self infoReady], @"info must be ready"); - return self.sharedAnimatedImage.height; -} - -- (NSError *)error -{ - return self.sharedAnimatedImage.error; -} - -- (PINAnimatedImageStatus)status -{ - if (self.sharedAnimatedImage == nil) { - return PINAnimatedImageStatusUnprocessed; - } - return self.sharedAnimatedImage.status; -} - -- (CGImageRef)imageAtIndex:(NSUInteger)index -{ - return [self imageAtIndex:index - inSharedImageFiles:self.sharedAnimatedImage.maps - width:(UInt32)self.sharedAnimatedImage.width - height:(UInt32)self.sharedAnimatedImage.height - bitsPerPixel:(UInt32)self.sharedAnimatedImage.bitsPerPixel - bitmapInfo:self.sharedAnimatedImage.bitmapInfo]; -} - -- (PINImage *)coverImage -{ - NSAssert(self.coverImageReady, @"cover image must be ready."); - return self.sharedAnimatedImage.coverImage; -} - -- (BOOL)infoReady -{ - return self.infoCompleted; -} - -- (BOOL)coverImageReady -{ - return self.status == PINAnimatedImageStatusInfoProcessed || self.status == PINAnimatedImageStatusFirstFileProcessed || self.status == PINAnimatedImageStatusProcessed; -} - -- (BOOL)playbackReady -{ - return self.status == PINAnimatedImageStatusProcessed || self.status == PINAnimatedImageStatusFirstFileProcessed; -} - -- (void)clearAnimatedImageCache -{ - [_dataLock lockWithBlock:^{ - _currentData = nil; - _nextData = nil; - }]; -} - -- (NSUInteger)frameInterval -{ - return MAX(self.minimumFrameInterval * kPINAnimatedImageDisplayRefreshRate, 1); -} - -//Credit to FLAnimatedImage ( https://github.com/Flipboard/FLAnimatedImage ) for display link interval calculations -- (NSTimeInterval)minimumFrameInterval -{ - const NSTimeInterval kGreatestCommonDivisorPrecision = 2.0 / kPINAnimatedImageMinimumDuration; - - // Scales the frame delays by `kGreatestCommonDivisorPrecision` - // then converts it to an UInteger for in order to calculate the GCD. - NSUInteger scaledGCD = lrint(self.durations[0] * kGreatestCommonDivisorPrecision); - for (NSUInteger durationIdx = 0; durationIdx < self.frameCount; durationIdx++) { - Float32 duration = self.durations[durationIdx]; - scaledGCD = gcd(lrint(duration * kGreatestCommonDivisorPrecision), scaledGCD); - } - - // Reverse to scale to get the value back into seconds. - return (scaledGCD / kGreatestCommonDivisorPrecision); -} - -//Credit to FLAnimatedImage ( https://github.com/Flipboard/FLAnimatedImage ) for display link interval calculations -static NSUInteger gcd(NSUInteger a, NSUInteger b) -{ - // http://en.wikipedia.org/wiki/Greatest_common_divisor - if (a < b) { - return gcd(b, a); - } else if (a == b) { - return b; - } - - while (true) { - NSUInteger remainder = a % b; - if (remainder == 0) { - return b; - } - a = b; - b = remainder; - } -} - -@end - -@implementation PINSharedAnimatedImage - -- (instancetype)init -{ - if (self = [super init]) { - _coverImageLock = [[PINRemoteLock alloc] initWithName:@"PINSharedAnimatedImage cover image lock"]; - _completions = @[]; - _infoCompletions = @[]; - _maps = @[]; - } - return self; -} - -- (void)setInfoProcessedWithCoverImage:(PINImage *)coverImage UUID:(NSUUID *)UUID durations:(Float32 *)durations totalDuration:(CFTimeInterval)totalDuration loopCount:(size_t)loopCount frameCount:(size_t)frameCount width:(size_t)width height:(size_t)height bitsPerPixel:(size_t)bitsPerPixel bitmapInfo:(CGBitmapInfo)bitmapInfo -{ - NSAssert(_status == PINAnimatedImageStatusUnprocessed, @"Status should be unprocessed."); - [_coverImageLock lockWithBlock:^{ - _coverImage = coverImage; - }]; - _UUID = UUID; - _durations = (Float32 *)malloc(sizeof(Float32) * frameCount); - memcpy(_durations, durations, sizeof(Float32) * frameCount); - _totalDuration = totalDuration; - _loopCount = loopCount; - _frameCount = frameCount; - _width = width; - _height = height; - _bitsPerPixel = bitsPerPixel; - _bitmapInfo = bitmapInfo; - _status = PINAnimatedImageStatusInfoProcessed; -} - -- (void)dealloc -{ - NSAssert(self.completions.count == 0 && self.infoCompletions.count == 0, @"Shouldn't be dealloc'd if we have a completion or an infoCompletion"); - - //Clean up shared files. - - //Get references to maps and UUID so the below block doesn't reference self. - NSArray *maps = self.maps; - self.maps = nil; - NSUUID *UUID = self.UUID; - - if (maps.count > 0) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - //ignore errors - [[NSFileManager defaultManager] removeItemAtPath:[PINAnimatedImageManager filePathWithTemporaryDirectory:[PINAnimatedImageManager temporaryDirectory] UUID:UUID count:0] error:nil]; - for (PINSharedAnimatedImageFile *file in maps) { - [[NSFileManager defaultManager] removeItemAtPath:file.path error:nil]; - } - }); - } - free(_durations); -} - -- (PINImage *)coverImage -{ - __block PINImage *coverImage = nil; - [_coverImageLock lockWithBlock:^{ - if (_coverImage == nil) { - CGImageRef imageRef = [PINAnimatedImage imageAtIndex:0 inMemoryMap:self.maps[0].memoryMappedData width:(UInt32)self.width height:(UInt32)self.height bitsPerPixel:(UInt32)self.bitsPerPixel bitmapInfo:self.bitmapInfo]; -#if PIN_TARGET_IOS - coverImage = [UIImage imageWithCGImage:imageRef]; -#elif PIN_TARGET_MAC - coverImage = [[NSImage alloc] initWithCGImage:imageRef size:CGSizeMake(self.width, self.height)]; -#endif - _coverImage = coverImage; - } else { - coverImage = _coverImage; - } - }]; - - return coverImage; -} - -@end - -@implementation PINSharedAnimatedImageFile - -@synthesize memoryMappedData = _memoryMappedData; -@synthesize frameCount = _frameCount; - -- (instancetype)init -{ - NSAssert(NO, @"Call initWithPath:"); - return [self initWithPath:nil]; -} - -- (instancetype)initWithPath:(NSString *)path -{ - if (self = [super init]) { - _lock = [[PINRemoteLock alloc] initWithName:@"PINSharedAnimatedImageFile lock"]; - _path = path; - } - return self; -} - -- (UInt32)frameCount -{ - __block UInt32 frameCount; - [_lock lockWithBlock:^{ - if (_frameCount == 0) { - NSData *memoryMappedData = _memoryMappedData; - if (memoryMappedData == nil) { - memoryMappedData = [self loadMemoryMappedData]; - } - [memoryMappedData getBytes:&_frameCount range:NSMakeRange(0, sizeof(_frameCount))]; - } - frameCount = _frameCount; - }]; - - return frameCount; -} - -- (NSData *)memoryMappedData -{ - __block NSData *memoryMappedData; - [_lock lockWithBlock:^{ - memoryMappedData = _memoryMappedData; - if (memoryMappedData == nil) { - memoryMappedData = [self loadMemoryMappedData]; - } - }]; - return memoryMappedData; -} - -//must be called within lock -- (NSData *)loadMemoryMappedData -{ - NSError *error = nil; - //local variable shenanigans due to weak ivar _memoryMappedData - NSData *memoryMappedData = [NSData dataWithContentsOfFile:self.path options:NSDataReadingMappedAlways error:&error]; - if (error) { -#if PINAnimatedImageDebug - NSLog(@"Could not memory map data: %@", error); -#endif - } else { - _memoryMappedData = memoryMappedData; - } - return memoryMappedData; -} - -@end diff --git a/Pod/Classes/PINAnimatedImageManager.h b/Pod/Classes/PINAnimatedImageManager.h deleted file mode 100644 index 0e7cff36..00000000 --- a/Pod/Classes/PINAnimatedImageManager.h +++ /dev/null @@ -1,82 +0,0 @@ -// -// PINAnimatedImageManager.h -// Pods -// -// Created by Garrett Moon on 4/5/16. -// -// - -#import - -#import "PINAnimatedImage.h" -#import "PINRemoteImageMacros.h" - -@class PINRemoteLock; -@class PINSharedAnimatedImage; -@class PINSharedAnimatedImageFile; - -typedef void(^PINAnimatedImageSharedReady)(PINImage *coverImage, PINSharedAnimatedImage *shared); -typedef void(^PINAnimatedImageDecodedPath)(BOOL finished, NSString *path, NSError *error); - -@interface PINAnimatedImageManager : NSObject - -+ (instancetype)sharedManager; -+ (NSString *)temporaryDirectory; -+ (NSString *)filePathWithTemporaryDirectory:(NSString *)temporaryDirectory UUID:(NSUUID *)UUID count:(NSUInteger)count; - -- (void)animatedPathForImageData:(NSData *)animatedImageData infoCompletion:(PINAnimatedImageSharedReady)infoCompletion completion:(PINAnimatedImageDecodedPath)completion; - -@end - -@interface PINSharedAnimatedImage : NSObject -{ - PINRemoteLock *_coverImageLock; -} - -//This is intentionally atomic. PINAnimatedImageManager must be able to add entries -//and clients must be able to read them concurrently. -@property (atomic, strong, readwrite) NSArray *maps; - -@property (nonatomic, strong, readwrite) NSArray *completions; -@property (nonatomic, strong, readwrite) NSArray *infoCompletions; -@property (nonatomic, weak, readwrite) PINImage *coverImage; - -//intentionally atomic -@property (atomic, strong, readwrite) NSError *error; -@property (atomic, assign, readwrite) PINAnimatedImageStatus status; - -- (void)setInfoProcessedWithCoverImage:(PINImage *)coverImage - UUID:(NSUUID *)UUID - durations:(Float32 *)durations - totalDuration:(CFTimeInterval)totalDuration - loopCount:(size_t)loopCount - frameCount:(size_t)frameCount - width:(size_t)width - height:(size_t)height - bitsPerPixel:(size_t)bitsPerPixel - bitmapInfo:(CGBitmapInfo)bitmapInfo; - -@property (nonatomic, readonly) NSUUID *UUID; -@property (nonatomic, readonly) Float32 *durations; -@property (nonatomic, readonly) CFTimeInterval totalDuration; -@property (nonatomic, readonly) size_t loopCount; -@property (nonatomic, readonly) size_t frameCount; -@property (nonatomic, readonly) size_t width; -@property (nonatomic, readonly) size_t height; -@property (nonatomic, readonly) size_t bitsPerPixel; -@property (nonatomic, readonly) CGBitmapInfo bitmapInfo; - -@end - -@interface PINSharedAnimatedImageFile : NSObject -{ - PINRemoteLock *_lock; -} - -@property (nonatomic, strong, readonly) NSString *path; -@property (nonatomic, assign, readonly) UInt32 frameCount; -@property (nonatomic, weak, readonly) NSData *memoryMappedData; - -- (instancetype)initWithPath:(NSString *)path NS_DESIGNATED_INITIALIZER; - -@end diff --git a/Pod/Classes/PINAnimatedImageManager.m b/Pod/Classes/PINAnimatedImageManager.m deleted file mode 100644 index 312c7e33..00000000 --- a/Pod/Classes/PINAnimatedImageManager.m +++ /dev/null @@ -1,564 +0,0 @@ -// -// PINAnimatedImageManager.m -// Pods -// -// Created by Garrett Moon on 4/5/16. -// -// - -#import "PINAnimatedImageManager.h" - -#import -#if PIN_TARGET_IOS -#import -#elif PIN_TARGET_MAC -#import -#endif - -#import "PINRemoteLock.h" - -static const NSUInteger maxFileSize = 50000000; //max file size in bytes -static const Float32 maxFileDuration = 1; //max duration of a file in seconds - -typedef void(^PINAnimatedImageInfoProcessed)(PINImage *coverImage, NSUUID *UUID, Float32 *durations, CFTimeInterval totalDuration, size_t loopCount, size_t frameCount, size_t width, size_t height, size_t bitsPerPixel, UInt32 bitmapInfo); - -BOOL PINStatusCoverImageCompleted(PINAnimatedImageStatus status); -BOOL PINStatusCoverImageCompleted(PINAnimatedImageStatus status) { - return status == PINAnimatedImageStatusInfoProcessed || status == PINAnimatedImageStatusFirstFileProcessed || status == PINAnimatedImageStatusProcessed; -} - -@interface PINAnimatedImageManager () -{ - PINRemoteLock *_lock; -} - -+ (instancetype)sharedManager; - -@property (nonatomic, strong, readonly) NSMapTable *animatedImages; -@property (nonatomic, strong, readonly) dispatch_queue_t serialProcessingQueue; - -@end - -static dispatch_once_t startupCleanupOnce; - -@implementation PINAnimatedImageManager - -+ (void)initialize -{ - if (self == [PINAnimatedImageManager class]) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - dispatch_once(&startupCleanupOnce, ^{ - [self cleanupFiles]; - }); - }); - } -} - -+ (instancetype)sharedManager -{ - static dispatch_once_t onceToken; - static PINAnimatedImageManager *sharedManager; - dispatch_once(&onceToken, ^{ - sharedManager = [[PINAnimatedImageManager alloc] init]; - }); - return sharedManager; -} - -+ (NSString *)temporaryDirectory -{ - static dispatch_once_t onceToken; - static NSString *temporaryDirectory; - dispatch_once(&onceToken, ^{ - //On iOS temp directories are not shared between apps. This may not be safe on OS X or other systems - temporaryDirectory = [NSTemporaryDirectory() stringByAppendingPathComponent:@"ASAnimatedImageCache"]; - }); - return temporaryDirectory; -} - -- (instancetype)init -{ - if (self = [super init]) { - dispatch_once(&startupCleanupOnce, ^{ - [PINAnimatedImageManager cleanupFiles]; - }); - - _lock = [[PINRemoteLock alloc] initWithName:@"PINAnimatedImageManager lock"]; - - if ([[NSFileManager defaultManager] fileExistsAtPath:[PINAnimatedImageManager temporaryDirectory]] == NO) { - [[NSFileManager defaultManager] createDirectoryAtPath:[PINAnimatedImageManager temporaryDirectory] withIntermediateDirectories:YES attributes:nil error:nil]; - } - - _animatedImages = [[NSMapTable alloc] initWithKeyOptions:NSMapTableWeakMemory valueOptions:NSMapTableWeakMemory capacity:1]; - _serialProcessingQueue = dispatch_queue_create("Serial animated image processing queue.", DISPATCH_QUEUE_SERIAL); - -#if PIN_TARGET_IOS - NSString * const notificationName = UIApplicationWillTerminateNotification; -#elif PIN_TARGET_MAC - NSString * const notificationName = NSApplicationWillTerminateNotification; -#endif - [[NSNotificationCenter defaultCenter] addObserverForName:notificationName - object:nil - queue:nil - usingBlock:^(NSNotification * _Nonnull note) { - [PINAnimatedImageManager cleanupFiles]; - }]; - } - return self; -} - -+ (void)cleanupFiles -{ - [[NSFileManager defaultManager] removeItemAtPath:[PINAnimatedImageManager temporaryDirectory] error:nil]; -} - -- (void)animatedPathForImageData:(NSData *)animatedImageData infoCompletion:(PINAnimatedImageSharedReady)infoCompletion completion:(PINAnimatedImageDecodedPath)completion -{ - __block BOOL startProcessing = NO; - __block PINSharedAnimatedImage *sharedAnimatedImage = nil; - { - [_lock lockWithBlock:^{ - sharedAnimatedImage = [self.animatedImages objectForKey:animatedImageData]; - if (sharedAnimatedImage == nil) { - sharedAnimatedImage = [[PINSharedAnimatedImage alloc] init]; - [self.animatedImages setObject:sharedAnimatedImage forKey:animatedImageData]; - startProcessing = YES; - } - - if (PINStatusCoverImageCompleted(sharedAnimatedImage.status)) { - //Info is already processed, call infoCompletion immediately - if (infoCompletion) { - infoCompletion(sharedAnimatedImage.coverImage, sharedAnimatedImage); - } - } else { - //Add infoCompletion to sharedAnimatedImage - if (infoCompletion) { - //Since ASSharedAnimatedImages are stored weakly in our map, we need a strong reference in completions - PINAnimatedImageSharedReady capturingInfoCompletion = ^(PINImage *coverImage, PINSharedAnimatedImage *newShared) { - __unused PINSharedAnimatedImage *strongShared = sharedAnimatedImage; - infoCompletion(coverImage, newShared); - }; - sharedAnimatedImage.infoCompletions = [sharedAnimatedImage.infoCompletions arrayByAddingObject:capturingInfoCompletion]; - } - } - - if (sharedAnimatedImage.status == PINAnimatedImageStatusProcessed) { - //Animated image is already fully processed, call completion immediately - if (completion) { - completion(YES, nil, nil); - } - } else if (sharedAnimatedImage.status == PINAnimatedImageStatusError) { - if (completion) { - completion(NO, nil, sharedAnimatedImage.error); - } - } else { - //Add completion to sharedAnimatedImage - if (completion) { - //Since PINSharedAnimatedImages are stored weakly in our map, we need a strong reference in completions - PINAnimatedImageDecodedPath capturingCompletion = ^(BOOL finished, NSString *path, NSError *error) { - __unused PINSharedAnimatedImage *strongShared = sharedAnimatedImage; - completion(finished, path, error); - }; - sharedAnimatedImage.completions = [sharedAnimatedImage.completions arrayByAddingObject:capturingCompletion]; - } - } - }]; - } - - if (startProcessing) { - dispatch_async(self.serialProcessingQueue, ^{ - [[self class] processAnimatedImage:animatedImageData temporaryDirectory:[PINAnimatedImageManager temporaryDirectory] infoCompletion:^(PINImage *coverImage, NSUUID *UUID, Float32 *durations, CFTimeInterval totalDuration, size_t loopCount, size_t frameCount, size_t width, size_t height, size_t bitsPerPixel, UInt32 bitmapInfo) { - __block NSArray *infoCompletions = nil; - __block PINSharedAnimatedImage *sharedAnimatedImage = nil; - [_lock lockWithBlock:^{ - sharedAnimatedImage = [self.animatedImages objectForKey:animatedImageData]; - [sharedAnimatedImage setInfoProcessedWithCoverImage:coverImage UUID:UUID durations:durations totalDuration:totalDuration loopCount:loopCount frameCount:frameCount width:width height:height bitsPerPixel:bitsPerPixel bitmapInfo:bitmapInfo]; - infoCompletions = sharedAnimatedImage.infoCompletions; - sharedAnimatedImage.infoCompletions = @[]; - }]; - - for (PINAnimatedImageSharedReady infoCompletion in infoCompletions) { - infoCompletion(coverImage, sharedAnimatedImage); - } - } decodedPath:^(BOOL finished, NSString *path, NSError *error) { - __block NSArray *completions = nil; - { - [_lock lockWithBlock:^{ - PINSharedAnimatedImage *sharedAnimatedImage = [self.animatedImages objectForKey:animatedImageData]; - - if (path && error == nil) { - sharedAnimatedImage.maps = [sharedAnimatedImage.maps arrayByAddingObject:[[PINSharedAnimatedImageFile alloc] initWithPath:path]]; - } - sharedAnimatedImage.error = error; - if (error) { - sharedAnimatedImage.status = PINAnimatedImageStatusError; - } - - completions = sharedAnimatedImage.completions; - if (finished || error) { - sharedAnimatedImage.completions = @[]; - } - - if (error == nil) { - if (finished) { - sharedAnimatedImage.status = PINAnimatedImageStatusProcessed; - } else { - sharedAnimatedImage.status = PINAnimatedImageStatusFirstFileProcessed; - } - } - }]; - } - - for (PINAnimatedImageDecodedPath completion in completions) { - completion(finished, path, error); - } - }]; - }); - } -} - -#define HANDLE_PROCESSING_ERROR(ERROR) \ -{ \ -if (ERROR != nil) { \ - [errorLock lockWithBlock:^{ \ - if (processingError == nil) { \ - processingError = ERROR; \ - } \ - }]; \ -\ -[fileHandle closeFile]; \ -[[NSFileManager defaultManager] removeItemAtPath:filePath error:nil]; \ -} \ -} - -#define PROCESSING_ERROR \ -({__block NSError *ERROR; \ -[errorLock lockWithBlock:^{ \ - ERROR = processingError; \ -}]; \ -ERROR;}) \ - -+ (void)processAnimatedImage:(NSData *)animatedImageData - temporaryDirectory:(NSString *)temporaryDirectory - infoCompletion:(PINAnimatedImageInfoProcessed)infoCompletion - decodedPath:(PINAnimatedImageDecodedPath)completion -{ - NSUUID *UUID = [NSUUID UUID]; - __block NSError *processingError = nil; - PINRemoteLock *errorLock = [[PINRemoteLock alloc] initWithName:@"animatedImage processing lock"]; - NSString *filePath = nil; - //TODO Must handle file handle errors! Documentation says it throws exceptions on any errors :( - NSError *fileHandleError = nil; - NSFileHandle *fileHandle = [self fileHandle:&fileHandleError filePath:&filePath temporaryDirectory:temporaryDirectory UUID:UUID count:0]; - HANDLE_PROCESSING_ERROR(fileHandleError); - UInt32 width; - UInt32 height; - UInt32 bitsPerPixel; - UInt32 bitmapInfo; - NSUInteger fileCount = 0; - UInt32 frameCountForFile = 0; - Float32 *durations = NULL; - -#if PINAnimatedImageDebug - CFTimeInterval start = CACurrentMediaTime(); -#endif - - if (fileHandle && PROCESSING_ERROR == nil) { - dispatch_queue_t diskWriteQueue = dispatch_queue_create("PINAnimatedImage disk write queue", DISPATCH_QUEUE_SERIAL); - dispatch_group_t diskGroup = dispatch_group_create(); - - CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)animatedImageData, - (CFDictionaryRef)@{(__bridge NSString *)kCGImageSourceTypeIdentifierHint : (__bridge NSString *)kUTTypeGIF, - (__bridge NSString *)kCGImageSourceShouldCache : (__bridge NSNumber *)kCFBooleanFalse}); - - if (imageSource) { - UInt32 frameCount = (UInt32)CGImageSourceGetCount(imageSource); - NSDictionary *imageProperties = (__bridge_transfer NSDictionary *)CGImageSourceCopyProperties(imageSource, nil); - UInt32 loopCount = (UInt32)[[[imageProperties objectForKey:(__bridge NSString *)kCGImagePropertyGIFDictionary] - objectForKey:(__bridge NSString *)kCGImagePropertyGIFLoopCount] unsignedLongValue]; - - Float32 fileDuration = 0; - NSUInteger fileSize = 0; - durations = (Float32 *)malloc(sizeof(Float32) * frameCount); - CFTimeInterval totalDuration = 0; - PINImage *coverImage = nil; - - //Gather header file info - for (NSUInteger frameIdx = 0; frameIdx < frameCount; frameIdx++) { - if (frameIdx == 0) { - CGImageRef frameImage = CGImageSourceCreateImageAtIndex(imageSource, frameIdx, (CFDictionaryRef)@{(__bridge NSString *)kCGImageSourceShouldCache : (__bridge NSNumber *)kCFBooleanFalse}); - if (frameImage == nil) { - NSError *frameError = [NSError errorWithDomain:kPINAnimatedImageErrorDomain code:PINAnimatedImageErrorImageFrameError userInfo:nil]; - HANDLE_PROCESSING_ERROR(frameError); - break; - } - - bitmapInfo = CGImageGetBitmapInfo(frameImage); - - width = (UInt32)CGImageGetWidth(frameImage); - height = (UInt32)CGImageGetHeight(frameImage); - bitsPerPixel = (UInt32)CGImageGetBitsPerPixel(frameImage); - -#if PIN_TARGET_IOS - coverImage = [UIImage imageWithCGImage:frameImage]; -#elif PIN_TARGET_MAC - coverImage = [[NSImage alloc] initWithCGImage:frameImage size:CGSizeMake(width, height)]; -#endif - CGImageRelease(frameImage); - } - - Float32 duration = [[self class] frameDurationAtIndex:frameIdx source:imageSource]; - durations[frameIdx] = duration; - totalDuration += duration; - } - - if (PROCESSING_ERROR == nil) { - //Get size, write file header get coverImage - dispatch_group_async(diskGroup, diskWriteQueue, ^{ - NSError *fileHeaderError = [self writeFileHeader:fileHandle width:width height:height bitsPerPixel:bitsPerPixel loopCount:loopCount frameCount:frameCount bitmapInfo:bitmapInfo durations:durations]; - HANDLE_PROCESSING_ERROR(fileHeaderError); - if (fileHeaderError == nil) { - [fileHandle closeFile]; - - PINLog(@"notifying info"); - infoCompletion(coverImage, UUID, durations, totalDuration, loopCount, frameCount, width, height, bitsPerPixel, bitmapInfo); - } - }); - fileCount = 1; - NSError *fileHandleError = nil; - fileHandle = [self fileHandle:&fileHandleError filePath:&filePath temporaryDirectory:temporaryDirectory UUID:UUID count:fileCount]; - HANDLE_PROCESSING_ERROR(fileHandleError); - - dispatch_group_async(diskGroup, diskWriteQueue, ^{ - //write empty frame count - @try { - [fileHandle writeData:[NSData dataWithBytes:&frameCountForFile length:sizeof(frameCountForFile)]]; - } @catch (NSException *exception) { - NSError *frameCountError = [NSError errorWithDomain:kPINAnimatedImageErrorDomain code:PINAnimatedImageErrorFileWrite userInfo:@{@"NSException" : exception}]; - HANDLE_PROCESSING_ERROR(frameCountError); - } @finally {} - }); - - //Process frames - for (NSUInteger frameIdx = 0; frameIdx < frameCount; frameIdx++) { - if (PROCESSING_ERROR != nil) { - break; - } - @autoreleasepool { - if (fileDuration > maxFileDuration || fileSize > maxFileSize) { - //create a new file - dispatch_group_async(diskGroup, diskWriteQueue, ^{ - //prepend file with frameCount - @try { - [fileHandle seekToFileOffset:0]; - [fileHandle writeData:[NSData dataWithBytes:&frameCountForFile length:sizeof(frameCountForFile)]]; - [fileHandle closeFile]; - } @catch (NSException *exception) { - NSError *frameCountError = [NSError errorWithDomain:kPINAnimatedImageErrorDomain code:PINAnimatedImageErrorFileWrite userInfo:@{@"NSException" : exception}]; - HANDLE_PROCESSING_ERROR(frameCountError); - } @finally {} - }); - - dispatch_group_async(diskGroup, diskWriteQueue, ^{ - PINLog(@"notifying file: %@", filePath); - completion(NO, filePath, PROCESSING_ERROR); - }); - - diskGroup = dispatch_group_create(); - fileCount++; - NSError *fileHandleError = nil; - fileHandle = [self fileHandle:&fileHandleError filePath:&filePath temporaryDirectory:temporaryDirectory UUID:UUID count:fileCount]; - HANDLE_PROCESSING_ERROR(fileHandleError); - frameCountForFile = 0; - fileDuration = 0; - fileSize = 0; - //write empty frame count - dispatch_group_async(diskGroup, diskWriteQueue, ^{ - @try { - [fileHandle writeData:[NSData dataWithBytes:&frameCountForFile length:sizeof(frameCountForFile)]]; - } @catch (NSException *exception) { - NSError *frameCountError = [NSError errorWithDomain:kPINAnimatedImageErrorDomain code:PINAnimatedImageErrorFileWrite userInfo:@{@"NSException" : exception}]; - HANDLE_PROCESSING_ERROR(frameCountError); - } @finally {} - }); - } - - Float32 duration = durations[frameIdx]; - fileDuration += duration; - - dispatch_group_async(diskGroup, diskWriteQueue, ^{ - if (PROCESSING_ERROR) { - return; - } - - CGImageRef frameImage = CGImageSourceCreateImageAtIndex(imageSource, frameIdx, (CFDictionaryRef)@{(__bridge NSString *)kCGImageSourceShouldCache : (__bridge NSNumber *)kCFBooleanFalse}); - if (frameImage == nil) { - NSError *frameImageError = [NSError errorWithDomain:kPINAnimatedImageErrorDomain code:PINAnimatedImageErrorImageFrameError userInfo:nil]; - HANDLE_PROCESSING_ERROR(frameImageError); - return; - } - - NSData *frameData = (__bridge_transfer NSData *)CGDataProviderCopyData(CGImageGetDataProvider(frameImage)); - NSAssert(frameData.length == width * height * bitsPerPixel / 8, @"data should be width * height * bytes per pixel"); - NSError *frameWriteError = [self writeFrameToFile:fileHandle duration:duration frameData:frameData]; - HANDLE_PROCESSING_ERROR(frameWriteError); - - CGImageRelease(frameImage); - }); - - frameCountForFile++; - } - } - } else { - completion(NO, nil, PROCESSING_ERROR); - } - } - - dispatch_group_wait(diskGroup, DISPATCH_TIME_FOREVER); - if (imageSource) { - CFRelease(imageSource); - } - - //close the file handle - PINLog(@"closing last file: %@", fileHandle); - @try { - [fileHandle seekToFileOffset:0]; - [fileHandle writeData:[NSData dataWithBytes:&frameCountForFile length:sizeof(frameCountForFile)]]; - [fileHandle closeFile]; - } @catch (NSException *exception) { - NSError *frameCountError = [NSError errorWithDomain:kPINAnimatedImageErrorDomain code:PINAnimatedImageErrorFileWrite userInfo:@{@"NSException" : exception}]; - HANDLE_PROCESSING_ERROR(frameCountError); - } @finally {} - } - -#if PINAnimatedImageDebug - CFTimeInterval interval = CACurrentMediaTime() - start; - NSLog(@"Encoding and write time: %f", interval); -#endif - - if (durations) { - free(durations); - } - - completion(YES, filePath, PROCESSING_ERROR); -} - -//http://stackoverflow.com/questions/16964366/delaytime-or-unclampeddelaytime-for-gifs -+ (Float32)frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source -{ - Float32 frameDuration = kPINAnimatedImageDefaultDuration; - NSDictionary *frameProperties = (__bridge_transfer NSDictionary *)CGImageSourceCopyPropertiesAtIndex(source, index, nil); - // use unclamped delay time before delay time before default - NSNumber *unclamedDelayTime = frameProperties[(__bridge NSString *)kCGImagePropertyGIFDictionary][(__bridge NSString *)kCGImagePropertyGIFUnclampedDelayTime]; - if (unclamedDelayTime) { - frameDuration = [unclamedDelayTime floatValue]; - } else { - NSNumber *delayTime = frameProperties[(__bridge NSString *)kCGImagePropertyGIFDictionary][(__bridge NSString *)kCGImagePropertyGIFDelayTime]; - if (delayTime) { - frameDuration = [delayTime floatValue]; - } - } - - if (frameDuration < kPINAnimatedImageMinimumDuration) { - frameDuration = kPINAnimatedImageDefaultDuration; - } - - return frameDuration; -} - -+ (NSString *)filePathWithTemporaryDirectory:(NSString *)temporaryDirectory UUID:(NSUUID *)UUID count:(NSUInteger)count -{ - NSString *filePath = [temporaryDirectory stringByAppendingPathComponent:[UUID UUIDString]]; - if (count > 0) { - filePath = [filePath stringByAppendingString:[@(count) stringValue]]; - } - return filePath; -} - -+ (NSFileHandle *)fileHandle:(NSError **)error filePath:(NSString **)filePath temporaryDirectory:(NSString *)temporaryDirectory UUID:(NSUUID *)UUID count:(NSUInteger)count; -{ - NSString *outFilePath = [self filePathWithTemporaryDirectory:temporaryDirectory UUID:UUID count:count]; - NSError *outError = nil; - NSFileHandle *fileHandle = nil; - - if (outError == nil) { - BOOL success = [[NSFileManager defaultManager] createFileAtPath:outFilePath contents:nil attributes:nil]; - if (success == NO) { - outError = [NSError errorWithDomain:kPINAnimatedImageErrorDomain code:PINAnimatedImageErrorFileCreationError userInfo:nil]; - } - } - - if (outError == nil) { - fileHandle = [NSFileHandle fileHandleForWritingAtPath:outFilePath]; - if (fileHandle == nil) { - outError = [NSError errorWithDomain:kPINAnimatedImageErrorDomain code:PINAnimatedImageErrorFileHandleError userInfo:nil]; - } - } - - if (error) { - *error = outError; - } - - if (filePath) { - *filePath = outFilePath; - } - - return fileHandle; -} - -/** - PINAnimatedImage file header - - Header: - [version] 2 bytes - [width] 4 bytes - [height] 4 bytes - [loop count] 4 bytes - [frame count] 4 bytes - [bitmap info] 4 bytes - [durations] 4 bytes * frame count - - */ - -+ (NSError *)writeFileHeader:(NSFileHandle *)fileHandle width:(UInt32)width height:(UInt32)height bitsPerPixel:(UInt32)bitsPerPixel loopCount:(UInt32)loopCount frameCount:(UInt32)frameCount bitmapInfo:(UInt32)bitmapInfo durations:(Float32*)durations -{ - NSError *error = nil; - @try { - UInt16 version = 2; - [fileHandle writeData:[NSData dataWithBytes:&version length:sizeof(version)]]; - [fileHandle writeData:[NSData dataWithBytes:&width length:sizeof(width)]]; - [fileHandle writeData:[NSData dataWithBytes:&height length:sizeof(height)]]; - [fileHandle writeData:[NSData dataWithBytes:&bitsPerPixel length:sizeof(bitsPerPixel)]]; - [fileHandle writeData:[NSData dataWithBytes:&loopCount length:sizeof(loopCount)]]; - [fileHandle writeData:[NSData dataWithBytes:&frameCount length:sizeof(frameCount)]]; - [fileHandle writeData:[NSData dataWithBytes:&bitmapInfo length:sizeof(bitmapInfo)]]; - //Since we can't get the length of the durations array from the pointer, we'll just calculate it based on the frameCount. - [fileHandle writeData:[NSData dataWithBytes:durations length:sizeof(Float32) * frameCount]]; - } @catch (NSException *exception) { - error = [NSError errorWithDomain:kPINAnimatedImageErrorDomain code:PINAnimatedImageErrorFileWrite userInfo:@{@"NSException" : exception}]; - } @finally {} - return error; -} - -/** - PINAnimatedImage frame file - [frame count(in file)] 4 bytes - [frame(s)] - - Each frame: - [duration] 4 bytes - [frame data] width * height * 4 bytes - */ - -+ (NSError *)writeFrameToFile:(NSFileHandle *)fileHandle duration:(Float32)duration frameData:(NSData *)frameData -{ - NSError *error = nil; - @try { - [fileHandle writeData:[NSData dataWithBytes:&duration length:sizeof(duration)]]; - [fileHandle writeData:frameData]; - } @catch (NSException *exception) { - error = [NSError errorWithDomain:kPINAnimatedImageErrorDomain code:PINAnimatedImageErrorFileWrite userInfo:@{@"NSException" : exception}]; - } @finally {} - return error; -} - -@end diff --git a/Pod/Classes/PINCache/PINCache+PINRemoteImageCaching.h b/Pod/Classes/PINCache/PINCache+PINRemoteImageCaching.h deleted file mode 100644 index f2ab9a9d..00000000 --- a/Pod/Classes/PINCache/PINCache+PINRemoteImageCaching.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// PINCache+PINRemoteImageCaching.h -// Pods -// -// Created by Aleksei Shevchenko on 7/28/16. -// -// - -#import -#import "PINRemoteImageCaching.h" - -@interface PINCache (PINRemoteImageCaching) - -@end diff --git a/Pod/Classes/PINCache/PINCache+PINRemoteImageCaching.m b/Pod/Classes/PINCache/PINCache+PINRemoteImageCaching.m deleted file mode 100644 index df3df6bc..00000000 --- a/Pod/Classes/PINCache/PINCache+PINRemoteImageCaching.m +++ /dev/null @@ -1,84 +0,0 @@ -// -// PINCache+PINRemoteImageCaching.m -// Pods -// -// Created by Aleksei Shevchenko on 7/28/16. -// -// - -#import "PINCache+PINRemoteImageCaching.h" - -@implementation PINCache (PINRemoteImageCaching) - -//****************************************************************************************************** -// Memory cache methods -//****************************************************************************************************** --(nullable id)objectFromMemoryCacheForKey:(NSString *)key -{ - return [self.memoryCache objectForKey:key]; -} - --(void)cacheObjectInMemory:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost -{ - [self.memoryCache setObject:object forKey:key withCost:cost]; -} - -- (void)removeCachedObjectForKeyFromMemoryCache:(NSString *)key -{ - [self.memoryCache removeObjectForKey:key]; -} - -//****************************************************************************************************** -// Disk cache methods -//****************************************************************************************************** --(nullable id)objectFromDiskCacheForKey:(NSString *)key -{ - return [self.diskCache objectForKey:key]; -} - --(void)objectFromDiskCacheForKey:(NSString *)key completion:(PINRemoteImageCachingObjectBlock)completion -{ - __weak typeof(self) weakSelf = self; - [self.diskCache objectForKey:key block:^(PINDiskCache * _Nonnull cache, NSString * _Nonnull key, id _Nullable object) { - if(completion) { - typeof(self) strongSelf = weakSelf; - completion(strongSelf, key, object); - } - }]; -} - --(void)cacheObjectOnDisk:(id)object forKey:(NSString *)key -{ - [self.diskCache setObject:object forKey:key]; -} - -- (BOOL)objectExistsInCacheForKey:(NSString *)key -{ - return [self containsObjectForKey:key]; -} - -//****************************************************************************************************** -// Common cache methods -//****************************************************************************************************** -- (void)removeCachedObjectForKey:(NSString *)key -{ - [self removeObjectForKey:key]; -} -- (void)removeCachedObjectForKey:(NSString *)key completion:(PINRemoteImageCachingObjectBlock)completion -{ - __weak typeof(self) weakSelf = self; - [self removeObjectForKey:key block:^(PINCache * _Nonnull cache, NSString * _Nonnull key, id _Nullable object) { - if(completion) { - typeof(self) strongSelf = weakSelf; - completion(strongSelf, key, object); - } - }]; -} - -- (void)removeAllCachedObjects -{ - [self removeAllObjects]; -} - - -@end diff --git a/Pod/Classes/PINDataTaskOperation.h b/Pod/Classes/PINDataTaskOperation.h deleted file mode 100644 index 56ba12db..00000000 --- a/Pod/Classes/PINDataTaskOperation.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// PINDataTaskOperation.h -// Pods -// -// Created by Garrett Moon on 3/12/15. -// -// - -#import - -#import "PINURLSessionManager.h" - -@interface PINDataTaskOperation : NSOperation - -@property (nonatomic, readonly, nullable) NSURLSessionDataTask *dataTask; - -+ (nonnull instancetype)dataTaskOperationWithSessionManager:(nonnull PINURLSessionManager *)sessionManager - request:(nonnull NSURLRequest *)request - completionHandler:(nonnull void (^)(NSURLResponse * _Nonnull response, NSError * _Nullable error))completionHandler; - -@end diff --git a/Pod/Classes/PINDataTaskOperation.m b/Pod/Classes/PINDataTaskOperation.m deleted file mode 100644 index fc66f447..00000000 --- a/Pod/Classes/PINDataTaskOperation.m +++ /dev/null @@ -1,148 +0,0 @@ -// -// PINDataTaskOperation.m -// Pods -// -// Created by Garrett Moon on 3/12/15. -// -// - -#import "PINDataTaskOperation.h" - -#import "PINURLSessionManager.h" - -typedef NS_ENUM(NSUInteger, PIDataTaskOperationState) { - PIDataTaskOperationStateReady, - PIDataTaskOperationStateExecuting, - PIDataTaskOperationStateFinished, -}; - -@interface PINDataTaskOperation () -{ - NSRecursiveLock *_lock;; -} - -@property (nonatomic, strong, readwrite) NSURLSessionDataTask *dataTask; -@property (nonatomic, assign, readwrite) PIDataTaskOperationState state; - -@end - -static inline NSString * PIKeyPathFromOperationState(PIDataTaskOperationState state) { - switch (state) { - case PIDataTaskOperationStateReady: - return @"isReady"; - case PIDataTaskOperationStateExecuting: - return @"isExecuting"; - case PIDataTaskOperationStateFinished: - return @"isFinished"; - } -} - -@implementation PINDataTaskOperation - -- (instancetype)init -{ - if (self = [super init]) { - _state = PIDataTaskOperationStateReady; - _lock = [[NSRecursiveLock alloc] init]; - } - return self; -} - -+ (instancetype)dataTaskOperationWithSessionManager:(PINURLSessionManager *)sessionManager - request:(NSURLRequest *)request - completionHandler:(void (^)(NSURLResponse *response, NSError *error))completionHandler -{ - PINDataTaskOperation *operation = [[self alloc] init]; - operation.dataTask = [sessionManager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, NSError *error) { - completionHandler(response, error); - if (operation.isCancelled == NO) { - [operation finish]; - } - }]; - - return operation; -} - -- (void)start -{ - [self lock]; - if ([self isCancelled]) { - [self cancelTask]; - } else if ([self isReady]) { - self.state = PIDataTaskOperationStateExecuting; - - [self.dataTask resume]; - } - [self unlock]; -} - -- (void)cancel -{ - [self lock]; - if (![self isFinished] && ![self isCancelled]) { - [super cancel]; - - if ([self isExecuting]) { - [self cancelTask]; - } - } - [self unlock]; -} - -- (BOOL)isConcurrent -{ - return YES; -} - -- (BOOL)isExecuting -{ - return self.state == PIDataTaskOperationStateExecuting; -} - -- (BOOL)isFinished -{ - return self.state == PIDataTaskOperationStateFinished; -} - -- (void)finish -{ - self.state = PIDataTaskOperationStateFinished; -} - -- (void)cancelTask -{ - [self lock]; - if (![self isFinished]) { - if (self.dataTask) { - [self.dataTask cancel]; - } - [self finish]; - } - [self unlock]; -} - -- (void)setState:(PIDataTaskOperationState)state -{ - [self lock]; - NSString *oldStateKey = PIKeyPathFromOperationState(self.state); - NSString *newStateKey = PIKeyPathFromOperationState(state); - - [self willChangeValueForKey:newStateKey]; - [self willChangeValueForKey:oldStateKey]; - _state = state; - [self didChangeValueForKey:oldStateKey]; - [self didChangeValueForKey:newStateKey]; - [self unlock]; -} - -- (void)lock -{ - [_lock lock]; -} - -- (void)unlock -{ - [_lock unlock]; -} - -@end diff --git a/Pod/Classes/PINProgressiveImage.h b/Pod/Classes/PINProgressiveImage.h deleted file mode 100644 index c552c6a7..00000000 --- a/Pod/Classes/PINProgressiveImage.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// PINProgressiveImage.h -// Pods -// -// Created by Garrett Moon on 2/9/15. -// -// - -#import - -#if PIN_TARGET_IOS -#import -#elif PIN_TARGET_MAC -#import -#endif - -#import "PINRemoteImageMacros.h" - -/** An object which store the data of a downloading image and vends progressive scans **/ -@interface PINProgressiveImage : NSObject - -@property (atomic, copy, nonnull) NSArray *progressThresholds; -@property (atomic, assign) CFTimeInterval estimatedRemainingTimeThreshold; -@property (atomic, assign) CFTimeInterval startTime; - -- (void)updateProgressiveImageWithData:(nonnull NSData *)data expectedNumberOfBytes:(int64_t)expectedNumberOfBytes; - -/** - Returns the latest image based on thresholds, returns nil if no new image is generated - - @param blurred A boolean to indicate if the image should be blurred - @param maxProgressiveRenderSize the maximum dimensions at which to apply a blur. If an image exceeds either the height - or width of this dimension, the image will *not* be blurred regardless of the blurred parameter. - @param renderedImageQuality Value between 0 and 1. Computed by dividing the received number of bytes by the expected number of bytes - @return PINImage a progressive scan of the image or nil if a new one has not been generated - */ -- (nullable PINImage *)currentImageBlurred:(BOOL)blurred maxProgressiveRenderSize:(CGSize)maxProgressiveRenderSize renderedImageQuality:(nonnull out CGFloat *)renderedImageQuality; - -/** - Returns the current data for the image. - - @return NSData the current data for the image - */ -- (nullable NSData *)data; - -@end diff --git a/Pod/Classes/PINRemoteImage.h b/Pod/Classes/PINRemoteImage.h deleted file mode 100644 index 834a6f19..00000000 --- a/Pod/Classes/PINRemoteImage.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// PINRemoteImage.h -// Pods -// -// Created by Garrett Moon on 8/17/14. -// -// - -#ifndef Pods_PINRemoteImage_h -#define Pods_PINRemoteImage_h - -#import "PINRemoteImageMacros.h" - -#import "PINRemoteImageManager.h" -#import "PINRemoteImageCategoryManager.h" -#import "PINRemoteImageManagerResult.h" -#import "PINProgressiveImage.h" -#import "PINURLSessionManager.h" - -#endif diff --git a/Pod/Classes/PINRemoteImageBasicCache.h b/Pod/Classes/PINRemoteImageBasicCache.h deleted file mode 100644 index 7219e131..00000000 --- a/Pod/Classes/PINRemoteImageBasicCache.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// PINRemoteImageBasicCache.h -// Pods -// -// Created by Aleksei Shevchenko on 7/28/16. -// -// - -#import -#import "PINRemoteImageCaching.h" - -/** - * Simplistic wrapper based on NSCache. - * not persisting any data on disk - */ -@interface PINRemoteImageBasicCache : NSObject - -@end diff --git a/Pod/Classes/PINRemoteImageBasicCache.m b/Pod/Classes/PINRemoteImageBasicCache.m deleted file mode 100644 index e31c9f7c..00000000 --- a/Pod/Classes/PINRemoteImageBasicCache.m +++ /dev/null @@ -1,98 +0,0 @@ -// -// PINRemoteImageBasicCache.m -// Pods -// -// Created by Aleksei Shevchenko on 7/28/16. -// -// - -#import "PINRemoteImageBasicCache.h" - -@interface PINRemoteImageBasicCache() -@property (nonatomic, strong) NSCache *cache; -@end - -@implementation PINRemoteImageBasicCache - -- (instancetype)init -{ - self = [super init]; - if (self) { - self.cache = [[NSCache alloc] init]; - } - return self; -} - -//****************************************************************************************************** -// Memory cache methods -//****************************************************************************************************** --(nullable id)objectFromMemoryCacheForKey:(NSString *)key -{ - return [self.cache objectForKey:key]; -} - --(void)cacheObjectInMemory:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost -{ - [self.cache setObject:object forKey:key cost:cost]; -} - -- (void)removeCachedObjectForKeyFromMemoryCache:(NSString *)key -{ - [self.cache removeObjectForKey:key]; -} - -//****************************************************************************************************** -// Disk cache methods -//****************************************************************************************************** --(nullable id)objectFromDiskCacheForKey:(NSString *)key -{ - return [self.cache objectForKey:key]; -} - --(void)objectFromDiskCacheForKey:(NSString *)key completion:(PINRemoteImageCachingObjectBlock)completion -{ - __weak typeof(self) weakSelf = self; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - if (completion) { - typeof(self) strongSelf = weakSelf; - completion(strongSelf, key, [strongSelf.cache objectForKey:key]); - } - }); -} - --(void)cacheObjectOnDisk:(id)object forKey:(NSString *)key -{ - [self.cache setObject:object forKey:key]; -} - -- (BOOL)objectExistsInCacheForKey:(NSString *)key -{ - return [self.cache objectForKey:key] != nil; -} - -//****************************************************************************************************** -// Common methods, should apply to both in-memory and disk storage -//****************************************************************************************************** -- (void)removeCachedObjectForKey:(NSString *)key -{ - [self.cache removeObjectForKey:key]; -} -- (void)removeCachedObjectForKey:(NSString *)key completion:(PINRemoteImageCachingObjectBlock)completion -{ - __weak typeof(self) weakSelf = self; - id object = [self.cache objectForKey:key]; - [self.cache removeObjectForKey:key]; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - if (completion) { - typeof(self) strongSelf = weakSelf; - completion(strongSelf, key, object); - } - }); -} - -- (void)removeAllCachedObjects -{ - [self.cache removeAllObjects]; -} - -@end diff --git a/Pod/Classes/PINRemoteImageCaching.h b/Pod/Classes/PINRemoteImageCaching.h deleted file mode 100644 index a3e01dad..00000000 --- a/Pod/Classes/PINRemoteImageCaching.h +++ /dev/null @@ -1,49 +0,0 @@ -// -// PINRemoteImageCaching.h -// Pods -// -// Created by Aleksei Shevchenko on 7/25/16. -// -// - -#import - - -NS_ASSUME_NONNULL_BEGIN - -@protocol PINRemoteImageCaching; -typedef void (^PINRemoteImageCachingObjectBlock)(id cache, NSString *key, id __nullable object); - -/** - * Image Cache is responsible for actual image caching. - */ -@protocol PINRemoteImageCaching - -//****************************************************************************************************** -// Memory cache methods -//****************************************************************************************************** -- (nullable id)objectFromMemoryCacheForKey:(NSString *)key; -- (void)cacheObjectInMemory:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost; - -//****************************************************************************************************** -// Disk cache methods -//****************************************************************************************************** -- (nullable id)objectFromDiskCacheForKey:(NSString *)key; -- (void)objectFromDiskCacheForKey:(NSString *)key completion:(nullable PINRemoteImageCachingObjectBlock)completion; -- (void)cacheObjectOnDisk:(id)object forKey:(NSString *)key; - - -- (BOOL)objectExistsInCacheForKey:(NSString *)key; - -- (void)removeCachedObjectForKey:(NSString *)key; -- (void)removeCachedObjectForKey:(NSString *)key completion:(nullable PINRemoteImageCachingObjectBlock)completion; -- (void)removeAllCachedObjects; - -@optional - -- (void)removeCachedObjectForKeyFromMemoryCache:(NSString *)key; - -@end - - -NS_ASSUME_NONNULL_END diff --git a/Pod/Classes/PINRemoteImageCallbacks.h b/Pod/Classes/PINRemoteImageCallbacks.h deleted file mode 100644 index 93e40328..00000000 --- a/Pod/Classes/PINRemoteImageCallbacks.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// PINRemoteImageCallbacks.h -// Pods -// -// Created by Garrett Moon on 3/9/15. -// -// - -#import - -#import "PINRemoteImageManager.h" - -@interface PINRemoteImageCallbacks : NSObject - -@property (nonatomic, strong, nullable) PINRemoteImageManagerImageCompletion completionBlock; -@property (nonatomic, strong, nullable) PINRemoteImageManagerImageCompletion progressImageBlock; -@property (nonatomic, strong, nullable) PINRemoteImageManagerProgressDownload progressDownloadBlock; -@property (nonatomic, assign) CFTimeInterval requestTime; - -@end diff --git a/Pod/Classes/PINRemoteImageCallbacks.m b/Pod/Classes/PINRemoteImageCallbacks.m deleted file mode 100644 index fbbbb9f2..00000000 --- a/Pod/Classes/PINRemoteImageCallbacks.m +++ /dev/null @@ -1,19 +0,0 @@ -// -// PINRemoteImageCallbacks.m -// Pods -// -// Created by Garrett Moon on 3/9/15. -// -// - -#import "PINRemoteImageCallbacks.h" - -@implementation PINRemoteImageCallbacks - -- (void)setCompletionBlock:(PINRemoteImageManagerImageCompletion)completionBlock -{ - _completionBlock = [completionBlock copy]; - self.requestTime = CACurrentMediaTime(); -} - -@end diff --git a/Pod/Classes/PINRemoteImageCategoryManager.h b/Pod/Classes/PINRemoteImageCategoryManager.h deleted file mode 100644 index 693a0878..00000000 --- a/Pod/Classes/PINRemoteImageCategoryManager.h +++ /dev/null @@ -1,228 +0,0 @@ -// -// PINRemoteImageCategory.h -// Pods -// -// Created by Garrett Moon on 11/4/14. -// -// - -#if PIN_TARGET_IOS -#import -#elif PIN_TARGET_MAC -#import -#endif - -#import "PINRemoteImageManager.h" - -@protocol PINRemoteImageCategory; - -/** - PINRemoteImageCategoryManager is a class that handles subclassing image display classes. PINImage+PINRemoteImage, UIButton+PINRemoteImage, etc, all delegate their work to this class. If you'd like to create a category to display an image on a view, you should mimic one of the above categories. - */ - -@interface PINRemoteImageCategoryManager : NSObject - -+ (void)setImageOnView:(nonnull id )view - fromURL:(nullable NSURL *)url; - -+ (void)setImageOnView:(nonnull id )view - fromURL:(nullable NSURL *)url - placeholderImage:(nullable PINImage *)placeholderImage; - -+ (void)setImageOnView:(nonnull id )view - fromURL:(nullable NSURL *)url - placeholderImage:(nullable PINImage *)placeholderImage - completion:(nullable PINRemoteImageManagerImageCompletion)completion; - -+ (void)setImageOnView:(nonnull id )view - fromURL:(nullable NSURL *)url - completion:(nullable PINRemoteImageManagerImageCompletion)completion; - -+ (void)setImageOnView:(nonnull id )view - fromURL:(nullable NSURL *)url - processorKey:(nullable NSString *)processorKey - processor:(nullable PINRemoteImageManagerImageProcessor)processor; - -+ (void)setImageOnView:(nonnull id )view - fromURL:(nullable NSURL *)url - placeholderImage:(nullable PINImage *)placeholderImage - processorKey:(nullable NSString *)processorKey - processor:(nullable PINRemoteImageManagerImageProcessor)processor; - -+ (void)setImageOnView:(nonnull id )view - fromURL:(nullable NSURL *)url - processorKey:(nullable NSString *)processorKey - processor:(nullable PINRemoteImageManagerImageProcessor)processor - completion:(nullable PINRemoteImageManagerImageCompletion)completion; - -+ (void)setImageOnView:(nonnull id )view - fromURLs:(nullable NSArray *)urls - placeholderImage:(nullable PINImage *)placeholderImage - processorKey:(nullable NSString *)processorKey - processor:(nullable PINRemoteImageManagerImageProcessor)processor - completion:(nullable PINRemoteImageManagerImageCompletion)completion; - -+ (void)setImageOnView:(nonnull id )view - fromURLs:(nullable NSArray *)urls; - -+ (void)setImageOnView:(nonnull id )view - fromURLs:(nullable NSArray *)urls - placeholderImage:(nullable PINImage *)placeholderImage; - -+ (void)setImageOnView:(nonnull id )view - fromURLs:(nullable NSArray *)urls - placeholderImage:(nullable PINImage *)placeholderImage - completion:(nullable PINRemoteImageManagerImageCompletion)completion; - -+ (void)cancelImageDownloadOnView:(nonnull id )view; - -+ (nullable NSUUID *)downloadImageOperationUUIDOnView:(nonnull id )view; - -+ (void)setDownloadImageOperationUUID:(nullable NSUUID *)downloadImageOperationUUID onView:(nonnull id )view; - -+ (BOOL)updateWithProgressOnView:(nonnull id )view; - -+ (void)setUpdateWithProgressOnView:(BOOL)updateWithProgress onView:(nonnull id )view; - -@end - -/** - Protocol to implement on UIView subclasses to support PINRemoteImage - */ -@protocol PINRemoteImageCategory - -//Call manager - -/** - Set the image from the given URL. - - @param url NSURL to fetch from. - */ -- (void)pin_setImageFromURL:(nullable NSURL *)url; - -/** - Set the image from the given URL and set placeholder image while image at URL is being retrieved. - - @param url NSURL to fetch from. - @param placeholderImage PINImage to set on the view while the image at URL is being retrieved. - */ -- (void)pin_setImageFromURL:(nullable NSURL *)url placeholderImage:(nullable PINImage *)placeholderImage; - -/** - Set the image from the given URL and call completion when finished. - - @param url NSURL to fetch from. - @param completion Called when url has been retrieved and set on view. - */ -- (void)pin_setImageFromURL:(nullable NSURL *)url completion:(nullable PINRemoteImageManagerImageCompletion)completion; - -/** - Set the image from the given URL, set placeholder while image at url is being retrieved and call completion when finished. - - @param url NSURL to fetch from. - @param placeholderImage PINImage to set on the view while the image at URL is being retrieved. - @param completion Called when url has been retrieved and set on view. - */ -- (void)pin_setImageFromURL:(nullable NSURL *)url placeholderImage:(nullable PINImage *)placeholderImage completion:(nullable PINRemoteImageManagerImageCompletion)completion; - -/** - Retrieve the image from the given URL, process it using the passed in processor block and set result on view. - - @param url NSURL to fetch from. - @param processorKey NSString key to uniquely identify processor. Used in caching. - @param processor PINRemoteImageManagerImageProcessor processor block which should return the processed image. - */ -- (void)pin_setImageFromURL:(nullable NSURL *)url processorKey:(nullable NSString *)processorKey processor:(nullable PINRemoteImageManagerImageProcessor)processor; - -/** - Set placeholder on view and retrieve the image from the given URL, process it using the passed in processor block and set result on view. - - @param url NSURL to fetch from. - @param placeholderImage PINImage to set on the view while the image at URL is being retrieved. - @param processorKey NSString key to uniquely identify processor. Used in caching. - @param processor PINRemoteImageManagerImageProcessor processor block which should return the processed image. - */ -- (void)pin_setImageFromURL:(nullable NSURL *)url placeholderImage:(nullable PINImage *)placeholderImage processorKey:(nullable NSString *)processorKey processor:(nullable PINRemoteImageManagerImageProcessor)processor; - -/** - Retrieve the image from the given URL, process it using the passed in processor block and set result on view. Call completion after image has been fetched, processed and set on view. - - @param url NSURL to fetch from. - @param processorKey NSString key to uniquely identify processor. Used in caching. - @param processor PINRemoteImageManagerImageProcessor processor block which should return the processed image. - @param completion Called when url has been retrieved and set on view. - */ -- (void)pin_setImageFromURL:(nullable NSURL *)url processorKey:(nullable NSString *)processorKey processor:(nullable PINRemoteImageManagerImageProcessor)processor completion:(nullable PINRemoteImageManagerImageCompletion)completion; - -/** - Set placeholder on view and retrieve the image from the given URL, process it using the passed in processor block and set result on view. Call completion after image has been fetched, processed and set on view. - - @param url NSURL to fetch from. - @param placeholderImage PINImage to set on the view while the image at URL is being retrieved. - @param processorKey NSString key to uniquely identify processor. Used in caching. - @param processor PINRemoteImageManagerImageProcessor processor block which should return the processed image. - @param completion Called when url has been retrieved and set on view. - */ -- (void)pin_setImageFromURL:(nullable NSURL *)url placeholderImage:(nullable PINImage *)placeholderImage processorKey:(nullable NSString *)processorKey processor:(nullable PINRemoteImageManagerImageProcessor)processor completion:(nullable PINRemoteImageManagerImageCompletion)completion; - -/** - Retrieve one of the images at the passed in URLs depending on previous network performance and set result on view. - - @param urls NSArray of NSURLs sorted in increasing quality - */ -- (void)pin_setImageFromURLs:(nullable NSArray *)urls; - -/** - Set placeholder on view and retrieve one of the images at the passed in URLs depending on previous network performance and set result on view. - - @param urls NSArray of NSURLs sorted in increasing quality - @param placeholderImage PINImage to set on the view while the image at URL is being retrieved. - */ -- (void)pin_setImageFromURLs:(nullable NSArray *)urls placeholderImage:(nullable PINImage *)placeholderImage; - -/** - Set placeholder on view and retrieve one of the images at the passed in URLs depending on previous network performance and set result on view. Call completion after image has been fetched and set on view. - - @param urls NSArray of NSURLs sorted in increasing quality - @param placeholderImage PINImage to set on the view while the image at URL is being retrieved. - @param completion Called when url has been retrieved and set on view. - */ -- (void)pin_setImageFromURLs:(nullable NSArray *)urls placeholderImage:(nullable PINImage *)placeholderImage completion:(nullable PINRemoteImageManagerImageCompletion)completion; - -/** - Cancels the image download. Guarantees that previous setImage calls will *not* have their results set on the image view after calling this (as opposed to PINRemoteImageManager which does not guarantee cancellation). - */ -- (void)pin_cancelImageDownload; - -/** - Returns the NSUUID associated with any PINRemoteImage task currently running on the view. - - @return NSUUID associated with any PINRemoteImage task currently running on the view. - */ -- (nullable NSUUID *)pin_downloadImageOperationUUID; - -/** - Set the current NSUUID associated with a PINRemoteImage task running on the view. - - @param downloadImageOperationUUID NSUUID associated with a PINRemoteImage task. - */ -- (void)pin_setDownloadImageOperationUUID:(nullable NSUUID *)downloadImageOperationUUID; - -/** - Whether the view should update with progress images (such as those provided by progressive JPEG images). - - @return BOOL value indicating whether the view should update with progress images - */ -@property (nonatomic, assign) BOOL pin_updateWithProgress; - -//Handle -- (void)pin_setPlaceholderWithImage:(nullable PINImage *)image; -- (void)pin_updateUIWithRemoteImageManagerResult:(nonnull PINRemoteImageManagerResult *)result; -- (void)pin_clearImages; -- (BOOL)pin_ignoreGIFs; - -@optional - -- (PINRemoteImageManagerDownloadOptions)pin_defaultOptions; - -@end diff --git a/Pod/Classes/PINRemoteImageDownloadTask.h b/Pod/Classes/PINRemoteImageDownloadTask.h deleted file mode 100644 index 4371aa03..00000000 --- a/Pod/Classes/PINRemoteImageDownloadTask.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// PINRemoteImageDownloadTask.h -// Pods -// -// Created by Garrett Moon on 3/9/15. -// -// - -#import "PINRemoteImageTask.h" -#import "PINProgressiveImage.h" -#import "PINDataTaskOperation.h" - -@interface PINRemoteImageDownloadTask : PINRemoteImageTask - -@property (nonatomic, strong, nullable) PINDataTaskOperation *urlSessionTaskOperation; -@property (nonatomic, assign) CFTimeInterval sessionTaskStartTime; -@property (nonatomic, assign) CFTimeInterval sessionTaskEndTime; -@property (nonatomic, assign) BOOL hasProgressBlocks; -@property (nonatomic, strong, nullable) PINProgressiveImage *progressImage; - -@property (nonatomic, assign) NSUInteger numberOfRetries; - -- (void)callProgressDownloadWithQueue:(nonnull dispatch_queue_t)queue completedBytes:(int64_t)completedBytes totalBytes:(int64_t)totalBytes; -- (void)callProgressImageWithQueue:(nonnull dispatch_queue_t)queue withImage:(nonnull PINImage *)image renderedImageQuality:(CGFloat)renderedImageQuality; - -@end diff --git a/Pod/Classes/PINRemoteImageDownloadTask.m b/Pod/Classes/PINRemoteImageDownloadTask.m deleted file mode 100644 index 4891d377..00000000 --- a/Pod/Classes/PINRemoteImageDownloadTask.m +++ /dev/null @@ -1,103 +0,0 @@ -// -// PINRemoteImageDownloadTask.m -// Pods -// -// Created by Garrett Moon on 3/9/15. -// -// - -#import "PINRemoteImageDownloadTask.h" - -#import "PINRemoteImage.h" -#import "PINRemoteImageCallbacks.h" - -@interface PINRemoteImageDownloadTask () { - BOOL _canSetDataTaskPriority; -} - -@end - -@implementation PINRemoteImageDownloadTask - -- (instancetype)init -{ - if (self = [super init]) { - _canSetDataTaskPriority = [NSURLSessionTask instancesRespondToSelector:@selector(setPriority:)]; - _numberOfRetries = 0; - } - return self; -} - -- (BOOL)hasProgressBlocks -{ - __block BOOL hasProgressBlocks = NO; - [self.callbackBlocks enumerateKeysAndObjectsUsingBlock:^(NSUUID *UUID, PINRemoteImageCallbacks *callback, BOOL *stop) { - if (callback.progressImageBlock) { - hasProgressBlocks = YES; - *stop = YES; - } - }]; - return hasProgressBlocks; -} - -- (void)callProgressDownloadWithQueue:(nonnull dispatch_queue_t)queue completedBytes:(int64_t)completedBytes totalBytes:(int64_t)totalBytes -{ - [self.callbackBlocks enumerateKeysAndObjectsUsingBlock:^(NSUUID *UUID, PINRemoteImageCallbacks *callback, BOOL *stop) { - if (callback.progressDownloadBlock != nil) { - PINLog(@"calling progress for UUID: %@ key: %@", UUID, self.key); - PINRemoteImageManagerProgressDownload progressDownloadBlock = callback.progressDownloadBlock; - //The code run asynchronously below is *not* guaranteed to be run in the manager's lock! - //All access to the callbacks and self should be done outside the block below! - dispatch_async(queue, ^ - { - progressDownloadBlock(completedBytes, totalBytes); - }); - } - }]; -} - -- (void)callProgressImageWithQueue:(nonnull dispatch_queue_t)queue withImage:(nonnull PINImage *)image renderedImageQuality:(CGFloat)renderedImageQuality -{ - [self.callbackBlocks enumerateKeysAndObjectsUsingBlock:^(NSUUID *UUID, PINRemoteImageCallbacks *callback, BOOL *stop) { - if (callback.progressImageBlock != nil) { - PINLog(@"calling progress for UUID: %@ key: %@", UUID, self.key); - PINRemoteImageManagerImageCompletion progressImageBlock = callback.progressImageBlock; - CFTimeInterval requestTime = callback.requestTime; - //The code run asynchronously below is *not* guaranteed to be run in the manager's lock! - //All access to the callbacks and self should be done outside the block below! - dispatch_async(queue, ^ - { - progressImageBlock([PINRemoteImageManagerResult imageResultWithImage:image - alternativeRepresentation:nil - requestLength:CACurrentMediaTime() - requestTime - error:nil - resultType:PINRemoteImageResultTypeProgress - UUID:UUID - renderedImageQuality:renderedImageQuality]); - }); - } - }]; -} - -- (BOOL)cancelWithUUID:(NSUUID *)UUID manager:(PINRemoteImageManager *)manager -{ - BOOL noMoreCompletions = [super cancelWithUUID:UUID manager:manager]; - if (noMoreCompletions) { - [self.urlSessionTaskOperation cancel]; - PINLog(@"Canceling download of URL: %@, UUID: %@", self.urlSessionTaskOperation.dataTask.originalRequest.URL, UUID); - } else { - PINLog(@"Decrementing download of URL: %@, UUID: %@", self.urlSessionTaskOperation.dataTask.originalRequest.URL, UUID); - } - return noMoreCompletions; -} - -- (void)setPriority:(PINRemoteImageManagerPriority)priority -{ - [super setPriority:priority]; - if (_canSetDataTaskPriority) { - self.urlSessionTaskOperation.dataTask.priority = dataTaskPriorityWithImageManagerPriority(priority); - } - self.urlSessionTaskOperation.queuePriority = operationPriorityWithImageManagerPriority(priority); -} - -@end diff --git a/Pod/Classes/PINRemoteImageMacros.h b/Pod/Classes/PINRemoteImageMacros.h deleted file mode 100644 index 923b31be..00000000 --- a/Pod/Classes/PINRemoteImageMacros.h +++ /dev/null @@ -1,55 +0,0 @@ -// -// PINRemoteImageMacros.h -// PINRemoteImage -// - -#import - -#ifndef PINRemoteImageMacros_h -#define PINRemoteImageMacros_h - -#define PIN_TARGET_IOS (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR || TARGET_OS_TV) -#define PIN_TARGET_MAC (TARGET_OS_MAC) - -#define PINRemoteImageLogging 0 -#if PINRemoteImageLogging -#define PINLog(args...) NSLog(args) -#else -#define PINLog(args...) -#endif - -#if __has_include() -#define USE_FLANIMATED_IMAGE 1 -#else -#define USE_FLANIMATED_IMAGE 0 -#define FLAnimatedImage NSObject -#endif - -#if __has_include() -#define USE_PINCACHE 1 -#else -#define USE_PINCACHE 0 -#endif - -#if PIN_TARGET_IOS -#define PINImage UIImage -#define PINImageView UIImageView -#define PINButton UIButton -#elif PIN_TARGET_MAC -#define PINImage NSImage -#define PINImageView NSImageView -#define PINButton NSButton -#endif - -#define BlockAssert(condition, desc, ...) \ -do { \ -__PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \ -if (!(condition)) { \ -[[NSAssertionHandler currentHandler] handleFailureInMethod:_cmd \ -object:strongSelf file:[NSString stringWithUTF8String:__FILE__] \ -lineNumber:__LINE__ description:(desc), ##__VA_ARGS__]; \ -} \ -__PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \ -} while(0); - -#endif /* PINRemoteImageMacros_h */ diff --git a/Pod/Classes/PINRemoteImageManager.h b/Pod/Classes/PINRemoteImageManager.h deleted file mode 100644 index 747da3e8..00000000 --- a/Pod/Classes/PINRemoteImageManager.h +++ /dev/null @@ -1,489 +0,0 @@ -// -// PINRemoteImageManager.h -// Pods -// -// Created by Garrett Moon on 8/17/14. -// -// - -#import - -#if PIN_TARGET_IOS -#import -#elif PIN_TARGET_MAC -#import -#endif - -@protocol PINRemoteImageManagerAlternateRepresentationProvider; -@protocol PINRemoteImageCaching; - -#import "PINRemoteImageManagerResult.h" - -@class PINRemoteImageManagerResult; - -extern NSString * __nonnull const PINRemoteImageManagerErrorDomain; - -/** - Error codes returned by PINRemoteImage - */ -typedef NS_ENUM(NSUInteger, PINRemoteImageManagerError) { - /** The image failed to decode */ - PINRemoteImageManagerErrorFailedToDecodeImage = 1, - /** The image could not be downloaded and therefore could not be processed */ - PINRemoteImageManagerErrorFailedToFetchImageForProcessing = 2, - /** The image returned by the processor block was nil */ - PINRemoteImageManagerErrorFailedToProcessImage = 3, - /** The image in the cache was invalid */ - PINRemoteImageManagerErrorInvalidItemInCache = 4, - /** The image at the URL was empty */ - PINRemoteImageManagerErrorImageEmpty = 5, -}; - -/** - Options with which to download and process images - */ -typedef NS_OPTIONS(NSUInteger, PINRemoteImageManagerDownloadOptions) { - /** Download and process with default options (no other options set) */ - PINRemoteImageManagerDownloadOptionsNone = 0, - /** Set to disallow any alternate representations such as FLAnimatedImage */ - PINRemoteImageManagerDisallowAlternateRepresentations = 1, - /** Skip decoding the image before returning. This means smaller images returned, but images will be decoded on the main thread when set on an image view */ - PINRemoteImageManagerDownloadOptionsSkipDecode = 1 << 1, - /** Skip the early check of the memory cache */ - PINRemoteImageManagerDownloadOptionsSkipEarlyCheck = 1 << 2, - /** Save processed images as JPEGs in the cache. The default is PNG to support transparency */ - PINRemoteImageManagerSaveProcessedImageAsJPEG = 1 << 3, -}; - -/** - Priority to download and process image at. - */ -typedef NS_ENUM(NSUInteger, PINRemoteImageManagerPriority) { - /** Very low priority */ - PINRemoteImageManagerPriorityVeryLow = 0, - /** Low priority */ - PINRemoteImageManagerPriorityLow, - /** Medium priority */ - PINRemoteImageManagerPriorityMedium, - /** High priority */ - PINRemoteImageManagerPriorityHigh, - /** Very high priority */ - PINRemoteImageManagerPriorityVeryHigh, -}; - -NSOperationQueuePriority operationPriorityWithImageManagerPriority(PINRemoteImageManagerPriority priority); -float dataTaskPriorityWithImageManagerPriority(PINRemoteImageManagerPriority priority); - -/** - Completion called for many PINRemoteImage tasks as well as progress updates. Passed in a PINRemoteImageManagerResult. - - @param result PINRemoteImageManagerResult which contains the downloaded image. - */ -typedef void (^PINRemoteImageManagerImageCompletion)(PINRemoteImageManagerResult * __nonnull result); - -/** - Processor block to post-process a downloaded image. Passed in a PINRemoteImageManagerResult and a pointer to an NSUInteger which can be updated to indicate the cost of processing the image. - - @param result PINRemoteImageManagerResult which contains the downloaded image. - @param cost NSUInteger point which can be modified to indicate the cost of processing the image. This is used when determining which cache objects to evict on memory pressure. - - @return return the processed UIImage - */ -typedef PINImage * _Nullable(^PINRemoteImageManagerImageProcessor)(PINRemoteImageManagerResult * __nonnull result, NSUInteger * __nonnull cost); - -/** - PINRemoteImageManager is the main workhorse of PINRemoteImage. It is unnecessary to access directly if you simply - wish to download images and have them rendered in a UIImageView, UIButton or FLAnimatedImageView. - - However, if you wish to download images directly, this class is your guy / gal. - - You can use this class to download images, postprocess downloaded images, prefetch images, download images progressively, or download one image in a set of images depending on network performance. - */ - -/** - Completion Handler block which will be forwarded to NSURLSessionTaskDelegate's completion handler - - @param disposition One of several constants that describes how the challenge should be handled. - @param credential The credential that should be used for authentication if disposition is NSURLSessionAuthChallengeUseCredential; otherwise, NULL. - */ -typedef void(^PINRemoteImageManagerAuthenticationChallengeCompletionHandler)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential); - -/** - Authentication challenge handler - - @param task The task whose request requires authentication. - @param challenge An object that contains the request for authentication. - @param aHandler A PINRemoteImageManagerAuthenticationChallengeCompletionHandler, see example for further details. - */ -typedef void(^PINRemoteImageManagerAuthenticationChallenge)(NSURLSessionTask * __nullable task, NSURLAuthenticationChallenge * __nonnull challenge, PINRemoteImageManagerAuthenticationChallengeCompletionHandler __nullable aHandler); - -/** - Handler called for many PINRemoteImage tasks providing the progress of the download. - - @param completedBytes Amount of bytes that have been downloaded so far. - @param totalBytes Total amount of bytes in the image being downloaded. - */ -typedef void(^PINRemoteImageManagerProgressDownload)(int64_t completedBytes, int64_t totalBytes); - -/** An image downloading, processing and caching manager. It uses the concept of download and processing tasks to ensure that even if multiple calls to download or process an image are made, it only occurs one time (unless an item is no longer in the cache). PINRemoteImageManager is backed by GCD and safe to access from multiple threads simultaneously. It ensures that images are decoded off the main thread so that animation performance isn't affected. None of its exposed methods allow for synchronous access. However, it is optimized to call completions on the calling thread if an item is in its memory cache. **/ -@interface PINRemoteImageManager : NSObject - - -@property (nonatomic, readonly, nonnull) id cache; - -/** - Create and return a PINRemoteImageManager created with the specified configuration. If configuration is nil, [NSURLSessionConfiguration defaultConfiguration] is used. Specify a custom configuration if you need to configure timeout values, cookie policies, additional HTTP headers, etc. - @param configuration The configuration used to create the PINRemoteImageManager. - @return A PINRemoteImageManager with the specified configuration. - */ -- (nonnull instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)configuration; - -/** - Create and return a PINRemoteImageManager with the specified configuration and alternative representation delegate. If configuration is nil, [NSURLSessionConfiguration defaultConfiguration] is used. Specify a custom configuration if you need to configure timeout values, cookie policies, additional HTTP headers, etc. If alternativeRepresentationProvider is nil, the default is used (and supports FLAnimatedImage). - @param configuration The configuration used to create the PINRemoteImageManager. - @param alternativeRepDelegate a delegate which conforms to the PINRemoteImageManagerAlternateRepresentationProvider protocol. Provide a delegate if you want to have non image results. @see PINRemoteImageManagerAlternateRepresentationProvider for an example. - @return A PINRemoteImageManager with the specified configuration. - */ -- (nonnull instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)configuration - alternativeRepresentationProvider:(nullable id )alternateRepDelegate; - -/** - Create and return a PINRemoteImageManager with the specified configuration and alternative representation delegate. If configuration is nil, [NSURLSessionConfiguration defaultConfiguration] is used. Specify a custom configuration if you need to configure timeout values, cookie policies, additional HTTP headers, etc. If alternativeRepresentationProvider is nil, the default is used (and supports FLAnimatedImage). - @param configuration The configuration used to create the PINRemoteImageManager. - @param alternativeRepDelegate a delegate which conforms to the PINRemoteImageManagerAlternateRepresentationProvider protocol. Provide a delegate if you want to have non image results. @see PINRemoteImageManagerAlternateRepresentationProvider for an example. - @param imageCache Optional delegate which conforms to the PINRemoteImageCaching protocol. Provide a delegate if you want to control image caching. By default, image manager will use most appropriate implementation available (based on PINCache or NSCache, depending on subspec)@see PINRemoteImageBasicCache for an example. - @return A PINRemoteImageManager with the specified configuration. - */ -- (nonnull instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)configuration - alternativeRepresentationProvider:(nullable id )alternateRepDelegate - imageCache:(nullable id)imageCache NS_DESIGNATED_INITIALIZER; - - -/** - Get the shared instance of PINRemoteImageManager - - @return Shared instance of PINRemoteImageManager - */ -+ (nonnull instancetype)sharedImageManager; - -/** - Sets the shared instance of PINRemoteImageManager to an instance with the supplied configuration. If configuration is nil, [NSURLSessionConfiguration defaultConfiguration] is used. You specify a custom configuration if you need to configure timeout values, cookie policies, additional HTTP headers, etc. This method should not be used if the shared instance has already been created. - - @param configuration The configuration used to create the PINRemoteImageManager. - */ -+ (void)setSharedImageManagerWithConfiguration:(nullable NSURLSessionConfiguration *)configuration; - - -/** - The result of this method is assigned to self.cache in init. If you wish to provide a customized cache to the manager you can subclass PINRemoteImageManager and return a custom object, implementing PINRemoteImageCaching protocol from this method. Same effect could be achieved by using initWithSessionConfiguration:alternativeRepresentationProvider:imageCache: initializer. - @return An instance of a object, implementing PINRemoteImageCaching protocol. - */ -- (nonnull id)defaultImageCache; - -/** - Set the Authentication Challenge Block. - - @param challengeBlock A PINRemoteImageManagerAuthenticationChallenge block. - */ -- (void)setAuthenticationChallenge:(nullable PINRemoteImageManagerAuthenticationChallenge)challengeBlock; - -/** - Set the minimum BPS to download the highest quality image in a set. - @see downloadImageWithURLs:options:progressImage:completion: - - @param highQualityBPSThreshold bytes per second minimum. Defaults to 500000. - @param completion Completion to be called once highQualityBPSThreshold has been set. - */ -- (void)setHighQualityBPSThreshold:(float)highQualityBPSThreshold completion:(nullable dispatch_block_t)completion; - -/** - Set the maximum BPS to download the lowest quality image in a set. - @see downloadImageWithURLs:options:progressImage:completion: - - @param lowQualityBPSThreshold bytes per second maximum. Defaults to 50000. - @param completion Completion to be called once lowQualityBPSThreshold has been set. - */ -- (void)setLowQualityBPSThreshold:(float)lowQualityBPSThreshold - completion:(nullable dispatch_block_t)completion; - -/** - Set whether high quality images should be downloaded when a low quality image is cached if network connectivity has improved. - @see downloadImageWithURLs:options:progressImage:completion: - - @param shouldUpgradeLowQualityImages if YES, low quality images will be 'upgraded'. - @param completion Completion to be called once shouldUpgradeLowQualityImages has been set. - */ -- (void)setShouldUpgradeLowQualityImages:(BOOL)shouldUpgradeLowQualityImages - completion:(nullable dispatch_block_t)completion; - -/** - Set the maximum number of concurrent operations (decompressing images, creating gifs, etc). - - @param maxNumberOfConcurrentOperations The maximum number of concurrent operations. Defaults to NSOperationQueueDefaultMaxConcurrentOperationCount. - @param completion Completion to be called once maxNumberOfConcurrentOperations is set. - */ -- (void)setMaxNumberOfConcurrentOperations:(NSInteger)maxNumberOfConcurrentOperations - completion:(nullable dispatch_block_t)completion; - -/** - Set the maximum number of concurrent downloads. - - @param maxNumberOfConcurrentDownloads The maximum number of concurrent downloads. Defaults to 10. - @param completion Completion to be called once maxNumberOfConcurrentDownloads is set. - */ -- (void)setMaxNumberOfConcurrentDownloads:(NSInteger)maxNumberOfConcurrentDownloads - completion:(nullable dispatch_block_t)completion; - -/** - Set the estimated time remaining to download threshold at which to generate progressive images. Progressive images previews will only be generated if the estimated remaining time on a download is greater than estimatedTimeRemainingThreshold. If estimatedTimeRemainingThreshold is less than or equal to zero, this check is skipped. - - @param estimatedRemainingTimeThreshold The estimated remaining time threshold used to decide to skip progressive rendering. Defaults to 0.1. - @param completion Completion to be called once estimatedTimeRemainingTimeThreshold is set. - */ -- (void)setEstimatedRemainingTimeThresholdForProgressiveDownloads:(NSTimeInterval)estimatedRemainingTimeThreshold - completion:(nullable dispatch_block_t)completion; - -/** - Sets the progress at which progressive images are generated. By default this is @[@0.00, @0.35, @0.65] which generates at most, 3 progressive images. The first progressive image will only be generated when at least one scan has been completed (so you never see half an image). - - @param progressThresholds an array of progress thresholds at which to generate progressive images. progress thresholds should range from 0.00 - 1.00. Defaults to @[@0.00, @0.35, @0.65] - @param completion Completion to be called once progressThresholds is set. - */ -- (void)setProgressThresholds:(nonnull NSArray *)progressThresholds - completion:(nullable dispatch_block_t)completion; - -/** - Sets whether PINRemoteImage should blur progressive render results - - @param shouldBlur A bool value indicating whether PINRemoteImage should blur progressive render results - @param completion Completion to be called once progressThresholds is set. - */ -- (void)setProgressiveRendersShouldBlur:(BOOL)shouldBlur - completion:(nullable dispatch_block_t)completion; - -/** - Sets the maximum size of an image that PINRemoteImage will render progessively. If the image is too large, progressive rendering is skipped. - - @param maxProgressiveRenderSize A CGSize which indicates the max size PINRemoteImage will render a progressive image. If an image is larger in either dimension, progressive rendering will be skipped - @param completion Completion to be called once maxProgressiveRenderSize is set. - */ -- (void)setProgressiveRendersMaxProgressiveRenderSize:(CGSize)maxProgressiveRenderSize - completion:(nullable dispatch_block_t)completion; - -/** - Prefetch an image at the given URL. - - @param url NSURL where the image to prefetch resides. - */ -- (nullable NSUUID *)prefetchImageWithURL:(nonnull NSURL *)url; - -/** - Prefetch an image at the given URL with given options. - - @param url NSURL where the image to prefetch resides. - @param options PINRemoteImageManagerDownloadOptions options with which to pefetch the image. - */ -- (nullable NSUUID *)prefetchImageWithURL:(nonnull NSURL *)url options:(PINRemoteImageManagerDownloadOptions)options; - -/** - Prefetch images at the given URLs. - - @param urls An array of NSURLs where the images to prefetch reside. - */ -- (nonnull NSArray *)prefetchImagesWithURLs:(nonnull NSArray *)urls; - -/** - Prefetch images at the given URLs with given options. - - @param urls An array of NSURLs where the images to prefetch reside. - @param options PINRemoteImageManagerDownloadOptions options with which to pefetch the image. - */ -- (nonnull NSArray *)prefetchImagesWithURLs:(nonnull NSArray *)urls options:(PINRemoteImageManagerDownloadOptions)options; - -/** - Download or retrieve from cache the image found at the url. All completions are called on an arbitrary callback queue unless called on the main thread and the result is in the memory cache (this is an optimization to allow synchronous results for the UI when an object is cached in memory). - - @param url NSURL where the image to download resides. - @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache or downloaded. - @return An NSUUID which uniquely identifies this request. To be used for canceling requests and verifying that the callback is for the request you expect (see categories for example). - */ -- (nullable NSUUID *)downloadImageWithURL:(nonnull NSURL *)url completion:(nullable PINRemoteImageManagerImageCompletion)completion; - -/** - Download or retrieve from cache the image found at the url. All completions are called on an arbitrary callback queue unless called on the main thread and the result is in the memory cache (this is an optimization to allow synchronous results for the UI when an object is cached in memory). - - @param url NSURL where the image to download resides. - @param options PINRemoteImageManagerDownloadOptions options with which to fetch the image. - @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache or downloaded. - @return An NSUUID which uniquely identifies this request. To be used for canceling requests and verifying that the callback is for the request you expect (see categories for example). - */ -- (nullable NSUUID *)downloadImageWithURL:(nonnull NSURL *)url - options:(PINRemoteImageManagerDownloadOptions)options - completion:(nullable PINRemoteImageManagerImageCompletion)completion; - -/** - Download or retrieve from cache the image found at the url. All completions are called on an arbitrary callback queue unless called on the main thread and the result is in the memory cache (this is an optimization to allow synchronous results for the UI when an object is cached in memory). - - @param url NSURL where the image to download resides. - @param options PINRemoteImageManagerDownloadOptions options with which to fetch the image. - @param progressImage PINRemoteImageManagerImageCompletion block which will be called to update progress of the image download. - @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache or downloaded. - - @return An NSUUID which uniquely identifies this request. To be used for canceling requests and verifying that the callback is for the request you expect (see categories for example). - */ -- (nullable NSUUID *)downloadImageWithURL:(nonnull NSURL *)url - options:(PINRemoteImageManagerDownloadOptions)options - progressImage:(nullable PINRemoteImageManagerImageCompletion)progressImage - completion:(nullable PINRemoteImageManagerImageCompletion)completion; - -/** - Download or retrieve from cache the image found at the url. All completions are called on an arbitrary callback queue unless called on the main thread and the result is in the memory cache (this is an optimization to allow synchronous results for the UI when an object is cached in memory). - - @param url NSURL where the image to download resides. - @param options PINRemoteImageManagerDownloadOptions options with which to fetch the image. - @param progressDownload PINRemoteImageManagerDownloadProgress block which will be called to update progress in bytes of the image download. NOTE: For performance reasons, this block is not called on the main thread every time, if you need to update your UI ensure that you dispatch to the main thread first. - @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache or downloaded. - - @return An NSUUID which uniquely identifies this request. To be used for canceling requests and verifying that the callback is for the request you expect (see categories for example). - */ -- (nullable NSUUID *)downloadImageWithURL:(nonnull NSURL *)url - options:(PINRemoteImageManagerDownloadOptions)options - progressDownload:(nullable PINRemoteImageManagerProgressDownload)progressDownload - completion:(nullable PINRemoteImageManagerImageCompletion)completion; - -/** - Download or retrieve from cache the image found at the url. All completions are called on an arbitrary callback queue unless called on the main thread and the result is in the memory cache (this is an optimization to allow synchronous results for the UI when an object is cached in memory). - - @param url NSURL where the image to download resides. - @param options PINRemoteImageManagerDownloadOptions options with which to fetch the image. - @param progressImage PINRemoteImageManagerImageCompletion block which will be called to update progress of the image download. - @param progressDownload PINRemoteImageManagerDownloadProgress block which will be called to update progress in bytes of the image download. NOTE: For performance reasons, this block is not called on the main thread every time, if you need to update your UI ensure that you dispatch to the main thread first. - @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache or downloaded. - - @return An NSUUID which uniquely identifies this request. To be used for canceling requests and verifying that the callback is for the request you expect (see categories for example). - */ -- (nullable NSUUID *)downloadImageWithURL:(nonnull NSURL *)url - options:(PINRemoteImageManagerDownloadOptions)options - progressImage:(nullable PINRemoteImageManagerImageCompletion)progressImage - progressDownload:(nullable PINRemoteImageManagerProgressDownload)progressDownload - completion:(nullable PINRemoteImageManagerImageCompletion)completion; - -/** - Download or retrieve from cache the image found at the url and process it before calling completion. All completions are called on an arbitrary callback queue unless called on the main thread and the result is in the memory cache (this is an optimization to allow synchronous results for the UI when an object is cached in memory). - - @param url NSURL where the image to download resides. - @param options PINRemoteImageManagerDownloadOptions options with which to fetch the image. - @param processorKey NSString key to uniquely identify processor and process. Will be used for caching processed images. - @param processor PINRemoteImageManagerImageProcessor block which will be called to post-process downloaded image. - @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache or downloaded. - - @return An NSUUID which uniquely identifies this request. To be used for canceling requests and verifying that the callback is for the request you expect (see categories for example). - */ -- (nullable NSUUID *)downloadImageWithURL:(nonnull NSURL *)url - options:(PINRemoteImageManagerDownloadOptions)options - processorKey:(nullable NSString *)processorKey - processor:(nullable PINRemoteImageManagerImageProcessor)processor - completion:(nullable PINRemoteImageManagerImageCompletion)completion; - -/** - Download or retrieve from cache the image found at the url and process it before calling completion. All completions are called on an arbitrary callback queue unless called on the main thread and the result is in the memory cache (this is an optimization to allow synchronous results for the UI when an object is cached in memory). - - @param url NSURL where the image to download resides. - @param options PINRemoteImageManagerDownloadOptions options with which to fetch the image. - @param processorKey NSString key to uniquely identify processor and process. Will be used for caching processed images. - @param progressDownload PINRemoteImageManagerDownloadProgress block which will be called to update progress in bytes of the image download. NOTE: For performance reasons, this block is not called on the main thread every time, if you need to update your UI ensure that you dispatch to the main thread first. - @param processor PINRemoteImageManagerImageProcessor block which will be called to post-process downloaded image. - @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache or downloaded. - - @return An NSUUID which uniquely identifies this request. To be used for canceling requests and verifying that the callback is for the request you expect (see categories for example). - */ -- (nullable NSUUID *)downloadImageWithURL:(nonnull NSURL *)url - options:(PINRemoteImageManagerDownloadOptions)options - processorKey:(nullable NSString *)processorKey - processor:(nullable PINRemoteImageManagerImageProcessor)processor - progressDownload:(nullable PINRemoteImageManagerProgressDownload)progressDownload - completion:(nullable PINRemoteImageManagerImageCompletion)completion; - -/** - Download or retrieve from cache one of the images found at the urls in the passed in array based on current network performance. URLs should be sorted from lowest quality image URL to highest. All completions are called on an arbitrary callback queue unless called on the main thread and the result is in the memory cache (this is an optimization to allow synchronous results for the UI when an object is cached in memory). - - Unless setShouldUpgradeLowQualityImages is set to YES, this method checks the cache for all URLs and returns the highest quality version stored. It is possible though unlikely for a cached image to not be returned if it is still being cached while a call is made to this method and if network conditions have changed. See source for more details. - - @param urls An array of NSURLs of increasing size. - @param options PINRemoteImageManagerDownloadOptions options with which to fetch the image. - @param progressImage PINRemoteImageManagerImageCompletion block which will be called to update progress of the image download. - @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache or downloaded. - - @return An NSUUID which uniquely identifies this request. To be used for canceling requests and verifying that the callback is for the request you expect (see categories for example). - */ -- (nullable NSUUID *)downloadImageWithURLs:(nonnull NSArray *)urls - options:(PINRemoteImageManagerDownloadOptions)options - progressImage:(nullable PINRemoteImageManagerImageCompletion)progressImage - completion:(nullable PINRemoteImageManagerImageCompletion)completion; - -/** - Returns the cacheKey for a given URL and processorKey. Exposed to be overridden if necessary or to be used with imageFromCacheWithCacheKey - @see imageFromCacheWithCacheKey:completion: - - @param url NSURL to be downloaded - @param processorKey NSString key to uniquely identify processor and process. - - @return returns an NSString which is the key used for caching. - */ -- (nonnull NSString *)cacheKeyForURL:(nonnull NSURL *)url processorKey:(nullable NSString *)processorKey; - -/** - @see imageFromCacheWithCacheKey:options:completion: instead - @deprecated - - @param cacheKey NSString key to look up image in the cache. - @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache. - */ -- (void)imageFromCacheWithCacheKey:(nonnull NSString *)cacheKey completion:(nonnull PINRemoteImageManagerImageCompletion)completion __attribute__((deprecated)); - -/** - Directly get an image from the underlying cache. - @see cacheKeyForURL:processorKey: - - @param cacheKey NSString key to look up image in the cache. - @param options options will be used to determine if the cached image should be decompressed or FLAnimatedImages should be returned. - @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache. - */ -- (void)imageFromCacheWithCacheKey:(nonnull NSString *)cacheKey options:(PINRemoteImageManagerDownloadOptions)options completion:(nonnull PINRemoteImageManagerImageCompletion)completion; - -/** - Directly get an image from the underlying memory cache synchronously. - @see cacheKeyForURL:processorKey: - - @param cacheKey NSString key to look up image in the cache. - @param options options will be used to determine if the cached image should be decompressed or FLAnimatedImages should be returned. - - @return A PINRemoteImageManagerResult - */ -- (nonnull PINRemoteImageManagerResult *)synchronousImageFromCacheWithCacheKey:(nonnull NSString *)cacheKey options:(PINRemoteImageManagerDownloadOptions)options; - -/** - Cancel a download. Canceling will only cancel the download if all other downloads are also canceled with their associated UUIDs. Canceling *does not* guarantee that your completion will not be called. You can use the UUID provided on the result object verify the completion you want called is being called. - @see PINRemoteImageCategoryManager - - @param UUID NSUUID of the task to cancel. - */ -- (void)cancelTaskWithUUID:(nonnull NSUUID *)UUID; - -/** - Set the priority of a download task. Since there is only one task per download, the priority of the download task will always be the last priority this method was called with. - - @param priority priority to set on the task. - @param UUID NSUUID of the task to set the priority on. - */ -- (void)setPriority:(PINRemoteImageManagerPriority)priority ofTaskWithUUID:(nonnull NSUUID *)UUID; - -/** - * @abstract set the progress callback on a download task. You can use this to add progress callbacks or remove them for in flight downloads - * - * @param progressImageCallback a PINRemoteImageManagerImageCompletion block to be called with a progress update - * @param UUID NSUUID of the task to set the priority on. - */ -- (void)setProgressImageCallback:(nullable PINRemoteImageManagerImageCompletion)progressImageCallback ofTaskWithUUID:(nonnull NSUUID *)UUID; - -@end diff --git a/Pod/Classes/PINRemoteImageManager.m b/Pod/Classes/PINRemoteImageManager.m deleted file mode 100644 index 30189496..00000000 --- a/Pod/Classes/PINRemoteImageManager.m +++ /dev/null @@ -1,1581 +0,0 @@ -// -// PINRemoteImageManager.m -// Pods -// -// Created by Garrett Moon on 8/17/14. -// -// - -#import "PINRemoteImageManager.h" - -#import - -#import "PINAlternateRepresentationProvider.h" -#import "PINRemoteImage.h" -#import "PINRemoteLock.h" -#import "PINProgressiveImage.h" -#import "PINRemoteImageCallbacks.h" -#import "PINRemoteImageTask.h" -#import "PINRemoteImageProcessorTask.h" -#import "PINRemoteImageDownloadTask.h" -#import "PINDataTaskOperation.h" -#import "PINURLSessionManager.h" -#import "PINRemoteImageMemoryContainer.h" -#import "PINRemoteImageCaching.h" - -#import "NSData+ImageDetectors.h" -#import "PINImage+DecodedImage.h" - -#if USE_PINCACHE -#import "PINCache+PINRemoteImageCaching.h" -#else -#import "PINRemoteImageBasicCache.h" -#endif - - -#define PINRemoteImageManagerDefaultTimeout 30.0 -#define PINRemoteImageMaxRetries 3 -#define PINRemoteImageRetryDelayBase 4 - -//A limit of 200 characters is chosen because PINDiskCache -//may expand the length by encoding certain characters -#define PINRemoteImageManagerCacheKeyMaxLength 200 - -NSOperationQueuePriority operationPriorityWithImageManagerPriority(PINRemoteImageManagerPriority priority) { - switch (priority) { - case PINRemoteImageManagerPriorityVeryLow: - return NSOperationQueuePriorityVeryLow; - break; - - case PINRemoteImageManagerPriorityLow: - return NSOperationQueuePriorityLow; - break; - - case PINRemoteImageManagerPriorityMedium: - return NSOperationQueuePriorityNormal; - break; - - case PINRemoteImageManagerPriorityHigh: - return NSOperationQueuePriorityHigh; - break; - - case PINRemoteImageManagerPriorityVeryHigh: - return NSOperationQueuePriorityVeryHigh; - break; - } -} - -float dataTaskPriorityWithImageManagerPriority(PINRemoteImageManagerPriority priority) { - switch (priority) { - case PINRemoteImageManagerPriorityVeryLow: - return 0.0; - break; - - case PINRemoteImageManagerPriorityLow: - return 0.25; - break; - - case PINRemoteImageManagerPriorityMedium: - return 0.5; - break; - - case PINRemoteImageManagerPriorityHigh: - return 0.75; - break; - - case PINRemoteImageManagerPriorityVeryHigh: - return 1.0; - break; - } -} - -NSString * const PINRemoteImageManagerErrorDomain = @"PINRemoteImageManagerErrorDomain"; -NSString * const PINRemoteImageCacheKey = @"cacheKey"; -typedef void (^PINRemoteImageManagerDataCompletion)(NSData *data, NSError *error); - -@interface NSOperationQueue (PINRemoteImageManager) - -- (void)pin_addOperationWithQueuePriority:(PINRemoteImageManagerPriority)priority block:(void (^)(void))block; - -@end - -@interface PINTaskQOS : NSObject - -- (instancetype)initWithBPS:(float)bytesPerSecond endDate:(NSDate *)endDate; - -@property (nonatomic, strong) NSDate *endDate; -@property (nonatomic, assign) float bytesPerSecond; - -@end - -@interface PINRemoteImageManager () -{ - dispatch_queue_t _callbackQueue; - PINRemoteLock *_lock; - NSOperationQueue *_concurrentOperationQueue; - NSOperationQueue *_urlSessionTaskQueue; - - // Necesarry to have a strong reference to _defaultAlternateRepresentationProvider because _alternateRepProvider is __weak - PINAlternateRepresentationProvider *_defaultAlternateRepresentationProvider; - __weak PINAlternateRepresentationProvider *_alternateRepProvider; - -} - -@property (nonatomic, strong) id cache; -@property (nonatomic, strong) PINURLSessionManager *sessionManager; -@property (nonatomic, assign) NSTimeInterval timeout; -@property (nonatomic, strong) NSMutableDictionary *tasks; -@property (nonatomic, strong) NSHashTable *canceledTasks; -@property (nonatomic, strong) NSArray *progressThresholds; -@property (nonatomic, assign) BOOL shouldBlurProgressive; -@property (nonatomic, assign) CGSize maxProgressiveRenderSize; -@property (nonatomic, assign) NSTimeInterval estimatedRemainingTimeThreshold; -@property (nonatomic, strong) dispatch_queue_t callbackQueue; -@property (nonatomic, strong) NSOperationQueue *concurrentOperationQueue; -@property (nonatomic, strong) NSOperationQueue *urlSessionTaskQueue; -@property (nonatomic, strong) NSMutableArray *taskQOS; -@property (nonatomic, assign) float highQualityBPSThreshold; -@property (nonatomic, assign) float lowQualityBPSThreshold; -@property (nonatomic, assign) BOOL shouldUpgradeLowQualityImages; -@property (nonatomic, copy) PINRemoteImageManagerAuthenticationChallenge authenticationChallengeHandler; -#if DEBUG -@property (nonatomic, assign) float currentBPS; -@property (nonatomic, assign) BOOL overrideBPS; -@property (nonatomic, assign) NSUInteger totalDownloads; -#endif - -@end - -#pragma mark PINRemoteImageManager - -@implementation PINRemoteImageManager - -static PINRemoteImageManager *sharedImageManager = nil; -static dispatch_once_t sharedDispatchToken; - -+ (BOOL)supportsQOS -{ - static dispatch_once_t onceToken; - static BOOL supportsQOS; - dispatch_once(&onceToken, ^{ - supportsQOS = [NSOperation instancesRespondToSelector:@selector(setQualityOfService:)]; - }); - return supportsQOS; -} - -+ (instancetype)sharedImageManager -{ - dispatch_once(&sharedDispatchToken, ^{ - sharedImageManager = [[[self class] alloc] init]; - }); - return sharedImageManager; -} - -+ (void)setSharedImageManagerWithConfiguration:(NSURLSessionConfiguration *)configuration -{ - NSAssert(sharedImageManager == nil, @"sharedImageManager singleton is already configured"); - - dispatch_once(&sharedDispatchToken, ^{ - sharedImageManager = [[[self class] alloc] initWithSessionConfiguration:configuration]; - }); -} - -- (instancetype)init -{ - return [self initWithSessionConfiguration:nil]; -} - -- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration -{ - return [self initWithSessionConfiguration:configuration alternativeRepresentationProvider:nil]; -} - -- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration alternativeRepresentationProvider:(id )alternateRepProvider -{ - return [self initWithSessionConfiguration:configuration alternativeRepresentationProvider:nil imageCache:nil]; -} - -- (nonnull instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)configuration alternativeRepresentationProvider:(nullable id )alternateRepProvider - imageCache:(nullable id)imageCache -{ - if (self = [super init]) { - - if (imageCache) { - self.cache = imageCache; - } else { - self.cache = [self defaultImageCache]; - } - - if (!configuration) { - configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration]; - } - _callbackQueue = dispatch_queue_create("PINRemoteImageManagerCallbackQueue", DISPATCH_QUEUE_CONCURRENT); - _lock = [[PINRemoteLock alloc] initWithName:@"PINRemoteImageManager"]; - _concurrentOperationQueue = [[NSOperationQueue alloc] init]; - _concurrentOperationQueue.name = @"PINRemoteImageManager Concurrent Operation Queue"; - _concurrentOperationQueue.maxConcurrentOperationCount = NSOperationQueueDefaultMaxConcurrentOperationCount; - if ([[self class] supportsQOS]) { - _concurrentOperationQueue.qualityOfService = NSQualityOfServiceUtility; - } - _urlSessionTaskQueue = [[NSOperationQueue alloc] init]; - _urlSessionTaskQueue.name = @"PINRemoteImageManager Concurrent URL Session Task Queue"; - _urlSessionTaskQueue.maxConcurrentOperationCount = 10; - - self.sessionManager = [[PINURLSessionManager alloc] initWithSessionConfiguration:configuration]; - self.sessionManager.delegate = self; - - self.estimatedRemainingTimeThreshold = 0.1; - self.timeout = PINRemoteImageManagerDefaultTimeout; - - _highQualityBPSThreshold = 500000; - _lowQualityBPSThreshold = 50000; // approximately edge speeds - _shouldUpgradeLowQualityImages = NO; - _shouldBlurProgressive = YES; - _maxProgressiveRenderSize = CGSizeMake(1024, 1024); - self.tasks = [[NSMutableDictionary alloc] init]; - self.canceledTasks = [[NSHashTable alloc] initWithOptions:NSHashTableWeakMemory capacity:5]; - self.taskQOS = [[NSMutableArray alloc] initWithCapacity:5]; - - if (alternateRepProvider == nil) { - _defaultAlternateRepresentationProvider = [[PINAlternateRepresentationProvider alloc] init]; - alternateRepProvider = _defaultAlternateRepresentationProvider; - } - _alternateRepProvider = alternateRepProvider; - } - return self; -} - -- (id)defaultImageCache -{ -#if USE_PINCACHE - NSString * const kPINRemoteImageDiskCacheName = @"PINRemoteImageManagerCache"; - NSString * const kPINRemoteImageDiskCacheVersionKey = @"kPINRemoteImageDiskCacheVersionKey"; - const NSInteger kPINRemoteImageDiskCacheVersion = 1; - NSUserDefaults *pinDefaults = [[NSUserDefaults alloc] init]; - - NSString *cacheURL = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0]; - - if ([pinDefaults integerForKey:kPINRemoteImageDiskCacheVersionKey] != kPINRemoteImageDiskCacheVersion) { - //remove the old version of the disk cache - PINDiskCache *tempDiskCache = [[PINDiskCache alloc] initWithName:kPINRemoteImageDiskCacheName]; - [[NSFileManager defaultManager] removeItemAtURL:[tempDiskCache cacheURL] error:nil]; - [pinDefaults setInteger:kPINRemoteImageDiskCacheVersion forKey:kPINRemoteImageDiskCacheVersionKey]; - } - - return [[PINCache alloc] initWithName:kPINRemoteImageDiskCacheName rootPath:cacheURL serializer:^NSData * _Nonnull(id _Nonnull object) { - return (NSData *)object; - } deserializer:^id _Nonnull(NSData * _Nonnull data) { - return data; - } fileExtension:nil]; -#else - return [[PINRemoteImageBasicCache alloc] init]; -#endif -} - -- (void)lockOnMainThread -{ -#if !DEBUG - NSAssert(NO, @"lockOnMainThread should only be called for testing on debug builds!"); -#endif - [_lock lock]; -} - -- (void)lock -{ - NSAssert([NSThread isMainThread] == NO, @"lock should not be called from the main thread!"); - [_lock lock]; -} - -- (void)unlock -{ - [_lock unlock]; -} - -- (void)setAuthenticationChallenge:(PINRemoteImageManagerAuthenticationChallenge)challengeBlock { - __weak typeof(self) weakSelf = self; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - typeof(self) strongSelf = weakSelf; - [strongSelf lock]; - strongSelf.authenticationChallengeHandler = challengeBlock; - [strongSelf unlock]; - }); -} - -- (void)setMaxNumberOfConcurrentOperations:(NSInteger)maxNumberOfConcurrentOperations completion:(dispatch_block_t)completion -{ - __weak typeof(self) weakSelf = self; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - typeof(self) strongSelf = weakSelf; - [strongSelf lock]; - strongSelf.concurrentOperationQueue.maxConcurrentOperationCount = maxNumberOfConcurrentOperations; - [strongSelf unlock]; - if (completion) { - completion(); - } - }); -} - -- (void)setMaxNumberOfConcurrentDownloads:(NSInteger)maxNumberOfConcurrentDownloads completion:(dispatch_block_t)completion -{ - __weak typeof(self) weakSelf = self; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - typeof(self) strongSelf = weakSelf; - [strongSelf lock]; - strongSelf.urlSessionTaskQueue.maxConcurrentOperationCount = maxNumberOfConcurrentDownloads; - [strongSelf unlock]; - if (completion) { - completion(); - } - }); -} - -- (void)setEstimatedRemainingTimeThresholdForProgressiveDownloads:(NSTimeInterval)estimatedRemainingTimeThreshold completion:(dispatch_block_t)completion -{ - __weak typeof(self) weakSelf = self; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - typeof(self) strongSelf = weakSelf; - [strongSelf lock]; - strongSelf.estimatedRemainingTimeThreshold = estimatedRemainingTimeThreshold; - [strongSelf unlock]; - if (completion) { - completion(); - } - }); -} - -- (void)setProgressThresholds:(NSArray *)progressThresholds completion:(dispatch_block_t)completion -{ - __weak typeof(self) weakSelf = self; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - typeof(self) strongSelf = weakSelf; - [strongSelf lock]; - strongSelf.progressThresholds = progressThresholds; - [strongSelf unlock]; - if (completion) { - completion(); - } - }); -} - -- (void)setProgressiveRendersShouldBlur:(BOOL)shouldBlur completion:(nullable dispatch_block_t)completion -{ - __weak typeof(self) weakSelf = self; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - typeof(self) strongSelf = weakSelf; - [strongSelf lock]; - strongSelf.shouldBlurProgressive = shouldBlur; - [strongSelf unlock]; - if (completion) { - completion(); - } - }); -} - -- (void)setProgressiveRendersMaxProgressiveRenderSize:(CGSize)maxProgressiveRenderSize completion:(nullable dispatch_block_t)completion -{ - __weak typeof(self) weakSelf = self; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - typeof(self) strongSelf = weakSelf; - [strongSelf lock]; - strongSelf.maxProgressiveRenderSize = maxProgressiveRenderSize; - [strongSelf unlock]; - if (completion) { - completion(); - } - }); -} - -- (void)setHighQualityBPSThreshold:(float)highQualityBPSThreshold completion:(dispatch_block_t)completion -{ - __weak typeof(self) weakSelf = self; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - typeof(self) strongSelf = weakSelf; - [strongSelf lock]; - strongSelf.highQualityBPSThreshold = highQualityBPSThreshold; - [strongSelf unlock]; - if (completion) { - completion(); - } - }); -} - -- (void)setLowQualityBPSThreshold:(float)lowQualityBPSThreshold completion:(dispatch_block_t)completion -{ - __weak typeof(self) weakSelf = self; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - typeof(self) strongSelf = weakSelf; - [strongSelf lock]; - strongSelf.lowQualityBPSThreshold = lowQualityBPSThreshold; - [strongSelf unlock]; - if (completion) { - completion(); - } - }); -} - -- (void)setShouldUpgradeLowQualityImages:(BOOL)shouldUpgradeLowQualityImages completion:(dispatch_block_t)completion -{ - __weak typeof(self) weakSelf = self; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - typeof(self) strongSelf = weakSelf; - [strongSelf lock]; - strongSelf.shouldUpgradeLowQualityImages = shouldUpgradeLowQualityImages; - [strongSelf unlock]; - if (completion) { - completion(); - } - }); -} - -- (NSUUID *)downloadImageWithURL:(NSURL *)url - completion:(PINRemoteImageManagerImageCompletion)completion -{ - return [self downloadImageWithURL:url - options:PINRemoteImageManagerDownloadOptionsNone - completion:completion]; -} - -- (NSUUID *)downloadImageWithURL:(NSURL *)url - options:(PINRemoteImageManagerDownloadOptions)options - completion:(PINRemoteImageManagerImageCompletion)completion -{ - return [self downloadImageWithURL:url - options:options - progressImage:nil - completion:completion]; -} - -- (NSUUID *)downloadImageWithURL:(NSURL *)url - options:(PINRemoteImageManagerDownloadOptions)options - progressImage:(PINRemoteImageManagerImageCompletion)progressImage - completion:(PINRemoteImageManagerImageCompletion)completion -{ - return [self downloadImageWithURL:url - options:options - priority:PINRemoteImageManagerPriorityMedium - processorKey:nil - processor:nil - progressImage:progressImage - progressDownload:nil - completion:completion - inputUUID:nil]; -} - -- (NSUUID *)downloadImageWithURL:(NSURL *)url - options:(PINRemoteImageManagerDownloadOptions)options - progressDownload:(PINRemoteImageManagerProgressDownload)progressDownload - completion:(PINRemoteImageManagerImageCompletion)completion -{ - return [self downloadImageWithURL:url - options:options - priority:PINRemoteImageManagerPriorityMedium - processorKey:nil - processor:nil - progressImage:nil - progressDownload:progressDownload - completion:completion - inputUUID:nil]; -} - -- (NSUUID *)downloadImageWithURL:(NSURL *)url - options:(PINRemoteImageManagerDownloadOptions)options - progressImage:(PINRemoteImageManagerImageCompletion)progressImage - progressDownload:(PINRemoteImageManagerProgressDownload)progressDownload - completion:(PINRemoteImageManagerImageCompletion)completion -{ - return [self downloadImageWithURL:url - options:options - priority:PINRemoteImageManagerPriorityMedium - processorKey:nil - processor:nil - progressImage:progressImage - progressDownload:progressDownload - completion:completion - inputUUID:nil]; -} - -- (NSUUID *)downloadImageWithURL:(NSURL *)url - options:(PINRemoteImageManagerDownloadOptions)options - processorKey:(NSString *)processorKey - processor:(PINRemoteImageManagerImageProcessor)processor - completion:(PINRemoteImageManagerImageCompletion)completion -{ - return [self downloadImageWithURL:url - options:options - priority:PINRemoteImageManagerPriorityMedium - processorKey:processorKey - processor:processor - progressImage:nil - progressDownload:nil - completion:completion - inputUUID:nil]; -} - -- (NSUUID *)downloadImageWithURL:(NSURL *)url - options:(PINRemoteImageManagerDownloadOptions)options - processorKey:(NSString *)processorKey - processor:(PINRemoteImageManagerImageProcessor)processor - progressDownload:(PINRemoteImageManagerProgressDownload)progressDownload - completion:(PINRemoteImageManagerImageCompletion)completion -{ - return [self downloadImageWithURL:url - options:options - priority:PINRemoteImageManagerPriorityMedium - processorKey:processorKey - processor:processor - progressImage:nil - progressDownload:progressDownload - completion:completion - inputUUID:nil]; -} - -- (NSUUID *)downloadImageWithURL:(NSURL *)url - options:(PINRemoteImageManagerDownloadOptions)options - priority:(PINRemoteImageManagerPriority)priority - processorKey:(NSString *)processorKey - processor:(PINRemoteImageManagerImageProcessor)processor - progressImage:(PINRemoteImageManagerImageCompletion)progressImage - progressDownload:(PINRemoteImageManagerProgressDownload)progressDownload - completion:(PINRemoteImageManagerImageCompletion)completion - inputUUID:(NSUUID *)UUID -{ - NSAssert((processor != nil && processorKey.length > 0) || (processor == nil && processorKey == nil), @"processor must not be nil and processorKey length must be greater than zero OR processor must be nil and processorKey must be nil"); - - Class taskClass; - if (processor && processorKey.length > 0) { - taskClass = [PINRemoteImageProcessorTask class]; - } else { - taskClass = [PINRemoteImageDownloadTask class]; - } - - NSString *key = [self cacheKeyForURL:url processorKey:processorKey]; - - if (url == nil) { - [self earlyReturnWithOptions:options url:nil key:key object:nil completion:completion]; - return nil; - } - - NSAssert([url isKindOfClass:[NSURL class]], @"url must be of type NSURL, if it's an NSString, we'll try to correct"); - if ([url isKindOfClass:[NSString class]]) { - url = [NSURL URLWithString:(NSString *)url]; - } - - if (UUID == nil) { - UUID = [NSUUID UUID]; - } - - //Check to see if the image is in memory cache and we're on the main thread. - //If so, special case this to avoid flashing the UI - id object = [self.cache objectFromMemoryCacheForKey:key]; - if (object) { - if ([self earlyReturnWithOptions:options url:url key:key object:object completion:completion]) { - return nil; - } - } - - if ([url.scheme isEqualToString:@"data"]) { - NSData *data = [NSData dataWithContentsOfURL:url]; - if (data) { - if ([self earlyReturnWithOptions:options url:url key:key object:data completion:completion]) { - return nil; - } - } - } - - __weak typeof(self) weakSelf = self; - [_concurrentOperationQueue pin_addOperationWithQueuePriority:priority block:^ - { - typeof(self) strongSelf = weakSelf; - [strongSelf lock]; - //check canceled tasks first - if ([strongSelf.canceledTasks containsObject:UUID]) { - PINLog(@"skipping starting %@ because it was canceled.", UUID); - [strongSelf unlock]; - return; - } - - PINRemoteImageTask *task = [strongSelf.tasks objectForKey:key]; - BOOL taskExisted = NO; - if (task == nil) { - task = [[taskClass alloc] init]; - PINLog(@"Task does not exist creating with key: %@, URL: %@, UUID: %@, task: %p", key, url, UUID, task); - #if PINRemoteImageLogging - task.key = key; - #endif - } else { - taskExisted = YES; - PINLog(@"Task exists, attaching with key: %@, URL: %@, UUID: %@, task: %@", key, url, UUID, task); - } - [task addCallbacksWithCompletionBlock:completion progressImageBlock:progressImage progressDownloadBlock:progressDownload withUUID:UUID]; - [strongSelf.tasks setObject:task forKey:key]; - - BlockAssert(taskClass == [task class], @"Task class should be the same!"); - [strongSelf unlock]; - - if (taskExisted == NO) { - [strongSelf.concurrentOperationQueue pin_addOperationWithQueuePriority:priority block:^ - { - typeof(self) strongSelf = weakSelf; - [strongSelf objectForKey:key options:options completion:^(BOOL found, BOOL valid, PINImage *image, id alternativeRepresentation) { - if (found) { - if (valid) { - typeof(self) strongSelf = weakSelf; - [strongSelf callCompletionsWithKey:key image:image alternativeRepresentation:alternativeRepresentation cached:YES error:nil finalized:YES]; - } else { - //Remove completion and try again - typeof(self) strongSelf = weakSelf; - [strongSelf lock]; - PINRemoteImageTask *task = [strongSelf.tasks objectForKey:key]; - [task removeCallbackWithUUID:UUID]; - if (task.callbackBlocks.count == 0) { - [strongSelf.tasks removeObjectForKey:key]; - } - [strongSelf unlock]; - - //Skip early check - [strongSelf downloadImageWithURL:url - options:options | PINRemoteImageManagerDownloadOptionsSkipEarlyCheck - priority:priority - processorKey:processorKey - processor:processor - progressImage:(PINRemoteImageManagerImageCompletion)progressImage - progressDownload:nil - completion:completion - inputUUID:UUID]; - } - } else { - if ([taskClass isSubclassOfClass:[PINRemoteImageProcessorTask class]]) { - //continue processing - [strongSelf downloadImageWithURL:url - options:options - priority:priority - key:key - processor:processor - UUID:UUID]; - } else if ([taskClass isSubclassOfClass:[PINRemoteImageDownloadTask class]]) { - //continue downloading - [strongSelf downloadImageWithURL:url - options:options - priority:priority - key:key - progressImage:progressImage - UUID:UUID]; - } - } - }]; - }]; - } - }]; - - return UUID; -} - -- (void)downloadImageWithURL:(NSURL *)url - options:(PINRemoteImageManagerDownloadOptions)options - priority:(PINRemoteImageManagerPriority)priority - key:(NSString *)key - processor:(PINRemoteImageManagerImageProcessor)processor - UUID:(NSUUID *)UUID -{ - PINRemoteImageProcessorTask *task = nil; - [self lock]; - task = [self.tasks objectForKey:key]; - //check processing task still exists and download hasn't been started for another task - if (task == nil || task.downloadTaskUUID != nil) { - [self unlock]; - return; - } - - __weak typeof(self) weakSelf = self; - NSUUID *downloadTaskUUID = [self downloadImageWithURL:url - options:options | PINRemoteImageManagerDownloadOptionsSkipEarlyCheck - completion:^(PINRemoteImageManagerResult *result) - { - typeof(self) strongSelf = weakSelf; - NSUInteger processCost = 0; - NSError *error = result.error; - PINRemoteImageProcessorTask *task = nil; - [strongSelf lock]; - task = [strongSelf.tasks objectForKey:key]; - [strongSelf unlock]; - //check processing task still exists - if (task == nil) { - return; - } - if (result.image && error == nil) { - //If completionBlocks.count == 0, we've canceled before we were even able to start. - PINImage *image = processor(result, &processCost); - - if (image == nil) { - error = [NSError errorWithDomain:PINRemoteImageManagerErrorDomain - code:PINRemoteImageManagerErrorFailedToProcessImage - userInfo:nil]; - } - [strongSelf callCompletionsWithKey:key image:image alternativeRepresentation:nil cached:NO error:error finalized:NO]; - - if (error == nil) { - BOOL saveAsJPEG = (options & PINRemoteImageManagerSaveProcessedImageAsJPEG) != 0; - NSData *diskData = nil; - if (saveAsJPEG) { - diskData = PINImageJPEGRepresentation(image, 1.0); - } else { - diskData = PINImagePNGRepresentation(image); - } - - [strongSelf materializeAndCacheObject:image cacheInDisk:diskData additionalCost:processCost key:key options:options outImage:nil outAltRep:nil]; - } - - [strongSelf callCompletionsWithKey:key image:image alternativeRepresentation:nil cached:NO error:error finalized:YES]; - } else { - if (error == nil) { - error = [NSError errorWithDomain:PINRemoteImageManagerErrorDomain - code:PINRemoteImageManagerErrorFailedToFetchImageForProcessing - userInfo:nil]; - } - - [strongSelf callCompletionsWithKey:key image:nil alternativeRepresentation:nil cached:NO error:error finalized:YES]; - } - }]; - task.downloadTaskUUID = downloadTaskUUID; - [self unlock]; -} - -- (void)downloadImageWithURL:(NSURL *)url - options:(PINRemoteImageManagerDownloadOptions)options - priority:(PINRemoteImageManagerPriority)priority - key:(NSString *)key - progressImage:(PINRemoteImageManagerImageCompletion)progressImage - UUID:(NSUUID *)UUID -{ - [self lock]; - PINRemoteImageDownloadTask *task = [self.tasks objectForKey:key]; - if (task.urlSessionTaskOperation == nil && task.callbackBlocks.count > 0 && task.numberOfRetries == 0) { - //If completionBlocks.count == 0, we've canceled before we were even able to start. - CFTimeInterval startTime = CACurrentMediaTime(); - PINDataTaskOperation *urlSessionTaskOperation = [self sessionTaskWithURL:url key:key options:options priority:priority]; - task.urlSessionTaskOperation = urlSessionTaskOperation; - task.sessionTaskStartTime = startTime; - } - [self unlock]; -} - -- (BOOL)earlyReturnWithOptions:(PINRemoteImageManagerDownloadOptions)options url:(NSURL *)url key:(NSString *)key object:(id)object completion:(PINRemoteImageManagerImageCompletion)completion -{ - PINImage *image = nil; - id alternativeRepresentation = nil; - PINRemoteImageResultType resultType = PINRemoteImageResultTypeNone; - - BOOL allowEarlyReturn = !(PINRemoteImageManagerDownloadOptionsSkipEarlyCheck & options); - - if (url != nil && object != nil) { - resultType = PINRemoteImageResultTypeMemoryCache; - [self materializeAndCacheObject:object key:key options:options outImage:&image outAltRep:&alternativeRepresentation]; - } - - if (completion && ((image || alternativeRepresentation) || (url == nil))) { - //If we're on the main thread, special case to call completion immediately - NSError *error = nil; - if (!url) { - error = [NSError errorWithDomain:NSURLErrorDomain - code:NSURLErrorUnsupportedURL - userInfo:@{ NSLocalizedDescriptionKey : @"unsupported URL" }]; - } - if (allowEarlyReturn && [NSThread isMainThread]) { - completion([PINRemoteImageManagerResult imageResultWithImage:image - alternativeRepresentation:alternativeRepresentation - requestLength:0 - error:error - resultType:resultType - UUID:nil]); - } else { - dispatch_async(self.callbackQueue, ^{ - completion([PINRemoteImageManagerResult imageResultWithImage:image - alternativeRepresentation:alternativeRepresentation - requestLength:0 - error:error - resultType:resultType - UUID:nil]); - }); - } - return YES; - } - return NO; -} - -- (PINDataTaskOperation *)sessionTaskWithURL:(NSURL *)URL - key:(NSString *)key - options:(PINRemoteImageManagerDownloadOptions)options - priority:(PINRemoteImageManagerPriority)priority -{ - __weak typeof(self) weakSelf = self; - return [self downloadDataWithURL:URL - key:key - priority:priority - completion:^(NSData *data, NSError *error) - { - [_concurrentOperationQueue pin_addOperationWithQueuePriority:priority block:^ - { - typeof(self) strongSelf = weakSelf; - NSError *remoteImageError = error; - PINImage *image = nil; - id alternativeRepresentation = nil; - - if (remoteImageError && [[self class] retriableError:remoteImageError]) { - //attempt to retry after delay - BOOL retry = NO; - NSUInteger newNumberOfRetries = 0; - [strongSelf lock]; - PINRemoteImageDownloadTask *task = [self.tasks objectForKey:key]; - if (task.numberOfRetries < PINRemoteImageMaxRetries) { - retry = YES; - newNumberOfRetries = ++task.numberOfRetries; - task.urlSessionTaskOperation = nil; - } - [strongSelf unlock]; - - if (retry) { - int64_t delay = powf(PINRemoteImageRetryDelayBase, newNumberOfRetries); - PINLog(@"Retrying download of %@ in %d seconds.", URL, delay); - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - typeof(self) strongSelf = weakSelf; - [strongSelf lock]; - PINRemoteImageDownloadTask *task = [strongSelf.tasks objectForKey:key]; - if (task.urlSessionTaskOperation == nil && task.callbackBlocks.count > 0) { - //If completionBlocks.count == 0, we've canceled before we were even able to start. - PINDataTaskOperation *urlSessionTaskOperation = [strongSelf sessionTaskWithURL:URL key:key options:options priority:priority]; - task.urlSessionTaskOperation = urlSessionTaskOperation; - } - [strongSelf unlock]; - }); - return; - } - } else if (remoteImageError == nil) { - //stores the object in the caches - [strongSelf materializeAndCacheObject:data cacheInDisk:data additionalCost:0 key:key options:options outImage:&image outAltRep:&alternativeRepresentation]; - } - - if (error == nil && image == nil && alternativeRepresentation == nil) { - remoteImageError = [NSError errorWithDomain:PINRemoteImageManagerErrorDomain - code:PINRemoteImageManagerErrorFailedToDecodeImage - userInfo:nil]; - } - - [strongSelf callCompletionsWithKey:key image:image alternativeRepresentation:alternativeRepresentation cached:NO error:remoteImageError finalized:YES]; - }]; - }]; -} - -+ (BOOL)retriableError:(NSError *)remoteImageError -{ - if ([remoteImageError.domain isEqualToString:PINURLErrorDomain]) { - return remoteImageError.code >= 500; - } else if ([remoteImageError.domain isEqualToString:NSURLErrorDomain] && remoteImageError.code == NSURLErrorUnsupportedURL) { - return NO; - } else if ([remoteImageError.domain isEqualToString:PINRemoteImageManagerErrorDomain]) { - return NO; - } - return YES; -} - -- (PINDataTaskOperation *)downloadDataWithURL:(NSURL *)url - key:(NSString *)key - priority:(PINRemoteImageManagerPriority)priority - completion:(PINRemoteImageManagerDataCompletion)completion -{ - NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url - cachePolicy:NSURLRequestReloadIgnoringLocalCacheData - timeoutInterval:self.timeout]; - [NSURLProtocol setProperty:key forKey:PINRemoteImageCacheKey inRequest:request]; - - __weak typeof(self) weakSelf = self; - PINDataTaskOperation *dataTaskOperation = [PINDataTaskOperation dataTaskOperationWithSessionManager:self.sessionManager - request:request - completionHandler:^(NSURLResponse *response, NSError *error) - { - typeof(self) strongSelf = weakSelf; -#if DEBUG - [strongSelf lock]; - strongSelf.totalDownloads++; - [strongSelf unlock]; -#endif - -#if PINRemoteImageLogging - if (error && error.code != NSURLErrorCancelled) { - PINLog(@"Failed downloading image: %@ with error: %@", url, error); - } else if (error == nil && response.expectedContentLength == 0) { - PINLog(@"image is empty at URL: %@", url); - } else { - PINLog(@"Finished downloading image: %@", url); - } -#endif - - if (error.code != NSURLErrorCancelled) { - [strongSelf lock]; - PINRemoteImageDownloadTask *task = [strongSelf.tasks objectForKey:key]; - NSData *data = task.progressImage.data; - [strongSelf unlock]; - - if (error == nil && data == nil) { - error = [NSError errorWithDomain:PINRemoteImageManagerErrorDomain - code:PINRemoteImageManagerErrorImageEmpty - userInfo:nil]; - } - - completion(data, error); - } - }]; - - if ([dataTaskOperation.dataTask respondsToSelector:@selector(setPriority:)]) { - dataTaskOperation.dataTask.priority = dataTaskPriorityWithImageManagerPriority(priority); - } - - dataTaskOperation.queuePriority = operationPriorityWithImageManagerPriority(priority); - [self.urlSessionTaskQueue addOperation:dataTaskOperation]; - - return dataTaskOperation; -} - -- (void)callCompletionsWithKey:(NSString *)key image:(PINImage *)image alternativeRepresentation:(id)alternativeRepresentation cached:(BOOL)cached error:(NSError *)error finalized:(BOOL)finalized -{ - [self lock]; - PINRemoteImageDownloadTask *task = [self.tasks objectForKey:key]; - [task callCompletionsWithQueue:self.callbackQueue remove:!finalized withImage:image alternativeRepresentation:alternativeRepresentation cached:cached error:error]; - if (finalized) { - [self.tasks removeObjectForKey:key]; - } - [self unlock]; -} - -#pragma mark - Prefetching - -- (NSArray *)prefetchImagesWithURLs:(NSArray *)urls -{ - return [self prefetchImagesWithURLs:urls options:PINRemoteImageManagerDownloadOptionsNone | PINRemoteImageManagerDownloadOptionsSkipEarlyCheck]; -} - -- (NSArray *)prefetchImagesWithURLs:(NSArray *)urls options:(PINRemoteImageManagerDownloadOptions)options -{ - NSMutableArray *tasks = [NSMutableArray arrayWithCapacity:urls.count]; - for (NSURL *url in urls) { - NSUUID *task = [self prefetchImageWithURL:url options:options]; - if (task != nil) { - [tasks addObject:task]; - } - } - return tasks; -} - -- (NSUUID *)prefetchImageWithURL:(NSURL *)url -{ - return [self prefetchImageWithURL:url options:PINRemoteImageManagerDownloadOptionsNone | PINRemoteImageManagerDownloadOptionsSkipEarlyCheck]; -} - -- (NSUUID *)prefetchImageWithURL:(NSURL *)url options:(PINRemoteImageManagerDownloadOptions)options -{ - return [self downloadImageWithURL:url - options:options - priority:PINRemoteImageManagerPriorityVeryLow - processorKey:nil - processor:nil - progressImage:nil - progressDownload:nil - completion:nil - inputUUID:nil]; -} - -#pragma mark - Cancelation & Priority - -- (void)cancelTaskWithUUID:(NSUUID *)UUID -{ - if (UUID == nil) { - return; - } - PINLog(@"Attempting to cancel UUID: %@", UUID); - __weak typeof(self) weakSelf = self; - [_concurrentOperationQueue pin_addOperationWithQueuePriority:PINRemoteImageManagerPriorityHigh block:^ - { - typeof(self) strongSelf = weakSelf; - //find the task associated with the UUID. This might be spead up by storing a mapping of UUIDs to tasks - [strongSelf lock]; - __block PINRemoteImageTask *taskToEvaluate = nil; - __block NSString *taskKey = nil; - [strongSelf.tasks enumerateKeysAndObjectsUsingBlock:^(NSString *key, PINRemoteImageTask *task, BOOL *stop) { - if (task.callbackBlocks[UUID]) { - taskToEvaluate = task; - taskKey = key; - *stop = YES; - } - }]; - - if (taskToEvaluate == nil) { - //maybe task hasn't been added to task list yet, add it to canceled tasks. - //there's no need to ever remove a UUID from canceledTasks because it is weak. - [strongSelf.canceledTasks addObject:UUID]; - } - - if ([taskToEvaluate cancelWithUUID:UUID manager:strongSelf]) { - [strongSelf.tasks removeObjectForKey:taskKey]; - } - [strongSelf unlock]; - }]; -} - -- (void)setPriority:(PINRemoteImageManagerPriority)priority ofTaskWithUUID:(NSUUID *)UUID -{ - if (UUID == nil) { - return; - } - PINLog(@"Setting priority of UUID: %@ priority: %lu", UUID, (unsigned long)priority); - __weak typeof(self) weakSelf = self; - [_concurrentOperationQueue pin_addOperationWithQueuePriority:PINRemoteImageManagerPriorityHigh block:^{ - typeof(self) strongSelf = weakSelf; - [strongSelf lock]; - PINRemoteImageTask *taskToEvaluate = nil; - for (NSString *key in [strongSelf.tasks allKeys]) { - PINRemoteImageTask *task = [strongSelf.tasks objectForKey:key]; - for (NSUUID *blockUUID in [task.callbackBlocks allKeys]) { - if ([blockUUID isEqual:UUID]) { - taskToEvaluate = task; - break; - } - } - } - - [taskToEvaluate setPriority:priority]; - [strongSelf unlock]; - }]; -} - -- (void)setProgressImageCallback:(nullable PINRemoteImageManagerImageCompletion)progressImageCallback ofTaskWithUUID:(nonnull NSUUID *)UUID -{ - if (UUID == nil) { - return; - } - - PINLog(@"setting progress block of UUID: %@ progressBlock: %@", UUID, progressImageCallback); - __weak typeof(self) weakSelf = self; - [_concurrentOperationQueue pin_addOperationWithQueuePriority:PINRemoteImageManagerPriorityHigh block:^{ - typeof(self) strongSelf = weakSelf; - [strongSelf lock]; - for (NSString *key in [strongSelf.tasks allKeys]) { - PINRemoteImageTask *task = [strongSelf.tasks objectForKey:key]; - for (NSUUID *blockUUID in [task.callbackBlocks allKeys]) { - if ([blockUUID isEqual:UUID]) { - if ([task isKindOfClass:[PINRemoteImageDownloadTask class]]) { - PINRemoteImageCallbacks *callbacks = task.callbackBlocks[blockUUID]; - callbacks.progressImageBlock = progressImageCallback; - } - break; - } - } - } - [strongSelf unlock]; - }]; -} - -#pragma mark - Caching - -- (void)imageFromCacheWithCacheKey:(NSString *)cacheKey - completion:(PINRemoteImageManagerImageCompletion)completion -{ - [self imageFromCacheWithCacheKey:cacheKey options:PINRemoteImageManagerDownloadOptionsNone completion:completion]; -} - -- (void)imageFromCacheWithCacheKey:(NSString *)cacheKey - options:(PINRemoteImageManagerDownloadOptions)options - completion:(PINRemoteImageManagerImageCompletion)completion -{ - CFTimeInterval requestTime = CACurrentMediaTime(); - - if ((PINRemoteImageManagerDownloadOptionsSkipEarlyCheck & options) == NO && [NSThread isMainThread]) { - PINRemoteImageManagerResult *result = [self synchronousImageFromCacheWithCacheKey:cacheKey options:options]; - if (result.image && result.error) { - completion((result)); - return; - } - } - - [self objectForKey:cacheKey options:options completion:^(BOOL found, BOOL valid, PINImage *image, id alternativeRepresentation) { - NSError *error = nil; - if (valid == NO) { - error = [NSError errorWithDomain:PINRemoteImageManagerErrorDomain - code:PINRemoteImageManagerErrorInvalidItemInCache - userInfo:nil]; - } - - dispatch_async(self.callbackQueue, ^{ - completion([PINRemoteImageManagerResult imageResultWithImage:image - alternativeRepresentation:alternativeRepresentation - requestLength:CACurrentMediaTime() - requestTime - error:error - resultType:PINRemoteImageResultTypeCache - UUID:nil]); - }); - }]; -} - -- (PINRemoteImageManagerResult *)synchronousImageFromCacheWithCacheKey:(NSString *)cacheKey options:(PINRemoteImageManagerDownloadOptions)options -{ - CFTimeInterval requestTime = CACurrentMediaTime(); - - id object = [self.cache objectFromMemoryCacheForKey:cacheKey]; - PINImage *image; - id alternativeRepresentation; - NSError *error = nil; - if (object == nil) { - image = nil; - alternativeRepresentation = nil; - } else if ([self materializeAndCacheObject:object key:cacheKey options:options outImage:&image outAltRep:&alternativeRepresentation] == NO) { - error = [NSError errorWithDomain:PINRemoteImageManagerErrorDomain - code:PINRemoteImageManagerErrorInvalidItemInCache - userInfo:nil]; - } - - return [PINRemoteImageManagerResult imageResultWithImage:image - alternativeRepresentation:alternativeRepresentation - requestLength:CACurrentMediaTime() - requestTime - error:error - resultType:PINRemoteImageResultTypeMemoryCache - UUID:nil]; -} - -#pragma mark - Session Task Blocks - -- (void)didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge forTask:(NSURLSessionTask *)task completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler { - [self lock]; - if (self.authenticationChallengeHandler) { - self.authenticationChallengeHandler(task, challenge, ^(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential){ - completionHandler(disposition, credential); - }); - } else { - completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); - } - - [self unlock]; -} - -- (void)didReceiveData:(NSData *)data forTask:(NSURLSessionDataTask *)dataTask -{ - [self lock]; - NSString *cacheKey = [NSURLProtocol propertyForKey:PINRemoteImageCacheKey inRequest:dataTask.originalRequest]; - PINRemoteImageDownloadTask *task = [self.tasks objectForKey:cacheKey]; - if (task.progressImage == nil) { - task.progressImage = [[PINProgressiveImage alloc] init]; - task.progressImage.startTime = task.sessionTaskStartTime; - task.progressImage.estimatedRemainingTimeThreshold = self.estimatedRemainingTimeThreshold; - if (self.progressThresholds) { - task.progressImage.progressThresholds = self.progressThresholds; - } - } - - PINProgressiveImage *progressiveImage = task.progressImage; - BOOL hasProgressBlocks = task.hasProgressBlocks; - BOOL shouldBlur = self.shouldBlurProgressive; - CGSize maxProgressiveRenderSize = self.maxProgressiveRenderSize; - - [task callProgressDownloadWithQueue:self.callbackQueue completedBytes:dataTask.countOfBytesReceived totalBytes:dataTask.countOfBytesExpectedToReceive]; - [self unlock]; - - [progressiveImage updateProgressiveImageWithData:data expectedNumberOfBytes:[dataTask countOfBytesExpectedToReceive]]; - - if (hasProgressBlocks && [NSOperation instancesRespondToSelector:@selector(qualityOfService)]) { - __weak typeof(self) weakSelf = self; - [_concurrentOperationQueue pin_addOperationWithQueuePriority:PINRemoteImageManagerPriorityLow block:^{ - typeof(self) strongSelf = weakSelf; - CGFloat renderedImageQuality = 1.0; - PINImage *progressImage = [progressiveImage currentImageBlurred:shouldBlur maxProgressiveRenderSize:maxProgressiveRenderSize renderedImageQuality:&renderedImageQuality]; - if (progressImage) { - [strongSelf lock]; - PINRemoteImageDownloadTask *task = strongSelf.tasks[cacheKey]; - [task callProgressImageWithQueue:strongSelf.callbackQueue withImage:progressImage renderedImageQuality:renderedImageQuality]; - [strongSelf unlock]; - } - }]; - } -} - -- (void)didCompleteTask:(NSURLSessionTask *)task withError:(NSError *)error -{ - if (error == nil && [task isKindOfClass:[NSURLSessionDataTask class]]) { - NSURLSessionDataTask *dataTask = (NSURLSessionDataTask *)task; - [self lock]; - NSString *cacheKey = [NSURLProtocol propertyForKey:PINRemoteImageCacheKey inRequest:dataTask.originalRequest]; - PINRemoteImageDownloadTask *task = [self.tasks objectForKey:cacheKey]; - task.sessionTaskEndTime = CACurrentMediaTime(); - CFTimeInterval taskLength = task.sessionTaskEndTime - task.sessionTaskStartTime; - [self unlock]; - - float bytesPerSecond = dataTask.countOfBytesReceived / taskLength; - [self addTaskBPS:bytesPerSecond endDate:[NSDate date]]; - } -} - -#pragma mark - QOS - -- (float)currentBytesPerSecond -{ - [self lock]; - #if DEBUG - if (self.overrideBPS) { - float currentBPS = self.currentBPS; - [self unlock]; - return currentBPS; - } - #endif - - const NSTimeInterval validThreshold = 60.0; - __block NSUInteger count = 0; - __block float bps = 0; - __block BOOL valid = NO; - - NSDate *threshold = [NSDate dateWithTimeIntervalSinceNow:-validThreshold]; - [self.taskQOS enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(PINTaskQOS *taskQOS, NSUInteger idx, BOOL *stop) { - if ([taskQOS.endDate compare:threshold] == NSOrderedAscending) { - *stop = YES; - return; - } - valid = YES; - count++; - bps += taskQOS.bytesPerSecond; - - }]; - [self unlock]; - - if (valid == NO) { - return -1; - } - - return bps / (float)count; -} - -- (void)addTaskBPS:(float)bytesPerSecond endDate:(NSDate *)endDate -{ - //if bytesPerSecond is less than or equal to zero, ignore. - if (bytesPerSecond <= 0) { - return; - } - - [self lock]; - if (self.taskQOS.count >= 5) { - [self.taskQOS removeObjectAtIndex:0]; - } - - PINTaskQOS *taskQOS = [[PINTaskQOS alloc] initWithBPS:bytesPerSecond endDate:endDate]; - - [self.taskQOS addObject:taskQOS]; - [self.taskQOS sortUsingComparator:^NSComparisonResult(PINTaskQOS *obj1, PINTaskQOS *obj2) { - return [obj1.endDate compare:obj2.endDate]; - }]; - - [self unlock]; -} - -#if DEBUG -- (void)setCurrentBytesPerSecond:(float)currentBPS -{ - [self lockOnMainThread]; - _overrideBPS = YES; - _currentBPS = currentBPS; - [self unlock]; -} -#endif - -- (NSUUID *)downloadImageWithURLs:(NSArray *)urls - options:(PINRemoteImageManagerDownloadOptions)options - progressImage:(PINRemoteImageManagerImageCompletion)progressImage - completion:(PINRemoteImageManagerImageCompletion)completion -{ - NSUUID *UUID = [NSUUID UUID]; - if (urls.count <= 1) { - NSURL *url = [urls firstObject]; - [self downloadImageWithURL:url - options:options - priority:PINRemoteImageManagerPriorityMedium - processorKey:nil - processor:nil - progressImage:progressImage - progressDownload:nil - completion:completion - inputUUID:UUID]; - return UUID; - } - - __weak typeof(self) weakSelf = self; - [self.concurrentOperationQueue pin_addOperationWithQueuePriority:PINRemoteImageManagerPriorityMedium block:^{ - __block NSInteger highestQualityDownloadedIdx = -1; - typeof(self) strongSelf = weakSelf; - - //check for the highest quality image already in cache. It's possible that an image is in the process of being - //cached when this is being run. In which case two things could happen: - // - If network conditions dictate that a lower quality image should be downloaded than the one that is currently - // being cached, it will be downloaded in addition. This is not ideal behavior, worst case scenario and unlikely. - // - If network conditions dictate that the same quality image should be downloaded as the one being cached, no - // new image will be downloaded as either the caching will have finished by the time we actually request it or - // the task will still exist and our callback will be attached. In this case, no detrimental behavior will have - // occurred. - [urls enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSURL *url, NSUInteger idx, BOOL *stop) { - typeof(self) strongSelf = weakSelf; - BlockAssert([url isKindOfClass:[NSURL class]], @"url must be of type URL"); - NSString *cacheKey = [strongSelf cacheKeyForURL:url processorKey:nil]; - - //we don't actually need the object, just need to know it exists so that we can request it later - BOOL hasObject = [self.cache objectExistsInCacheForKey:cacheKey]; - - if (hasObject) { - highestQualityDownloadedIdx = idx; - *stop = YES; - } - }]; - - float currentBytesPerSecond = [strongSelf currentBytesPerSecond]; - [strongSelf lock]; - float highQualityQPSThreshold = [strongSelf highQualityBPSThreshold]; - float lowQualityQPSThreshold = [strongSelf lowQualityBPSThreshold]; - BOOL shouldUpgradeLowQualityImages = [strongSelf shouldUpgradeLowQualityImages]; - [strongSelf unlock]; - - NSUInteger desiredImageURLIdx; - if (currentBytesPerSecond == -1 || currentBytesPerSecond >= highQualityQPSThreshold) { - desiredImageURLIdx = urls.count - 1; - } else if (currentBytesPerSecond <= lowQualityQPSThreshold) { - desiredImageURLIdx = 0; - } else if (urls.count == 2) { - desiredImageURLIdx = roundf((currentBytesPerSecond - lowQualityQPSThreshold) / ((highQualityQPSThreshold - lowQualityQPSThreshold) / (float)(urls.count - 1))); - } else { - desiredImageURLIdx = ceilf((currentBytesPerSecond - lowQualityQPSThreshold) / ((highQualityQPSThreshold - lowQualityQPSThreshold) / (float)(urls.count - 2))); - } - - NSUInteger downloadIdx; - //if the highest quality already downloaded is less than what currentBPS would dictate and shouldUpgrade is - //set, download the new higher quality image. If no image has been cached, download the image dictated by - //current bps - if ((highestQualityDownloadedIdx < desiredImageURLIdx && shouldUpgradeLowQualityImages) || highestQualityDownloadedIdx == -1) { - downloadIdx = desiredImageURLIdx; - } else { - downloadIdx = highestQualityDownloadedIdx; - } - - NSURL *downloadURL = [urls objectAtIndex:downloadIdx]; - - [strongSelf downloadImageWithURL:downloadURL - options:options - priority:PINRemoteImageManagerPriorityMedium - processorKey:nil - processor:nil - progressImage:progressImage - progressDownload:nil - completion:^(PINRemoteImageManagerResult *result) { - typeof(self) strongSelf = weakSelf; - //clean out any lower quality images from the cache - for (NSInteger idx = downloadIdx - 1; idx >= 0; idx--) { - [[strongSelf cache] removeCachedObjectForKey:[strongSelf cacheKeyForURL:[urls objectAtIndex:idx] processorKey:nil]]; - } - - if (completion) { - completion(result); - } - } - inputUUID:UUID]; - }]; - return UUID; -} - -#pragma mark - Caching - -- (BOOL)materializeAndCacheObject:(id)object - key:(NSString *)key - options:(PINRemoteImageManagerDownloadOptions)options - outImage:(PINImage **)outImage - outAltRep:(id *)outAlternateRepresentation -{ - return [self materializeAndCacheObject:object cacheInDisk:nil additionalCost:0 key:key options:options outImage:outImage outAltRep:outAlternateRepresentation]; -} - -//takes the object from the cache and returns an image or animated image. -//if it's a non-alternative representation and skipDecode is not set it also decompresses the image. -- (BOOL)materializeAndCacheObject:(id)object - cacheInDisk:(NSData *)diskData - additionalCost:(NSUInteger)additionalCost - key:(NSString *)key - options:(PINRemoteImageManagerDownloadOptions)options - outImage:(PINImage **)outImage - outAltRep:(id *)outAlternateRepresentation -{ - NSAssert(object != nil, @"Object should not be nil."); - if (object == nil) { - return NO; - } - BOOL alternateRepresentationsAllowed = (PINRemoteImageManagerDisallowAlternateRepresentations & options) == 0; - BOOL skipDecode = (options & PINRemoteImageManagerDownloadOptionsSkipDecode) != 0; - __block id alternateRepresentation = nil; - __block PINImage *image = nil; - __block NSData *data = nil; - __block BOOL updateMemoryCache = NO; - NSUInteger cacheCost = additionalCost; - - PINRemoteImageMemoryContainer *container = nil; - if ([object isKindOfClass:[PINRemoteImageMemoryContainer class]]) { - container = (PINRemoteImageMemoryContainer *)object; - [container.lock lockWithBlock:^{ - data = container.data; - }]; - } else { - updateMemoryCache = YES; - - // don't need to lock the container here because we just init it. - container = [[PINRemoteImageMemoryContainer alloc] init]; - - if ([object isKindOfClass:[PINImage class]]) { - data = diskData; - container.image = (PINImage *)object; - } else if ([object isKindOfClass:[NSData class]]) { - data = (NSData *)object; - } else { - //invalid item in cache - updateMemoryCache = NO; - data = nil; - container = nil; - } - - container.data = data; - } - - if (alternateRepresentationsAllowed) { - alternateRepresentation = [_alternateRepProvider alternateRepresentationWithData:data options:options]; - } - - if (alternateRepresentation == nil) { - //we need the image - [container.lock lockWithBlock:^{ - image = container.image; - }]; - if (image == nil) { - image = [PINImage pin_decodedImageWithData:container.data skipDecodeIfPossible:skipDecode]; - if (skipDecode == NO) { - [container.lock lockWithBlock:^{ - updateMemoryCache = YES; - container.image = image; - }]; - } - } - } - - if (updateMemoryCache) { - cacheCost += [data length]; - cacheCost += (image.size.width + image.size.height) * 4; // 4 bytes per pixel - [self.cache cacheObjectInMemory:container forKey:key withCost:cacheCost]; - } - - if (diskData) { - [self.cache cacheObjectOnDisk:diskData forKey:key]; - } - - if (outImage) { - *outImage = image; - } - - if (outAlternateRepresentation) { - *outAlternateRepresentation = alternateRepresentation; - } - - if (image == nil && alternateRepresentation == nil) { - PINLog(@"Invalid item in cache"); - [self.cache removeCachedObjectForKey:key completion:nil]; - return NO; - } - return YES; -} - -- (NSString *)cacheKeyForURL:(NSURL *)url processorKey:(NSString *)processorKey -{ - NSString *cacheKey = [url absoluteString]; - if (processorKey.length > 0) { - cacheKey = [cacheKey stringByAppendingString:[NSString stringWithFormat:@"-<%@>", processorKey]]; - } - - //PINDiskCache uses this key as the filename of the file written to disk - //Due to the current filesystem used in Darwin, this name must be limited to 255 chars. - //In case the generated key exceeds PINRemoteImageManagerCacheKeyMaxLength characters, - //we return the hash of it instead. - if (cacheKey.length > PINRemoteImageManagerCacheKeyMaxLength) { - __block CC_MD5_CTX ctx; - CC_MD5_Init(&ctx); - NSData *data = [cacheKey dataUsingEncoding:NSUTF8StringEncoding]; - [data enumerateByteRangesUsingBlock:^(const void * _Nonnull bytes, NSRange byteRange, BOOL * _Nonnull stop) { - CC_MD5_Update(&ctx, bytes, (CC_LONG)byteRange.length); - }]; - - unsigned char digest[CC_MD5_DIGEST_LENGTH]; - CC_MD5_Final(digest, &ctx); - - NSMutableString *hexString = [NSMutableString stringWithCapacity:(CC_MD5_DIGEST_LENGTH * 2)]; - for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) { - [hexString appendFormat:@"%02lx", (unsigned long)digest[i]]; - } - cacheKey = [hexString copy]; - } - - return cacheKey; -} - -- (void)objectForKey:(NSString *)key options:(PINRemoteImageManagerDownloadOptions)options completion:(void (^)(BOOL found, BOOL valid, PINImage *image, id alternativeRepresentation))completion -{ - void (^materialize)(id object) = ^(id object) { - PINImage *image = nil; - id alternativeRepresentation = nil; - BOOL valid = [self materializeAndCacheObject:object - key:key - options:options - outImage:&image - outAltRep:&alternativeRepresentation]; - - completion(YES, valid, image, alternativeRepresentation); - }; - - PINRemoteImageMemoryContainer *container = [self.cache objectFromMemoryCacheForKey:key]; - if (container) { - materialize(container); - } else { - [self.cache objectFromDiskCacheForKey:key completion:^(id _Nonnull cache, - NSString *_Nonnull key, - id _Nullable object) { - if (object) { - materialize(object); - } else { - completion(NO, NO, nil, nil); - } - }]; - } -} - -@end - -@implementation NSOperationQueue (PINRemoteImageManager) - -- (void)pin_addOperationWithQueuePriority:(PINRemoteImageManagerPriority)priority block:(void (^)(void))block -{ - NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:block]; - operation.queuePriority = operationPriorityWithImageManagerPriority(priority); - if ([PINRemoteImageManager supportsQOS] == NO) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - operation.threadPriority = 0.2; -#pragma clang diagnostic pop - } - [self addOperation:operation]; -} - -@end - -@implementation PINTaskQOS - -- (instancetype)initWithBPS:(float)bytesPerSecond endDate:(NSDate *)endDate -{ - if (self = [super init]) { - self.endDate = endDate; - self.bytesPerSecond = bytesPerSecond; - } - return self; -} - -@end diff --git a/Pod/Classes/PINRemoteImageManagerResult.h b/Pod/Classes/PINRemoteImageManagerResult.h deleted file mode 100644 index 4e71063e..00000000 --- a/Pod/Classes/PINRemoteImageManagerResult.h +++ /dev/null @@ -1,61 +0,0 @@ -// -// PINRemoteImageManagerResult.h -// Pods -// -// Created by Garrett Moon on 3/9/15. -// -// - -#import - -#if PIN_TARGET_IOS -#import -#elif PIN_TARGET_MAC -#import -#endif - -#import "PINRemoteImageMacros.h" -#if USE_FLANIMATED_IMAGE -#import -#endif - -/** How the image was fetched. */ -typedef NS_ENUM(NSUInteger, PINRemoteImageResultType) { - /** Returned if no image is returned */ - PINRemoteImageResultTypeNone = 0, - /** Image was fetched from the memory cache */ - PINRemoteImageResultTypeMemoryCache, - /** Image was fetched from the disk cache */ - PINRemoteImageResultTypeCache, - /** Image was downloaded */ - PINRemoteImageResultTypeDownload, - /** Image is progress */ - PINRemoteImageResultTypeProgress, -}; - -@interface PINRemoteImageManagerResult : NSObject - -@property (nonatomic, readonly, strong, nullable) PINImage *image; -@property (nonatomic, readonly, strong, nullable) id alternativeRepresentation; -@property (nonatomic, readonly, assign) NSTimeInterval requestDuration; -@property (nonatomic, readonly, strong, nullable) NSError *error; -@property (nonatomic, readonly, assign) PINRemoteImageResultType resultType; -@property (nonatomic, readonly, strong, nullable) NSUUID *UUID; -@property (nonatomic, readonly, assign) CGFloat renderedImageQuality; - -+ (nonnull instancetype)imageResultWithImage:(nullable PINImage *)image - alternativeRepresentation:(nullable id)alternativeRepresentation - requestLength:(NSTimeInterval)requestLength - error:(nullable NSError *)error - resultType:(PINRemoteImageResultType)resultType - UUID:(nullable NSUUID *)uuid; - -+ (nonnull instancetype)imageResultWithImage:(nullable PINImage *)image - alternativeRepresentation:(nullable id)alternativeRepresentation - requestLength:(NSTimeInterval)requestLength - error:(nullable NSError *)error - resultType:(PINRemoteImageResultType)resultType - UUID:(nullable NSUUID *)uuid - renderedImageQuality:(CGFloat)renderedImageQuality; - -@end diff --git a/Pod/Classes/PINRemoteImageManagerResult.m b/Pod/Classes/PINRemoteImageManagerResult.m deleted file mode 100644 index b8220d72..00000000 --- a/Pod/Classes/PINRemoteImageManagerResult.m +++ /dev/null @@ -1,85 +0,0 @@ -// -// PINRemoteImageManagerResult.m -// Pods -// -// Created by Garrett Moon on 3/9/15. -// -// - -#import "PINRemoteImageManagerResult.h" - -@implementation PINRemoteImageManagerResult - -+ (instancetype)imageResultWithImage:(PINImage *)image - alternativeRepresentation:(id)alternativeRepresentation - requestLength:(NSTimeInterval)requestLength - error:(NSError *)error - resultType:(PINRemoteImageResultType)resultType - UUID:(NSUUID *)uuid -{ - return [self imageResultWithImage:image - alternativeRepresentation:alternativeRepresentation - requestLength:requestLength - error:error - resultType:resultType - UUID:uuid - renderedImageQuality:1.0]; -} - -+ (instancetype)imageResultWithImage:(PINImage *)image - alternativeRepresentation:(id)alternativeRepresentation - requestLength:(NSTimeInterval)requestLength - error:(NSError *)error - resultType:(PINRemoteImageResultType)resultType - UUID:(NSUUID *)uuid - renderedImageQuality:(CGFloat)renderedImageQuality -{ - return [[self alloc] initWithImage:image - alternativeRepresentation:alternativeRepresentation - requestLength:requestLength - error:error - resultType:resultType - UUID:uuid - renderedImageQuality:renderedImageQuality]; -} - -- (instancetype)initWithImage:(PINImage *)image - alternativeRepresentation:(id)alternativeRepresentation - requestLength:(NSTimeInterval)requestLength - error:(NSError *)error - resultType:(PINRemoteImageResultType)resultType - UUID:(NSUUID *)uuid - renderedImageQuality:(CGFloat)renderedImageQuality -{ - if (self = [super init]) { - _image = image; - _alternativeRepresentation = alternativeRepresentation; - _requestDuration = requestLength; - _error = error; - _resultType = resultType; - _UUID = uuid; - _renderedImageQuality = renderedImageQuality; - } - return self; -} - -- (NSString *)description -{ - NSString *description = [super description]; - description = [description stringByAppendingString:[NSString stringWithFormat:@"image: %@", self.image]]; - description = [description stringByAppendingString:@"\n"]; - description = [description stringByAppendingString:[NSString stringWithFormat:@"alternativeRepresentation: %@", self.alternativeRepresentation]]; - description = [description stringByAppendingString:@"\n"]; - description = [description stringByAppendingString:[NSString stringWithFormat:@"requestDuration: %f", self.requestDuration]]; - description = [description stringByAppendingString:@"\n"]; - description = [description stringByAppendingString:[NSString stringWithFormat:@"error: %@", self.error]]; - description = [description stringByAppendingString:@"\n"]; - description = [description stringByAppendingString:[NSString stringWithFormat:@"resultType: %lu", (unsigned long)self.resultType]]; - description = [description stringByAppendingString:@"\n"]; - description = [description stringByAppendingString:[NSString stringWithFormat:@"UUID: %@", self.UUID]]; - description = [description stringByAppendingString:@"\n"]; - description = [description stringByAppendingString:[NSString stringWithFormat:@"UUID: %f", self.renderedImageQuality]]; - return description; -} - -@end diff --git a/Pod/Classes/PINRemoteImageMemoryContainer.h b/Pod/Classes/PINRemoteImageMemoryContainer.h deleted file mode 100644 index 2d1d62bf..00000000 --- a/Pod/Classes/PINRemoteImageMemoryContainer.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// PINRemoteImageMemoryContainer.h -// Pods -// -// Created by Garrett Moon on 3/17/16. -// -// - -#import - -#import "PINRemoteImageMacros.h" -#import "PINRemoteLock.h" - -@class PINImage; - -@interface PINRemoteImageMemoryContainer : NSObject - -@property (nonatomic, strong) PINImage *image; -@property (nonatomic, strong) NSData *data; -@property (nonatomic, strong) PINRemoteLock *lock; - -@end diff --git a/Pod/Classes/PINRemoteImageProcessorTask.m b/Pod/Classes/PINRemoteImageProcessorTask.m deleted file mode 100644 index b4c406e6..00000000 --- a/Pod/Classes/PINRemoteImageProcessorTask.m +++ /dev/null @@ -1,29 +0,0 @@ -// -// PINRemoteImageProcessorTask.m -// Pods -// -// Created by Garrett Moon on 3/9/15. -// -// - -#import "PINRemoteImageProcessorTask.h" - -@implementation PINRemoteImageProcessorTask - -- (BOOL)cancelWithUUID:(NSUUID *)UUID manager:(PINRemoteImageManager *)manager -{ - BOOL noMoreCompletions = [super cancelWithUUID:UUID manager:manager]; - if (noMoreCompletions && self.downloadTaskUUID) { - [manager cancelTaskWithUUID:self.downloadTaskUUID]; - _downloadTaskUUID = nil; - } - return noMoreCompletions; -} - -- (void)setDownloadTaskUUID:(NSUUID *)downloadTaskUUID -{ - NSAssert(_downloadTaskUUID == nil, @"downloadTaskUUID should be nil"); - _downloadTaskUUID = downloadTaskUUID; -} - -@end diff --git a/Pod/Classes/PINRemoteImageTask.h b/Pod/Classes/PINRemoteImageTask.h deleted file mode 100644 index 7346d9ab..00000000 --- a/Pod/Classes/PINRemoteImageTask.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// PINRemoteImageTask.h -// Pods -// -// Created by Garrett Moon on 3/9/15. -// -// - -#import - -#import "PINRemoteImageManager.h" -#import "PINRemoteImageMacros.h" - -@interface PINRemoteImageTask : NSObject - -@property (nonatomic, strong, nonnull) NSMutableDictionary *callbackBlocks; -#if PINRemoteImageLogging -@property (nonatomic, copy, nullable) NSString *key; -#endif - -- (void)addCallbacksWithCompletionBlock:(nonnull PINRemoteImageManagerImageCompletion)completionBlock - progressImageBlock:(nullable PINRemoteImageManagerImageCompletion)progressImageBlock - progressDownloadBlock:(nullable PINRemoteImageManagerProgressDownload)progressDownloadBlock - withUUID:(nonnull NSUUID *)UUID; - -- (void)removeCallbackWithUUID:(nonnull NSUUID *)UUID; - -- (void)callCompletionsWithQueue:(nonnull dispatch_queue_t)queue - remove:(BOOL)remove - withImage:(nullable PINImage *)image - alternativeRepresentation:(nullable id)alternativeRepresentation - cached:(BOOL)cached - error:(nullable NSError *)error; - -//returns YES if no more attached completionBlocks -- (BOOL)cancelWithUUID:(nonnull NSUUID *)UUID manager:(nullable PINRemoteImageManager *)manager; - -- (void)setPriority:(PINRemoteImageManagerPriority)priority; - -@end diff --git a/Pod/Classes/PINRemoteImageTask.m b/Pod/Classes/PINRemoteImageTask.m deleted file mode 100644 index 24986241..00000000 --- a/Pod/Classes/PINRemoteImageTask.m +++ /dev/null @@ -1,100 +0,0 @@ -// -// PINRemoteImageTask.m -// Pods -// -// Created by Garrett Moon on 3/9/15. -// -// - -#import "PINRemoteImageTask.h" - -#import "PINRemoteImageCallbacks.h" - -@implementation PINRemoteImageTask - -- (instancetype)init -{ - if (self = [super init]) { - self.callbackBlocks = [[NSMutableDictionary alloc] init]; - } - return self; -} - -- (NSString *)description -{ - return [NSString stringWithFormat:@"<%@: %p> completionBlocks: %lu", NSStringFromClass([self class]), self, (unsigned long)self.callbackBlocks.count]; -} - -- (void)addCallbacksWithCompletionBlock:(PINRemoteImageManagerImageCompletion)completionBlock - progressImageBlock:(PINRemoteImageManagerImageCompletion)progressImageBlock - progressDownloadBlock:(PINRemoteImageManagerProgressDownload)progressDownloadBlock - withUUID:(NSUUID *)UUID -{ - PINRemoteImageCallbacks *completion = [[PINRemoteImageCallbacks alloc] init]; - completion.completionBlock = completionBlock; - completion.progressImageBlock = progressImageBlock; - completion.progressDownloadBlock = progressDownloadBlock; - - [self.callbackBlocks setObject:completion forKey:UUID]; -} - -- (void)removeCallbackWithUUID:(NSUUID *)UUID -{ - [self.callbackBlocks removeObjectForKey:UUID]; -} - -- (void)callCompletionsWithQueue:(dispatch_queue_t)queue - remove:(BOOL)remove - withImage:(PINImage *)image - alternativeRepresentation:(id)alternativeRepresentation - cached:(BOOL)cached - error:(NSError *)error -{ - __weak typeof(self) weakSelf = self; - [self.callbackBlocks enumerateKeysAndObjectsUsingBlock:^(NSUUID *UUID, PINRemoteImageCallbacks *callback, BOOL *stop) { - typeof(self) strongSelf = weakSelf; - if (callback.completionBlock != nil) { - PINLog(@"calling completion for UUID: %@ key: %@", UUID, strongSelf.key); - PINRemoteImageManagerImageCompletion completionBlock = callback.completionBlock; - CFTimeInterval requestTime = callback.requestTime; - - //The code run asynchronously below is *not* guaranteed to be run in the manager's lock! - //All access to the callbacks and self should be done outside the block below! - dispatch_async(queue, ^ - { - PINRemoteImageResultType result; - if (image || alternativeRepresentation) { - result = cached ? PINRemoteImageResultTypeCache : PINRemoteImageResultTypeDownload; - } else { - result = PINRemoteImageResultTypeNone; - } - completionBlock([PINRemoteImageManagerResult imageResultWithImage:image - alternativeRepresentation:alternativeRepresentation - requestLength:CACurrentMediaTime() - requestTime - error:error - resultType:result - UUID:UUID]); - }); - } - if (remove) { - [strongSelf removeCallbackWithUUID:UUID]; - } - }]; -} - -- (BOOL)cancelWithUUID:(NSUUID *)UUID manager:(PINRemoteImageManager *)manager -{ - BOOL noMoreCompletions = NO; - [self removeCallbackWithUUID:UUID]; - if ([self.callbackBlocks count] == 0) { - noMoreCompletions = YES; - } - return noMoreCompletions; -} - -- (void)setPriority:(PINRemoteImageManagerPriority)priority -{ - -} - -@end diff --git a/Pod/Classes/PINURLSessionManager.h b/Pod/Classes/PINURLSessionManager.h deleted file mode 100644 index 9c353ddf..00000000 --- a/Pod/Classes/PINURLSessionManager.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// PINURLSessionManager.h -// Pods -// -// Created by Garrett Moon on 6/26/15. -// -// - -#import - -extern NSString * __nonnull const PINURLErrorDomain; - -@protocol PINURLSessionManagerDelegate - -@required -- (void)didReceiveData:(nonnull NSData *)data forTask:(nonnull NSURLSessionTask *)task; -- (void)didCompleteTask:(nonnull NSURLSessionTask *)task withError:(nullable NSError *)error; - -@optional -- (void)didReceiveAuthenticationChallenge:(nonnull NSURLAuthenticationChallenge *)challenge forTask:(nullable NSURLSessionTask *)task completionHandler:(nonnull void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler; - - -@end - -@interface PINURLSessionManager : NSObject - -- (nonnull instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)configuration; - -- (nonnull NSURLSessionDataTask *)dataTaskWithRequest:(nonnull NSURLRequest *)request completionHandler:(nullable void (^)(NSURLResponse * _Nonnull response, NSError * _Nullable error))completionHandler; - -- (void)invalidateSessionAndCancelTasks; - -@property (atomic, weak, nullable) id delegate; - -@end diff --git a/Pod/Classes/PINURLSessionManager.m b/Pod/Classes/PINURLSessionManager.m deleted file mode 100644 index f9890cd5..00000000 --- a/Pod/Classes/PINURLSessionManager.m +++ /dev/null @@ -1,151 +0,0 @@ -// -// PINURLSessionManager.m -// Pods -// -// Created by Garrett Moon on 6/26/15. -// -// - -#import "PINURLSessionManager.h" - -NSString * const PINURLErrorDomain = @"PINURLErrorDomain"; - -@interface PINURLSessionManager () - -@property (nonatomic, strong) NSLock *sessionManagerLock; -@property (nonatomic, strong) NSURLSession *session; -@property (nonatomic, strong) NSOperationQueue *operationQueue; -@property (nonatomic, strong) NSMutableDictionary *delegateQueues; -@property (nonatomic, strong) NSMutableDictionary *completions; - -@end - -@implementation PINURLSessionManager - -- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration -{ - if (self = [super init]) { - self.sessionManagerLock = [[NSLock alloc] init]; - self.sessionManagerLock.name = @"PINURLSessionManager"; - self.operationQueue = [[NSOperationQueue alloc] init]; - self.operationQueue.name = @"PINURLSessionManager Operation Queue"; - - //queue must be serial to ensure proper ordering - [self.operationQueue setMaxConcurrentOperationCount:1]; - self.session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:self.operationQueue]; - self.completions = [[NSMutableDictionary alloc] init]; - self.delegateQueues = [[NSMutableDictionary alloc] init]; - } - return self; -} - -- (void)invalidateSessionAndCancelTasks -{ - [self lock]; - [self.session invalidateAndCancel]; - [self unlock]; -} - -- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLResponse *response, NSError *error))completionHandler -{ - [self lock]; - NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:request]; - if (completionHandler) { - [self.completions setObject:completionHandler forKey:@(dataTask.taskIdentifier)]; - } - NSString *queueName = [NSString stringWithFormat:@"PINURLSessionManager delegate queue - %ld", (unsigned long)dataTask.taskIdentifier]; - dispatch_queue_t delegateQueue = dispatch_queue_create([queueName UTF8String], DISPATCH_QUEUE_SERIAL); - [self.delegateQueues setObject:delegateQueue forKey:@(dataTask.taskIdentifier)]; - [self unlock]; - return dataTask; -} - -- (void)lock -{ - [self.sessionManagerLock lock]; -} - -- (void)unlock -{ - [self.sessionManagerLock unlock]; -} - -#pragma mark NSURLSessionDataDelegate - -- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler -{ - if ([self.delegate respondsToSelector:@selector(didReceiveAuthenticationChallenge:forTask:completionHandler:)]) { - [self.delegate didReceiveAuthenticationChallenge:challenge forTask:nil completionHandler:completionHandler]; - } else { - //Even though this is documented to be non-nil, in the wild it sometimes is - if (completionHandler) { - completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); - } - - } -} - -- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler -{ - [self lock]; - dispatch_queue_t delegateQueue = self.delegateQueues[@(task.taskIdentifier)]; - [self unlock]; - - __weak typeof(self) weakSelf = self; - dispatch_async(delegateQueue, ^{ - typeof(self) strongSelf = weakSelf; - if ([strongSelf.delegate respondsToSelector:@selector(didReceiveAuthenticationChallenge:forTask:completionHandler:)]) { - [strongSelf.delegate didReceiveAuthenticationChallenge:challenge forTask:task completionHandler:completionHandler]; - } else { - //Even though this is documented to be non-nil, in the wild it sometimes is - if (completionHandler) { - completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); - } - } - }); -} - -- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data -{ - [self lock]; - dispatch_queue_t delegateQueue = self.delegateQueues[@(dataTask.taskIdentifier)]; - [self unlock]; - - __weak typeof(self) weakSelf = self; - dispatch_async(delegateQueue, ^{ - typeof(self) strongSelf = weakSelf; - [strongSelf.delegate didReceiveData:data forTask:dataTask]; - }); -} - -- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error -{ - [self lock]; - dispatch_queue_t delegateQueue = self.delegateQueues[@(task.taskIdentifier)]; - [self unlock]; - if (!error && [task.response isKindOfClass:[NSHTTPURLResponse class]]) { - NSInteger statusCode = [(NSHTTPURLResponse *)task.response statusCode]; - if (statusCode >= 400) { - error = [NSError errorWithDomain:PINURLErrorDomain - code:statusCode - userInfo:@{NSLocalizedDescriptionKey : @"HTTP Error Response."}]; - } - } - __weak typeof(self) weakSelf = self; - dispatch_async(delegateQueue, ^{ - typeof(self) strongSelf = weakSelf; - [strongSelf.delegate didCompleteTask:task withError:error]; - - [strongSelf lock]; - void (^completionHandler)(NSURLResponse *, NSError *) = strongSelf.completions[@(task.taskIdentifier)]; - [strongSelf.completions removeObjectForKey:@(task.taskIdentifier)]; - [strongSelf.delegateQueues removeObjectForKey:@(task.taskIdentifier)]; - [strongSelf unlock]; - - if (completionHandler) { - completionHandler(task.response, error); - } - }); -} - -@end diff --git a/README.md b/README.md index 2b63ef43..c497cc01 100644 --- a/README.md +++ b/README.md @@ -4,63 +4,93 @@ [![CocoaPods compatible](https://img.shields.io/cocoapods/v/PINRemoteImage.svg?style=flat)](https://cocoapods.org/pods/PINRemoteImage) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) -[![Tavis CI build](https://img.shields.io/travis/pinterest/PINRemoteImage.svg?style=flat)](https://travis-ci.org/pinterest/PINRemoteImage) +[![Build status](https://github.com/pinterest/PINRemoteImage/workflows/CI/badge.svg)](https://github.com/pinterest/PINRemoteImage/actions?query=workflow%3ACI+branch%3Amaster) -[PINRemoteImageManager](Pod/Classes/PINRemoteImageManager.h) is an image downloading, processing and caching manager. It uses the concept of download and processing tasks to ensure that even if multiple calls to download or process an image are made, it only occurs one time (unless an item is no longer in the cache). PINRemoteImageManager is backed by GCD and safe to access from multiple threads simultaneously. It ensures that images are decoded off the main thread so that animation performance isn't affected. None of its exposed methods allow for synchronous access. However, it is optimized to call completions on the calling thread if an item is in its memory cache. +[PINRemoteImageManager](Source/Classes/PINRemoteImageManager.h) is an image downloading, processing and caching manager. It uses the concept of download and processing tasks to ensure that even if multiple calls to download or process an image are made, it only occurs one time (unless an item is no longer in the cache). PINRemoteImageManager is backed by **GCD** and safe to **access** from **multiple threads** simultaneously. It ensures that images are decoded off the main thread so that animation performance isn't affected. None of its exposed methods allow for synchronous access. However, it is optimized to call completions on the calling thread if an item is in its memory cache. -PINRemoteImage supports downloading many types of files. It, of course, supports both PNGs and JPGs. It also supports decoding WebP images if Google's library is available. It even supports returning [FLAnimatedImages](https://github.com/Flipboard/FLAnimatedImage) if it's compiled in (though this can be disabled). +PINRemoteImage supports downloading many types of files. It, of course, **supports** both **PNGs** and **JPGs**. It also supports decoding **WebP** images if Google's library is available. It even supports **GIFs** and **Animated WebP** via PINAnimatedImageView. -PINRemoteImage also has two methods to improve the experience of downloading images on slow network connections. The first is support for progressive JPGs. This isn't any old support for progressive JPGs though: PINRemoteImage adds an attractive blur to progressive scans before returning them. +PINRemoteImage also has two methods to improve the experience of downloading images on slow network connections. The first is support for **progressive JPGs**. This isn't any old support for progressive JPGs though: PINRemoteImage adds an attractive blur to progressive scans before returning them. ![Progressive JPG with Blur](/progressive.gif "Looks better on device.") -[PINRemoteImageCategoryManager](Pod/Classes/PINRemoteImageCategoryManager.h) defines a protocol which UIView subclasses can implement and provide easy access to -PINRemoteImageManager's methods. There are built-in categories on UIImageView, FLAnimatedImageView and UIButton, and it's very easy to implement a new category. See [PINImageView+PINRemoteImage](/Pod/Classes/Image Categories/PINImageView+PINRemoteImage.h) of the existing categories for reference. +[PINRemoteImageCategoryManager](Pod/Classes/PINRemoteImageCategoryManager.h) defines a protocol which UIView subclasses can implement and provide easy access to +PINRemoteImageManager's methods. There are **built-in categories** on **UIImageView**, **PINAnimatedImageView** and **UIButton**, and it's very easy to implement a new category. See [UIImageView+PINRemoteImage](/Pod/Classes/Image Categories/UIImageView+PINRemoteImage.h) of the existing categories for reference. -Download an image and set it on an image view: +### Download an image and set it on an image view: +**Objective-C** ```objc UIImageView *imageView = [[UIImageView alloc] init]; [imageView pin_setImageFromURL:[NSURL URLWithString:@"http://pinterest.com/kitten.jpg"]]; ``` - -Download a progressive jpeg and get attractive blurred updates: +**Swift** +```swift +let imageView = UIImageView() +imageView.pin_setImage(from: URL(string: "https://pinterest.com/kitten.jpg")!) +``` + +### Download a progressive jpeg and get attractive blurred updates: + +**Objective-C** ```objc UIImageView *imageView = [[UIImageView alloc] init]; [imageView setPin_updateWithProgress:YES]; [imageView pin_setImageFromURL:[NSURL URLWithString:@"http://pinterest.com/progressiveKitten.jpg"]]; ``` -Download a WebP file +**Swift** +```swift +let imageView = UIImageView() +imageView.pin_updateWithProgress = true +imageView.pin_setImage(from: URL(string: "https://pinterest.com/progressiveKitten.jpg")!) +``` + +### Download a WebP file +**Objective-C** ```objc UIImageView *imageView = [[UIImageView alloc] init]; [imageView pin_setImageFromURL:[NSURL URLWithString:@"http://pinterest.com/googleKitten.webp"]]; ``` -Download a GIF and display with FLAnimatedImageView +**Swift** +```swift +let imageView = UIImageView() +imageView.pin_setImage(from: URL(string: "https://pinterest.com/googleKitten.webp")!) +``` + +### Download a GIF and display with PINAnimatedImageView +**Objective-C** ```objc -FLAnimatedImageView *animatedImageView = [[FLAnimatedImageView alloc] init]; +PINAnimatedImageView *animatedImageView = [[PINAnimatedImageView alloc] init]; [animatedImageView pin_setImageFromURL:[NSURL URLWithString:@"http://pinterest.com/flyingKitten.gif"]]; ``` -Download and process an image +**Swift** +```swift +let animatedImageView = PINAnimatedImageView() +animatedImageView.pin_setImage(from: URL(string: "http://pinterest.com/flyingKitten.gif")!) +``` +### Download and process an image + +**Objective-C** ```objc UIImageView *imageView = [[UIImageView alloc] init]; -[self.imageView pin_setImageFromURL:[NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/736x/5b/c6/c5/5bc6c5387ff6f104fd642f2b375efba3.jpg"] processorKey:@"rounded" processor:^UIImage *(PINRemoteImageManagerResult *result, NSUInteger *cost) +[self.imageView pin_setImageFromURL:[NSURL URLWithString:@"https://i.pinimg.com/736x/5b/c6/c5/5bc6c5387ff6f104fd642f2b375efba3.jpg"] processorKey:@"rounded" processor:^UIImage *(PINRemoteImageManagerResult *result, NSUInteger *cost) { CGSize targetSize = CGSizeMake(200, 300); CGRect imageRect = CGRectMake(0, 0, targetSize.width, targetSize.height); UIGraphicsBeginImageContext(imageRect.size); UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:imageRect cornerRadius:7.0]; [bezierPath addClip]; - + CGFloat sizeMultiplier = MAX(targetSize.width / result.image.size.width, targetSize.height / result.image.size.height); - + CGRect drawRect = CGRectMake(0, 0, result.image.size.width * sizeMultiplier, result.image.size.height * sizeMultiplier); if (CGRectGetMaxX(drawRect) > CGRectGetMaxX(imageRect)) { drawRect.origin.x -= (CGRectGetMaxX(drawRect) - CGRectGetMaxX(imageRect)) / 2.0; @@ -68,21 +98,113 @@ UIImageView *imageView = [[UIImageView alloc] init]; if (CGRectGetMaxY(drawRect) > CGRectGetMaxY(imageRect)) { drawRect.origin.y -= (CGRectGetMaxY(drawRect) - CGRectGetMaxY(imageRect)) / 2.0; } - + [result.image drawInRect:drawRect]; - + UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return processedImage; }]; ``` -Handle Authentication +**Swift** +```swift +let imageView = FLAnimatedImageView() +imageView.pin_setImage(from: URL(string: "https://i.pinimg.com/736x/5b/c6/c5/5bc6c5387ff6f104fd642f2b375efba3.jpg")!, processorKey: "rounded") { (result, unsafePointer) -> UIImage? in + + guard let image = result.image else { return nil } + + let radius : CGFloat = 7.0 + let targetSize = CGSize(width: 200, height: 300) + let imageRect = CGRect(x: 0, y: 0, width: targetSize.width, height: targetSize.height) + + UIGraphicsBeginImageContext(imageRect.size) + + let bezierPath = UIBezierPath(roundedRect: imageRect, cornerRadius: radius) + bezierPath.addClip() + + let widthMultiplier : CGFloat = targetSize.width / image.size.width + let heightMultiplier : CGFloat = targetSize.height / image.size.height + let sizeMultiplier = max(widthMultiplier, heightMultiplier) + + var drawRect = CGRect(x: 0, y: 0, width: image.size.width * sizeMultiplier, height: image.size.height * sizeMultiplier) + if (drawRect.maxX > imageRect.maxX) { + drawRect.origin.x -= (drawRect.maxX - imageRect.maxX) / 2 + } + if (drawRect.maxY > imageRect.maxY) { + drawRect.origin.y -= (drawRect.maxY - imageRect.maxY) / 2 + } + + image.draw(in: drawRect) + + UIColor.red.setStroke() + bezierPath.lineWidth = 5.0 + bezierPath.stroke() + + let ctx = UIGraphicsGetCurrentContext() + ctx?.setBlendMode(CGBlendMode.overlay) + ctx?.setAlpha(0.5) + + let logo = UIImage(named: "white-pinterest-logo") + ctx?.scaleBy(x: 1.0, y: -1.0) + ctx?.translateBy(x: 0.0, y: -drawRect.size.height) + + if let coreGraphicsImage = logo?.cgImage { + ctx?.draw(coreGraphicsImage, in: CGRect(x: 90, y: 10, width: logo!.size.width, height: logo!.size.height)) + } + + let processedImage = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + + return processedImage + +} +``` + +### Handle Authentication + +**Objective-C** ```objc [[PINRemoteImageManager sharedImageManager] setAuthenticationChallenge:^(NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, PINRemoteImageManagerAuthenticationChallengeCompletionHandler aCompletion) { aCompletion(NSURLSessionAuthChallengePerformDefaultHandling, nil)]; ``` +**Swift** +```swift +PINRemoteImageManager.shared().setAuthenticationChallenge { (task, challenge, completion) in + completion?(.performDefaultHandling, nil) +} +``` + +### Support for high resolution images +Currently there are two ways PINRemoteImage is supporting high resolution images: +1. If the URL contains an `_2x.` or an `_3x.` postfix it will be automatically handled by PINRemoteImage and the resulting image will be returned at the right scale. +2. If it's not possible to provide an URL with an `_2x.` or `_3x.` postfix, you can also handle it with a completion handler: +```objc +NSURL *url = ...; +__weak UIImageView *weakImageView = self.imageView; +[self.imageView pin_setImageFromURL:url completion:^(PINRemoteImageManagerResult * _Nonnull result) { + CGFloat scale = UIScreen.mainScreen.scale; + if (scale > 1.0) { + UIImage *image = result.image; + weakImageView.image = [UIImage imageWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation]; + } +}]; +``` + +### Set some limits +``` +// cache is an instance of PINCache as long as you haven't overridden defaultImageCache +PINCache *cache = (PINCache *)[[PINRemoteImageManager sharedImageManager] cache]; +// Max memory cost is based on number of pixels, we estimate the size of one hundred 600x600 images as our max memory image cache. +[[cache memoryCache] setCostLimit:600 * [[UIScreen mainScreen] scale] * 600 * [[UIScreen mainScreen] scale] * 100]; + +// ~50 MB +[[cache diskCache] setByteLimit:50 * 1024 * 1024]; +// 30 days +[[cache diskCache] setAgeLimit:60 * 60 * 24 * 30]; +``` + ## Installation ### CocoaPods @@ -113,7 +235,7 @@ You can set up PINRemoteImage as a submodule of your repo instead of cloning and ## Requirements -__PINRemoteImage__ requires iOS 7.0 or greater. +__PINRemoteImage__ requires iOS 12.0 or greater. ## Contact diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 00000000..94fa7d3b --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,7 @@ +# Release Process +This document describes the process for a public PINRemoteImage release. + +### Process +- Ensure the latest master build is green. +- Run the github action 'Create Release'. +- Check that the release was successfully published to [Github](https://github.com/pinterest/PINRemoteImage/releases) and [Cocoapods](https://cocoapods.org/pods/PINRemoteImage). diff --git a/Scripts/release.sh b/Scripts/release.sh new file mode 100755 index 00000000..bd685725 --- /dev/null +++ b/Scripts/release.sh @@ -0,0 +1,98 @@ +#!/bin/bash +set -e + +if [ -z "$OSS_PROJECT" ]; then + echo "Must set \$OSS_PROJECT envirnonment variable before running." +fi + +PROJECT="$OSS_PROJECT" + +if ! git diff-index --quiet HEAD --; then + echo "Please commit or stash any changes before running." + exit 1 +fi + +if [ -z "$GITHUB_CHANGELOG_API_KEY" ]; then + echo "Must set \$GITHUB_CHANGELOG_API_KEY environment variable" + exit 1 +fi + +case $1 in + "--major") + UPDATE_TYPE="major" + ;; + + "--minor") + UPDATE_TYPE="minor" + ;; + + "--patch") + UPDATE_TYPE="patch" + ;; + + *) + echo "Usage release.sh --patch / --minor / --major" + exit 1 + ;; +esac + +PODSPEC="$PROJECT.podspec" +CURRENT_VERSION=$(grep "version" -m 1 $PODSPEC | sed -E "s/^.*version[ \t]*=[ \t]*['\"]([0-9\.]+)['\"]/\1/") +DOT_COUNT=$(echo "$CURRENT_VERSION" | grep -o '\.' | wc -l) + +if [ "$DOT_COUNT" -eq "0" ]; then + major=$CURRENT_VERSION + minor="0" + patch="0" +elif [ "$DOT_COUNT" -eq "1" ]; then + major=$(echo "$CURRENT_VERSION" | sed -E "s/([0-9])+\.([0-9]+)/\1/") + minor=$(echo "$CURRENT_VERSION" | sed -E "s/([0-9])+\.([0-9]+)/\2/") + patch="0" +elif [ "$DOT_COUNT" -eq "2" ]; then + major=$(echo "$CURRENT_VERSION" | sed -E "s/([0-9])+\.([0-9]+)\.([0-9]+)/\1/") + minor=$(echo "$CURRENT_VERSION" | sed -E "s/([0-9])+\.([0-9]+)\.([0-9]+)/\2/") + patch=$(echo "$CURRENT_VERSION" | sed -E "s/([0-9])+\.([0-9]+)\.([0-9]+)/\3/") +fi + +echo "Current version: $major.$minor.$patch" + +if [ "$UPDATE_TYPE" == "major" ]; then + major=$((major + 1)) + minor=0 + patch=0 +elif [ "$UPDATE_TYPE" == "minor" ]; then + minor=$((minor + 1)) + patch=0 +elif [ "$UPDATE_TYPE" == "patch" ]; then + patch=$((patch + 1)) +fi + +NEW_VERSION="$major.$minor.$patch" +echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV +echo "New version: $NEW_VERSION" + +echo "Updating $PODSPEC" +sed -E "s/^(.*version[ \t]*=[ \t]*)['|\"]$CURRENT_VERSION['|\"]/\1'$NEW_VERSION'/" $PODSPEC > new.podspec +mv new.podspec $PODSPEC + +echo "Updating .github_changelog_generator" +cat << EOF > .github_changelog_generator +issues=false +since-tag=$CURRENT_VERSION +future-release=$NEW_VERSION +EOF + +github_changelog_generator --token $GITHUB_CHANGELOG_API_KEY --user Pinterest --project $PROJECT --output NEW_CHANGES.md + +# Delete # Changelog at the top of the old CHANGELOG +grep -v "# Changelog" CHANGELOG.md > CHANGELOG.tmp && mv CHANGELOG.tmp CHANGELOG.md + +# Delete the last line and first line then use a magic sed command the internet told me +# about to delete trailing newlines (except the last one) +# Then prepend to existing changelog +grep -v "\*" NEW_CHANGES.md | sed -e :a -e '/^\n*$/{$d;N;};/\n$/ba' | cat - CHANGELOG.md > CHANGELOG.tmp +mv CHANGELOG.tmp CHANGELOG.md +rm NEW_CHANGES.md + +git add .github_changelog_generator CHANGELOG.md $PODSPEC +git commit --message "[AUTO] Update CHANGELOG.md and bump for $UPDATE_TYPE update." diff --git a/Scripts/tag-release-branch.sh b/Scripts/tag-release-branch.sh new file mode 100755 index 00000000..a66af230 --- /dev/null +++ b/Scripts/tag-release-branch.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -ex + +echo "Tagging release branch" +TAG=$NEW_VERSION + +echo "RELEASE_TAG=$TAG" >> $GITHUB_ENV +git tag $TAG +git push origin --tags + +echo "Setting Release Notes" +cat CHANGELOG.md | awk '/^#/{f=1} f; /^#/ && ++c==3{exit}' | sed '$ d' > RELEASE_NOTES.md diff --git a/Pod/Classes/.gitkeep b/Source/Classes/.gitkeep similarity index 100% rename from Pod/Classes/.gitkeep rename to Source/Classes/.gitkeep diff --git a/Source/Classes/AnimatedImages/PINAPNGAnimatedImage.m b/Source/Classes/AnimatedImages/PINAPNGAnimatedImage.m new file mode 100644 index 00000000..0d39d833 --- /dev/null +++ b/Source/Classes/AnimatedImages/PINAPNGAnimatedImage.m @@ -0,0 +1,170 @@ +// +// PINAPNGAnimatedImage.m +// PINRemoteImage +// +// Created by SAGESSE on 2020/2/28. +// Copyright © 2020 Pinterest. All rights reserved. +// + +#import + +#if PIN_APNG + +#import +#if PIN_TARGET_IOS +#import +#elif PIN_TARGET_MAC +#import +#endif + +#import +#import + +@interface PINAPNGAnimatedImage () +{ + NSData *_animatedImageData; + CGImageSourceRef _imageSource; + uint32_t _width; + uint32_t _height; + BOOL _hasAlpha; + size_t _frameCount; + size_t _loopCount; + CFTimeInterval *_durations; + NSError *_error; +} +@end + +@implementation PINAPNGAnimatedImage + +- (instancetype)initWithAnimatedImageData:(NSData *)animatedImageData +{ + if (self = [super init]) { + _animatedImageData = animatedImageData; + _imageSource = + CGImageSourceCreateWithData((CFDataRef)animatedImageData, + (CFDictionaryRef)@{(__bridge NSString *)kCGImageSourceTypeIdentifierHint: + (__bridge NSString *)kUTTypePNG, + (__bridge NSString *)kCGImageSourceShouldCache: + (__bridge NSNumber *)kCFBooleanFalse}); + if (_imageSource && [animatedImageData pin_isAPNG]) { + _frameCount = (uint32_t)CGImageSourceGetCount(_imageSource); + NSDictionary *imageProperties = (__bridge_transfer NSDictionary *)CGImageSourceCopyProperties(_imageSource, nil); + _loopCount = (uint32_t)[[[imageProperties objectForKey:(__bridge NSString *)kCGImagePropertyPNGDictionary] + objectForKey:(__bridge NSString *)kCGImagePropertyAPNGLoopCount] unsignedLongValue]; + _durations = malloc(sizeof(CFTimeInterval) * _frameCount); + imageProperties = (__bridge_transfer NSDictionary *) + CGImageSourceCopyPropertiesAtIndex(_imageSource, + 0, + (CFDictionaryRef)@{(__bridge NSString *)kCGImageSourceShouldCache: + (__bridge NSNumber *)kCFBooleanFalse}); + _width = (uint32_t)[(NSNumber *)imageProperties[(__bridge NSString *)kCGImagePropertyPixelWidth] unsignedIntegerValue]; + _height = (uint32_t)[(NSNumber *)imageProperties[(__bridge NSString *)kCGImagePropertyPixelHeight] unsignedIntegerValue]; + + for (NSUInteger frameIdx = 0; frameIdx < _frameCount; frameIdx++) { + _durations[frameIdx] = [PINAPNGAnimatedImage frameDurationAtIndex:frameIdx source:_imageSource]; + } + } else { + return nil; + } + } + return self; +} + ++ (Float32)frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source +{ + Float32 frameDuration = kPINAnimatedImageDefaultDuration; + NSDictionary *frameProperties = (__bridge_transfer NSDictionary *)CGImageSourceCopyPropertiesAtIndex(source, index, nil); + // use unclamped delay time before delay time before default + NSNumber *unclamedDelayTime = frameProperties[(__bridge NSString *)kCGImagePropertyPNGDictionary][(__bridge NSString *)kCGImagePropertyAPNGUnclampedDelayTime]; + if (unclamedDelayTime != nil) { + frameDuration = [unclamedDelayTime floatValue]; + } else { + NSNumber *delayTime = frameProperties[(__bridge NSString *)kCGImagePropertyPNGDictionary][(__bridge NSString *)kCGImagePropertyAPNGDelayTime]; + if (delayTime != nil) { + frameDuration = [delayTime floatValue]; + } + } + + static dispatch_once_t onceToken; + static Float32 maximumFrameDuration; + dispatch_once(&onceToken, ^{ + maximumFrameDuration = 1.0 / [PINAnimatedImage maximumFramesPerSecond]; + }); + + if (frameDuration < maximumFrameDuration) { + frameDuration = kPINAnimatedImageDefaultDuration; + } + + return frameDuration; +} + +- (void)dealloc +{ + if (_imageSource) { + CFRelease(_imageSource); + } + if (_durations) { + free(_durations); + } +} + +- (NSData *)data +{ + return _animatedImageData; +} + +- (size_t)frameCount +{ + return _frameCount; +} + +- (size_t)loopCount +{ + return _loopCount; +} + +- (uint32_t)width +{ + return _width; +} + +- (uint32_t)height +{ + return _height; +} + +- (uint32_t)bytesPerFrame +{ + return _width * _height * 4; +} + +- (NSError *)error +{ + return _error; +} + +- (CFTimeInterval)durationAtIndex:(NSUInteger)index +{ + return _durations[index]; +} + +- (CGImageRef)imageAtIndex:(NSUInteger)index cacheProvider:(nullable id)cacheProvider +{ + // I believe this is threadsafe as CGImageSource *seems* immutable… + CGImageRef imageRef = + CGImageSourceCreateImageAtIndex(_imageSource, + index, + (CFDictionaryRef)@{(__bridge NSString *)kCGImageSourceShouldCache: + (__bridge NSNumber *)kCFBooleanFalse}); + if (imageRef) { + CGImageRef decodedImageRef = [PINImage pin_decodedImageRefWithCGImageRef:imageRef]; + CGImageRelease(imageRef); + imageRef = decodedImageRef; + } + + return imageRef; +} + +@end + +#endif diff --git a/Source/Classes/AnimatedImages/PINAnimatedImage.m b/Source/Classes/AnimatedImages/PINAnimatedImage.m new file mode 100644 index 00000000..e9ed7717 --- /dev/null +++ b/Source/Classes/AnimatedImages/PINAnimatedImage.m @@ -0,0 +1,124 @@ +// +// PINAnimatedImage.m +// PINRemoteImage +// +// Created by Garrett Moon on 9/17/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import + +NSErrorDomain const kPINAnimatedImageErrorDomain = @"kPINAnimatedImageErrorDomain"; + +//http://nullsleep.tumblr.com/post/16524517190/animated-gif-minimum-frame-delay-browser +const Float32 kPINAnimatedImageDefaultDuration = 0.1; + +@interface PINAnimatedImage () +{ + CFTimeInterval _totalDuration; +} +@end + +@implementation PINAnimatedImage + ++ (NSInteger)maximumFramesPerSecond +{ + static dispatch_once_t onceToken; + static NSInteger maximumFramesPerSecond = 60; + + dispatch_once(&onceToken, ^{ +#if PIN_TARGET_IOS + maximumFramesPerSecond = 0; + for (UIScreen *screen in [UIScreen screens]) { + if ([screen maximumFramesPerSecond] > maximumFramesPerSecond) { + maximumFramesPerSecond = [screen maximumFramesPerSecond]; + } + } +#endif + }); + return maximumFramesPerSecond; +} + +- (instancetype)init +{ + if (self = [super init]) { + _totalDuration = -1; + } + return self; +} + +- (CFTimeInterval)durationAtIndex:(NSUInteger)index +{ + NSAssert(NO, @"Must be overridden by subclass"); + return 0; +} + +- (size_t)frameCount +{ + NSAssert(NO, @"Must be overridden by subclass"); + return 0; +} + + +- (CFTimeInterval)totalDuration +{ + if (_totalDuration == -1) { + _totalDuration = 0; + for (NSUInteger idx = 0; idx < self.frameCount; idx++) { + _totalDuration += [self durationAtIndex:idx]; + } + } + + return _totalDuration; +} + +- (NSUInteger)frameInterval +{ + return MAX(self.minimumFrameInterval * [PINAnimatedImage maximumFramesPerSecond], 1); +} + +//Credit to FLAnimatedImage ( https://github.com/Flipboard/FLAnimatedImage ) for display link interval calculations +- (NSTimeInterval)minimumFrameInterval +{ + static dispatch_once_t onceToken; + static NSTimeInterval kGreatestCommonDivisorPrecision; + dispatch_once(&onceToken, ^{ + kGreatestCommonDivisorPrecision = 2.0 / (1.0 / [PINAnimatedImage maximumFramesPerSecond]); + }); + + // Scales the frame delays by `kGreatestCommonDivisorPrecision` + // then converts it to an UInteger for in order to calculate the GCD. + NSUInteger scaledGCD = lrint([self durationAtIndex:0] * kGreatestCommonDivisorPrecision); + for (NSUInteger durationIdx = 1; durationIdx < self.frameCount; durationIdx++) { + CFTimeInterval duration = [self durationAtIndex:durationIdx]; + scaledGCD = gcd(lrint(duration * kGreatestCommonDivisorPrecision), scaledGCD); + } + + // Reverse to scale to get the value back into seconds. + return (scaledGCD / kGreatestCommonDivisorPrecision); +} + +// This likely isn't the most efficient but it's easy to reason about and we don't call it +// with super large numbers. +static NSUInteger gcd(NSUInteger a, NSUInteger b) +{ + // http://en.wikipedia.org/wiki/Greatest_common_divisor + NSCAssert(a > 0 && b > 0, @"A and B must be greater than 0"); + + while (a != b) { + if (a > b) { + a = a - b; + } else { + b = b - a; + } + } + return a; +} + +// Used only in testing ++ (NSUInteger)greatestCommonDivisorOfA:(NSUInteger)a andB:(NSUInteger)b +{ + return gcd(a, b); +} + +@end diff --git a/Source/Classes/AnimatedImages/PINAnimatedImageView.m b/Source/Classes/AnimatedImages/PINAnimatedImageView.m new file mode 100644 index 00000000..c7998b69 --- /dev/null +++ b/Source/Classes/AnimatedImages/PINAnimatedImageView.m @@ -0,0 +1,446 @@ +// +// PINAnimatedImageView.m +// Pods +// +// Created by Garrett Moon on 4/17/18. +// + +#import + +#import "PINRemoteLock.h" +#import "PINDisplayLink.h" +#import +#import "PINRemoteWeakProxy.h" + +@interface PINAnimatedImageView () +{ + CFTimeInterval _playHead; + NSUInteger _playedLoops; + NSUInteger _lastSuccessfulFrameIndex; + CFTimeInterval *_durations; +} + +@property (nonatomic, assign) CGImageRef frameImage; +@property (nonatomic, strong) PINDisplayLink *displayLink; + +@property (nonatomic, assign) CFTimeInterval lastDisplayLinkFire; + +@end + +@implementation PINAnimatedImageView + +@synthesize animatedImage = _animatedImage; +@synthesize displayLink = _displayLink; +@synthesize playbackPaused = _playbackPaused; +@synthesize animatedImageRunLoopMode = _animatedImageRunLoopMode; + +- (instancetype)initWithAnimatedImage:(PINCachedAnimatedImage *)animatedImage +{ + if (self = [super initWithFrame:CGRectZero]) { + [self commonInit:animatedImage]; + } + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + [self commonInit:nil]; + } + return self; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder +{ + if (self = [super initWithCoder:aDecoder]) { + [self commonInit:nil]; + } + return self; +} + +- (void)commonInit:(PINCachedAnimatedImage *)animatedImage +{ + _animatedImage = animatedImage; + _animatedImageRunLoopMode = NSRunLoopCommonModes; + _durations = NULL; + + if (animatedImage) { + [self initializeAnimatedImage:animatedImage]; + } +} + +- (void)initializeAnimatedImage:(nonnull PINCachedAnimatedImage *)animatedImage +{ + PINWeakify(self); + animatedImage.coverImageReadyCallback = ^(PINImage *coverImage) { + dispatch_async(dispatch_get_main_queue(), ^{ + PINStrongify(self); + // In this case the lock is already gone we have to call the unlocked version therefore + [self coverImageCompleted:coverImage]; + }); + }; + + animatedImage.playbackReadyCallback = ^{ + dispatch_async(dispatch_get_main_queue(), ^{ + // In this case the lock is already gone we have to call the unlocked version therefore + PINStrongify(self); + [self checkIfShouldAnimate]; + }); + }; + if (animatedImage.playbackReady) { + [self checkIfShouldAnimate]; + } + + [self resetDurationsWithAnimatedImage:animatedImage]; +} + +- (void)dealloc +{ + if (_frameImage) { + CGImageRelease(_frameImage); + } + if (_durations) { + free(_durations); + } +} + +#pragma mark - Public + +- (void)setAnimatedImage:(PINCachedAnimatedImage *)animatedImage +{ + PINAssertMain(); + if (_animatedImage == animatedImage && animatedImage.playbackReady) { + return; + } + + PINCachedAnimatedImage *previousAnimatedImage = _animatedImage; + + _animatedImage = animatedImage; + + if (animatedImage != nil) { + [self initializeAnimatedImage:animatedImage]; + } else { + // Clean up after ourselves. + self.layer.contents = nil; + [self setCoverImage:nil]; + } + + // Animated Image can take a while to dealloc, let's try and do it off main. + __block PINCachedAnimatedImage *strongAnimatedImage = previousAnimatedImage; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + strongAnimatedImage = nil; + }); +} + +- (PINCachedAnimatedImage *)animatedImage +{ + PINAssertMain(); + return _animatedImage; +} + +- (NSString *)animatedImageRunLoopMode +{ + PINAssertMain(); + return _animatedImageRunLoopMode; +} + +- (void)setAnimatedImageRunLoopMode:(NSString *)newRunLoopMode +{ + PINAssertMain(); + + NSString *runLoopMode = newRunLoopMode ?: NSRunLoopCommonModes; + + if (_displayLink != nil) { + [_displayLink removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:_animatedImageRunLoopMode]; + [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:runLoopMode]; + } + _animatedImageRunLoopMode = runLoopMode; +} + +- (BOOL)isPlaybackPaused +{ + PINAssertMain(); + return _playbackPaused; +} + +- (void)setPlaybackPaused:(BOOL)playbackPaused +{ + PINAssertMain(); + + _playbackPaused = playbackPaused; + [self checkIfShouldAnimate]; +} + +- (void)coverImageCompleted:(PINImage *)coverImage +{ + PINAssertMain(); + BOOL setCoverImage = (_displayLink == nil) || _displayLink.paused; + + if (setCoverImage) { + [self setCoverImage:coverImage]; + } +} + +- (void)setCoverImage:(PINImage *)coverImage +{ + PINAssertMain(); + if (_frameImage) { + CGImageRelease(_frameImage); + } + _frameImage = CGImageRetain([coverImage CGImage]); +} + +#pragma mark - Animating + +- (void)checkIfShouldAnimate +{ + PINAssertMain(); + BOOL shouldAnimate = _playbackPaused == NO && _animatedImage.playbackReady && [self canBeVisible]; + if (shouldAnimate) { + [self startAnimating]; + } else { + [self stopAnimating]; + } +} + +- (void)startAnimating +{ + PINAssertMain(); + + if (_playbackPaused) { + return; + } + + if (_animatedImage.playbackReady == NO) { + return; + } + + if ([self canBeVisible] == NO) { + return; + } + + NSUInteger frameInterval = self.animatedImage.frameInterval; + + if (_displayLink == nil) { + _playHead = 0; + _displayLink = [PINDisplayLink displayLinkWithTarget:[PINRemoteWeakProxy weakProxyWithTarget:self] selector:@selector(displayLinkFired:)]; +#if PIN_TARGET_IOS + // Convert from display link fractional value to fps (note: frameInterval is always at least 1) + NSInteger frameRate = ceil([PINAnimatedImage maximumFramesPerSecond] / ((double) frameInterval)); + _displayLink.preferredFramesPerSecond = frameRate; +#else + _displayLink.frameInterval = frameInterval; +#endif + _lastSuccessfulFrameIndex = NSUIntegerMax; + + [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:self.animatedImageRunLoopMode]; + } else { + _displayLink.paused = NO; + } +} + +- (void)stopAnimating +{ + PINAssertMain(); + + _displayLink.paused = YES; + _lastDisplayLinkFire = 0; + + [_animatedImage clearAnimatedImageCache]; +} + +#pragma mark - Overrides + +- (PINImage *)image +{ + PINAssertMain(); + if (_animatedImage) { + return [PINImage imageWithCGImage:_frameImage]; + } + return [super image]; +} + +- (CGImageRef)imageRef +{ + PINAssertMain(); + PINImage *underlyingImage = nil; + if (_animatedImage) { + return _frameImage; + } else if ((underlyingImage = [super image])) { +#if PIN_TARGET_IOS + if (@available(iOS 13.0, tvOS 10.0, *)) { + if (underlyingImage.imageAsset != nil) { + underlyingImage = [underlyingImage.imageAsset imageWithTraitCollection:self.traitCollection]; + } + } +#endif + return (CGImageRef)CFAutorelease(CFRetain([underlyingImage CGImage])); + } + return nil; +} + +- (void)setImage:(PINImage *)image +{ + PINAssertMain(); + if (image) { + self.animatedImage = nil; + } + + super.image = image; +} + +- (void)displayLayer:(CALayer *)layer +{ + PINAssertMain(); + layer.contents = (__bridge id)[self imageRef]; +} + +#if PIN_TARGET_MAC + +- (void)_setImage:(PINImage *)image +{ + super.image = image; +} + +- (void)setAlphaValue:(CGFloat)alphaValue +{ + [super setAlphaValue:alphaValue]; + [self updateAnimationForPossibleVisibility]; +} + +- (void)viewDidMoveToWindow +{ + [super viewDidMoveToWindow]; + [self updateAnimationForPossibleVisibility]; +} + +- (void)viewDidMoveToSuperview +{ + [super viewDidMoveToSuperview]; + [self updateAnimationForPossibleVisibility]; +} +#else +- (void)setAlpha:(CGFloat)alpha +{ + [super setAlpha:alpha]; + [self updateAnimationForPossibleVisibility]; +} + +- (void)didMoveToWindow +{ + [super didMoveToWindow]; + [self updateAnimationForPossibleVisibility]; +} + +- (void)didMoveToSuperview +{ + [super didMoveToSuperview]; + [self updateAnimationForPossibleVisibility]; +} +#endif + +- (void)setHidden:(BOOL)hidden +{ + [super setHidden:hidden]; + [self updateAnimationForPossibleVisibility]; +} + +#pragma mark - Display Link Callbacks + +- (BOOL)canBeVisible +{ +#if PIN_TARGET_MAC + return self.window && self.superview && self.isHidden == NO && self.alphaValue > 0.0; +#else + return self.window && self.superview && self.isHidden == NO && self.alpha > 0.0; +#endif +} + +- (void)updateAnimationForPossibleVisibility +{ + [self checkIfShouldAnimate]; +} + +- (void)displayLinkFired:(PINDisplayLink *)displayLink +{ + PINAssertMain(); + CFTimeInterval timeBetweenLastFire; + if (_lastDisplayLinkFire == 0) { + timeBetweenLastFire = 0; + } else { + timeBetweenLastFire = CACurrentMediaTime() - self.lastDisplayLinkFire; + } + + self.lastDisplayLinkFire = CACurrentMediaTime(); + + _playHead += timeBetweenLastFire; + + while (_playHead > self.animatedImage.totalDuration) { + // Set playhead to zero to keep from showing different frames on different playthroughs + _playHead = 0; + _playedLoops++; + } + + if (self.animatedImage.loopCount > 0 && _playedLoops >= self.animatedImage.loopCount) { + [self stopAnimating]; + return; + } + + NSUInteger frameIndex = [self frameIndexAtPlayHeadPosition:_playHead]; + if (frameIndex == _lastSuccessfulFrameIndex) { + return; + } + CGImageRef frameImage = [self.animatedImage imageAtIndex:frameIndex]; + + if (frameImage == nil) { + //Pause the display link until we get a file ready notification + displayLink.paused = YES; + self.lastDisplayLinkFire = 0; + } else { + if (_frameImage) { + CGImageRelease(_frameImage); + } + _frameImage = CGImageRetain(frameImage); + _lastSuccessfulFrameIndex = frameIndex; +#if PIN_TARGET_MAC + [self _setImage:[NSImage imageWithCGImage:_frameImage]]; +#else + [self.layer setNeedsDisplay]; +#endif + } +} + +- (void)resetDurationsWithAnimatedImage:(PINCachedAnimatedImage *)animatedImage +{ + PINAssertMain(); + if (!animatedImage) { + return; + } + if (_durations) { + free(_durations); + } + _durations = malloc(sizeof(CFTimeInterval) * animatedImage.frameCount); + CFTimeInterval sum = 0.0f; + for (int i = 0; i < animatedImage.frameCount; i++) { + sum += [animatedImage durationAtIndex:i]; + _durations[i] = sum; + } +} + +- (NSUInteger)frameIndexAtPlayHeadPosition:(CFTimeInterval)playHead +{ + PINAssertMain(); + int low = 0, high = (int)_animatedImage.frameCount - 1; + + while (low <= high) { + int mid = low + (high - low) / 2; + if (_durations[mid] < playHead) { + low = mid + 1; + } else { + high = mid - 1; + } + } + return MAX(MIN(low, (int)_animatedImage.frameCount - 1), 0); +} + +@end diff --git a/Source/Classes/AnimatedImages/PINCachedAnimatedImage.m b/Source/Classes/AnimatedImages/PINCachedAnimatedImage.m new file mode 100644 index 00000000..25201228 --- /dev/null +++ b/Source/Classes/AnimatedImages/PINCachedAnimatedImage.m @@ -0,0 +1,536 @@ +// +// PINCachedAnimatedImage.m +// PINRemoteImage +// +// Created by Garrett Moon on 9/17/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import + +#import "PINRemoteLock.h" +#import +#if PIN_WEBP +#import +#endif +#if PIN_APNG +#import +#endif + +#if !__has_include() +#import "PINOperation.h" +#else +#import +#endif + +#import + +static const NSUInteger kFramesToRenderForLargeFrames = 4; +static const NSUInteger kFramesToRenderMinimum = 2; + +static const CFTimeInterval kSecondsAfterMemWarningToMinimumCache = 1; +static const CFTimeInterval kSecondsAfterMemWarningToLargeCache = 5; +static const CFTimeInterval kSecondsAfterMemWarningToAllCache = 10; +#if PIN_TARGET_IOS +static const CFTimeInterval kSecondsBetweenMemoryWarnings = 15; +#endif + +@interface PINCachedAnimatedImage () +{ + // Since _animatedImage is set on init it is thread-safe. + id _animatedImage; + + PINImage *_coverImage; + PINAnimatedImageInfoReady _coverImageReadyCallback; + dispatch_block_t _playbackReadyCallback; + NSMutableDictionary *_frameCache; + NSInteger _frameRenderCount; // Number of frames to cache until playback is ready. + BOOL _playbackReady; + PINOperationQueue *_operationQueue; + dispatch_queue_t _cachingQueue; + + NSUInteger _playhead; + BOOL _notifyOnReady; + NSMutableIndexSet *_cachedOrCachingFrames; + PINRemoteLock *_lock; + BOOL _cacheCleared; // Flag used to cancel any caching operations after clear cache is called. +} + +@property (atomic, strong) NSDate *lastMemoryWarning; + +// Set to YES if we continually see memory warnings after ramping up the number of cached frames. +@property (atomic, assign) BOOL cachingFramesCausingMemoryWarnings; + +@end + +@implementation PINCachedAnimatedImage + +- (instancetype)initWithAnimatedImageData:(NSData *)animatedImageData +{ + if ([animatedImageData pin_isAnimatedGIF]) { + return [self initWithAnimatedImage:[[PINGIFAnimatedImage alloc] initWithAnimatedImageData:animatedImageData]]; + } +#if PIN_WEBP + if ([animatedImageData pin_isAnimatedWebP]) { + return [self initWithAnimatedImage:[[PINWebPAnimatedImage alloc] initWithAnimatedImageData:animatedImageData]]; + } +#endif +#if PIN_APNG + if ([animatedImageData pin_isAPNG]) { + return [self initWithAnimatedImage:[[PINAPNGAnimatedImage alloc] initWithAnimatedImageData:animatedImageData]]; + } +#endif + return nil; +} + +- (instancetype)initWithAnimatedImage:(id )animatedImage +{ + if (self = [super init]) { + _animatedImage = animatedImage; + _frameCache = [[NSMutableDictionary alloc] init]; + _frameRenderCount = 0; + _playhead = 0; + _notifyOnReady = YES; + _cachedOrCachingFrames = [[NSMutableIndexSet alloc] init]; + _lock = [[PINRemoteLock alloc] initWithName:@"PINCachedAnimatedImage Lock"]; + +#if PIN_TARGET_IOS + _lastMemoryWarning = [NSDate distantPast]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didReceiveMemoryWarningNotification:) + name:UIApplicationDidReceiveMemoryWarningNotification + object:nil]; +#endif + + _operationQueue = [[PINOperationQueue alloc] initWithMaxConcurrentOperations:kFramesToRenderForLargeFrames]; + _cachingQueue = dispatch_queue_create("Caching Queue", DISPATCH_QUEUE_SERIAL); + + // dispatch later so that blocks can be set after init this runloop + PINWeakify(self); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + PINStrongify(self); + [self imageAtIndex:0]; + }); + } + return self; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +#if PIN_TARGET_IOS +- (void)didReceiveMemoryWarningNotification:(NSNotification *)notification +{ + NSDate *now = [NSDate date]; + if (-[self.lastMemoryWarning timeIntervalSinceDate:now] < kSecondsBetweenMemoryWarnings) { + self.cachingFramesCausingMemoryWarnings = YES; + } + self.lastMemoryWarning = now; + [self cleanupFrames]; +} +#endif + +- (PINImage *)coverImage +{ + __block PINImage *coverImage = nil; + __block PINAnimatedImageInfoReady coverImageReadyCallback = nil; + [_lock lockWithBlock:^{ + if (self->_coverImage == nil) { + CGImageRef coverImageRef = [self->_animatedImage imageAtIndex:0 cacheProvider:self]; + BOOL notifyCallback = [self _locked_updateCoverImage:coverImageRef]; + coverImageReadyCallback = notifyCallback ? self->_coverImageReadyCallback : nil; + } + coverImage = self->_coverImage; + }]; + if (coverImageReadyCallback) { + coverImageReadyCallback(coverImage); + } + return coverImage; +} + +// Update _coverImage property and return if it should notify the callback +- (BOOL)_locked_updateCoverImage:(CGImageRef)coverImageRef +{ + BOOL notifyCallback = NO; + if (coverImageRef) { + notifyCallback = (_coverImage == nil && coverImageRef != nil); +#if PIN_TARGET_IOS + _coverImage = [UIImage imageWithCGImage:coverImageRef]; +#elif PIN_TARGET_MAC + _coverImage = [[NSImage alloc] initWithCGImage:coverImageRef size:CGSizeMake(_animatedImage.width, _animatedImage.height)]; +#endif + } else { + _coverImage = nil; + } + return notifyCallback; +} + +- (BOOL)coverImageReady +{ + __block PINImage *coverImage = nil; + __block PINAnimatedImageInfoReady coverImageReadyCallback = nil; + [_lock lockWithBlock:^{ + if (self->_coverImage == nil) { + CGImageRef coverImageRef = (__bridge CGImageRef)[self->_frameCache objectForKey:@(0)]; + if (coverImageRef) { + BOOL notifyCallback = [self _locked_updateCoverImage:coverImageRef]; + coverImageReadyCallback = notifyCallback ? self->_coverImageReadyCallback : nil; + } + } + + coverImage = self->_coverImage; + }]; + if (coverImageReadyCallback) { + coverImageReadyCallback(coverImage); + } + return (coverImage != nil); +} + +#pragma mark - passthrough +- (CGSize)size +{ + return CGSizeMake(_animatedImage.width, _animatedImage.height); +} + +- (NSData *)data +{ + return _animatedImage.data; +} + +- (CFTimeInterval)totalDuration +{ + return _animatedImage.totalDuration; +} + +- (NSUInteger)frameInterval +{ + return _animatedImage.frameInterval; +} + +- (size_t)loopCount +{ + return _animatedImage.loopCount; +} + +- (size_t)frameCount +{ + return _animatedImage.frameCount; +} + +- (NSError *)error +{ + return _animatedImage.error; +} + +- (CGImageRef)imageAtIndex:(NSUInteger)index +{ + __block CGImageRef imageRef; + __block BOOL cachingDisabled = NO; + [_lock lockWithBlock:^{ + // Reset cache cleared flag if it's been set. + self->_cacheCleared = NO; + imageRef = (__bridge CGImageRef)[self->_frameCache objectForKey:@(index)]; + + self->_playhead = index; + if (imageRef == NULL) { + if ([self framesToCache] == 0) { + // We're not caching so we should just generate the frame. + cachingDisabled = YES; + } else { + PINLog(@"cache miss, aww."); + self->_notifyOnReady = YES; + } + } + + // Retain and autorelease while we have the lock, another thread could remove it from the cache + // and allow it to be released. + if (imageRef) { + CGImageRetain(imageRef); + CFAutorelease(imageRef); + } + }]; + + if (cachingDisabled && imageRef == NULL) { + imageRef = [_animatedImage imageAtIndex:index cacheProvider:self]; + } else { + PINWeakify(self); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + PINStrongify(self); + [self updateCache]; + }); + } + + return imageRef; +} + +- (void)_updateCacheOnQueue +{ + // Kick off, in order, caching frames which need to be cached + NSRange endKeepRange; + NSRange beginningKeepRange; + + [self getKeepRanges:&endKeepRange beginningKeepRange:&beginningKeepRange]; + + [self->_lock lockWithBlock:^{ + for (NSUInteger idx = endKeepRange.location; idx < NSMaxRange(endKeepRange); idx++) { + if ([self->_cachedOrCachingFrames containsIndex:idx] == NO) { + [self _locked_cacheFrame:idx]; + } + } + + if (beginningKeepRange.location != NSNotFound) { + for (NSUInteger idx = beginningKeepRange.location; idx < NSMaxRange(beginningKeepRange); idx++) { + if ([self->_cachedOrCachingFrames containsIndex:idx] == NO) { + [self _locked_cacheFrame:idx]; + } + } + } + }]; +} + +- (void)updateCache +{ + PINWeakify(self); + // skip if we don't have any frames to cache + if ([self framesToCache] > 0) { + [_operationQueue scheduleOperation:^{ + PINStrongify(self); + [self _updateCacheOnQueue]; + }]; + } + + [_operationQueue scheduleOperation:^{ + PINStrongify(self); + [self cleanupFrames]; + }]; +} + +- (void)getKeepRanges:(nonnull out NSRange *)endKeepRangeIn beginningKeepRange:(nonnull out NSRange *)beginningKeepRangeIn +{ + __block NSRange endKeepRange; + __block NSRange beginningKeepRange; + + NSUInteger framesToCache = [self framesToCache]; + + [self->_lock lockWithBlock:^{ + // find the range of frames we want to keep + endKeepRange = NSMakeRange(self->_playhead, framesToCache); + beginningKeepRange = NSMakeRange(NSNotFound, 0); + if (NSMaxRange(endKeepRange) > self->_animatedImage.frameCount) { + beginningKeepRange = NSMakeRange(0, NSMaxRange(endKeepRange) - self->_animatedImage.frameCount); + endKeepRange.length = self->_animatedImage.frameCount - self->_playhead; + } + }]; + + if (endKeepRangeIn) { + *endKeepRangeIn = endKeepRange; + } + if (beginningKeepRangeIn) { + *beginningKeepRangeIn = beginningKeepRange; + } +} + +- (void)cleanupFrames +{ + NSRange endKeepRange; + NSRange beginningKeepRange; + [self getKeepRanges:&endKeepRange beginningKeepRange:&beginningKeepRange]; + + [_lock lockWithBlock:^{ + NSMutableIndexSet *removedFrames = [[NSMutableIndexSet alloc] init]; + PINLog(@"Checking if frames need removing: %lu", _cachedOrCachingFrames.count); + [self->_cachedOrCachingFrames enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) { + BOOL shouldKeepFrame = NSLocationInRange(idx, endKeepRange); + if (beginningKeepRange.location != NSNotFound) { + shouldKeepFrame |= NSLocationInRange(idx, beginningKeepRange); + } + if (shouldKeepFrame == NO) { + [removedFrames addIndex:idx]; + [self->_frameCache removeObjectForKey:@(idx)]; + PINLog(@"Removing: %lu", (unsigned long)idx); + } + }]; + [self->_cachedOrCachingFrames removeIndexes:removedFrames]; + }]; +} + +- (void)_cacheWithFrameIndex:(NSUInteger)frameIndex +{ + CGImageRef imageRef = [self->_animatedImage imageAtIndex:frameIndex cacheProvider:self]; + PINLog(@"Generating: %lu", (unsigned long)frameIndex); + + if (imageRef) { + __block PINImage *coverImage = nil; + __block PINAnimatedImageInfoReady coverImageReadyCallback = nil; + [self->_lock lockWithBlock:^{ + [self->_frameCache setObject:(__bridge id _Nonnull)(imageRef) forKey:@(frameIndex)]; + + // Update the cover image + if (frameIndex == 0) { + BOOL notifyCallback = [self _locked_updateCoverImage:imageRef]; + coverImageReadyCallback = notifyCallback ? self->_coverImageReadyCallback : nil; + coverImage = self->_coverImage; + } + + self->_frameRenderCount--; + NSAssert(self->_frameRenderCount >= 0, @"playback ready is less than zero, something is wrong :("); + + PINLog(@"Frames left: %ld", (long)_frameRenderCount); + + dispatch_block_t notify = nil; + if (self->_frameRenderCount == 0 && self->_notifyOnReady) { + self->_notifyOnReady = NO; + if (self->_playbackReadyCallback) { + notify = self->_playbackReadyCallback; + [self->_operationQueue scheduleOperation:^{ + notify(); + }]; + } + } + }]; + if (coverImageReadyCallback) { + coverImageReadyCallback(coverImage); + } + } +} + +- (void)_locked_cacheFrame:(NSUInteger)frameIndex +{ + if ([_cachedOrCachingFrames containsIndex:frameIndex] == NO && _cacheCleared == NO) { + PINLog(@"Requesting: %lu", (unsigned long)frameIndex); + [_cachedOrCachingFrames addIndex:frameIndex]; + _frameRenderCount++; + + PINWeakify(self); + dispatch_async(_cachingQueue, ^{ + PINStrongify(self); + [self _cacheWithFrameIndex:frameIndex]; + }); + } +} + +// Returns the number of frames that should be cached +- (NSUInteger)framesToCache +{ + unsigned long long totalBytes = [NSProcessInfo processInfo].physicalMemory; + NSUInteger framesToCache = 0; + + NSUInteger frameCost = _animatedImage.bytesPerFrame; + if (frameCost * _animatedImage.frameCount < totalBytes / 250) { + // If the total number of bytes takes up less than a 250th of total memory, lets just cache 'em all. + framesToCache = _animatedImage.frameCount; + } else if (frameCost < totalBytes / 1000) { + // If the cost of a frame is less than 1000th of physical memory, cache 4 frames to smooth animation. + framesToCache = kFramesToRenderForLargeFrames; + } else if (frameCost < totalBytes / 500) { + // Oooph, lets just try to get ahead of things by one. + framesToCache = kFramesToRenderMinimum; + } else { + // No caching :( + framesToCache = 0; + } + + // If it's been less than 5 seconds, we're not caching + CFTimeInterval timeSinceLastWarning = -[self.lastMemoryWarning timeIntervalSinceNow]; + if (self.cachingFramesCausingMemoryWarnings || timeSinceLastWarning < kSecondsAfterMemWarningToMinimumCache) { + framesToCache = 0; + } else if (timeSinceLastWarning < kSecondsAfterMemWarningToLargeCache) { + framesToCache = MIN(framesToCache, kFramesToRenderMinimum); + } else if (timeSinceLastWarning < kSecondsAfterMemWarningToAllCache) { + framesToCache = MIN(framesToCache, kFramesToRenderForLargeFrames); + } + + return framesToCache; +} + +- (CFTimeInterval)durationAtIndex:(NSUInteger)index +{ + return [_animatedImage durationAtIndex:index]; +} + +- (BOOL)playbackReady +{ + __block BOOL playbackReady = NO; + [_lock lockWithBlock:^{ + if (self->_playbackReady == NO) { + self->_playbackReady = self->_frameRenderCount == 0; + } + playbackReady = self->_playbackReady; + }]; + return playbackReady; +} + +- (dispatch_block_t)playbackReadyCallback +{ + __block dispatch_block_t playbackReadyCallback = nil; + [_lock lockWithBlock:^{ + playbackReadyCallback = self->_playbackReadyCallback; + }]; + return playbackReadyCallback; +} + +- (void)setPlaybackReadyCallback:(dispatch_block_t)playbackReadyCallback +{ + [_lock lockWithBlock:^{ + self->_playbackReadyCallback = playbackReadyCallback; + }]; +} + +- (PINAnimatedImageInfoReady)coverImageReadyCallback +{ + __block PINAnimatedImageInfoReady coverImageReadyCallback; + [_lock lockWithBlock:^{ + coverImageReadyCallback = self->_coverImageReadyCallback; + }]; + return coverImageReadyCallback; +} + +- (void)setCoverImageReadyCallback:(PINAnimatedImageInfoReady)coverImageReadyCallback +{ + [_lock lockWithBlock:^{ + self->_coverImageReadyCallback = coverImageReadyCallback; + }]; +} + +- (void)_clearAnimatedImageCache +{ + [self->_lock lockWithBlock:^{ + self->_cacheCleared = YES; + self->_coverImage = nil; + [self->_cachedOrCachingFrames enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) { + [self->_frameCache removeObjectForKey:@(idx)]; + }]; + [self->_cachedOrCachingFrames removeAllIndexes]; + }]; +} + +/** + @abstract Clear any cached data. Called when playback is paused. + */ +- (void)clearAnimatedImageCache +{ + PINWeakify(self); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + PINStrongify(self); + [self _clearAnimatedImageCache]; + }); +} + +# pragma mark - PINCachedAnimatedFrameProvider + +- (CGImageRef)cachedFrameImageAtIndex:(NSUInteger)index +{ + __block CGImageRef imageRef; + [_lock lockWithBlock:^{ + imageRef = (__bridge CGImageRef)[self->_frameCache objectForKey:@(index)]; + if (imageRef) { + CGImageRetain(imageRef); + CFAutorelease(imageRef); + } + }]; + return imageRef; +} + +@end diff --git a/Source/Classes/AnimatedImages/PINGIFAnimatedImage.m b/Source/Classes/AnimatedImages/PINGIFAnimatedImage.m new file mode 100644 index 00000000..e93763e8 --- /dev/null +++ b/Source/Classes/AnimatedImages/PINGIFAnimatedImage.m @@ -0,0 +1,166 @@ +// +// PINGIFAnimatedImage.m +// PINRemoteImage +// +// Created by Garrett Moon on 9/17/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import + +#import +#if PIN_TARGET_IOS +#import +#elif PIN_TARGET_MAC +#import +#endif + +#import +#import + +@interface PINGIFAnimatedImage () +{ + NSData *_animatedImageData; + CGImageSourceRef _imageSource; + uint32_t _width; + uint32_t _height; + BOOL _hasAlpha; + size_t _frameCount; + size_t _loopCount; + CFTimeInterval *_durations; + NSError *_error; +} +@end + +@implementation PINGIFAnimatedImage + +- (instancetype)initWithAnimatedImageData:(NSData *)animatedImageData +{ + if (self = [super init]) { + _animatedImageData = animatedImageData; + _imageSource = + CGImageSourceCreateWithData((CFDataRef)animatedImageData, + (CFDictionaryRef)@{(__bridge NSString *)kCGImageSourceTypeIdentifierHint: + (__bridge NSString *)kUTTypeGIF, + (__bridge NSString *)kCGImageSourceShouldCache: + (__bridge NSNumber *)kCFBooleanFalse}); + if (_imageSource && [animatedImageData pin_isGIF]) { + _frameCount = (uint32_t)CGImageSourceGetCount(_imageSource); + NSDictionary *imageProperties = (__bridge_transfer NSDictionary *)CGImageSourceCopyProperties(_imageSource, nil); + _loopCount = (uint32_t)[[[imageProperties objectForKey:(__bridge NSString *)kCGImagePropertyGIFDictionary] + objectForKey:(__bridge NSString *)kCGImagePropertyGIFLoopCount] unsignedLongValue]; + _durations = malloc(sizeof(CFTimeInterval) * _frameCount); + imageProperties = (__bridge_transfer NSDictionary *) + CGImageSourceCopyPropertiesAtIndex(_imageSource, + 0, + (CFDictionaryRef)@{(__bridge NSString *)kCGImageSourceShouldCache: + (__bridge NSNumber *)kCFBooleanFalse}); + _width = (uint32_t)[(NSNumber *)imageProperties[(__bridge NSString *)kCGImagePropertyPixelWidth] unsignedIntegerValue]; + _height = (uint32_t)[(NSNumber *)imageProperties[(__bridge NSString *)kCGImagePropertyPixelHeight] unsignedIntegerValue]; + + for (NSUInteger frameIdx = 0; frameIdx < _frameCount; frameIdx++) { + _durations[frameIdx] = [PINGIFAnimatedImage frameDurationAtIndex:frameIdx source:_imageSource]; + } + } else { + return nil; + } + } + return self; +} + ++ (Float32)frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source +{ + Float32 frameDuration = kPINAnimatedImageDefaultDuration; + NSDictionary *frameProperties = (__bridge_transfer NSDictionary *)CGImageSourceCopyPropertiesAtIndex(source, index, nil); + // use unclamped delay time before delay time before default + NSNumber *unclamedDelayTime = frameProperties[(__bridge NSString *)kCGImagePropertyGIFDictionary][(__bridge NSString *)kCGImagePropertyGIFUnclampedDelayTime]; + if (unclamedDelayTime != nil) { + frameDuration = [unclamedDelayTime floatValue]; + } else { + NSNumber *delayTime = frameProperties[(__bridge NSString *)kCGImagePropertyGIFDictionary][(__bridge NSString *)kCGImagePropertyGIFDelayTime]; + if (delayTime != nil) { + frameDuration = [delayTime floatValue]; + } + } + + static dispatch_once_t onceToken; + static Float32 maximumFrameDuration; + dispatch_once(&onceToken, ^{ + maximumFrameDuration = 1.0 / [PINAnimatedImage maximumFramesPerSecond]; + }); + + if (frameDuration < maximumFrameDuration) { + frameDuration = kPINAnimatedImageDefaultDuration; + } + + return frameDuration; +} + +- (void)dealloc +{ + if (_imageSource) { + CFRelease(_imageSource); + } + if (_durations) { + free(_durations); + } +} + +- (NSData *)data +{ + return _animatedImageData; +} + +- (size_t)frameCount +{ + return _frameCount; +} + +- (size_t)loopCount +{ + return _loopCount; +} + +- (uint32_t)width +{ + return _width; +} + +- (uint32_t)height +{ + return _height; +} + +- (uint32_t)bytesPerFrame +{ + return _width * _height * 4; +} + +- (NSError *)error +{ + return _error; +} + +- (CFTimeInterval)durationAtIndex:(NSUInteger)index +{ + return _durations[index]; +} + +- (CGImageRef)imageAtIndex:(NSUInteger)index cacheProvider:(nullable id)cacheProvider +{ + // I believe this is threadsafe as CGImageSource *seems* immutable… + CGImageRef imageRef = + CGImageSourceCreateImageAtIndex(_imageSource, + index, + (CFDictionaryRef)@{(__bridge NSString *)kCGImageSourceShouldCache: + (__bridge NSNumber *)kCFBooleanFalse}); + if (imageRef) { + CGImageRef decodedImageRef = [PINImage pin_decodedImageRefWithCGImageRef:imageRef]; + CGImageRelease(imageRef); + imageRef = decodedImageRef; + } + + return imageRef; +} + +@end diff --git a/Source/Classes/AnimatedImages/PINWebPAnimatedImage.m b/Source/Classes/AnimatedImages/PINWebPAnimatedImage.m new file mode 100644 index 00000000..9fe43e31 --- /dev/null +++ b/Source/Classes/AnimatedImages/PINWebPAnimatedImage.m @@ -0,0 +1,172 @@ +// +// PINWebPAnimatedImage.m +// PINRemoteImage +// +// Created by Garrett Moon on 9/14/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import + +#if PIN_WEBP + +#import +#import +#if PIN_TARGET_IOS +#import +#elif PIN_TARGET_MAC +#import +#endif + +#import +#import + +@interface PINWebPAnimatedImage () +{ + NSData *_animatedImageData; + CGImageSourceRef _imageSource; + uint32_t _width; + uint32_t _height; + BOOL _hasAlpha; + size_t _frameCount; + size_t _loopCount; + CFTimeInterval *_durations; + NSError *_error; +} +@end + +@implementation PINWebPAnimatedImage + +- (instancetype)initWithAnimatedImageData:(NSData *)animatedImageData +{ + if (self = [super init]) { + _animatedImageData = animatedImageData; + + _imageSource = + CGImageSourceCreateWithData((CFDataRef)animatedImageData, + (CFDictionaryRef)@{(__bridge NSString *)kCGImageSourceTypeIdentifierHint: + [UTTypeWebP identifier], + (__bridge NSString *)kCGImageSourceShouldCache: + (__bridge NSNumber *)kCFBooleanFalse}); + if (_imageSource && [animatedImageData pin_isWebP]) { + _frameCount = (uint32_t)CGImageSourceGetCount(_imageSource); + NSDictionary *imageProperties = (__bridge_transfer NSDictionary *)CGImageSourceCopyProperties(_imageSource, nil); + _loopCount = (uint32_t)[[[imageProperties objectForKey:(__bridge NSString *)kCGImagePropertyWebPDictionary] + objectForKey:(__bridge NSString *)kCGImagePropertyWebPLoopCount] unsignedLongValue]; + _durations = malloc(sizeof(CFTimeInterval) * _frameCount); + imageProperties = (__bridge_transfer NSDictionary *) + CGImageSourceCopyPropertiesAtIndex(_imageSource, + 0, + (CFDictionaryRef)@{(__bridge NSString *)kCGImageSourceShouldCache: + (__bridge NSNumber *)kCFBooleanFalse}); + _width = (uint32_t)[(NSNumber *)imageProperties[(__bridge NSString *)kCGImagePropertyPixelWidth] unsignedIntegerValue]; + _height = (uint32_t)[(NSNumber *)imageProperties[(__bridge NSString *)kCGImagePropertyPixelHeight] unsignedIntegerValue]; + + for (NSUInteger frameIdx = 0; frameIdx < _frameCount; frameIdx++) { + _durations[frameIdx] = [PINWebPAnimatedImage frameDurationAtIndex:frameIdx source:_imageSource]; + } + } else { + return nil; + } + } + return self; +} + ++ (Float32)frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source +{ + Float32 frameDuration = kPINAnimatedImageDefaultDuration; + NSDictionary *frameProperties = (__bridge_transfer NSDictionary *)CGImageSourceCopyPropertiesAtIndex(source, index, nil); + // use unclamped delay time before delay time before default + NSNumber *unclamedDelayTime = frameProperties[(__bridge NSString *)kCGImagePropertyWebPDictionary][(__bridge NSString *)kCGImagePropertyWebPUnclampedDelayTime]; + if (unclamedDelayTime != nil) { + frameDuration = [unclamedDelayTime floatValue]; + } else { + NSNumber *delayTime = frameProperties[(__bridge NSString *)kCGImagePropertyWebPDictionary][(__bridge NSString *)kCGImagePropertyWebPDelayTime]; + if (delayTime != nil) { + frameDuration = [delayTime floatValue]; + } + } + + static dispatch_once_t onceToken; + static Float32 maximumFrameDuration; + dispatch_once(&onceToken, ^{ + maximumFrameDuration = 1.0 / [PINAnimatedImage maximumFramesPerSecond]; + }); + + if (frameDuration < maximumFrameDuration) { + frameDuration = kPINAnimatedImageDefaultDuration; + } + + return frameDuration; +} + +- (void)dealloc +{ + if (_imageSource) { + CFRelease(_imageSource); + } + if (_durations) { + free(_durations); + } +} + +- (NSData *)data +{ + return _animatedImageData; +} + +- (size_t)frameCount +{ + return _frameCount; +} + +- (size_t)loopCount +{ + return _loopCount; +} + +- (uint32_t)width +{ + return _width; +} + +- (uint32_t)height +{ + return _height; +} + +- (uint32_t)bytesPerFrame +{ + return _width * _height * 4; +} + +- (NSError *)error +{ + return _error; +} + +- (CFTimeInterval)durationAtIndex:(NSUInteger)index +{ + return _durations[index]; +} + +- (CGImageRef)imageAtIndex:(NSUInteger)index cacheProvider:(nullable id)cacheProvider +{ + // I believe this is threadsafe as CGImageSource *seems* immutable… + CGImageRef imageRef = + CGImageSourceCreateImageAtIndex(_imageSource, + index, + (CFDictionaryRef)@{(__bridge NSString *)kCGImageSourceShouldCache: + (__bridge NSNumber *)kCFBooleanFalse}); + if (imageRef) { + CGImageRef decodedImageRef = [PINImage pin_decodedImageRefWithCGImageRef:imageRef]; + CGImageRelease(imageRef); + imageRef = decodedImageRef; + } + + return imageRef; +} + +@end + +#endif diff --git a/Source/Classes/Categories/NSData+ImageDetectors.m b/Source/Classes/Categories/NSData+ImageDetectors.m new file mode 100644 index 00000000..eb8130ed --- /dev/null +++ b/Source/Classes/Categories/NSData+ImageDetectors.m @@ -0,0 +1,188 @@ +// +// NSData+ImageDetectors.m +// Pods +// +// Created by Garrett Moon on 11/19/14. +// +// + +#import + +@implementation NSData (PINImageDetectors) + +- (BOOL)pin_isGIF +{ + const NSInteger length = 3; + Byte firstBytes[length]; + if ([self length] >= length) { + [self getBytes:&firstBytes length:length]; + //G, I, F + if (firstBytes[0] == 0x47 && firstBytes[1] == 0x49 && firstBytes[2] == 0x46) { + return YES; + } + } + return NO; +} + +#define BREAK_IF_INVALID(position) if (position >= length) break; + +static inline BOOL advancePositionWithCount(NSUInteger *position, NSUInteger length, NSUInteger count) +{ + if (*position + count >= length) { + return NO; + } + *position = *position + count; + + return YES; +} + +static inline BOOL advancePositionWithBytes(NSUInteger *position, Byte *bytes, NSUInteger length, NSUInteger count) +{ + BOOL readAgain; + do { + readAgain = NO; + if (*position + count >= length ) { + return NO; + } + *position = *position + count; + NSUInteger bytesToAdvance = *(bytes + *position); + if (bytesToAdvance == 0xFF) { + readAgain = YES; + count = 0; + } + // Advance the byte read as well. + bytesToAdvance++; + + if (*position + bytesToAdvance >= length) { + return NO; + } + *position = *position + bytesToAdvance; + } while (readAgain); + + return YES; +} + +- (BOOL)pin_isAnimatedGIF +{ + if ([self pin_isGIF] == NO) { + return NO; + } + + Byte *bytes = (Byte *)self.bytes; + NSUInteger length = self.length; + NSUInteger position = 0; + NSUInteger GCECount = 0; + + while (bytes && position < length) { + // Look for Graphic Control Extension + if (*(bytes + position) == 0x21) { + if (!advancePositionWithCount(&position, length, 1)) break; + if (*(bytes + position) == 0xF9) { + GCECount++; + if (GCECount > 1) { + break; + } + // Found GCE, advance to image. Next byte is size of GCE + if (!advancePositionWithBytes(&position, bytes, length, 1)) break; + // Advance 1 for 00 at the end of GCE + if (!advancePositionWithCount(&position, length, 1)) break; + // Advance image descriptor + if (!advancePositionWithCount(&position, length, 11)) break; + // Advance image + if (!advancePositionWithBytes(&position, bytes, length, 0)) break; + // Advance 1 for 00 at the end of image + if (!advancePositionWithCount(&position, length, 1)) break; + } + continue; + } + if (!advancePositionWithCount(&position, length, 1)) break; + } + + return GCECount > 1; +} + +#if PIN_WEBP +- (BOOL)pin_isWebP +{ + const NSInteger length = 12; + Byte firstBytes[length]; + if ([self length] >= length) { + [self getBytes:&firstBytes length:length]; + //R, I, F, F, -, -, -, -, W, E, B, P + if (firstBytes[0] == 0x52 && firstBytes[1] == 0x49 && firstBytes[2] == 0x46 && firstBytes[3] == 0x46 && firstBytes[8] == 0x57 && firstBytes[9] == 0x45 && firstBytes[10] == 0x42 && firstBytes[11] == 0x50) { + return YES; + } + } + return NO; +} + +- (BOOL)pin_isAnimatedWebP +{ + if (![self pin_isWebP]) { + return NO; + } + + const NSInteger formatSize = 4; + + NSInteger offset = 12; + if ([self length] < (offset + formatSize)) { + return NO; + } + + // VP8X is extended, which means this might be animated + Byte formatBytes[formatSize]; + [self getBytes:&formatBytes range:NSMakeRange(offset, formatSize)]; + if (formatBytes[0] != 'V' || formatBytes[1] != 'P' || formatBytes[2] != '8' || formatBytes[3] != 'X') { + return NO; + } + + offset += formatSize + 14; + + // Expecting `ANIM` + Byte animateBytes[formatSize]; + [self getBytes:animateBytes range:NSMakeRange(offset, formatSize)]; + if (animateBytes[0] != 'A' || animateBytes[1] != 'N' || animateBytes[2] != 'I' || animateBytes[3] != 'M') { + return NO; + } + + return YES; +} + +#endif +#if PIN_APNG +- (BOOL)pin_isAPNG +{ + const void* bytes = self.bytes; + if (self.length < 16) { + return NO; + } + + // This is a PNG signature. + if (memcmp(bytes, "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", 8)) { + return NO; + } + // The correct PNG must exist in the head chunk. + bytes += 8; /* skip signature */ + if (memcmp(bytes + 4, "IHDR", 4)) { + return NO; + } + + uint32_t length = ntohl(*(uint32_t*)(bytes)); + bytes += 4; /* skip length */ + bytes += 4; /* skip type code */ + bytes += length; /* skip type data */ + bytes += 4; /* skip crc */ + if ((uint32_t)(bytes - self.bytes) > self.length - 4) { + return NO; + } + + // The correct APNG equal correct PNG + animation control chunk. + if (memcmp(bytes + 4, "acTL", 4)) { + return NO; + } + + return YES; +} +#endif + +@end diff --git a/Source/Classes/Categories/NSHTTPURLResponse+MaxAge.m b/Source/Classes/Categories/NSHTTPURLResponse+MaxAge.m new file mode 100644 index 00000000..c5db19c4 --- /dev/null +++ b/Source/Classes/Categories/NSHTTPURLResponse+MaxAge.m @@ -0,0 +1,71 @@ +// +// NSHTTPURLResponse+MaxAge.m +// +// Created by Kevin Smith on 6/15/18. +// +// + +#import + +@implementation NSHTTPURLResponse (MaxAge) + +static NSDateFormatter *sharedFormatter; +static dispatch_once_t sharedFormatterToken; + ++ (NSDateFormatter *)RFC7231PreferredDateFormatter +{ + dispatch_once(&sharedFormatterToken, ^{ + NSLocale *enUSPOSIXLocale; + + sharedFormatter = [[NSDateFormatter alloc] init]; + + enUSPOSIXLocale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]; + + [sharedFormatter setLocale:enUSPOSIXLocale]; + [sharedFormatter setDateFormat:@"E, d MMM yyyy HH:mm:ss Z"]; + + }); + return sharedFormatter; +} + +- (NSNumber *)findMaxAge +{ + NSDictionary * headerFields = [self allHeaderFields]; + NSNumber *maxAge = nil; + + for (NSString * component in [headerFields[@"Cache-Control"] componentsSeparatedByString:@","]) { + NSString * trimmed = [[component stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] lowercaseString]; + + if ([trimmed isEqualToString:@"no-store"] || [trimmed isEqualToString:@"must-revalidate"] || [trimmed isEqualToString:@"no-cache"]) { + maxAge = @(0); + break; + } else { + // max-age + NSArray * split = [trimmed componentsSeparatedByString:@"max-age="]; + if ([split count] == 2) { + // if the max-age provided is invalid (does not parse into an + // int), we wind up with 0 which will be treated as do-not-cache. + // This is the RFC defined behavior for a malformed "expires" header, + // and while I cannot find any explicit instruction of how to behave + // with a malformed "max-age" header, it seems like a reasonable approach. + maxAge = @([split[1] integerValue]); + } else if ([split count] > 2) { + // very weird case "maxage=maxage=123" + maxAge = @(0); + } + } + } + + // If there is a Cache-Control header with the "max-age" directive in the response, the Expires header is ignored. + if (!maxAge && headerFields[@"Expires"]) { + NSString * expires = headerFields[@"Expires"]; + NSDate * date = [[NSHTTPURLResponse RFC7231PreferredDateFormatter] dateFromString:expires]; + + // Invalid dates (notably "0") or dates in the past must not be cached (RFC7231 5.3) + maxAge = @((NSInteger) MAX(([date timeIntervalSinceNow]), 0)); + } + + return maxAge; +} + +@end diff --git a/Source/Classes/Categories/PINImage+DecodedImage.m b/Source/Classes/Categories/PINImage+DecodedImage.m new file mode 100644 index 00000000..38da3eb5 --- /dev/null +++ b/Source/Classes/Categories/PINImage+DecodedImage.m @@ -0,0 +1,318 @@ +// +// UIImage+DecodedImage.m +// Pods +// +// Created by Garrett Moon on 11/19/14. +// +// + +#import + +#import + +#import + +NS_INLINE BOOL pin_CGImageRefIsOpaque(CGImageRef imageRef) { + CGImageAlphaInfo alpha = CGImageGetAlphaInfo(imageRef); + switch (alpha) { + case kCGImageAlphaNone: + case kCGImageAlphaNoneSkipLast: + case kCGImageAlphaNoneSkipFirst: + return YES; + default: + return NO; + } +} + +#if PIN_TARGET_IOS +NS_INLINE BOOL pin_CGImageRefIsGrayscale(CGImageRef imageRef) { + CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef); + return CGColorSpaceGetNumberOfComponents(colorSpace) == 1; +} + +NS_INLINE void pin_degreesFromOrientation(UIImageOrientation orientation, void (^completion)(CGFloat degrees, BOOL horizontalFlip, BOOL verticalFlip)) { + switch (orientation) { + case UIImageOrientationUp: // default orientation + completion(0.0, NO, NO); + break; + case UIImageOrientationDown: // 180 deg rotation + completion(180.0, NO, NO); + break; + case UIImageOrientationLeft: + completion(270.0, NO, NO); // 90 deg CCW + break; + case UIImageOrientationRight: + completion(90.0, NO, NO); // 90 deg CW + break; + case UIImageOrientationUpMirrored: // as above but image mirrored along other axis. horizontal flip + completion(0.0, YES, NO); + break; + case UIImageOrientationDownMirrored: // horizontal flip + completion(180.0, YES, NO); + break; + case UIImageOrientationLeftMirrored: // vertical flip + completion(270.0, NO, YES); + break; + case UIImageOrientationRightMirrored: // vertical flip + completion(90.0, NO, YES); + break; + } +} +#endif + +#if !PIN_TARGET_IOS +@implementation NSImage (PINiOSMapping) + +- (CGImageRef)CGImage +{ + NSGraphicsContext *context = [NSGraphicsContext currentContext]; + NSRect rect = NSMakeRect(0.0, 0.0, self.size.width, self.size.height); + return [self CGImageForProposedRect:&rect context:context hints:NULL]; +} + ++ (NSImage *)imageWithData:(NSData *)imageData; +{ + return [[self alloc] initWithData:imageData]; +} + ++ (NSImage *)imageWithContentsOfFile:(NSString *)path +{ + return path ? [[self alloc] initWithContentsOfFile:path] : nil; +} + ++ (NSImage *)imageWithCGImage:(CGImageRef)imageRef +{ + return [[self alloc] initWithCGImage:imageRef size:CGSizeZero]; +} + +@end +#endif + +NSData * __nullable PINImageJPEGRepresentation(PINImage * __nonnull image, CGFloat compressionQuality) +{ +#if PIN_TARGET_IOS + return UIImageJPEGRepresentation(image, compressionQuality); +#elif PIN_TARGET_MAC + NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:[image TIFFRepresentation]]; + NSDictionary *imageProperties = @{NSImageCompressionFactor : @(compressionQuality)}; + return [imageRep representationUsingType:NSBitmapImageFileTypeJPEG properties:imageProperties]; +#endif +} + +NSData * __nullable PINImagePNGRepresentation(PINImage * __nonnull image) { +#if PIN_TARGET_IOS + return UIImagePNGRepresentation(image); +#elif PIN_TARGET_MAC + NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:[image TIFFRepresentation]]; + NSDictionary *imageProperties = @{NSImageCompressionFactor : @1}; + return [imageRep representationUsingType:NSBitmapImageFileTypePNG properties:imageProperties]; +#endif +} + + +@implementation PINImage (PINDecodedImage) + ++ (PINImage *)pin_decodedImageWithData:(NSData *)data +{ + return [self pin_decodedImageWithData:data skipDecodeIfPossible:NO]; +} + ++ (PINImage *)pin_decodedImageWithData:(NSData *)data skipDecodeIfPossible:(BOOL)skipDecodeIfPossible +{ + if (data == nil) { + return nil; + } + + PINImage *decodedImage = nil; + + CGImageSourceRef imageSourceRef = CGImageSourceCreateWithData((CFDataRef)data, NULL); + + if (imageSourceRef) { + CGImageRef imageRef = CGImageSourceCreateImageAtIndex(imageSourceRef, 0, (CFDictionaryRef)@{(NSString *)kCGImageSourceShouldCache : (NSNumber *)kCFBooleanFalse}); + if (imageRef) { +#if PIN_TARGET_IOS + UIImageOrientation orientation = pin_UIImageOrientationFromImageSource(imageSourceRef); + if (skipDecodeIfPossible) { + decodedImage = [PINImage imageWithCGImage:imageRef scale:1.0 orientation:orientation]; + } else { + decodedImage = [self pin_decodedImageWithCGImageRef:imageRef orientation:orientation]; + } +#elif PIN_TARGET_MAC + if (skipDecodeIfPossible) { + CGSize imageSize = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)); + decodedImage = [[NSImage alloc] initWithCGImage:imageRef size:imageSize]; + } else { + decodedImage = [self pin_decodedImageWithCGImageRef:imageRef]; + } +#endif + CGImageRelease(imageRef); + } + + CFRelease(imageSourceRef); + } + + return decodedImage; +} + ++ (PINImage *)pin_decodedImageWithCGImageRef:(CGImageRef)imageRef +{ +#if PIN_TARGET_IOS + return [self pin_decodedImageWithCGImageRef:imageRef orientation:UIImageOrientationUp]; +} + ++ (PINImage *)pin_decodedImageWithCGImageRef:(CGImageRef)imageRef orientation:(UIImageOrientation)orientation +{ +#endif +#if PIN_TARGET_IOS + return [self pin_decodedImageUsingGraphicsImageRendererRefWithCGImageRef:imageRef scale:1.0 orientation:orientation]; +#elif PIN_TARGET_MAC + return [[NSImage alloc] initWithCGImage:[self pin_decodedImageRefWithCGImageRef:imageRef] size:NSZeroSize]; +#endif +} + +#if PIN_TARGET_IOS ++ (PINImage *)pin_decodedImageUsingGraphicsImageRendererRefWithCGImageRef:(CGImageRef)imageRef + scale:(CGFloat)scale + orientation:(UIImageOrientation)orientation { + UIGraphicsImageRendererFormat *format = [UIGraphicsImageRendererFormat preferredFormat]; + + format.scale = scale; + format.opaque = pin_CGImageRefIsOpaque(imageRef); + if (format.opaque && !pin_CGImageRefIsGrayscale(imageRef)) { + // For color images, if we leave `preferredRange` alone it'll add alpha + // even to opaque images. So we set it to standard, which respects opaque + // For grayscale images, if we set `preferredRange` it'll add all other color + // channels (rgb). If we leave it alone, it'll keep it just gray (grayscale) + format.preferredRange = UIGraphicsImageRendererFormatRangeStandard; + } + + __block CGFloat radians = 0.0; + __block BOOL doHorizontalFlip = NO; + __block BOOL doVerticalFlip = NO; + + pin_degreesFromOrientation(orientation, ^(CGFloat degrees, BOOL horizontalFlip, BOOL verticalFlip) { + // Convert degrees to radians + radians = [[[NSMeasurement alloc] initWithDoubleValue:degrees + unit:[NSUnitAngle degrees]] + measurementByConvertingToUnit:[NSUnitAngle radians]].doubleValue; + doHorizontalFlip = horizontalFlip; + doVerticalFlip = verticalFlip; + }); + + // Create rotation out of radians + CGAffineTransform transform = CGAffineTransformMakeRotation(radians); + + // Grab image size + CGSize imageSize = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)); + + // Rotate rect by transformation + CGRect rotatedRect = CGRectApplyAffineTransform(CGRectMake(0.0, 0.0, imageSize.width, imageSize.height), transform); + + // Use graphics renderer to render image + UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:rotatedRect.size format:format]; + + return [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) { + CGContextRef ctx = rendererContext.CGContext; + + // Flip the default coordinate system for iOS/tvOS: https://developer.apple.com/library/archive/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/GraphicsDrawingOverview/GraphicsDrawingOverview.html#//apple_ref/doc/uid/TP40010156-CH14-SW4 + CGContextTranslateCTM(ctx, rotatedRect.size.width / 2.0, rotatedRect.size.height / 2.0); + CGContextScaleCTM(ctx, (doHorizontalFlip ? -1.0 : 1.0), (doVerticalFlip ? 1.0 : -1.0)); + + // Apply transformation + CGContextConcatCTM(ctx, transform); + + // Draw image + CGContextDrawImage(ctx, CGRectMake(-(imageSize.width / 2.0), -(imageSize.height / 2.0), imageSize.width, imageSize.height), imageRef); + }]; +} +#endif + ++ (CGImageRef)pin_decodedImageRefWithCGImageRef:(CGImageRef)imageRef +{ + CGSize imageSize = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)); + + CGBitmapInfo info = pin_CGImageRefIsOpaque(imageRef) ? (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host) : (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host); + CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); + + //Use UIGraphicsBeginImageContext parameters from docs: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIKitFunctionReference/#//apple_ref/c/func/UIGraphicsBeginImageContextWithOptions + CGContextRef ctx = CGBitmapContextCreate(NULL, imageSize.width, imageSize.height, + 8, + 0, + colorspace, + info); + + CGColorSpaceRelease(colorspace); + + if (ctx) { + CGContextSetBlendMode(ctx, kCGBlendModeCopy); + CGContextDrawImage(ctx, CGRectMake(0, 0, imageSize.width, imageSize.height), imageRef); + + CGImageRef decodedImageRef = CGBitmapContextCreateImage(ctx); + if (decodedImageRef) { + CFAutorelease(decodedImageRef); + } + CGContextRelease(ctx); + return decodedImageRef; + + } + + return imageRef; +} + +#if PIN_TARGET_IOS +UIImageOrientation pin_UIImageOrientationFromImageSource(CGImageSourceRef imageSourceRef) { + UIImageOrientation orientation = UIImageOrientationUp; + + if (imageSourceRef != nil) { + NSDictionary *dict = (NSDictionary *)CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(imageSourceRef, 0, NULL)); + + if (dict != nil) { + + NSNumber* exifOrientation = dict[(id)kCGImagePropertyOrientation]; + if (exifOrientation != nil) { + + switch (exifOrientation.intValue) { + case 1: /*kCGImagePropertyOrientationUp*/ + orientation = UIImageOrientationUp; + break; + + case 2: /*kCGImagePropertyOrientationUpMirrored*/ + orientation = UIImageOrientationUpMirrored; + break; + + case 3: /*kCGImagePropertyOrientationDown*/ + orientation = UIImageOrientationDown; + break; + + case 4: /*kCGImagePropertyOrientationDownMirrored*/ + orientation = UIImageOrientationDownMirrored; + break; + case 5: /*kCGImagePropertyOrientationLeftMirrored*/ + orientation = UIImageOrientationLeftMirrored; + break; + + case 6: /*kCGImagePropertyOrientationRight*/ + orientation = UIImageOrientationRight; + break; + + case 7: /*kCGImagePropertyOrientationRightMirrored*/ + orientation = UIImageOrientationRightMirrored; + break; + + case 8: /*kCGImagePropertyOrientationLeft*/ + orientation = UIImageOrientationLeft; + break; + + default: + break; + } + } + } + } + + return orientation; +} + +#endif + +@end diff --git a/Source/Classes/Categories/PINImage+ScaledImage.m b/Source/Classes/Categories/PINImage+ScaledImage.m new file mode 100644 index 00000000..0f1fae0b --- /dev/null +++ b/Source/Classes/Categories/PINImage+ScaledImage.m @@ -0,0 +1,56 @@ +// +// UIImage+ScaledImage.m +// Pods +// +// Created by Michael Schneider on 2/9/17. +// +// + +#import + +static inline PINImage *PINScaledImageForKey(NSString * __nullable key, PINImage * __nullable image) { + if (image == nil) { + return nil; + } + +#if PIN_TARGET_IOS + + NSCAssert(image.CGImage != NULL, @"CGImage should not be NULL"); + + CGFloat scale = 1.0; + if (key.length >= 8) { + if ([key rangeOfString:@"_2x."].location != NSNotFound || + [key rangeOfString:@"@2x."].location != NSNotFound) { + scale = 2.0; + } + + if ([key rangeOfString:@"_3x."].location != NSNotFound || + [key rangeOfString:@"@3x."].location != NSNotFound) { + scale = 3.0; + } + } + + if (scale != image.scale) { + return [[UIImage alloc] initWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation]; + } + + return image; + +#elif PIN_TARGET_MAC + return image; +#endif +} + +@implementation PINImage (ScaledImage) + +- (PINImage *)pin_scaledImageForKey:(NSString *)key +{ + return PINScaledImageForKey(key, self); +} + ++ (PINImage *)pin_scaledImageForImage:(PINImage *)image withKey:(NSString *)key +{ + return PINScaledImageForKey(key, image); +} + +@end diff --git a/Source/Classes/ImageCategories/PINAnimatedImageView+PINRemoteImage.m b/Source/Classes/ImageCategories/PINAnimatedImageView+PINRemoteImage.m new file mode 100644 index 00000000..780fe645 --- /dev/null +++ b/Source/Classes/ImageCategories/PINAnimatedImageView+PINRemoteImage.m @@ -0,0 +1,118 @@ +// +// PINAnimatedImageView+PINRemoteImage.m +// Pods +// +// Created by Garrett Moon on 4/19/18. +// + +#import +#import + +@implementation PINAnimatedImageView (PINRemoteImage) + +- (void)pin_setImageFromURL:(NSURL *)url +{ + [PINRemoteImageCategoryManager setImageOnView:self fromURL:url]; +} + +- (void)pin_setImageFromURL:(NSURL *)url placeholderImage:(PINImage *)placeholderImage +{ + [PINRemoteImageCategoryManager setImageOnView:self fromURL:url placeholderImage:placeholderImage]; +} + +- (void)pin_setImageFromURL:(NSURL *)url completion:(PINRemoteImageManagerImageCompletion)completion +{ + [PINRemoteImageCategoryManager setImageOnView:self fromURL:url completion:completion]; +} + +- (void)pin_setImageFromURL:(NSURL *)url placeholderImage:(PINImage *)placeholderImage completion:(PINRemoteImageManagerImageCompletion)completion +{ + [PINRemoteImageCategoryManager setImageOnView:self fromURL:url placeholderImage:placeholderImage completion:completion]; +} + +- (void)pin_setImageFromURL:(NSURL *)url processorKey:(NSString *)processorKey processor:(PINRemoteImageManagerImageProcessor)processor +{ + [PINRemoteImageCategoryManager setImageOnView:self fromURL:url processorKey:processorKey processor:processor]; +} + +- (void)pin_setImageFromURL:(NSURL *)url placeholderImage:(PINImage *)placeholderImage processorKey:(NSString *)processorKey processor:(PINRemoteImageManagerImageProcessor)processor +{ + [PINRemoteImageCategoryManager setImageOnView:self fromURL:url placeholderImage:placeholderImage processorKey:processorKey processor:processor]; +} + +- (void)pin_setImageFromURL:(NSURL *)url processorKey:(NSString *)processorKey processor:(PINRemoteImageManagerImageProcessor)processor completion:(PINRemoteImageManagerImageCompletion)completion +{ + [PINRemoteImageCategoryManager setImageOnView:self fromURL:url processorKey:processorKey processor:processor completion:completion]; +} + +- (void)pin_setImageFromURL:(NSURL *)url placeholderImage:(PINImage *)placeholderImage processorKey:(NSString *)processorKey processor:(PINRemoteImageManagerImageProcessor)processor completion:(PINRemoteImageManagerImageCompletion)completion +{ + [PINRemoteImageCategoryManager setImageOnView:self fromURLs:@[url] placeholderImage:placeholderImage processorKey:processorKey processor:processor completion:completion]; +} + +- (void)pin_setImageFromURLs:(NSArray *)urls +{ + [PINRemoteImageCategoryManager setImageOnView:self fromURLs:urls]; +} + +- (void)pin_setImageFromURLs:(NSArray *)urls placeholderImage:(PINImage *)placeholderImage +{ + [PINRemoteImageCategoryManager setImageOnView:self fromURLs:urls placeholderImage:placeholderImage]; +} + +- (void)pin_setImageFromURLs:(NSArray *)urls placeholderImage:(PINImage *)placeholderImage completion:(PINRemoteImageManagerImageCompletion)completion +{ + [PINRemoteImageCategoryManager setImageOnView:self fromURLs:urls placeholderImage:placeholderImage completion:completion]; +} + +- (void)pin_cancelImageDownload +{ + [PINRemoteImageCategoryManager cancelImageDownloadOnView:self]; +} + +- (NSUUID *)pin_downloadImageOperationUUID +{ + return [PINRemoteImageCategoryManager downloadImageOperationUUIDOnView:self]; +} + +- (void)pin_setDownloadImageOperationUUID:(NSUUID *)downloadImageOperationUUID +{ + [PINRemoteImageCategoryManager setDownloadImageOperationUUID:downloadImageOperationUUID onView:self]; +} + +- (BOOL)pin_updateWithProgress +{ + return [PINRemoteImageCategoryManager updateWithProgressOnView:self]; +} + +- (void)setPin_updateWithProgress:(BOOL)updateWithProgress +{ + [PINRemoteImageCategoryManager setUpdateWithProgressOnView:updateWithProgress onView:self]; +} + +- (void)pin_setPlaceholderWithImage:(PINImage *)image +{ + self.image = image; +} + +- (void)pin_updateUIWithRemoteImageManagerResult:(PINRemoteImageManagerResult *)result +{ + if (result.alternativeRepresentation && [result.alternativeRepresentation isKindOfClass:[PINCachedAnimatedImage class]]) { + self.animatedImage = (PINCachedAnimatedImage *)result.alternativeRepresentation; + } else if (result.image) { + self.image = result.image; + } +} + +- (void)pin_clearImages +{ + self.animatedImage = nil; + self.image = nil; +} + +- (BOOL)pin_ignoreGIFs +{ + return NO; +} + +@end diff --git a/Pod/Classes/Image Categories/PINButton+PINRemoteImage.m b/Source/Classes/ImageCategories/PINButton+PINRemoteImage.m similarity index 98% rename from Pod/Classes/Image Categories/PINButton+PINRemoteImage.m rename to Source/Classes/ImageCategories/PINButton+PINRemoteImage.m index 50f5d802..168c1a07 100644 --- a/Pod/Classes/Image Categories/PINButton+PINRemoteImage.m +++ b/Source/Classes/ImageCategories/PINButton+PINRemoteImage.m @@ -6,7 +6,7 @@ // // -#import "PINButton+PINRemoteImage.h" +#import @implementation PINButton (PINRemoteImage) diff --git a/Pod/Classes/Image Categories/PINImageView+PINRemoteImage.m b/Source/Classes/ImageCategories/PINImageView+PINRemoteImage.m similarity index 98% rename from Pod/Classes/Image Categories/PINImageView+PINRemoteImage.m rename to Source/Classes/ImageCategories/PINImageView+PINRemoteImage.m index 1e6a6ab2..ef5d911f 100644 --- a/Pod/Classes/Image Categories/PINImageView+PINRemoteImage.m +++ b/Source/Classes/ImageCategories/PINImageView+PINRemoteImage.m @@ -6,7 +6,7 @@ // // -#import "PINImageView+PINRemoteImage.h" +#import @implementation PINImageView (PINRemoteImage) diff --git a/Source/Classes/PINAlternateRepresentationProvider.m b/Source/Classes/PINAlternateRepresentationProvider.m new file mode 100644 index 00000000..9fae69ac --- /dev/null +++ b/Source/Classes/PINAlternateRepresentationProvider.m @@ -0,0 +1,34 @@ +// +// PINAlternateRepresentationProvider.m +// Pods +// +// Created by Garrett Moon on 3/17/16. +// +// + +#import + +#import +#import + +@implementation PINAlternateRepresentationProvider + +- (id)alternateRepresentationWithData:(NSData *)data options:(PINRemoteImageManagerDownloadOptions)options +{ + if ([data pin_isAnimatedGIF]) { + return [[PINCachedAnimatedImage alloc] initWithAnimatedImageData:data]; + } +#if PIN_WEBP + if ([data pin_isAnimatedWebP]) { + return [[PINCachedAnimatedImage alloc] initWithAnimatedImageData:data]; + } +#endif +#if PIN_APNG + if ([data pin_isAPNG]) { + return [[PINCachedAnimatedImage alloc] initWithAnimatedImageData:data]; + } +#endif + return nil; +} + +@end diff --git a/Source/Classes/PINCache/PINCache+PINRemoteImageCaching.m b/Source/Classes/PINCache/PINCache+PINRemoteImageCaching.m new file mode 100644 index 00000000..d462b15a --- /dev/null +++ b/Source/Classes/PINCache/PINCache+PINRemoteImageCaching.m @@ -0,0 +1,113 @@ +// +// PINCache+PINRemoteImageCaching.m +// Pods +// +// Created by Aleksei Shevchenko on 7/28/16. +// +// + +#import + +@implementation PINCache (PINRemoteImageCaching) + +//****************************************************************************************************** +// Memory cache methods +//****************************************************************************************************** +- (nullable id)objectFromMemoryForKey:(NSString *)key +{ + return [self.memoryCache objectForKey:key]; +} + +- (void)setObjectInMemory:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost withAgeLimit:(NSTimeInterval)ageLimit +{ + [self.memoryCache setObject:object forKey:key withCost:cost ageLimit:ageLimit]; +} + +- (void)setObjectInMemory:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost +{ + [self.memoryCache setObject:object forKey:key withCost:cost]; +} + +- (void)removeObjectForKeyFromMemory:(NSString *)key +{ + [self.memoryCache removeObjectForKey:key]; +} + +//****************************************************************************************************** +// Disk cache methods +//****************************************************************************************************** +- (nullable id)objectFromDiskForKey:(NSString *)key +{ + return [self.diskCache objectForKey:key]; +} + +- (void)objectFromDiskForKey:(NSString *)key completion:(PINRemoteImageCachingObjectBlock)completion +{ + __weak typeof(self) weakSelf = self; + [self.diskCache objectForKeyAsync:key completion:^(PINDiskCache * _Nonnull cache, NSString * _Nonnull key, id _Nullable object) { + if(completion) { + typeof(self) strongSelf = weakSelf; + completion(strongSelf, key, object); + } + }]; +} + +- (void)setObjectOnDisk:(id)object forKey:(NSString *)key withAgeLimit:(NSTimeInterval)ageLimit +{ + [self.diskCache setObject:object forKey:key withAgeLimit:ageLimit]; +} + +- (void)setObjectOnDisk:(id)object forKey:(NSString *)key +{ + [self.diskCache setObject:object forKey:key withAgeLimit:0]; +} + +- (BOOL)objectExistsForKey:(NSString *)key +{ + return [self containsObjectForKey:key]; +} + +//****************************************************************************************************** +// Common cache methods +//****************************************************************************************************** +- (void)removeObjectForKey:(NSString *)key completion:(PINRemoteImageCachingObjectBlock)completion +{ + if (completion) { + __weak typeof(self) weakSelf = self; + [self removeObjectForKeyAsync:key completion:^(id _Nonnull cache, NSString * _Nonnull key, id _Nullable object) { + typeof(self) strongSelf = weakSelf; + completion(strongSelf, key, object); + }]; + } else { + [self removeObjectForKeyAsync:key completion:nil]; + } +} + +- (BOOL)diskCacheIsTTLCache +{ + return self.diskCache.isTTLCache; +} + +- (BOOL)memoryCacheIsTTLCache +{ + return self.memoryCache.isTTLCache; +} + +@end + +@implementation PINRemoteImageManager (PINCache) + +- (PINCache *)pinCache +{ + static BOOL isCachePINCache = NO; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + isCachePINCache = [self.cache isKindOfClass:[PINCache class]]; + }); + if (isCachePINCache) { + return (PINCache *)self.cache; + } + return nil; +} + +@end diff --git a/Source/Classes/PINDisplayLink.h b/Source/Classes/PINDisplayLink.h new file mode 100644 index 00000000..27f81f0c --- /dev/null +++ b/Source/Classes/PINDisplayLink.h @@ -0,0 +1,25 @@ +// +// PINDisplayLink.h +// Pods +// +// Created by Garrett Moon on 4/23/18. +// + +#import + +#import + +#if PIN_TARGET_IOS +#define PINDisplayLink CADisplayLink +#elif PIN_TARGET_MAC +@interface PINDisplayLink : NSObject + ++ (PINDisplayLink *)displayLinkWithTarget:(id)target selector:(SEL)sel; +- (void)addToRunLoop:(NSRunLoop *)runloop forMode:(NSRunLoopMode)mode; +- (void)removeFromRunLoop:(NSRunLoop *)runloop forMode:(NSRunLoopMode)mode; + +@property(getter=isPaused, nonatomic) BOOL paused; +@property(nonatomic) NSInteger frameInterval; + +@end +#endif diff --git a/Source/Classes/PINDisplayLink.m b/Source/Classes/PINDisplayLink.m new file mode 100644 index 00000000..4e70d464 --- /dev/null +++ b/Source/Classes/PINDisplayLink.m @@ -0,0 +1,129 @@ +// +// PINDisplayLink.m +// Pods +// +// Created by Garrett Moon on 4/23/18. +// + +#import "PINDisplayLink.h" + +#if PIN_TARGET_MAC + +#import + +@interface PINDisplayLink () + +@property (nonatomic, readonly) id target; +@property (nonatomic, readonly) SEL selector; +@property (nonatomic, readonly) NSRunLoop *runloop; +@property (nonatomic, readonly) NSRunLoopMode mode; + +- (void)displayLinkFired; + +@end + +static CVReturn displayLinkFired (CVDisplayLinkRef displayLink, + const CVTimeStamp *inNow, + const CVTimeStamp *inOutputTime, + CVOptionFlags flagsIn, + CVOptionFlags *flagsOut, + void *displayLinkContext) +{ + PINDisplayLink *link = (__bridge PINDisplayLink *)displayLinkContext; + [link displayLinkFired]; + return kCVReturnSuccess; +} + +@implementation PINDisplayLink +{ + CVDisplayLinkRef _displayLinkRef; + + BOOL _paused; + NSInteger _frameInterval; +} + ++ (PINDisplayLink *)displayLinkWithTarget:(id)target selector:(SEL)sel +{ + return [[PINDisplayLink alloc] initWithTarget:target selector:sel]; +} + +- (PINDisplayLink *)initWithTarget:(id)target selector:(SEL)sel +{ + if (self = [super init]) { + _target = target; + _selector = sel; + CVDisplayLinkCreateWithActiveCGDisplays(&_displayLinkRef); + CVDisplayLinkSetOutputCallback(_displayLinkRef, &displayLinkFired, (__bridge void * _Nullable)(self)); + } + return self; +} + +- (void)dealloc +{ + if (_displayLinkRef) { + CVDisplayLinkRelease(_displayLinkRef); + } +} + +- (void)displayLinkFired +{ + dispatch_async(dispatch_get_main_queue(), ^{ + [self.runloop performSelector:self.selector target:self.target argument:self order:NSUIntegerMax modes:@[self.mode]]; + }); +} + +- (void)addToRunLoop:(NSRunLoop *)runloop forMode:(NSRunLoopMode)mode +{ + PINAssertMain(); + NSAssert(runloop && mode, @"Must set a runloop and a mode."); + _runloop = runloop; + _mode = mode; + if (_paused == NO) { + CVDisplayLinkStart(_displayLinkRef); + } +} + +- (void)removeFromRunLoop:(NSRunLoop *)runloop forMode:(NSRunLoopMode)mode +{ + _runloop = nil; + _mode = nil; + if (_paused == NO) { + CVDisplayLinkStop(_displayLinkRef); + } +} + +- (BOOL)isPaused +{ + PINAssertMain(); + return _paused; +} + +- (void)setPaused:(BOOL)paused +{ + PINAssertMain(); + if (_paused == paused) { + return; + } + + _paused = paused; + if (paused) { + CVDisplayLinkStop(_displayLinkRef); + } else { + CVDisplayLinkStart(_displayLinkRef); + } +} + +- (NSInteger)frameInterval +{ + PINAssertMain(); + return _frameInterval; +} + +- (void)setFrameInterval:(NSInteger)frameInterval +{ + PINAssertMain(); + _frameInterval = frameInterval; +} + +@end +#endif diff --git a/Pod/Classes/PINProgressiveImage.m b/Source/Classes/PINProgressiveImage.m similarity index 84% rename from Pod/Classes/PINProgressiveImage.m rename to Source/Classes/PINProgressiveImage.m index 47e9fc3e..ff37e8b9 100644 --- a/Pod/Classes/PINProgressiveImage.m +++ b/Source/Classes/PINProgressiveImage.m @@ -6,26 +6,28 @@ // // -#import "PINProgressiveImage.h" +#import #import #import -#import "PINRemoteImage.h" -#import "PINImage+DecodedImage.h" +#import +#import "PINRemoteImageDownloadTask.h" +#import "PINSpeedRecorder.h" @interface PINProgressiveImage () +@property (nonatomic, strong) NSURLSessionDataTask *dataTask; @property (nonatomic, strong) NSMutableData *mutableData; @property (nonatomic, assign) int64_t expectedNumberOfBytes; @property (nonatomic, assign) CGImageSourceRef imageSource; @property (nonatomic, assign) CGSize size; @property (nonatomic, assign) BOOL isProgressiveJPEG; @property (nonatomic, assign) NSUInteger currentThreshold; -@property (nonatomic, assign) float bytesPerSecond; +@property (nonatomic, assign) NSUInteger startingBytes; @property (nonatomic, assign) NSUInteger scannedByte; @property (nonatomic, assign) NSInteger sosCount; -@property (nonatomic, strong) NSLock *lock; +@property (nonatomic, strong) PINRemoteLock *lock; #if DEBUG @property (nonatomic, assign) CFTimeInterval scanTime; #endif @@ -36,20 +38,18 @@ @implementation PINProgressiveImage @synthesize progressThresholds = _progressThresholds; @synthesize estimatedRemainingTimeThreshold = _estimatedRemainingTimeThreshold; -@synthesize startTime = _startTime; -- (instancetype)init +- (nonnull instancetype)initWithDataTask:(nonnull NSURLSessionDataTask *)dataTask { if (self = [super init]) { - self.lock = [[NSLock alloc] init]; - self.lock.name = @"PINProgressiveImage"; + self.lock = [[PINRemoteLock alloc] initWithName:@"PINProgressiveImage"]; + _dataTask = dataTask; _imageSource = CGImageSourceCreateIncremental(NULL);; self.size = CGSizeZero; self.isProgressiveJPEG = NO; self.currentThreshold = 0; self.progressThresholds = @[@0.00, @0.35, @0.65]; - self.startTime = CACurrentMediaTime(); self.estimatedRemainingTimeThreshold = -1; self.sosCount = 0; self.scannedByte = 0; @@ -73,9 +73,12 @@ - (void)dealloc - (void)setProgressThresholds:(NSArray *)progressThresholds { - [self.lock lock]; - _progressThresholds = [progressThresholds copy]; - [self.lock unlock]; + // There's no reason to set an empty progress thresholds array, instead don't use the progressive feature + if (progressThresholds.count > 0) { + [self.lock lock]; + _progressThresholds = [progressThresholds copy]; + [self.lock unlock]; + } } - (NSArray *)progressThresholds @@ -101,24 +104,40 @@ - (CFTimeInterval)estimatedRemainingTimeThreshold return estimatedRemainingTimeThreshold; } -- (void)setStartTime:(CFTimeInterval)startTime +- (CFTimeInterval)estimatedRemainingTime { - [self.lock lock]; - _startTime = startTime; - [self.lock unlock]; + __block CFTimeInterval estimatedRemainingTime; + [self.lock lockWithBlock:^{ + estimatedRemainingTime = [self l_estimatedRemainingTime]; + }]; + return estimatedRemainingTime; } -- (CFTimeInterval)startTime +- (CFTimeInterval)l_estimatedRemainingTime { - [self.lock lock]; - CFTimeInterval startTime = _startTime; - [self.lock unlock]; - return startTime; + if (_dataTask.countOfBytesExpectedToReceive == NSURLSessionTransferSizeUnknown) { + return MAXFLOAT; + } + NSUInteger remainingBytes = (NSUInteger)_dataTask.countOfBytesExpectedToReceive - (NSUInteger)_dataTask.countOfBytesReceived; + if (remainingBytes == 0) { + return 0; + } + + float bytesPerSecond = [[PINSpeedRecorder sharedRecorder] weightedAdjustedBytesPerSecondForHost:[_dataTask.currentRequest.URL host]]; + if (bytesPerSecond == -1) { + return MAXFLOAT; + } + return remainingBytes / bytesPerSecond; } -- (void)updateProgressiveImageWithData:(NSData *)data expectedNumberOfBytes:(int64_t)expectedNumberOfBytes +- (void)updateProgressiveImageWithData:(nonnull NSData *)data expectedNumberOfBytes:(int64_t)expectedNumberOfBytes isResume:(BOOL)isResume { [self.lock lock]; + if (isResume) { + NSAssert(self.mutableData == nil, @"If we're resuming, data shouldn't be setup yet."); + self.startingBytes = data.length; + } + if (self.mutableData == nil) { NSUInteger bytesToAlloc = 0; if (expectedNumberOfBytes > 0) { @@ -129,7 +148,7 @@ - (void)updateProgressiveImageWithData:(NSData *)data expectedNumberOfBytes:(int } [self.mutableData appendData:data]; - while ([self hasCompletedFirstScan] == NO && self.scannedByte < self.mutableData.length) { + while ([self l_hasCompletedFirstScan] == NO && self.scannedByte < self.mutableData.length) { #if DEBUG CFTimeInterval start = CACurrentMediaTime(); #endif @@ -137,7 +156,7 @@ - (void)updateProgressiveImageWithData:(NSData *)data expectedNumberOfBytes:(int if (startByte > 0) { startByte--; } - if ([self scanForSOSinData:self.mutableData startByte:startByte scannedByte:&_scannedByte]) { + if ([self l_scanForSOSinData:self.mutableData startByte:startByte scannedByte:&_scannedByte]) { self.sosCount++; } #if DEBUG @@ -165,12 +184,12 @@ - (PINImage *)currentImageBlurred:(BOOL)blurred maxProgressiveRenderSize:(CGSize return nil; } - if (_estimatedRemainingTimeThreshold > 0 && self.estimatedRemainingTime < _estimatedRemainingTimeThreshold) { + if (_estimatedRemainingTimeThreshold > 0 && [self l_estimatedRemainingTime] < _estimatedRemainingTimeThreshold) { [self.lock unlock]; return nil; } - if ([self hasCompletedFirstScan] == NO) { + if ([self l_hasCompletedFirstScan] == NO) { [self.lock unlock]; return nil; } @@ -219,7 +238,7 @@ - (PINImage *)currentImageBlurred:(BOOL)blurred maxProgressiveRenderSize:(CGSize [self.lock unlock]; return nil; } - + if (self.isProgressiveJPEG && self.size.width > 0 && self.size.height > 0 && progress > [_progressThresholds[self.currentThreshold] floatValue]) { while (self.currentThreshold < _progressThresholds.count && progress > [_progressThresholds[self.currentThreshold] floatValue]) { self.currentThreshold++; @@ -228,7 +247,7 @@ - (PINImage *)currentImageBlurred:(BOOL)blurred maxProgressiveRenderSize:(CGSize CGImageRef image = CGImageSourceCreateImageAtIndex(self.imageSource, 0, NULL); if (image) { if (blurred) { - currentImage = [self postProcessImage:[PINImage imageWithCGImage:image] withProgress:progress]; + currentImage = [self l_postProcessImage:[PINImage imageWithCGImage:image] withProgress:progress]; } else { currentImage = [PINImage imageWithCGImage:image]; } @@ -246,15 +265,14 @@ - (PINImage *)currentImageBlurred:(BOOL)blurred maxProgressiveRenderSize:(CGSize - (NSData *)data { [self.lock lock]; - NSData *data = [self.mutableData copy]; + NSData *data = [self.mutableData copy]; [self.lock unlock]; return data; } #pragma mark - private -//Must be called within lock -- (BOOL)scanForSOSinData:(NSData *)data startByte:(NSUInteger)startByte scannedByte:(NSUInteger *)scannedByte +- (BOOL)l_scanForSOSinData:(NSData *)data startByte:(NSUInteger)startByte scannedByte:(NSUInteger *)scannedByte { //check if we have a complete scan Byte scanMarker[2]; @@ -279,41 +297,13 @@ - (BOOL)scanForSOSinData:(NSData *)data startByte:(NSUInteger)startByte scannedB return NO; } -//Must be called within lock -- (BOOL)hasCompletedFirstScan +- (BOOL)l_hasCompletedFirstScan { return self.sosCount >= 2; } -//Must be called within lock -- (float)bytesPerSecond -{ - CFTimeInterval length = CACurrentMediaTime() - _startTime; - return self.mutableData.length / length; -} - -//Must be called within lock -- (CFTimeInterval)estimatedRemainingTime -{ - if (self.expectedNumberOfBytes < 0) { - return MAXFLOAT; - } - - NSUInteger remainingBytes = (NSUInteger)self.expectedNumberOfBytes - self.mutableData.length; - if (remainingBytes == 0) { - return 0; - } - - float bytesPerSecond = self.bytesPerSecond; - if (bytesPerSecond == 0) { - return MAXFLOAT; - } - return remainingBytes / self.bytesPerSecond; -} - -//Must be called within lock //Heavily cribbed from https://developer.apple.com/library/ios/samplecode/UIImageEffects/Listings/UIImageEffects_UIImageEffects_m.html#//apple_ref/doc/uid/DTS40013396-UIImageEffects_UIImageEffects_m-DontLinkElementID_9 -- (PINImage *)postProcessImage:(PINImage *)inputImage withProgress:(float)progress +- (PINImage *)l_postProcessImage:(PINImage *)inputImage withProgress:(float)progress { PINImage *outputImage = nil; CGImageRef inputImageRef = CGImageRetain(inputImage.CGImage); diff --git a/Source/Classes/PINRemoteImageBasicCache.h b/Source/Classes/PINRemoteImageBasicCache.h new file mode 100644 index 00000000..b6ec7c1c --- /dev/null +++ b/Source/Classes/PINRemoteImageBasicCache.h @@ -0,0 +1,19 @@ +// +// PINRemoteImageBasicCache.h +// Pods +// +// Created by Aleksei Shevchenko on 7/28/16. +// +// + +#import +#import + +/** + * Simplistic wrapper based on NSCache. + * + * No data is persisted on disk. The disk cache methods are no-op. + */ +@interface PINRemoteImageBasicCache : NSObject + +@end diff --git a/Source/Classes/PINRemoteImageBasicCache.m b/Source/Classes/PINRemoteImageBasicCache.m new file mode 100644 index 00000000..a3953ce8 --- /dev/null +++ b/Source/Classes/PINRemoteImageBasicCache.m @@ -0,0 +1,99 @@ +// +// PINRemoteImageBasicCache.m +// Pods +// +// Created by Aleksei Shevchenko on 7/28/16. +// +// + +#import "PINRemoteImageBasicCache.h" + +@interface PINRemoteImageBasicCache() +@property (nonatomic, strong) NSCache *cache; +@end + +@implementation PINRemoteImageBasicCache + +- (instancetype)init +{ + self = [super init]; + if (self) { + self.cache = [[NSCache alloc] init]; + } + return self; +} + +//****************************************************************************************************** +// Memory cache methods +//****************************************************************************************************** +-(nullable id)objectFromMemoryForKey:(NSString *)key +{ + return [self.cache objectForKey:key]; +} + +-(void)setObjectInMemory:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost +{ + [self.cache setObject:object forKey:key cost:cost]; +} + +- (void)removeObjectForKeyFromMemory:(NSString *)key +{ + [self.cache removeObjectForKey:key]; +} + +//****************************************************************************************************** +// Disk cache methods +//****************************************************************************************************** +-(nullable id)objectFromDiskForKey:(NSString *)key +{ + return nil; +} + +-(void)objectFromDiskForKey:(NSString *)key completion:(PINRemoteImageCachingObjectBlock)completion +{ + __weak typeof(self) weakSelf = self; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + if (completion) { + typeof(self) strongSelf = weakSelf; + completion(strongSelf, key, nil); + } + }); +} + +-(void)setObjectOnDisk:(id)object forKey:(NSString *)key +{ + +} + +//****************************************************************************************************** +// Common methods, should apply to both in-memory and disk storage +//****************************************************************************************************** +- (BOOL)objectExistsForKey:(NSString *)key +{ + return [self.cache objectForKey:key] != nil; +} + +- (void)removeObjectForKey:(NSString *)key +{ + [self.cache removeObjectForKey:key]; +} + +- (void)removeObjectForKey:(NSString *)key completion:(PINRemoteImageCachingObjectBlock)completion +{ + __weak typeof(self) weakSelf = self; + id object = [self.cache objectForKey:key]; + [self.cache removeObjectForKey:key]; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + if (completion) { + typeof(self) strongSelf = weakSelf; + completion(strongSelf, key, object); + } + }); +} + +- (void)removeAllObjects +{ + [self.cache removeAllObjects]; +} + +@end diff --git a/Source/Classes/PINRemoteImageCallbacks.h b/Source/Classes/PINRemoteImageCallbacks.h new file mode 100644 index 00000000..7304518e --- /dev/null +++ b/Source/Classes/PINRemoteImageCallbacks.h @@ -0,0 +1,20 @@ +// +// PINRemoteImageCallbacks.h +// Pods +// +// Created by Garrett Moon on 3/9/15. +// +// + +#import + +#import + +@interface PINRemoteImageCallbacks : NSObject + +@property (atomic, strong, nullable) PINRemoteImageManagerImageCompletion completionBlock; +@property (atomic, strong, nullable) PINRemoteImageManagerImageCompletion progressImageBlock; +@property (atomic, strong, nullable) PINRemoteImageManagerProgressDownload progressDownloadBlock; +@property (assign, readonly) CFTimeInterval requestTime; + +@end diff --git a/Source/Classes/PINRemoteImageCallbacks.m b/Source/Classes/PINRemoteImageCallbacks.m new file mode 100644 index 00000000..f64795bc --- /dev/null +++ b/Source/Classes/PINRemoteImageCallbacks.m @@ -0,0 +1,21 @@ +// +// PINRemoteImageCallbacks.m +// Pods +// +// Created by Garrett Moon on 3/9/15. +// +// + +#import "PINRemoteImageCallbacks.h" + +@implementation PINRemoteImageCallbacks + +- (instancetype)init +{ + if (self = [super init]) { + _requestTime = CACurrentMediaTime(); + } + return self; +} + +@end diff --git a/Pod/Classes/PINRemoteImageCategoryManager.m b/Source/Classes/PINRemoteImageCategoryManager.m similarity index 98% rename from Pod/Classes/PINRemoteImageCategoryManager.m rename to Source/Classes/PINRemoteImageCategoryManager.m index 712ea1b4..9333d680 100644 --- a/Pod/Classes/PINRemoteImageCategoryManager.m +++ b/Source/Classes/PINRemoteImageCategoryManager.m @@ -6,7 +6,7 @@ // // -#import "PINRemoteImageCategoryManager.h" +#import #import @@ -191,7 +191,7 @@ + (void)setImageOnView:(id )view if ([self updateWithProgressOnView:view] && processorKey.length <= 0 && processor == nil) { internalProgress = ^(PINRemoteImageManagerResult *result) { - void (^mainQueue)() = ^{ + void (^mainQueue)(void) = ^{ //if result.UUID is nil, we returned immediately and want this result NSUUID *currentUUID = [self downloadImageOperationUUIDOnView:view]; if (![currentUUID isEqual:result.UUID] && result.UUID != nil) { @@ -214,7 +214,7 @@ + (void)setImageOnView:(id )view PINRemoteImageManagerImageCompletion internalCompletion = ^(PINRemoteImageManagerResult *result) { - void (^mainQueue)() = ^{ + void (^mainQueue)(void) = ^{ //if result.UUID is nil, we returned immediately and want this result NSUUID *currentUUID = [self downloadImageOperationUUIDOnView:view]; if (![currentUUID isEqual:result.UUID] && result.UUID != nil) { diff --git a/Source/Classes/PINRemoteImageDownloadQueue.h b/Source/Classes/PINRemoteImageDownloadQueue.h new file mode 100644 index 00000000..7269b9ec --- /dev/null +++ b/Source/Classes/PINRemoteImageDownloadQueue.h @@ -0,0 +1,47 @@ +// +// PINRemoteImageDownloadQueue.h +// PINRemoteImage +// +// Created by Garrett Moon on 3/1/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import + +#import + +@class PINURLSessionManager; + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^PINRemoteImageDownloadCompletion)(NSURLResponse * _Nullable response, NSError *error); + +@interface PINRemoteImageDownloadQueue : NSObject + +@property (atomic, assign) NSUInteger maxNumberOfConcurrentDownloads; + +- (instancetype)init NS_UNAVAILABLE; ++ (PINRemoteImageDownloadQueue *)queueWithMaxConcurrentDownloads:(NSUInteger)maxNumberOfConcurrentDownloads; + +- (NSURLSessionDataTask *)addDownloadWithSessionManager:(PINURLSessionManager *)sessionManager + request:(NSURLRequest *)request + priority:(PINRemoteImageManagerPriority)priority + completionHandler:(PINRemoteImageDownloadCompletion)completionHandler; + +/*** + This prevents a task from being run if it hasn't already started yet. It is the caller's responsibility to cancel + the task if it has already been started. + + @return BOOL Returns YES if the task was in the queue. + */ +- (BOOL)removeDownloadTaskFromQueue:(NSURLSessionDataTask *)downloadTask; + +/* + This sets the tasks priority of execution. It is the caller's responsibility to set the priority on the task itself + for NSURLSessionManager. + */ +- (void)setQueuePriority:(PINRemoteImageManagerPriority)priority forTask:(NSURLSessionDataTask *)downloadTask; + +NS_ASSUME_NONNULL_END + +@end diff --git a/Source/Classes/PINRemoteImageDownloadQueue.m b/Source/Classes/PINRemoteImageDownloadQueue.m new file mode 100644 index 00000000..2965fffc --- /dev/null +++ b/Source/Classes/PINRemoteImageDownloadQueue.m @@ -0,0 +1,177 @@ +// +// PINRemoteImageDownloadQueue.m +// PINRemoteImage +// +// Created by Garrett Moon on 3/1/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import "PINRemoteImageDownloadQueue.h" + +#import +#import "PINRemoteLock.h" + +@interface PINRemoteImageDownloadQueue () +{ + PINRemoteLock *_lock; + + NSMutableOrderedSet *_highPriorityQueuedOperations; + NSMutableOrderedSet *_defaultPriorityQueuedOperations; + NSMutableOrderedSet *_lowPriorityQueuedOperations; + NSMutableSet *_runningTasks; +} + +@end + +@implementation PINRemoteImageDownloadQueue + +@synthesize maxNumberOfConcurrentDownloads = _maxNumberOfConcurrentDownloads; + ++ (PINRemoteImageDownloadQueue *)queueWithMaxConcurrentDownloads:(NSUInteger)maxNumberOfConcurrentDownloads +{ + return [[PINRemoteImageDownloadQueue alloc] initWithMaxConcurrentDownloads:maxNumberOfConcurrentDownloads]; +} + +- (PINRemoteImageDownloadQueue *)initWithMaxConcurrentDownloads:(NSUInteger)maxNumberOfConcurrentDownloads +{ + if (self = [super init]) { + _maxNumberOfConcurrentDownloads = maxNumberOfConcurrentDownloads; + + _lock = [[PINRemoteLock alloc] initWithName:@"PINRemoteImageDownloadQueue Lock"]; + _highPriorityQueuedOperations = [[NSMutableOrderedSet alloc] init]; + _defaultPriorityQueuedOperations = [[NSMutableOrderedSet alloc] init]; + _lowPriorityQueuedOperations = [[NSMutableOrderedSet alloc] init]; + _runningTasks = [[NSMutableSet alloc] init]; + } + return self; +} + +- (NSUInteger)maxNumberOfConcurrentDownloads +{ + [self lock]; + NSUInteger maxNumberOfConcurrentDownloads = _maxNumberOfConcurrentDownloads; + [self unlock]; + return maxNumberOfConcurrentDownloads; +} + +- (void)setMaxNumberOfConcurrentDownloads:(NSUInteger)maxNumberOfConcurrentDownloads +{ + [self lock]; + _maxNumberOfConcurrentDownloads = maxNumberOfConcurrentDownloads; + [self unlock]; + + [self scheduleDownloadsIfNeeded]; +} + +- (NSURLSessionDataTask *)addDownloadWithSessionManager:(PINURLSessionManager *)sessionManager + request:(NSURLRequest *)request + priority:(PINRemoteImageManagerPriority)priority + completionHandler:(PINRemoteImageDownloadCompletion)completionHandler +{ + NSURLSessionDataTask *dataTask = [sessionManager dataTaskWithRequest:request + priority:priority + completionHandler:^(NSURLSessionTask *task, NSError *error) { + completionHandler(task.response, error); + [self lock]; + [self->_runningTasks removeObject:task]; + [self unlock]; + + [self scheduleDownloadsIfNeeded]; + }]; + + [self setQueuePriority:priority forTask:dataTask addIfNecessary:YES]; + + [self scheduleDownloadsIfNeeded]; + + return dataTask; +} + +- (void)scheduleDownloadsIfNeeded +{ + [self lock]; + while (_runningTasks.count < _maxNumberOfConcurrentDownloads) { + NSMutableOrderedSet *queue = nil; + if (_highPriorityQueuedOperations.count > 0) { + queue = _highPriorityQueuedOperations; + } else if (_defaultPriorityQueuedOperations.count > 0) { + queue = _defaultPriorityQueuedOperations; + } else if (_lowPriorityQueuedOperations.count > 0) { + queue = _lowPriorityQueuedOperations; + } + + if (!queue) { + break; + } + + NSURLSessionDataTask *task = [queue firstObject]; + [queue removeObjectAtIndex:0]; + [task resume]; + + [_runningTasks addObject:task]; + } + [self unlock]; +} + +- (BOOL)removeDownloadTaskFromQueue:(NSURLSessionDataTask *)downloadTask +{ + BOOL containsTask = NO; + [self lock]; + if ([_highPriorityQueuedOperations containsObject:downloadTask]) { + containsTask = YES; + [_highPriorityQueuedOperations removeObject:downloadTask]; + } else if ([_defaultPriorityQueuedOperations containsObject:downloadTask]) { + containsTask = YES; + [_defaultPriorityQueuedOperations removeObject:downloadTask]; + } else if ([_lowPriorityQueuedOperations containsObject:downloadTask]) { + containsTask = YES; + [_lowPriorityQueuedOperations removeObject:downloadTask]; + } + [self unlock]; + return containsTask; +} + +- (void)setQueuePriority:(PINRemoteImageManagerPriority)priority forTask:(NSURLSessionDataTask *)downloadTask +{ + [self setQueuePriority:priority forTask:downloadTask addIfNecessary:NO]; +} + +- (void)setQueuePriority:(PINRemoteImageManagerPriority)priority forTask:(NSURLSessionDataTask *)downloadTask addIfNecessary:(BOOL)addIfNecessary +{ + BOOL containsTask = [self removeDownloadTaskFromQueue:downloadTask]; + + if (containsTask || addIfNecessary) { + NSMutableOrderedSet *queue = nil; + [self lock]; + switch (priority) { + case PINRemoteImageManagerPriorityLow: + queue = _lowPriorityQueuedOperations; + break; + + case PINRemoteImageManagerPriorityDefault: + queue = _defaultPriorityQueuedOperations; + break; + + case PINRemoteImageManagerPriorityHigh: + queue = _highPriorityQueuedOperations; + break; + + default: + NSAssert(NO, @"invalid priority: %tu", priority); + break; + } + [queue addObject:downloadTask]; + [self unlock]; + } +} + +- (void)lock +{ + [_lock lock]; +} + +- (void)unlock +{ + [_lock unlock]; +} + +@end diff --git a/Source/Classes/PINRemoteImageDownloadTask.h b/Source/Classes/PINRemoteImageDownloadTask.h new file mode 100644 index 00000000..2ee67d5e --- /dev/null +++ b/Source/Classes/PINRemoteImageDownloadTask.h @@ -0,0 +1,37 @@ +// +// PINRemoteImageDownloadTask.h +// Pods +// +// Created by Garrett Moon on 3/9/15. +// +// + +#if !__has_include() +#import "PINOperation.h" +#else +#import +#endif + +#import "PINRemoteImageManager+Private.h" +#import "PINRemoteImageTask.h" +#import +#import "PINResume.h" + +@interface PINRemoteImageDownloadTask : PINRemoteImageTask + +@property (nonatomic, strong, nullable, readonly) NSURL *URL; +@property (nonatomic, copy, nullable) NSString *ifRange; +@property (nonatomic, copy, readonly, nullable) NSData *data; + +@property (nonatomic, readonly) CFTimeInterval estimatedRemainingTime; + +- (void)scheduleDownloadWithRequest:(nonnull NSURLRequest *)request + resume:(nullable PINResume *)resume + skipRetry:(BOOL)skipRetry + priority:(PINRemoteImageManagerPriority)priority + completionHandler:(nonnull PINRemoteImageManagerDataCompletion)completionHandler; + +- (void)didReceiveData:(nonnull NSData *)data; +- (void)didReceiveResponse:(nonnull NSURLResponse *)response; + +@end diff --git a/Source/Classes/PINRemoteImageDownloadTask.m b/Source/Classes/PINRemoteImageDownloadTask.m new file mode 100644 index 00000000..3c062b7d --- /dev/null +++ b/Source/Classes/PINRemoteImageDownloadTask.m @@ -0,0 +1,379 @@ +// +// PINRemoteImageDownloadTask.m +// Pods +// +// Created by Garrett Moon on 3/9/15. +// +// + +#import "PINRemoteImageDownloadTask.h" + +#import +#import +#import "PINRemoteImageTask+Subclassing.h" +#import "PINRemoteImageCallbacks.h" +#import "PINRemoteLock.h" +#import "PINSpeedRecorder.h" + +@interface PINRemoteImageDownloadTask () +{ + PINProgressiveImage *_progressImage; + PINResume *_resume; + id _retryStrategy; +} + +@end + +@implementation PINRemoteImageDownloadTask + +- (instancetype)initWithManager:(PINRemoteImageManager *)manager +{ + if (self = [super initWithManager:manager]) { + _retryStrategy = manager.retryStrategyCreationBlock(); + } + return self; +} + +- (void)callProgressDownload +{ + NSDictionary *callbackBlocks = self.callbackBlocks; + #if PINRemoteImageLogging + NSString *key = self.key; + #endif + + __block int64_t completedBytes; + __block int64_t totalBytes; + + [self.lock lockWithBlock:^{ + completedBytes = self->_progressImage.dataTask.countOfBytesReceived; + totalBytes = self->_progressImage.dataTask.countOfBytesExpectedToReceive; + }]; + + [callbackBlocks enumerateKeysAndObjectsUsingBlock:^(NSUUID *UUID, PINRemoteImageCallbacks *callback, BOOL *stop) { + PINRemoteImageManagerProgressDownload progressDownloadBlock = callback.progressDownloadBlock; + if (progressDownloadBlock != nil) { + PINLog(@"calling progress for UUID: %@ key: %@", UUID, key); + dispatch_async(self.manager.callbackQueue, ^ + { + progressDownloadBlock(completedBytes, totalBytes); + }); + } + }]; +} + +- (void)callProgressImageWithImage:(nonnull PINImage *)image renderedImageQuality:(CGFloat)renderedImageQuality +{ + NSDictionary *callbackBlocks = self.callbackBlocks; +#if PINRemoteImageLogging + NSString *key = self.key; +#endif + + + [callbackBlocks enumerateKeysAndObjectsUsingBlock:^(NSUUID *UUID, PINRemoteImageCallbacks *callback, BOOL *stop) { + PINRemoteImageManagerImageCompletion progressImageBlock = callback.progressImageBlock; + if (progressImageBlock != nil) { + PINLog(@"calling progress for UUID: %@ key: %@", UUID, key); + CFTimeInterval requestTime = callback.requestTime; + + dispatch_async(self.manager.callbackQueue, ^ + { + progressImageBlock([PINRemoteImageManagerResult imageResultWithImage:image + alternativeRepresentation:nil + requestLength:CACurrentMediaTime() - requestTime + resultType:PINRemoteImageResultTypeProgress + UUID:UUID + response:nil + error:nil + renderedImageQuality:renderedImageQuality]); + }); + } + }]; +} + +- (BOOL)cancelWithUUID:(NSUUID *)UUID resume:(PINResume **)resume +{ + __block BOOL noMoreCompletions; + __block PINResume *strongResume; + BOOL hasResume = resume != nil; + [self.lock lockWithBlock:^{ + if (hasResume) { + //consider skipping cancellation if there's a request for resume data and the time to start the connection is greater than + //the time remaining to download. + NSTimeInterval timeToFirstByte = [[PINSpeedRecorder sharedRecorder] weightedTimeToFirstByteForHost:self->_progressImage.dataTask.currentRequest.URL.host]; + if (self->_progressImage.estimatedRemainingTime <= timeToFirstByte) { + noMoreCompletions = NO; + return; + } + } + + noMoreCompletions = [super l_cancelWithUUID:UUID]; + + if (noMoreCompletions) { + [self.manager.urlSessionTaskQueue removeDownloadTaskFromQueue:self->_progressImage.dataTask]; + [self->_progressImage.dataTask cancel]; + + if (hasResume && self->_ifRange && self->_progressImage.dataTask.countOfBytesExpectedToReceive > 0 && self->_progressImage.dataTask.countOfBytesExpectedToReceive != NSURLSessionTransferSizeUnknown) { + NSData *progressData = self->_progressImage.data; + if (progressData.length > 0) { + strongResume = [PINResume resumeData:progressData ifRange:self->_ifRange totalBytes:self->_progressImage.dataTask.countOfBytesExpectedToReceive]; + } + } + + PINLog(@"Canceling download of URL: %@, UUID: %@", _progressImage.dataTask.originalRequest.URL, UUID); + } +#if PINRemoteImageLogging + else { + PINLog(@"Decrementing download of URL: %@, UUID: %@", _progressImage.dataTask.originalRequest.URL, UUID); + } +#endif + }]; + + if (hasResume) { + *resume = strongResume; + } + + return noMoreCompletions; +} + +- (void)setPriority:(PINRemoteImageManagerPriority)priority +{ + [super setPriority:priority]; + [self.lock lockWithBlock:^{ + NSURLSessionDataTask *dataTask = self->_progressImage.dataTask; + if (dataTask) { + dataTask.priority = dataTaskPriorityWithImageManagerPriority(priority); + [self.manager.urlSessionTaskQueue setQueuePriority:priority forTask:dataTask]; + } + }]; +} + +- (NSURL *)URL +{ + __block NSURL *url; + [self.lock lockWithBlock:^{ + url = self->_progressImage.dataTask.originalRequest.URL; + }]; + return url; +} + +- (nonnull PINRemoteImageManagerResult *)imageResultWithImage:(nullable PINImage *)image + alternativeRepresentation:(nullable id)alternativeRepresentation + requestLength:(NSTimeInterval)requestLength + error:(nullable NSError *)error + resultType:(PINRemoteImageResultType)resultType + UUID:(nullable NSUUID *)UUID + response:(nonnull NSURLResponse *)response +{ + __block NSUInteger bytesSavedByResuming; + [self.lock lockWithBlock:^{ + bytesSavedByResuming = self->_resume.resumeData.length; + }]; + return [PINRemoteImageManagerResult imageResultWithImage:image + alternativeRepresentation:alternativeRepresentation + requestLength:requestLength + resultType:resultType + UUID:UUID + response:response + error:error + bytesSavedByResuming:bytesSavedByResuming]; +} + +- (void)didReceiveData:(NSData *_Nonnull)data +{ + [self callProgressDownload]; + + __block int64_t expectedNumberOfBytes; + [self.lock lockWithBlock:^{ + expectedNumberOfBytes = self->_progressImage.dataTask.countOfBytesExpectedToReceive; + }]; + + [self updateData:data isResume:NO expectedBytes:expectedNumberOfBytes]; +} + +- (void)updateData:(NSData *)data isResume:(BOOL)isResume expectedBytes:(int64_t)expectedBytes +{ + __block PINProgressiveImage *progressImage; + __block BOOL hasProgressBlocks = NO; + [self.lock lockWithBlock:^{ + progressImage = self->_progressImage; + [[self l_callbackBlocks] enumerateKeysAndObjectsUsingBlock:^(NSUUID *UUID, PINRemoteImageCallbacks *callback, BOOL *stop) { + if (callback.progressImageBlock) { + hasProgressBlocks = YES; + *stop = YES; + } + }]; + }]; + + [progressImage updateProgressiveImageWithData:data expectedNumberOfBytes:expectedBytes isResume:isResume]; + + if (hasProgressBlocks) { + if (PINNSOperationSupportsBlur) { + [self.manager.concurrentOperationQueue scheduleOperation:^{ + CGFloat renderedImageQuality = 1.0; + PINImage *image = [progressImage currentImageBlurred:self.manager.shouldBlurProgressive maxProgressiveRenderSize:self.manager.maxProgressiveRenderSize renderedImageQuality:&renderedImageQuality]; + if (image) { + [self callProgressImageWithImage:image renderedImageQuality:renderedImageQuality]; + } + } withPriority:PINOperationQueuePriorityLow]; + } + } +} + +- (void)didReceiveResponse:(nonnull NSURLResponse *)response +{ + if ([response isKindOfClass:[NSHTTPURLResponse class]]) { + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; + + // Got partial data back for a resume + if (httpResponse.statusCode == 206) { + __block PINResume *resume; + [self.lock lockWithBlock:^{ + resume = self->_resume; + }]; + + [self updateData:resume.resumeData isResume:YES expectedBytes:resume.totalBytes]; + } else { + //Check if there's resume data and we didn't get back a 206, get rid of it + [self.lock lockWithBlock:^{ + self->_resume = nil; + }]; + } + + // Check to see if the server supports resume + if ([[httpResponse allHeaderFields][@"Accept-Ranges"] isEqualToString:@"bytes"]) { + NSString *ifRange = nil; + NSString *etag = nil; + + if ((etag = [httpResponse allHeaderFields][@"ETag"])) { + if ([etag hasPrefix:@"W/"] == NO) { + ifRange = etag; + } + } else { + ifRange = [httpResponse allHeaderFields][@"Last-Modified"]; + } + + if (ifRange.length > 0) { + [self.lock lockWithBlock:^{ + self->_ifRange = ifRange; + }]; + } + } + } +} + +- (void)scheduleDownloadWithRequest:(nonnull NSURLRequest *)request + resume:(nullable PINResume *)resume + skipRetry:(BOOL)skipRetry + priority:(PINRemoteImageManagerPriority)priority + completionHandler:(nonnull PINRemoteImageManagerDataCompletion)completionHandler +{ + [self scheduleDownloadWithRequest:request resume:resume skipRetry:skipRetry priority:priority isRetry:NO completionHandler:completionHandler]; +} + +- (void)scheduleDownloadWithRequest:(NSURLRequest *)request + resume:(PINResume *)resume + skipRetry:(BOOL)skipRetry + priority:(PINRemoteImageManagerPriority)priority + isRetry:(BOOL)isRetry + completionHandler:(PINRemoteImageManagerDataCompletion)completionHandler +{ + [self.lock lockWithBlock:^{ + if (self->_progressImage != nil || [self l_callbackBlocks].count == 0 || (isRetry == NO && self->_retryStrategy.numberOfRetries > 0)) { + return; + } + self->_resume = resume; + + NSURLRequest *adjustedRequest = request; + if (self->_resume) { + NSMutableURLRequest *mutableRequest = [request mutableCopy]; + NSMutableDictionary *headers = [[mutableRequest allHTTPHeaderFields] mutableCopy]; + headers[@"If-Range"] = self->_resume.ifRange; + headers[@"Range"] = [NSString stringWithFormat:@"bytes=%tu-", self->_resume.resumeData.length]; + mutableRequest.allHTTPHeaderFields = headers; + adjustedRequest = mutableRequest; + } + + self->_progressImage = [[PINProgressiveImage alloc] initWithDataTask:[self.manager.urlSessionTaskQueue addDownloadWithSessionManager:self.manager.sessionManager + request:adjustedRequest + priority:priority + completionHandler:^(NSURLResponse * _Nonnull response, NSError * _Nonnull remoteError) + { + [self.manager.concurrentOperationQueue scheduleOperation:^{ + NSError *error = remoteError; +#if PINRemoteImageLogging + if (error && error.code != NSURLErrorCancelled) { + PINLog(@"Failed downloading image: %@ with error: %@", request.URL, error); + } else if (error == nil && response.expectedContentLength == 0) { + PINLog(@"image is empty at URL: %@", request.URL); + } else { + PINLog(@"Finished downloading image: %@", request.URL); + } +#endif + + if (error.code != NSURLErrorCancelled) { + NSData *data = self.progressImage.data; + + if (error == nil && data == nil) { + error = [NSError errorWithDomain:PINRemoteImageManagerErrorDomain + code:PINRemoteImageManagerErrorImageEmpty + userInfo:nil]; + } + + __block BOOL retry = NO; + __block int64_t delay = 0; + [self.lock lockWithBlock:^{ + retry = skipRetry == NO && [self->_retryStrategy shouldRetryWithError:error]; + if (retry) { + // Clear out the existing progress image or else new data from retry will be appended + self->_progressImage = nil; + [self->_retryStrategy incrementRetryCount]; + delay = [self->_retryStrategy nextDelay]; + } + }]; + if (retry) { + PINLog(@"Retrying download of %@ in %lld seconds.", request.URL, delay); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [self scheduleDownloadWithRequest:request resume:nil skipRetry:skipRetry priority:priority isRetry:YES completionHandler:completionHandler]; + }); + return; + } + + completionHandler(data, response, error); + } + }]; + }]]; + }]; +} + +- (PINProgressiveImage *)progressImage +{ + __block PINProgressiveImage *progressImage = nil; + [self.lock lockWithBlock:^{ + progressImage = self->_progressImage; + }]; + return progressImage; +} + ++ (BOOL)retriableError:(NSError *)remoteImageError +{ + if ([remoteImageError.domain isEqualToString:PINURLErrorDomain]) { + return remoteImageError.code >= 500; + } else if ([remoteImageError.domain isEqualToString:NSURLErrorDomain] && remoteImageError.code == NSURLErrorUnsupportedURL) { + return NO; + } else if ([remoteImageError.domain isEqualToString:PINRemoteImageManagerErrorDomain]) { + return NO; + } + return YES; +} + +- (CFTimeInterval)estimatedRemainingTime +{ + return self.progressImage.estimatedRemainingTime; +} + +- (NSData *)data +{ + return self.progressImage.data; +} + +@end diff --git a/Source/Classes/PINRemoteImageManager+Private.h b/Source/Classes/PINRemoteImageManager+Private.h new file mode 100644 index 00000000..39550e32 --- /dev/null +++ b/Source/Classes/PINRemoteImageManager+Private.h @@ -0,0 +1,30 @@ +// +// PINRemoteImageManager+Private.h +// PINRemoteImage +// +// Created by Garrett Moon on 5/18/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#ifndef PINRemoteImageManager_Private_h +#define PINRemoteImageManager_Private_h + +#import "PINRemoteImageDownloadQueue.h" + +typedef void (^PINRemoteImageManagerDataCompletion)(NSData *data, NSURLResponse *response, NSError *error); + +@interface PINRemoteImageManager (PrivateExtension) + +@property (nonatomic, strong, readonly) dispatch_queue_t callbackQueue; +@property (nonatomic, strong, readonly) PINOperationQueue *concurrentOperationQueue; +@property (nonatomic, strong, readonly) PINRemoteImageDownloadQueue *urlSessionTaskQueue; +@property (nonatomic, strong, readonly) PINURLSessionManager *sessionManager; + +@property (nonatomic, readonly) NSArray *progressThresholds; +@property (nonatomic, readonly) NSTimeInterval estimatedRemainingTimeThreshold; +@property (nonatomic, readonly) BOOL shouldBlurProgressive; +@property (nonatomic, readonly) CGSize maxProgressiveRenderSize; + +@end + +#endif /* PINRemoteImageManager_Private_h */ diff --git a/Source/Classes/PINRemoteImageManager.m b/Source/Classes/PINRemoteImageManager.m new file mode 100644 index 00000000..aa48d0da --- /dev/null +++ b/Source/Classes/PINRemoteImageManager.m @@ -0,0 +1,1667 @@ +// +// PINRemoteImageManager.m +// Pods +// +// Created by Garrett Moon on 8/17/14. +// +// + +#import + +#import + +#if !__has_include() +#import "PINOperation.h" +#else +#import +#endif + +#import + +#import +#import +#import "PINRemoteLock.h" +#import +#import "PINRemoteImageCallbacks.h" +#import "PINRemoteImageTask.h" +#import "PINRemoteImageProcessorTask.h" +#import "PINRemoteImageDownloadTask.h" +#import "PINResume.h" +#import "PINRemoteImageMemoryContainer.h" +#import +#import +#import "PINRemoteImageDownloadQueue.h" +#import "PINSpeedRecorder.h" +#import + +#import +#import +#import +#import "PINRemoteImageManager+Private.h" +#import + +#if USE_PINCACHE +#import +#else +#import "PINRemoteImageBasicCache.h" +#endif + + +#define PINRemoteImageManagerDefaultTimeout 30.0 +//A limit of 200 characters is chosen because PINDiskCache +//may expand the length by encoding certain characters +#define PINRemoteImageManagerCacheKeyMaxLength 200 + +PINOperationQueuePriority operationPriorityWithImageManagerPriority(PINRemoteImageManagerPriority priority); +PINOperationQueuePriority operationPriorityWithImageManagerPriority(PINRemoteImageManagerPriority priority) { + switch (priority) { + case PINRemoteImageManagerPriorityLow: + return PINOperationQueuePriorityLow; + break; + + case PINRemoteImageManagerPriorityDefault: + return PINOperationQueuePriorityDefault; + break; + + case PINRemoteImageManagerPriorityHigh: + return PINOperationQueuePriorityHigh; + break; + } +} + +float dataTaskPriorityWithImageManagerPriority(PINRemoteImageManagerPriority priority) { + switch (priority) { + case PINRemoteImageManagerPriorityLow: + return 0.0; + break; + + case PINRemoteImageManagerPriorityDefault: + return 0.5; + break; + + case PINRemoteImageManagerPriorityHigh: + return 1.0; + break; + } +} + +// Reference: https://github.com/TextureGroup/Texture/blob/5dd5611/Source/Private/ASInternalHelpers.m#L60 +BOOL PINRemoteImageManagerSubclassOverridesSelector(Class subclass, SEL selector) +{ + Class superclass = [PINRemoteImageManager class]; + if (superclass == subclass) return NO; // Even if the class implements the selector, it doesn't override itself. + Method superclassMethod = class_getInstanceMethod(superclass, selector); + Method subclassMethod = class_getInstanceMethod(subclass, selector); + return (superclassMethod != subclassMethod); +} + +NSErrorDomain const PINRemoteImageManagerErrorDomain = @"PINRemoteImageManagerErrorDomain"; +NSString * const PINRemoteImageWeakTaskKey = @"PINRemoteImageWeakTaskKey"; +NSString * const PINRemoteImageCacheKeyResumePrefix = @"R-"; +typedef void (^PINRemoteImageManagerDataCompletion)(NSData *data, NSURLResponse *response, NSError *error); + +@interface PINRemoteImageWeakTask : NSObject + +@property (nonatomic, readonly, weak) PINRemoteImageTask *task; + +- (instancetype)initWithTask:(PINRemoteImageTask *)task; + +@end + +@implementation PINRemoteImageWeakTask + +- (instancetype)initWithTask:(PINRemoteImageTask *)task +{ + if (self = [super init]) { + _task = task; + } + return self; +} + +@end + +@interface PINRemoteImageManager () +{ + dispatch_queue_t _callbackQueue; + PINRemoteLock *_lock; + PINOperationQueue *_concurrentOperationQueue; + PINRemoteImageDownloadQueue *_urlSessionTaskQueue; + + // Necessary to have a strong reference to _defaultAlternateRepresentationProvider because _alternateRepProvider is __weak + PINAlternateRepresentationProvider *_defaultAlternateRepresentationProvider; + __weak PINAlternateRepresentationProvider *_alternateRepProvider; + NSURLSessionConfiguration *_sessionConfiguration; +} + +@property (nonatomic, strong) id cache; +@property (nonatomic, strong) PINURLSessionManager *sessionManager; +@property (nonatomic, strong) NSMutableDictionary *tasks; +@property (nonatomic, strong) NSHashTable *canceledTasks; +@property (nonatomic, strong) NSMapTable *UUIDToTask; +@property (nonatomic, strong) NSArray *progressThresholds; +@property (nonatomic, assign) BOOL shouldBlurProgressive; +@property (nonatomic, assign) CGSize maxProgressiveRenderSize; +@property (nonatomic, assign) NSTimeInterval estimatedRemainingTimeThreshold; +@property (nonatomic, strong) dispatch_queue_t callbackQueue; +@property (nonatomic, strong) PINOperationQueue *concurrentOperationQueue; +@property (nonatomic, strong) PINRemoteImageDownloadQueue *urlSessionTaskQueue; +@property (nonatomic, assign) float highQualityBPSThreshold; +@property (nonatomic, assign) float lowQualityBPSThreshold; +@property (nonatomic, assign) BOOL shouldUpgradeLowQualityImages; +@property (nonatomic, strong) PINRemoteImageManagerMetrics metricsCallback; +@property (nonatomic, copy) PINRemoteImageManagerAuthenticationChallenge authenticationChallengeHandler; +@property (nonatomic, copy) id (^retryStrategyCreationBlock)(void); +@property (nonatomic, copy) PINRemoteImageManagerRequestConfigurationHandler requestConfigurationHandler; +@property (nonatomic, strong) NSMutableDictionary *httpHeaderFields; +@property (nonatomic, readonly) BOOL diskCacheTTLIsEnabled; +@property (nonatomic, readonly) BOOL memoryCacheTTLIsEnabled; + +#if DEBUG +@property (nonatomic, assign) NSUInteger totalDownloads; +#endif + +@end + +#pragma mark PINRemoteImageManager + +@implementation PINRemoteImageManager + +static PINRemoteImageManager *sharedImageManager = nil; +static dispatch_once_t sharedDispatchToken; + ++ (instancetype)sharedImageManager +{ + dispatch_once(&sharedDispatchToken, ^{ + sharedImageManager = [[[self class] alloc] init]; + }); + return sharedImageManager; +} + ++ (void)setSharedImageManagerWithConfiguration:(NSURLSessionConfiguration *)configuration +{ + NSAssert(sharedImageManager == nil, @"sharedImageManager singleton is already configured"); + + dispatch_once(&sharedDispatchToken, ^{ + sharedImageManager = [[[self class] alloc] initWithSessionConfiguration:configuration]; + }); +} + +- (instancetype)init +{ + return [self initWithSessionConfiguration:nil]; +} + +- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)sessionConfiguration +{ + return [self initWithSessionConfiguration:sessionConfiguration alternativeRepresentationProvider:nil]; +} + +- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)sessionConfiguration alternativeRepresentationProvider:(id )alternateRepProvider +{ + return [self initWithSessionConfiguration:sessionConfiguration alternativeRepresentationProvider:alternateRepProvider imageCache:nil managerConfiguration:nil]; +} + +- (nonnull instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)sessionConfiguration + alternativeRepresentationProvider:(nullable id )alternateRepDelegate + imageCache:(nullable id)imageCache { + return [self initWithSessionConfiguration:sessionConfiguration alternativeRepresentationProvider:alternateRepDelegate imageCache:imageCache managerConfiguration:nil]; +} + +-(nonnull instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)sessionConfiguration + alternativeRepresentationProvider:(id)alternateRepProvider + imageCache:(id)imageCache + managerConfiguration:(nullable PINRemoteImageManagerConfiguration *)managerConfiguration +{ + if (self = [super init]) { + PINRemoteImageManagerConfiguration *configuration = managerConfiguration; + if (!configuration) { + configuration = [[PINRemoteImageManagerConfiguration alloc] init]; + } + + if (imageCache) { + self.cache = imageCache; + } else if (PINRemoteImageManagerSubclassOverridesSelector([self class], @selector(defaultImageCache))) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + self.cache = [self defaultImageCache]; +#pragma clang diagnostic pop + } else { + self.cache = [[self class] defaultImageCache]; + } + + if ([self.cache respondsToSelector:@selector(setObjectOnDisk:forKey:withAgeLimit:)] && + [self.cache respondsToSelector:@selector(setObjectInMemory:forKey:withCost:withAgeLimit:)] && + [self.cache respondsToSelector:@selector(diskCacheIsTTLCache)] && + [self.cache respondsToSelector:@selector(memoryCacheIsTTLCache)]) { + _diskCacheTTLIsEnabled = [self.cache diskCacheIsTTLCache]; + _memoryCacheTTLIsEnabled = [self.cache memoryCacheIsTTLCache]; + } + + _sessionConfiguration = [sessionConfiguration copy]; + if (!_sessionConfiguration) { + _sessionConfiguration = [NSURLSessionConfiguration ephemeralSessionConfiguration]; + _sessionConfiguration.timeoutIntervalForRequest = PINRemoteImageManagerDefaultTimeout; + _sessionConfiguration.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData; + _sessionConfiguration.URLCache = nil; + _sessionConfiguration.HTTPMaximumConnectionsPerHost = PINRemoteImageHTTPMaximumConnectionsPerHost; + } + + _callbackQueue = dispatch_queue_create("PINRemoteImageManagerCallbackQueue", DISPATCH_QUEUE_CONCURRENT); + _lock = [[PINRemoteLock alloc] initWithName:@"PINRemoteImageManager"]; + + _concurrentOperationQueue = [[PINOperationQueue alloc] initWithMaxConcurrentOperations: configuration.maxConcurrentOperations]; + _urlSessionTaskQueue = [PINRemoteImageDownloadQueue queueWithMaxConcurrentDownloads:configuration.maxConcurrentDownloads]; + + self.sessionManager = [[PINURLSessionManager alloc] initWithSessionConfiguration:_sessionConfiguration]; + self.sessionManager.delegate = self; + + self.estimatedRemainingTimeThreshold = configuration.estimatedRemainingTimeThreshold; + + _highQualityBPSThreshold = configuration.highQualityBPSThreshold; + _lowQualityBPSThreshold = configuration.lowQualityBPSThreshold; + _shouldUpgradeLowQualityImages = configuration.shouldUpgradeLowQualityImages; + _shouldBlurProgressive = configuration.shouldBlurProgressive; + _maxProgressiveRenderSize = configuration.maxProgressiveRenderSize; + self.tasks = [[NSMutableDictionary alloc] init]; + self.canceledTasks = [[NSHashTable alloc] initWithOptions:NSHashTableWeakMemory capacity:5]; + self.UUIDToTask = [NSMapTable weakToWeakObjectsMapTable]; + + if (alternateRepProvider == nil) { + _defaultAlternateRepresentationProvider = [[PINAlternateRepresentationProvider alloc] init]; + alternateRepProvider = _defaultAlternateRepresentationProvider; + } + _alternateRepProvider = alternateRepProvider; + __weak typeof(self) weakSelf = self; + _retryStrategyCreationBlock = ^id{ + return [weakSelf defaultRetryStrategy]; + }; + _httpHeaderFields = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (id)defaultRetryStrategy { + return [[PINRequestExponentialRetryStrategy alloc] initWithRetryMaxCount:3 delayBase:4]; +} + +- (void)dealloc +{ + [self.sessionManager invalidateSessionAndCancelTasks]; +} + +- (id)defaultImageCache { + return [PINRemoteImageManager defaultImageCache]; +} + ++ (id)defaultImageCache { + return [PINRemoteImageManager defaultImageCacheEnablingTtl:NO]; +} + ++ (id)defaultImageTtlCache { + return [PINRemoteImageManager defaultImageCacheEnablingTtl:YES]; +} + ++ (id)defaultImageCacheEnablingTtl:(BOOL)enableTtl +{ +#if USE_PINCACHE + NSString * const kPINRemoteImageDiskCacheName = @"PINRemoteImageManagerCache"; + NSString * const kPINRemoteImageDiskCacheVersionKey = @"kPINRemoteImageDiskCacheVersionKey"; + const NSInteger kPINRemoteImageDiskCacheVersion = 1; + NSUserDefaults *pinDefaults = [[NSUserDefaults alloc] init]; + + NSString *cacheURLRoot = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0]; + + if ([pinDefaults integerForKey:kPINRemoteImageDiskCacheVersionKey] != kPINRemoteImageDiskCacheVersion) { + //remove the old version of the disk cache + NSURL *diskCacheURL = [PINDiskCache cacheURLWithRootPath:cacheURLRoot prefix:PINDiskCachePrefix name:kPINRemoteImageDiskCacheName]; + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSURL *dstURL = [[[NSURL alloc] initFileURLWithPath:NSTemporaryDirectory()] URLByAppendingPathComponent:kPINRemoteImageDiskCacheName]; + [fileManager moveItemAtURL:diskCacheURL toURL:dstURL error:nil]; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [fileManager removeItemAtURL:dstURL error:nil]; + }); + [pinDefaults setInteger:kPINRemoteImageDiskCacheVersion forKey:kPINRemoteImageDiskCacheVersionKey]; + } + + PINCache *pinCache = [[PINCache alloc] initWithName:kPINRemoteImageDiskCacheName rootPath:cacheURLRoot serializer:^NSData * _Nonnull(id _Nonnull object, NSString * _Nonnull key) { + id obj = (id )object; + if ([key hasPrefix:PINRemoteImageCacheKeyResumePrefix]) { + return [NSKeyedArchiver archivedDataWithRootObject:obj requiringSecureCoding:NO error:nil]; + } + return (NSData *)object; + } deserializer:^id _Nonnull(NSData * _Nonnull data, NSString * _Nonnull key) { + if ([key hasPrefix:PINRemoteImageCacheKeyResumePrefix]) { + NSError *error = nil; + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data error:&error]; + NSAssert(!error, @"unarchiver init failed with error"); + unarchiver.requiresSecureCoding = NO; + return [unarchiver decodeObjectForKey:NSKeyedArchiveRootObjectKey]; + } + return data; + } keyEncoder:nil keyDecoder:nil ttlCache:enableTtl]; + + return pinCache; +#else + return [[PINRemoteImageBasicCache alloc] init]; +#endif +} + +- (void)lockOnMainThread +{ +#if !DEBUG + NSAssert(NO, @"lockOnMainThread should only be called for testing on debug builds!"); +#endif + [_lock lock]; +} + +- (void)lock +{ + NSAssert([NSThread isMainThread] == NO, @"lock should not be called from the main thread!"); + [_lock lock]; +} + +- (void)unlock +{ + [_lock unlock]; +} + +- (void)setValue:(nullable NSString *)value forHTTPHeaderField:(nullable NSString *)header { + __weak typeof(self) weakSelf = self; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + typeof(self) strongSelf = weakSelf; + [strongSelf lock]; + strongSelf.httpHeaderFields[[header copy]] = [value copy]; + [strongSelf unlock]; + }); +} + +- (void)setRequestConfiguration:(PINRemoteImageManagerRequestConfigurationHandler)configurationBlock + completion:(void (^)(void))completion; { + __weak typeof(self) weakSelf = self; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + typeof(self) strongSelf = weakSelf; + [strongSelf lock]; + strongSelf.requestConfigurationHandler = configurationBlock; + [strongSelf unlock]; + + if(completion != nil) { + completion(); + } + }); +} + +- (void)setRequestConfiguration:(PINRemoteImageManagerRequestConfigurationHandler)configurationBlock { + [self setRequestConfiguration:configurationBlock completion:nil]; +} + +- (void)setAuthenticationChallenge:(PINRemoteImageManagerAuthenticationChallenge)challengeBlock { + __weak typeof(self) weakSelf = self; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + typeof(self) strongSelf = weakSelf; + [strongSelf lock]; + strongSelf.authenticationChallengeHandler = challengeBlock; + [strongSelf unlock]; + }); +} + +- (void)setMaxNumberOfConcurrentOperations:(NSInteger)maxNumberOfConcurrentOperations completion:(dispatch_block_t)completion +{ + __weak typeof(self) weakSelf = self; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + typeof(self) strongSelf = weakSelf; + [strongSelf lock]; + strongSelf.concurrentOperationQueue.maxConcurrentOperations = maxNumberOfConcurrentOperations; + [strongSelf unlock]; + if (completion) { + completion(); + } + }); +} + +- (void)setMaxNumberOfConcurrentDownloads:(NSInteger)maxNumberOfConcurrentDownloads completion:(dispatch_block_t)completion +{ + NSAssert(maxNumberOfConcurrentDownloads <= PINRemoteImageHTTPMaximumConnectionsPerHost, @"maxNumberOfConcurrentDownloads must be less than or equal to %d", PINRemoteImageHTTPMaximumConnectionsPerHost); + __weak typeof(self) weakSelf = self; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + typeof(self) strongSelf = weakSelf; + [strongSelf lock]; + strongSelf.urlSessionTaskQueue.maxNumberOfConcurrentDownloads = maxNumberOfConcurrentDownloads; + [strongSelf unlock]; + if (completion) { + completion(); + } + }); +} + +- (void)setEstimatedRemainingTimeThresholdForProgressiveDownloads:(NSTimeInterval)estimatedRemainingTimeThreshold completion:(dispatch_block_t)completion +{ + __weak typeof(self) weakSelf = self; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + typeof(self) strongSelf = weakSelf; + [strongSelf lock]; + strongSelf.estimatedRemainingTimeThreshold = estimatedRemainingTimeThreshold; + [strongSelf unlock]; + if (completion) { + completion(); + } + }); +} + +- (void)setProgressThresholds:(NSArray *)progressThresholds completion:(dispatch_block_t)completion +{ + __weak typeof(self) weakSelf = self; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + typeof(self) strongSelf = weakSelf; + [strongSelf lock]; + strongSelf.progressThresholds = progressThresholds; + [strongSelf unlock]; + if (completion) { + completion(); + } + }); +} + +- (void)setProgressiveRendersShouldBlur:(BOOL)shouldBlur completion:(nullable dispatch_block_t)completion +{ + __weak typeof(self) weakSelf = self; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + typeof(self) strongSelf = weakSelf; + [strongSelf lock]; + strongSelf.shouldBlurProgressive = shouldBlur; + [strongSelf unlock]; + if (completion) { + completion(); + } + }); +} + +- (void)setProgressiveRendersMaxProgressiveRenderSize:(CGSize)maxProgressiveRenderSize completion:(nullable dispatch_block_t)completion +{ + __weak typeof(self) weakSelf = self; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + typeof(self) strongSelf = weakSelf; + [strongSelf lock]; + strongSelf.maxProgressiveRenderSize = maxProgressiveRenderSize; + [strongSelf unlock]; + if (completion) { + completion(); + } + }); +} + +- (void)setHighQualityBPSThreshold:(float)highQualityBPSThreshold completion:(dispatch_block_t)completion +{ + __weak typeof(self) weakSelf = self; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + typeof(self) strongSelf = weakSelf; + [strongSelf lock]; + strongSelf.highQualityBPSThreshold = highQualityBPSThreshold; + [strongSelf unlock]; + if (completion) { + completion(); + } + }); +} + +- (void)setLowQualityBPSThreshold:(float)lowQualityBPSThreshold completion:(dispatch_block_t)completion +{ + __weak typeof(self) weakSelf = self; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + typeof(self) strongSelf = weakSelf; + [strongSelf lock]; + strongSelf.lowQualityBPSThreshold = lowQualityBPSThreshold; + [strongSelf unlock]; + if (completion) { + completion(); + } + }); +} + +- (void)setShouldUpgradeLowQualityImages:(BOOL)shouldUpgradeLowQualityImages completion:(dispatch_block_t)completion +{ + __weak typeof(self) weakSelf = self; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + typeof(self) strongSelf = weakSelf; + [strongSelf lock]; + strongSelf.shouldUpgradeLowQualityImages = shouldUpgradeLowQualityImages; + [strongSelf unlock]; + if (completion) { + completion(); + } + }); +} + +- (void)setMetricsCallback:(nullable PINRemoteImageManagerMetrics)metricsCallback completion:(nullable dispatch_block_t)completion +{ + __weak typeof(self) weakSelf = self; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + typeof(self) strongSelf = weakSelf; + [self lock]; + strongSelf.metricsCallback = metricsCallback; + [self unlock]; + if (completion) { + completion(); + } + }); +} + +- (NSUUID *)downloadImageWithURL:(NSURL *)url + completion:(PINRemoteImageManagerImageCompletion)completion +{ + return [self downloadImageWithURL:url + options:PINRemoteImageManagerDownloadOptionsNone + completion:completion]; +} + +- (NSUUID *)downloadImageWithURL:(NSURL *)url + options:(PINRemoteImageManagerDownloadOptions)options + completion:(PINRemoteImageManagerImageCompletion)completion +{ + return [self downloadImageWithURL:url + options:options + progressImage:nil + completion:completion]; +} + +- (NSUUID *)downloadImageWithURL:(NSURL *)url + options:(PINRemoteImageManagerDownloadOptions)options + progressImage:(PINRemoteImageManagerImageCompletion)progressImage + completion:(PINRemoteImageManagerImageCompletion)completion +{ + return [self downloadImageWithURL:url + options:options + progressImage:progressImage + progressDownload:nil + completion:completion]; +} + +- (NSUUID *)downloadImageWithURL:(NSURL *)url + options:(PINRemoteImageManagerDownloadOptions)options + progressDownload:(PINRemoteImageManagerProgressDownload)progressDownload + completion:(PINRemoteImageManagerImageCompletion)completion +{ + return [self downloadImageWithURL:url + options:options + progressImage:nil + progressDownload:progressDownload + completion:completion]; +} + +- (NSUUID *)downloadImageWithURL:(NSURL *)url + options:(PINRemoteImageManagerDownloadOptions)options + progressImage:(PINRemoteImageManagerImageCompletion)progressImage + progressDownload:(PINRemoteImageManagerProgressDownload)progressDownload + completion:(PINRemoteImageManagerImageCompletion)completion +{ + return [self downloadImageWithURL:url + options:options + priority:PINRemoteImageManagerPriorityDefault + progressImage:progressImage + progressDownload:progressDownload + completion:completion]; +} + +- (nullable NSUUID *)downloadImageWithURL:(nonnull NSURL *)url + options:(PINRemoteImageManagerDownloadOptions)options + priority:(PINRemoteImageManagerPriority)priority + progressImage:(PINRemoteImageManagerImageCompletion)progressImage + progressDownload:(nullable PINRemoteImageManagerProgressDownload)progressDownload + completion:(nullable PINRemoteImageManagerImageCompletion)completion; +{ + return [self downloadImageWithURL:url + options:options + priority:priority + processorKey:nil + processor:nil + progressImage:progressImage + progressDownload:progressDownload + completion:completion + inputUUID:nil]; +} + +- (NSUUID *)downloadImageWithURL:(NSURL *)url + options:(PINRemoteImageManagerDownloadOptions)options + processorKey:(NSString *)processorKey + processor:(PINRemoteImageManagerImageProcessor)processor + completion:(PINRemoteImageManagerImageCompletion)completion +{ + return [self downloadImageWithURL:url + options:options + priority:PINRemoteImageManagerPriorityDefault + processorKey:processorKey + processor:processor + progressImage:nil + progressDownload:nil + completion:completion + inputUUID:nil]; +} + +- (NSUUID *)downloadImageWithURL:(NSURL *)url + options:(PINRemoteImageManagerDownloadOptions)options + processorKey:(NSString *)processorKey + processor:(PINRemoteImageManagerImageProcessor)processor + progressDownload:(PINRemoteImageManagerProgressDownload)progressDownload + completion:(PINRemoteImageManagerImageCompletion)completion +{ + return [self downloadImageWithURL:url + options:options + priority:PINRemoteImageManagerPriorityDefault + processorKey:processorKey + processor:processor + progressImage:nil + progressDownload:progressDownload + completion:completion + inputUUID:nil]; +} + +- (NSUUID *)downloadImageWithURL:(NSURL *)url + options:(PINRemoteImageManagerDownloadOptions)options + priority:(PINRemoteImageManagerPriority)priority + processorKey:(NSString *)processorKey + processor:(PINRemoteImageManagerImageProcessor)processor + progressImage:(PINRemoteImageManagerImageCompletion)progressImage + progressDownload:(PINRemoteImageManagerProgressDownload)progressDownload + completion:(PINRemoteImageManagerImageCompletion)completion + inputUUID:(NSUUID *)UUID +{ + NSAssert((processor != nil && processorKey.length > 0) || (processor == nil && processorKey == nil), @"processor must not be nil and processorKey length must be greater than zero OR processor must be nil and processorKey must be nil"); + + Class taskClass; + if (processor && processorKey.length > 0) { + taskClass = [PINRemoteImageProcessorTask class]; + } else { + taskClass = [PINRemoteImageDownloadTask class]; + } + + NSString *key = [self cacheKeyForURL:url processorKey:processorKey]; + + if (url == nil) { + [self earlyReturnWithOptions:options url:nil key:key object:nil completion:completion]; + return nil; + } + + NSAssert([url isKindOfClass:[NSURL class]], @"url must be of type NSURL, if it's an NSString, we'll try to correct"); + if ([url isKindOfClass:[NSString class]]) { + url = [NSURL URLWithString:(NSString *)url]; + } + + if (UUID == nil) { + UUID = [NSUUID UUID]; + } + + if ((options & PINRemoteImageManagerDownloadOptionsIgnoreCache) == 0) { + //Check to see if the image is in memory cache and we're on the main thread. + //If so, special case this to avoid flashing the UI + id object = [self.cache objectFromMemoryForKey:key]; + if (object) { + if ([self earlyReturnWithOptions:options url:url key:key object:object completion:completion]) { + return nil; + } + } + } + + if ([url.scheme isEqualToString:@"data"]) { + NSData *data = [NSData dataWithContentsOfURL:url]; + if (data) { + if ([self earlyReturnWithOptions:options url:url key:key object:data completion:completion]) { + return nil; + } + } + } + + [_concurrentOperationQueue scheduleOperation:^ + { + [self lock]; + //check canceled tasks first + if ([self.canceledTasks containsObject:UUID]) { + PINLog(@"skipping starting %@ because it was canceled.", UUID); + [self unlock]; + return; + } + + PINRemoteImageTask *task = [self.tasks objectForKey:key]; + BOOL taskExisted = NO; + if (task == nil) { + task = [[taskClass alloc] initWithManager:self]; + PINLog(@"Task does not exist creating with key: %@, URL: %@, UUID: %@, task: %p", key, url, UUID, task); + task.key = key; + } else { + taskExisted = YES; + PINLog(@"Task exists, attaching with key: %@, URL: %@, UUID: %@, task: %@", key, url, UUID, task); + } + [task addCallbacksWithCompletionBlock:completion progressImageBlock:progressImage progressDownloadBlock:progressDownload withUUID:UUID]; + [self.tasks setObject:task forKey:key]; + // Relax :), task retain the UUID for us, it's ok to have a weak reference to UUID here. + [self.UUIDToTask setObject:task forKey:UUID]; + + NSAssert(taskClass == [task class], @"Task class should be the same!"); + [self unlock]; + + if (taskExisted == NO) { + [self.concurrentOperationQueue scheduleOperation:^ + { + [self objectForKey:key options:options completion:^(BOOL found, BOOL valid, PINImage *image, id alternativeRepresentation) { + if (found) { + if (valid) { + [self callCompletionsWithKey:key image:image alternativeRepresentation:alternativeRepresentation cached:YES response:nil error:nil finalized:YES]; + } else { + //Remove completion and try again + [self lock]; + PINRemoteImageTask *task = [self.tasks objectForKey:key]; + [task removeCallbackWithUUID:UUID]; + if (task.callbackBlocks.count == 0) { + [self.tasks removeObjectForKey:key]; + } + [self unlock]; + + //Skip early check + [self downloadImageWithURL:url + options:options | PINRemoteImageManagerDownloadOptionsSkipEarlyCheck + priority:priority + processorKey:processorKey + processor:processor + progressImage:(PINRemoteImageManagerImageCompletion)progressImage + progressDownload:nil + completion:completion + inputUUID:UUID]; + } + } else { + if ([taskClass isSubclassOfClass:[PINRemoteImageProcessorTask class]]) { + //continue processing + [self downloadImageWithURL:url + options:options + priority:priority + key:key + processor:processor + UUID:UUID]; + } else if ([taskClass isSubclassOfClass:[PINRemoteImageDownloadTask class]]) { + //continue downloading + [self downloadImageWithURL:url + options:options + priority:priority + key:key + progressImage:progressImage + UUID:UUID]; + } + } + }]; + } withPriority:operationPriorityWithImageManagerPriority(priority)]; + } + } withPriority:operationPriorityWithImageManagerPriority(priority)]; + + return UUID; +} + +- (void)downloadImageWithURL:(NSURL *)url + options:(PINRemoteImageManagerDownloadOptions)options + priority:(PINRemoteImageManagerPriority)priority + key:(NSString *)key + processor:(PINRemoteImageManagerImageProcessor)processor + UUID:(NSUUID *)UUID +{ + PINRemoteImageProcessorTask *task = nil; + [self lock]; + task = [self.tasks objectForKey:key]; + //check processing task still exists and download hasn't been started for another task + if (task == nil || task.downloadTaskUUID != nil) { + [self unlock]; + return; + } + + __weak typeof(self) weakSelf = self; + NSUUID *downloadTaskUUID = [self downloadImageWithURL:url + options:options | PINRemoteImageManagerDownloadOptionsSkipEarlyCheck + completion:^(PINRemoteImageManagerResult *result) + { + typeof(self) strongSelf = weakSelf; + NSUInteger processCost = 0; + NSError *error = result.error; + PINRemoteImageProcessorTask *task = nil; + [strongSelf lock]; + task = [strongSelf.tasks objectForKey:key]; + [strongSelf unlock]; + //check processing task still exists + if (task == nil) { + return; + } + if (result.image && error == nil) { + //If completionBlocks.count == 0, we've canceled before we were even able to start. + PINImage *image = processor(result, &processCost); + + if (image == nil) { + error = [NSError errorWithDomain:PINRemoteImageManagerErrorDomain + code:PINRemoteImageManagerErrorFailedToProcessImage + userInfo:nil]; + } + [strongSelf callCompletionsWithKey:key image:image alternativeRepresentation:nil cached:NO response:result.response error:error finalized:NO]; + + if (error == nil && image != nil) { + BOOL saveAsJPEG = (options & PINRemoteImageManagerSaveProcessedImageAsJPEG) != 0; + NSData *diskData = nil; + if (saveAsJPEG) { + diskData = PINImageJPEGRepresentation(image, 1.0); + } else { + diskData = PINImagePNGRepresentation(image); + } + + [strongSelf materializeAndCacheObject:image cacheInDisk:diskData additionalCost:processCost url:url key:key options:options outImage:nil outAltRep:nil]; + } + + [strongSelf callCompletionsWithKey:key image:image alternativeRepresentation:nil cached:NO response:result.response error:error finalized:YES]; + } else { + if (error == nil) { + error = [NSError errorWithDomain:PINRemoteImageManagerErrorDomain + code:PINRemoteImageManagerErrorFailedToFetchImageForProcessing + userInfo:nil]; + } + + [strongSelf callCompletionsWithKey:key image:nil alternativeRepresentation:nil cached:NO response:result.response error:error finalized:YES]; + } + }]; + task.downloadTaskUUID = downloadTaskUUID; + [self unlock]; +} + +- (void)downloadImageWithURL:(NSURL *)url + options:(PINRemoteImageManagerDownloadOptions)options + priority:(PINRemoteImageManagerPriority)priority + key:(NSString *)key + progressImage:(PINRemoteImageManagerImageCompletion)progressImage + UUID:(NSUUID *)UUID +{ + PINResume *resume = nil; + if ((options & PINRemoteImageManagerDownloadOptionsIgnoreCache) == 0) { + NSString *resumeKey = [self resumeCacheKeyForURL:url]; + resume = [self.cache objectFromDiskForKey:resumeKey]; + [self.cache removeObjectForKey:resumeKey completion:nil]; + } + + [self lock]; + PINRemoteImageDownloadTask *task = [self.tasks objectForKey:key]; + [self unlock]; + + [task scheduleDownloadWithRequest:[self requestWithURL:url task:task downloadOption:options] + resume:resume + skipRetry:(options & PINRemoteImageManagerDownloadOptionsSkipRetry) + priority:priority + completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) + { + [self->_concurrentOperationQueue scheduleOperation:^ + { + NSError *remoteImageError = error; + PINImage *image = nil; + id alternativeRepresentation = nil; + NSNumber *maxAge = nil; + if (remoteImageError == nil) { + BOOL ignoreHeaders = (options & PINRemoteImageManagerDownloadOptionsIgnoreCacheControlHeaders) != 0; + if ((self.diskCacheTTLIsEnabled || self.memoryCacheTTLIsEnabled) && !ignoreHeaders) { + // examine Cache-Control headers (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control) + if ([response isKindOfClass:[NSHTTPURLResponse class]]) { + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response; + maxAge = [httpResponse findMaxAge]; + } + } + // Stores the object in the cache. + [self materializeAndCacheObject:data cacheInDisk:data additionalCost:0 maxAge:maxAge url:url key:key options:options outImage:&image outAltRep:&alternativeRepresentation]; + } + + if (error == nil && image == nil && alternativeRepresentation == nil) { + remoteImageError = [NSError errorWithDomain:PINRemoteImageManagerErrorDomain + code:PINRemoteImageManagerErrorFailedToDecodeImage + userInfo:nil]; + } + + [self callCompletionsWithKey:key image:image alternativeRepresentation:alternativeRepresentation cached:NO response:response error:remoteImageError finalized:YES]; + } withPriority:operationPriorityWithImageManagerPriority(priority)]; + }]; +} + +-(BOOL)insertImageDataIntoCache:(nonnull NSData*)data + withURL:(nonnull NSURL *)url + processorKey:(nullable NSString *)processorKey + additionalCost:(NSUInteger)additionalCost +{ + + if (url != nil) { + NSString *key = [self cacheKeyForURL:url processorKey:processorKey]; + + PINRemoteImageManagerDownloadOptions options = PINRemoteImageManagerDownloadOptionsSkipDecode | PINRemoteImageManagerDownloadOptionsSkipEarlyCheck; + PINRemoteImageMemoryContainer *container = [[PINRemoteImageMemoryContainer alloc] init]; + container.data = data; + + return [self materializeAndCacheObject:container cacheInDisk:data additionalCost:additionalCost url:url key:key options:options outImage: nil outAltRep: nil]; + } + + return NO; +} + +- (BOOL)earlyReturnWithOptions:(PINRemoteImageManagerDownloadOptions)options url:(NSURL *)url key:(NSString *)key object:(id)object completion:(PINRemoteImageManagerImageCompletion)completion +{ + PINImage *image = nil; + id alternativeRepresentation = nil; + PINRemoteImageResultType resultType = PINRemoteImageResultTypeNone; + + BOOL allowEarlyReturn = !(PINRemoteImageManagerDownloadOptionsSkipEarlyCheck & options); + + if (url != nil && object != nil) { + resultType = PINRemoteImageResultTypeMemoryCache; + [self materializeAndCacheObject:object url:url key:key options:options outImage:&image outAltRep:&alternativeRepresentation]; + } + + if (completion && ((image || alternativeRepresentation) || (url == nil))) { + //If we're on the main thread, special case to call completion immediately + NSError *error = nil; + if (!url) { + error = [NSError errorWithDomain:NSURLErrorDomain + code:NSURLErrorUnsupportedURL + userInfo:@{ NSLocalizedDescriptionKey : @"unsupported URL" }]; + } + PINRemoteImageManagerResult *result = [PINRemoteImageManagerResult imageResultWithImage:image + alternativeRepresentation:alternativeRepresentation + requestLength:0 + resultType:resultType + UUID:nil + response:nil + error:error]; + if (allowEarlyReturn && [NSThread isMainThread]) { + completion(result); + } else { + dispatch_async(self.callbackQueue, ^{ + completion(result); + }); + } + return YES; + } + return NO; +} + +- (NSURLRequest *)requestWithURL:(NSURL *)url task:(PINRemoteImageTask *)task downloadOption:(PINRemoteImageManagerDownloadOptions)options +{ + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + + //set request cache policy as caller might pass in their own NSURLSessionConfiguration that enables cache + if ((options & PINRemoteImageManagerDownloadOptionsIgnoreCache) != 0) { + request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData; + } + + NSMutableDictionary *headers = [self.httpHeaderFields mutableCopy]; + + if (headers.count > 0) { + request.allHTTPHeaderFields = headers; + } + + if (_requestConfigurationHandler) { + request = [_requestConfigurationHandler(request) mutableCopy]; + } + + PINRemoteImageWeakTask *weakTask = [[PINRemoteImageWeakTask alloc] initWithTask:task]; + [NSURLProtocol setProperty:weakTask forKey:PINRemoteImageWeakTaskKey inRequest:request]; + + return request; +} + +- (void)callCompletionsWithKey:(NSString *)key + image:(PINImage *)image + alternativeRepresentation:(id)alternativeRepresentation + cached:(BOOL)cached + response:(NSURLResponse *)response + error:(NSError *)error + finalized:(BOOL)finalized +{ + [self lock]; + PINRemoteImageDownloadTask *task = [self.tasks objectForKey:key]; + [task callCompletionsWithImage:image alternativeRepresentation:alternativeRepresentation cached:cached response:response error:error remove:!finalized]; + if (finalized) { + [self.tasks removeObjectForKey:key]; + } + [self unlock]; +} + +#pragma mark - Prefetching + +- (NSArray *)prefetchImagesWithURLs:(NSArray *)urls +{ + return [self prefetchImagesWithURLs:urls options:PINRemoteImageManagerDownloadOptionsNone | PINRemoteImageManagerDownloadOptionsSkipEarlyCheck]; +} + +- (NSArray *)prefetchImagesWithURLs:(NSArray *)urls options:(PINRemoteImageManagerDownloadOptions)options +{ + return [self prefetchImagesWithURLs:urls options:options priority:PINRemoteImageManagerPriorityLow]; +} + +- (NSArray *)prefetchImagesWithURLs:(NSArray *)urls options:(PINRemoteImageManagerDownloadOptions)options priority:(PINRemoteImageManagerPriority)priority +{ + NSMutableArray *tasks = [NSMutableArray arrayWithCapacity:urls.count]; + for (NSURL *url in urls) { + NSUUID *task = [self prefetchImageWithURL:url options:options priority:priority]; + if (task != nil) { + [tasks addObject:task]; + } + } + return tasks; +} + +- (NSUUID *)prefetchImageWithURL:(NSURL *)url +{ + return [self prefetchImageWithURL:url options:PINRemoteImageManagerDownloadOptionsNone | PINRemoteImageManagerDownloadOptionsSkipEarlyCheck]; +} + +- (NSUUID *)prefetchImageWithURL:(NSURL *)url options:(PINRemoteImageManagerDownloadOptions)options +{ + return [self prefetchImageWithURL:url options:options priority:PINRemoteImageManagerPriorityLow]; +} + +- (NSUUID *)prefetchImageWithURL:(NSURL *)url options:(PINRemoteImageManagerDownloadOptions)options priority:(PINRemoteImageManagerPriority)priority +{ + return [self downloadImageWithURL:url + options:options + priority:priority + processorKey:nil + processor:nil + progressImage:nil + progressDownload:nil + completion:nil + inputUUID:nil]; +} + +#pragma mark - Cancellation & Priority + +- (void)cancelTaskWithUUID:(NSUUID *)UUID +{ + [self cancelTaskWithUUID:UUID storeResumeData:NO]; +} + +- (void)cancelTaskWithUUID:(nonnull NSUUID *)UUID storeResumeData:(BOOL)storeResumeData +{ + if (UUID == nil) { + return; + } + PINLog(@"Attempting to cancel UUID: %@", UUID); + [_concurrentOperationQueue scheduleOperation:^{ + PINResume *resume = nil; + [self lock]; + PINRemoteImageTask *taskToEvaluate = [self.UUIDToTask objectForKey:UUID]; + if (taskToEvaluate == nil) { + //maybe task hasn't been added to task list yet, add it to canceled tasks. + //there's no need to ever remove a UUID from canceledTasks because it is weak. + [self.canceledTasks addObject:UUID]; + } + + if ([taskToEvaluate cancelWithUUID:UUID resume:storeResumeData ? &resume : NULL]) { + [self.tasks removeObjectForKey:taskToEvaluate.key]; + } + [self unlock]; + + if (resume) { + //store resume data away, only download tasks currently return resume data + [self storeResumeData:resume forURL:[(PINRemoteImageDownloadTask *)taskToEvaluate URL]]; + } + } withPriority:PINOperationQueuePriorityHigh]; +} + +- (void)cancelAllTasks +{ + [self cancelAllTasksAndStoreResumeData:NO]; +} + +- (void)cancelAllTasksAndStoreResumeData:(BOOL)storeResumeData +{ + [_concurrentOperationQueue scheduleOperation:^{ + [self lock]; + NSMapTable *uuidToTask = [self.UUIDToTask copy]; + [self unlock]; + + for (NSUUID *uuid in uuidToTask) { + [self cancelTaskWithUUID:uuid storeResumeData:storeResumeData]; + } + } withPriority:PINOperationQueuePriorityHigh]; +} + +- (void)setPriority:(PINRemoteImageManagerPriority)priority ofTaskWithUUID:(NSUUID *)UUID +{ + if (UUID == nil) { + return; + } + PINLog(@"Setting priority of UUID: %@ priority: %lu", UUID, (unsigned long)priority); + [_concurrentOperationQueue scheduleOperation:^{ + [self lock]; + PINRemoteImageTask *task = [self.UUIDToTask objectForKey:UUID]; + [task setPriority:priority]; + [self unlock]; + } withPriority:PINOperationQueuePriorityHigh]; +} + +- (void)setProgressImageCallback:(nullable PINRemoteImageManagerImageCompletion)progressImageCallback ofTaskWithUUID:(nonnull NSUUID *)UUID +{ + if (UUID == nil) { + return; + } + + PINLog(@"setting progress block of UUID: %@ progressBlock: %@", UUID, progressImageCallback); + [_concurrentOperationQueue scheduleOperation:^{ + [self lock]; + PINRemoteImageTask *task = [self.UUIDToTask objectForKey:UUID]; + if ([task isKindOfClass:[PINRemoteImageDownloadTask class]]) { + PINRemoteImageCallbacks *callbacks = task.callbackBlocks[UUID]; + callbacks.progressImageBlock = progressImageCallback; + } + [self unlock]; + } withPriority:PINOperationQueuePriorityHigh]; +} + +- (void)setRetryStrategyCreationBlock:(id (^)(void))retryStrategyCreationBlock { + [_concurrentOperationQueue scheduleOperation:^{ + [self lock]; + self->_retryStrategyCreationBlock = retryStrategyCreationBlock; + [self unlock]; + } withPriority:PINOperationQueuePriorityHigh]; +} + +#pragma mark - Caching + +- (void)imageFromCacheWithCacheKey:(NSString *)cacheKey + completion:(PINRemoteImageManagerImageCompletion)completion +{ + [self imageFromCacheWithCacheKey:cacheKey options:PINRemoteImageManagerDownloadOptionsNone completion:completion]; +} + +- (void)imageFromCacheWithCacheKey:(NSString *)cacheKey + options:(PINRemoteImageManagerDownloadOptions)options + completion:(PINRemoteImageManagerImageCompletion)completion +{ + [self imageFromCacheWithURL:nil processorKey:nil cacheKey:cacheKey options:options completion:completion]; +} + +- (void)imageFromCacheWithURL:(nonnull NSURL *)url + processorKey:(nullable NSString *)processorKey + options:(PINRemoteImageManagerDownloadOptions)options + completion:(nonnull PINRemoteImageManagerImageCompletion)completion +{ + [self imageFromCacheWithURL:url processorKey:processorKey cacheKey:nil options:options completion:completion]; +} + +- (void)imageFromCacheWithURL:(NSURL *)url + processorKey:(NSString *)processorKey + cacheKey:(NSString *)cacheKey + options:(PINRemoteImageManagerDownloadOptions)options + completion:(PINRemoteImageManagerImageCompletion)completion +{ + CFTimeInterval requestTime = CACurrentMediaTime(); + + if ((PINRemoteImageManagerDownloadOptionsSkipEarlyCheck & options) == NO && [NSThread isMainThread]) { + PINRemoteImageManagerResult *result = [self synchronousImageFromCacheWithURL:url processorKey:processorKey cacheKey:cacheKey options:options]; + if (result.image && result.error == nil) { + completion((result)); + return; + } + } + + [self objectForURL:url processorKey:processorKey key:cacheKey options:options completion:^(BOOL found, BOOL valid, PINImage *image, id alternativeRepresentation) { + NSError *error = nil; + if (valid == NO) { + error = [NSError errorWithDomain:PINRemoteImageManagerErrorDomain + code:PINRemoteImageManagerErrorInvalidItemInCache + userInfo:nil]; + } + + dispatch_async(self.callbackQueue, ^{ + completion([PINRemoteImageManagerResult imageResultWithImage:image + alternativeRepresentation:alternativeRepresentation + requestLength:CACurrentMediaTime() - requestTime + resultType:PINRemoteImageResultTypeCache + UUID:nil + response:nil + error:error]); + }); + }]; +} + +- (PINRemoteImageManagerResult *)synchronousImageFromCacheWithCacheKey:(NSString *)cacheKey options:(PINRemoteImageManagerDownloadOptions)options +{ + return [self synchronousImageFromCacheWithURL:nil processorKey:nil cacheKey:cacheKey options:options]; +} + +- (nonnull PINRemoteImageManagerResult *)synchronousImageFromCacheWithURL:(NSURL *)url processorKey:(nullable NSString *)processorKey options:(PINRemoteImageManagerDownloadOptions)options +{ + return [self synchronousImageFromCacheWithURL:url processorKey:processorKey cacheKey:nil options:options]; +} + +- (PINRemoteImageManagerResult *)synchronousImageFromCacheWithURL:(NSURL *)url processorKey:(NSString *)processorKey cacheKey:(NSString *)cacheKey options:(PINRemoteImageManagerDownloadOptions)options +{ + CFTimeInterval requestTime = CACurrentMediaTime(); + + if (cacheKey == nil && url == nil) { + return nil; + } + + cacheKey = cacheKey ?: [self cacheKeyForURL:url processorKey:processorKey]; + + id object = [self.cache objectFromMemoryForKey:cacheKey]; + PINImage *image; + id alternativeRepresentation; + NSError *error = nil; + if (object == nil) { + image = nil; + alternativeRepresentation = nil; + } else if ([self materializeAndCacheObject:object url:url key:cacheKey options:options outImage:&image outAltRep:&alternativeRepresentation] == NO) { + error = [NSError errorWithDomain:PINRemoteImageManagerErrorDomain + code:PINRemoteImageManagerErrorInvalidItemInCache + userInfo:nil]; + } + + return [PINRemoteImageManagerResult imageResultWithImage:image + alternativeRepresentation:alternativeRepresentation + requestLength:CACurrentMediaTime() - requestTime + resultType:PINRemoteImageResultTypeMemoryCache + UUID:nil + response:nil + error:error]; +} + +#pragma mark - Session Task Blocks + +- (void)didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge forTask:(NSURLSessionTask *)dataTask completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler { + [self lock]; + if (self.authenticationChallengeHandler) { + self.authenticationChallengeHandler(dataTask, challenge, completionHandler); + } else { + completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); + } + [self unlock]; +} + +- (void)didReceiveResponse:(nonnull NSURLResponse *)response forTask:(nonnull NSURLSessionTask *)dataTask +{ + [self lock]; + PINRemoteImageWeakTask *weakTask = [NSURLProtocol propertyForKey:PINRemoteImageWeakTaskKey inRequest:dataTask.originalRequest]; + PINRemoteImageDownloadTask *task = (PINRemoteImageDownloadTask *)weakTask.task; + [self unlock]; + [task didReceiveResponse:response]; +} + +- (void)didReceiveData:(NSData *)data forTask:(NSURLSessionTask *)dataTask +{ + [self lock]; + PINRemoteImageWeakTask *weakTask = [NSURLProtocol propertyForKey:PINRemoteImageWeakTaskKey inRequest:dataTask.originalRequest]; + PINRemoteImageDownloadTask *task = (PINRemoteImageDownloadTask *)weakTask.task; + [self unlock]; + [task didReceiveData:data]; +} + +- (void)didCollectMetrics:(nonnull NSURLSessionTaskMetrics *)metrics forURL:(nonnull NSURL *)url +{ + [self lock]; + if (self.metricsCallback) { + self.metricsCallback(url, metrics); + } + [self unlock]; +} + +#pragma mark - QOS + +- (NSUUID *)downloadImageWithURLs:(NSArray *)urls + options:(PINRemoteImageManagerDownloadOptions)options + progressImage:(PINRemoteImageManagerImageCompletion)progressImage + completion:(PINRemoteImageManagerImageCompletion)completion +{ + return [self downloadImageWithURLs:urls + options:options + progressImage:progressImage + progressDownload:nil + completion:completion]; +} + +- (nullable NSUUID *)downloadImageWithURLs:(nonnull NSArray *)urls + options:(PINRemoteImageManagerDownloadOptions)options + progressImage:(nullable PINRemoteImageManagerImageCompletion)progressImage + progressDownload:(nullable PINRemoteImageManagerProgressDownload)progressDownload + completion:(nullable PINRemoteImageManagerImageCompletion)completion +{ + NSUUID *UUID = [NSUUID UUID]; + if (urls.count <= 1) { + NSURL *url = [urls firstObject]; + [self downloadImageWithURL:url + options:options + priority:PINRemoteImageManagerPriorityDefault + processorKey:nil + processor:nil + progressImage:progressImage + progressDownload:progressDownload + completion:completion + inputUUID:UUID]; + return UUID; + } + + [self.concurrentOperationQueue scheduleOperation:^{ + __block NSInteger highestQualityDownloadedIdx = -1; + + //check for the highest quality image already in cache. It's possible that an image is in the process of being + //cached when this is being run. In which case two things could happen: + // - If network conditions dictate that a lower quality image should be downloaded than the one that is currently + // being cached, it will be downloaded in addition. This is not ideal behavior, worst case scenario and unlikely. + // - If network conditions dictate that the same quality image should be downloaded as the one being cached, no + // new image will be downloaded as either the caching will have finished by the time we actually request it or + // the task will still exist and our callback will be attached. In this case, no detrimental behavior will have + // occurred. + [urls enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSURL *url, NSUInteger idx, BOOL *stop) { + NSAssert([url isKindOfClass:[NSURL class]], @"url must be of type URL"); + NSString *cacheKey = [self cacheKeyForURL:url processorKey:nil]; + + //we don't actually need the object, just need to know it exists so that we can request it later + BOOL hasObject = [self.cache objectExistsForKey:cacheKey]; + + if (hasObject) { + highestQualityDownloadedIdx = idx; + *stop = YES; + } + }]; + + [self lock]; + float highQualityQPSThreshold = [self highQualityBPSThreshold]; + float lowQualityQPSThreshold = [self lowQualityBPSThreshold]; + BOOL shouldUpgradeLowQualityImages = [self shouldUpgradeLowQualityImages]; + [self unlock]; + + NSUInteger desiredImageURLIdx = [PINSpeedRecorder appropriateImageIdxForURLsGivenHistoricalNetworkConditions:urls + lowQualityQPSThreshold:lowQualityQPSThreshold + highQualityQPSThreshold:highQualityQPSThreshold]; + + NSUInteger downloadIdx; + //if the highest quality already downloaded is less than what currentBPS would dictate and shouldUpgrade is + //set, download the new higher quality image. If no image has been cached, download the image dictated by + //current bps + + if ((highestQualityDownloadedIdx < desiredImageURLIdx && shouldUpgradeLowQualityImages) || highestQualityDownloadedIdx == -1) { + downloadIdx = desiredImageURLIdx; + } else { + downloadIdx = highestQualityDownloadedIdx; + } + + NSURL *downloadURL = [urls objectAtIndex:downloadIdx]; + + [self downloadImageWithURL:downloadURL + options:options + priority:PINRemoteImageManagerPriorityDefault + processorKey:nil + processor:nil + progressImage:progressImage + progressDownload:progressDownload + completion:^(PINRemoteImageManagerResult *result) { + //clean out any lower quality images from the cache + for (NSInteger idx = downloadIdx - 1; idx >= 0; idx--) { + [[self cache] removeObjectForKey:[self cacheKeyForURL:[urls objectAtIndex:idx] processorKey:nil]]; + } + + if (completion) { + completion(result); + } + } + inputUUID:UUID]; + } withPriority:PINOperationQueuePriorityDefault]; + return UUID; +} + +#pragma mark - Caching + +- (BOOL)materializeAndCacheObject:(id)object + url:(NSURL *)url + key:(NSString *)key + options:(PINRemoteImageManagerDownloadOptions)options + outImage:(PINImage **)outImage + outAltRep:(id *)outAlternateRepresentation +{ + return [self materializeAndCacheObject:object cacheInDisk:nil additionalCost:0 url:url key:key options:options outImage:outImage outAltRep:outAlternateRepresentation]; +} + +- (BOOL)materializeAndCacheObject:(id)object + cacheInDisk:(NSData *)diskData + additionalCost:(NSUInteger)additionalCost + url:(NSURL *)url + key:(NSString *)key + options:(PINRemoteImageManagerDownloadOptions)options + outImage:(PINImage **)outImage + outAltRep:(id *)outAlternateRepresentation { + return [self materializeAndCacheObject:object cacheInDisk:diskData additionalCost:additionalCost maxAge:nil url:url key:key options:options outImage:outImage outAltRep:outAlternateRepresentation]; +} + +//takes the object from the cache and returns an image or animated image. +//if it's a non-alternative representation and skipDecode is not set it also decompresses the image. +- (BOOL)materializeAndCacheObject:(id)object + cacheInDisk:(NSData *)diskData + additionalCost:(NSUInteger)additionalCost + maxAge:(NSNumber *)maxAge + url:(NSURL *)url + key:(NSString *)key + options:(PINRemoteImageManagerDownloadOptions)options + outImage:(PINImage **)outImage + outAltRep:(id *)outAlternateRepresentation +{ + NSAssert(object != nil, @"Object should not be nil."); + if (object == nil) { + return NO; + } + BOOL alternateRepresentationsAllowed = (PINRemoteImageManagerDisallowAlternateRepresentations & options) == 0; + BOOL skipDecode = (options & PINRemoteImageManagerDownloadOptionsSkipDecode) != 0; + __block id alternateRepresentation = nil; + __block PINImage *image = nil; + __block NSData *data = nil; + __block BOOL updateMemoryCache = NO; + + PINRemoteImageMemoryContainer *container = nil; + if ([object isKindOfClass:[PINRemoteImageMemoryContainer class]]) { + container = (PINRemoteImageMemoryContainer *)object; + [container.lock lockWithBlock:^{ + data = container.data; + }]; + } else { + updateMemoryCache = YES; + + // don't need to lock the container here because we just init it. + container = [[PINRemoteImageMemoryContainer alloc] init]; + + if ([object isKindOfClass:[PINImage class]]) { + data = diskData; + container.image = (PINImage *)object; + } else if ([object isKindOfClass:[NSData class]]) { + data = (NSData *)object; + } else { + //invalid item in cache + updateMemoryCache = NO; + data = nil; + container = nil; + } + + container.data = data; + } + + if (alternateRepresentationsAllowed) { + alternateRepresentation = [_alternateRepProvider alternateRepresentationWithData:data options:options]; + } + + if (alternateRepresentation == nil) { + //we need the image + [container.lock lockWithBlock:^{ + image = container.image; + }]; + if (image == nil && container.data) { + image = [PINImage pin_decodedImageWithData:container.data skipDecodeIfPossible:skipDecode]; + + if (url != nil) { + image = [PINImage pin_scaledImageForImage:image withKey:key]; + } + + if (skipDecode == NO) { + [container.lock lockWithBlock:^{ + updateMemoryCache = YES; + container.image = image; + }]; + } + } + } + + // maxAge set to 0 means that images should not be stored at all. + BOOL doNotCache = (maxAge != nil && [maxAge integerValue] == 0); + + // There is no HTTP header that can be sent to indicate "infinite". However not setting a value at all, which in + // our case is represented by maxAge == nil, effectively means that. + BOOL cacheIndefinitely = (maxAge == nil); + + if (!doNotCache) { + if (updateMemoryCache) { + [container.lock lockWithBlock:^{ + NSUInteger cacheCost = additionalCost; + cacheCost += [container.data length]; + CGImageRef imageRef = container.image.CGImage; + NSAssert(container.image == nil || imageRef != NULL, @"We only cache a decompressed image if we decompressed it ourselves. In that case, it should be backed by a CGImageRef."); + if (imageRef) { + cacheCost += CGImageGetHeight(imageRef) * CGImageGetBytesPerRow(imageRef); + } + if (!self.memoryCacheTTLIsEnabled || cacheIndefinitely) { + [self.cache setObjectInMemory:container forKey:key withCost:cacheCost]; + } else { + [self.cache setObjectInMemory:container forKey:key withCost:cacheCost withAgeLimit:[maxAge integerValue]]; + } + }]; + } + + if (diskData) { + if (!self.diskCacheTTLIsEnabled || cacheIndefinitely) { + // with an unset (nil) maxAge, or a cache that is not _isTtlCache, behave as before (will use cache global behavior) + [self.cache setObjectOnDisk:diskData forKey:key]; + } else { + [self.cache setObjectOnDisk:diskData forKey:key withAgeLimit:[maxAge integerValue]]; + } + } + } + + if (outImage) { + *outImage = image; + } + + if (outAlternateRepresentation) { + *outAlternateRepresentation = alternateRepresentation; + } + + if (image == nil && alternateRepresentation == nil) { + PINLog(@"Invalid item in cache"); + [self.cache removeObjectForKey:key completion:nil]; + return NO; + } + return YES; +} + +- (NSString *)cacheKeyForURL:(NSURL *)url processorKey:(NSString *)processorKey +{ + return [self cacheKeyForURL:url processorKey:processorKey resume:NO]; +} + +- (NSString *)cacheKeyForURL:(NSURL *)url processorKey:(NSString *)processorKey resume:(BOOL)resume +{ + NSString *cacheKey = [url absoluteString]; + NSAssert((processorKey.length == 0 && resume == YES) || resume == NO, @"It doesn't make sense to use resume with processing."); + if (processorKey.length > 0) { + cacheKey = [cacheKey stringByAppendingFormat:@"-<%@>", processorKey]; + } + + //PINDiskCache uses this key as the filename of the file written to disk + //Due to the current filesystem used in Darwin, this name must be limited to 255 chars. + //In case the generated key exceeds PINRemoteImageManagerCacheKeyMaxLength characters, + //we return the hash of it instead. + if (cacheKey.length > PINRemoteImageManagerCacheKeyMaxLength) { + __block CC_MD5_CTX ctx; + CC_MD5_Init(&ctx); + NSData *data = [cacheKey dataUsingEncoding:NSUTF8StringEncoding]; + [data enumerateByteRangesUsingBlock:^(const void * _Nonnull bytes, NSRange byteRange, BOOL * _Nonnull stop) { + CC_MD5_Update(&ctx, bytes, (CC_LONG)byteRange.length); + }]; + + unsigned char digest[CC_MD5_DIGEST_LENGTH]; + CC_MD5_Final(digest, &ctx); + + NSMutableString *hexString = [NSMutableString stringWithCapacity:(CC_MD5_DIGEST_LENGTH * 2)]; + for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) { + [hexString appendFormat:@"%02lx", (unsigned long)digest[i]]; + } + cacheKey = [hexString copy]; + } + //The resume key must not be hashed, it is used to decide whether or not to decode from the disk cache. + if (resume) { + cacheKey = [PINRemoteImageCacheKeyResumePrefix stringByAppendingString:cacheKey]; + } + + return cacheKey; +} + +- (void)objectForKey:(NSString *)key options:(PINRemoteImageManagerDownloadOptions)options completion:(void (^)(BOOL found, BOOL valid, PINImage *image, id alternativeRepresentation))completion +{ + return [self objectForURL:nil processorKey:nil key:key options:options completion:completion]; +} + +- (void)objectForURL:(NSURL *)url processorKey:(NSString *)processorKey key:(NSString *)key options:(PINRemoteImageManagerDownloadOptions)options completion:(void (^)(BOOL found, BOOL valid, PINImage *image, id alternativeRepresentation))completion +{ + if ((options & PINRemoteImageManagerDownloadOptionsIgnoreCache) != 0) { + completion(NO, YES, nil, nil); + return; + } + + if (key == nil && url == nil) { + completion(NO, YES, nil, nil); + return; + } + + key = key ?: [self cacheKeyForURL:url processorKey:processorKey]; + + void (^materialize)(id object) = ^(id object) { + PINImage *image = nil; + id alternativeRepresentation = nil; + BOOL valid = [self materializeAndCacheObject:object + url:nil + key:key + options:options + outImage:&image + outAltRep:&alternativeRepresentation]; + + completion(YES, valid, image, alternativeRepresentation); + }; + + PINRemoteImageMemoryContainer *container = [self.cache objectFromMemoryForKey:key]; + if (container) { + materialize(container); + } else { + [self.cache objectFromDiskForKey:key completion:^(id _Nonnull cache, + NSString *_Nonnull key, + id _Nullable object) { + if (object) { + materialize(object); + } else { + completion(NO, YES, nil, nil); + } + }]; + } +} + +#pragma mark - Resume support + +- (NSString *)resumeCacheKeyForURL:(NSURL *)url +{ + return [self cacheKeyForURL:url processorKey:nil resume:YES]; +} + +- (void)storeResumeData:(PINResume *)resume forURL:(NSURL *)URL +{ + NSString *resumeKey = [self resumeCacheKeyForURL:URL]; + [self.cache setObjectOnDisk:resume forKey:resumeKey]; +} + +#if DEBUG +- (NSUInteger)totalDownloads +{ + //hack to avoid main thread assertion since these are only used in testing + [_lock lock]; + NSUInteger totalDownloads = _totalDownloads; + [_lock unlock]; + return totalDownloads; +} +#endif + +@end diff --git a/Source/Classes/PINRemoteImageManagerConfiguration.m b/Source/Classes/PINRemoteImageManagerConfiguration.m new file mode 100644 index 00000000..88896fd0 --- /dev/null +++ b/Source/Classes/PINRemoteImageManagerConfiguration.m @@ -0,0 +1,35 @@ +// +// PINRemoteImageManagerConfiguration.m +// Pods +// +// Created by Ryan Quan on 2/22/19. +// +// + +#import +#import + +@implementation PINRemoteImageManagerConfiguration + +- (nonnull instancetype)init { + if (self = [super init]) { + _maxConcurrentOperations = [[NSProcessInfo processInfo] activeProcessorCount] * 2; + _maxConcurrentDownloads = 10; + _estimatedRemainingTimeThreshold = 0.1; + _shouldBlurProgressive = YES; + _maxProgressiveRenderSize = CGSizeMake(1024, 1024); + _highQualityBPSThreshold = 500000; + _lowQualityBPSThreshold = 50000; // approximately edge speed + _shouldUpgradeLowQualityImages = NO; + } + return self; +} + +#pragma mark - Setters + +- (void)setMaxConcurrentDownloads:(NSUInteger)maxConcurrentDownloads { + NSAssert(maxConcurrentDownloads <= PINRemoteImageHTTPMaximumConnectionsPerHost, @"maxNumberOfConcurrentDownloads must be less than or equal to %d", PINRemoteImageHTTPMaximumConnectionsPerHost); + _maxConcurrentDownloads = maxConcurrentDownloads; +} + +@end diff --git a/Source/Classes/PINRemoteImageManagerResult.m b/Source/Classes/PINRemoteImageManagerResult.m new file mode 100644 index 00000000..7bd92e61 --- /dev/null +++ b/Source/Classes/PINRemoteImageManagerResult.m @@ -0,0 +1,118 @@ +// +// PINRemoteImageManagerResult.m +// Pods +// +// Created by Garrett Moon on 3/9/15. +// +// + +#import + +@implementation PINRemoteImageManagerResult + ++ (nonnull instancetype)imageResultWithImage:(nullable PINImage *)image + alternativeRepresentation:(nullable id)alternativeRepresentation + requestLength:(NSTimeInterval)requestLength + resultType:(PINRemoteImageResultType)resultType + UUID:(nullable NSUUID *)uuid + response:(nullable NSURLResponse *)response + error:(nullable NSError *)error +{ + return [self imageResultWithImage:image + alternativeRepresentation:alternativeRepresentation + requestLength:requestLength + resultType:resultType + UUID:uuid + response:response + error:error + renderedImageQuality:1.0]; +} + ++ (nonnull instancetype)imageResultWithImage:(nullable PINImage *)image + alternativeRepresentation:(nullable id)alternativeRepresentation + requestLength:(NSTimeInterval)requestLength + resultType:(PINRemoteImageResultType)resultType + UUID:(nullable NSUUID *)uuid + response:(nullable NSURLResponse *)response + error:(nullable NSError *)error + bytesSavedByResuming:(NSUInteger)bytesSavedByResuming +{ + return [[self alloc] initWithImage:image + alternativeRepresentation:alternativeRepresentation + requestLength:requestLength + error:error + resultType:resultType + UUID:uuid + response:response + renderedImageQuality:1.0 + bytesSavedByResuming:bytesSavedByResuming]; +} + ++ (nonnull instancetype)imageResultWithImage:(nullable PINImage *)image + alternativeRepresentation:(nullable id)alternativeRepresentation + requestLength:(NSTimeInterval)requestLength + resultType:(PINRemoteImageResultType)resultType + UUID:(nullable NSUUID *)uuid + response:(nullable NSURLResponse *)response + error:(nullable NSError *)error + renderedImageQuality:(CGFloat)renderedImageQuality +{ + return [[self alloc] initWithImage:image + alternativeRepresentation:alternativeRepresentation + requestLength:requestLength + error:error + resultType:resultType + UUID:uuid + response:response + renderedImageQuality:renderedImageQuality + bytesSavedByResuming:0]; +} + +- (instancetype)initWithImage:(PINImage *)image + alternativeRepresentation:(id)alternativeRepresentation + requestLength:(NSTimeInterval)requestLength + error:(NSError *)error + resultType:(PINRemoteImageResultType)resultType + UUID:(NSUUID *)uuid + response:(NSURLResponse *)response + renderedImageQuality:(CGFloat)renderedImageQuality + bytesSavedByResuming:(NSUInteger)bytesSavedByResuming; +{ + if (self = [super init]) { + _image = image; + _alternativeRepresentation = alternativeRepresentation; + _requestDuration = requestLength; + _error = error; + _resultType = resultType; + _UUID = uuid; + _response = response; + _renderedImageQuality = renderedImageQuality; + _bytesSavedByResuming = bytesSavedByResuming; + } + return self; +} + +- (NSString *)description +{ + NSString *description = [super description]; + description = [description stringByAppendingString:[NSString stringWithFormat:@"image: %@", self.image]]; + description = [description stringByAppendingString:@"\n"]; + description = [description stringByAppendingString:[NSString stringWithFormat:@"alternativeRepresentation: %@", self.alternativeRepresentation]]; + description = [description stringByAppendingString:@"\n"]; + description = [description stringByAppendingString:[NSString stringWithFormat:@"requestDuration: %f", self.requestDuration]]; + description = [description stringByAppendingString:@"\n"]; + description = [description stringByAppendingString:[NSString stringWithFormat:@"error: %@", self.error]]; + description = [description stringByAppendingString:@"\n"]; + description = [description stringByAppendingString:[NSString stringWithFormat:@"resultType: %lu", (unsigned long)self.resultType]]; + description = [description stringByAppendingString:@"\n"]; + description = [description stringByAppendingString:[NSString stringWithFormat:@"UUID: %@", self.UUID]]; + description = [description stringByAppendingString:@"\n"]; + description = [description stringByAppendingString:[NSString stringWithFormat:@"response: %@", self.response]]; + description = [description stringByAppendingString:@"\n"]; + description = [description stringByAppendingString:[NSString stringWithFormat:@"renderedImageQuality: %f", self.renderedImageQuality]]; + description = [description stringByAppendingString:@"\n"]; + description = [description stringByAppendingString:[NSString stringWithFormat:@"bytesSavedByResuming: %lu", (unsigned long)self.bytesSavedByResuming]]; + return description; +} + +@end diff --git a/Source/Classes/PINRemoteImageMemoryContainer.h b/Source/Classes/PINRemoteImageMemoryContainer.h new file mode 100644 index 00000000..18a50ff3 --- /dev/null +++ b/Source/Classes/PINRemoteImageMemoryContainer.h @@ -0,0 +1,23 @@ +// +// PINRemoteImageMemoryContainer.h +// Pods +// +// Created by Garrett Moon on 3/17/16. +// +// + +#import + +#import +#import +#import "PINRemoteLock.h" + +@class PINImage; + +@interface PINRemoteImageMemoryContainer : NSObject + +@property (nonatomic, strong) PINImage *image; +@property (nonatomic, strong) NSData *data; +@property (nonatomic, strong) PINRemoteLock *lock; + +@end diff --git a/Pod/Classes/PINRemoteImageMemoryContainer.m b/Source/Classes/PINRemoteImageMemoryContainer.m similarity index 100% rename from Pod/Classes/PINRemoteImageMemoryContainer.m rename to Source/Classes/PINRemoteImageMemoryContainer.m diff --git a/Pod/Classes/PINRemoteImageProcessorTask.h b/Source/Classes/PINRemoteImageProcessorTask.h similarity index 100% rename from Pod/Classes/PINRemoteImageProcessorTask.h rename to Source/Classes/PINRemoteImageProcessorTask.h diff --git a/Source/Classes/PINRemoteImageProcessorTask.m b/Source/Classes/PINRemoteImageProcessorTask.m new file mode 100644 index 00000000..2f950227 --- /dev/null +++ b/Source/Classes/PINRemoteImageProcessorTask.m @@ -0,0 +1,44 @@ +// +// PINRemoteImageProcessorTask.m +// Pods +// +// Created by Garrett Moon on 3/9/15. +// +// + +#import "PINRemoteImageProcessorTask.h" + +@implementation PINRemoteImageProcessorTask + +@synthesize downloadTaskUUID = _downloadTaskUUID; + +- (BOOL)cancelWithUUID:(NSUUID *)UUID resume:(PINResume **)resume +{ + BOOL noMoreCompletions = [super cancelWithUUID:UUID resume:resume]; + [self.lock lockWithBlock:^{ + if (noMoreCompletions && self->_downloadTaskUUID) { + [self.manager cancelTaskWithUUID:self->_downloadTaskUUID]; + self->_downloadTaskUUID = nil; + } + }]; + return noMoreCompletions; +} + +- (void)setDownloadTaskUUID:(NSUUID *)downloadTaskUUID +{ + [self.lock lockWithBlock:^{ + NSAssert(self->_downloadTaskUUID == nil, @"downloadTaskUUID should be nil"); + self->_downloadTaskUUID = downloadTaskUUID; + }]; +} + +- (NSUUID *)downloadTaskUUID +{ + __block NSUUID *downloadTaskUUID; + [self.lock lockWithBlock:^{ + downloadTaskUUID = self->_downloadTaskUUID; + }]; + return downloadTaskUUID; +} + +@end diff --git a/Source/Classes/PINRemoteImageTask+Subclassing.h b/Source/Classes/PINRemoteImageTask+Subclassing.h new file mode 100644 index 00000000..8e0c6005 --- /dev/null +++ b/Source/Classes/PINRemoteImageTask+Subclassing.h @@ -0,0 +1,20 @@ +// +// PINRemoteImageTask+Subclassing.h +// PINRemoteImage +// +// Created by Garrett Moon on 5/22/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import "PINRemoteImageTask.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface PINRemoteImageTask (Subclassing) + +- (NSMutableDictionary *)l_callbackBlocks; +- (BOOL)l_cancelWithUUID:(NSUUID *)UUID; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Source/Classes/PINRemoteImageTask.h b/Source/Classes/PINRemoteImageTask.h new file mode 100644 index 00000000..e6c34dab --- /dev/null +++ b/Source/Classes/PINRemoteImageTask.h @@ -0,0 +1,65 @@ +// +// PINRemoteImageTask.h +// Pods +// +// Created by Garrett Moon on 3/9/15. +// +// + +#import + +#if !__has_include() +#import "PINOperation.h" +#else +#import +#endif + +#import "PINRemoteImageCallbacks.h" +#import +#import +#import "PINRemoteLock.h" +#import "PINResume.h" + +@interface PINRemoteImageTask : NSObject + +@property (nonatomic, strong, readonly, nonnull) PINRemoteLock *lock; + +@property (nonatomic, copy, readonly, nonnull) NSDictionary *callbackBlocks; + +@property (nonatomic, weak, nullable) PINRemoteImageManager *manager; + +@property (nonatomic, strong, nullable) id retryStrategy; + +@property (nonatomic, copy, nullable) NSString *key; + +- (_Nonnull instancetype)init NS_UNAVAILABLE; +- (_Nonnull instancetype)initWithManager:(nonnull PINRemoteImageManager *)manager NS_DESIGNATED_INITIALIZER; + +- (void)addCallbacksWithCompletionBlock:(nonnull PINRemoteImageManagerImageCompletion)completionBlock + progressImageBlock:(nullable PINRemoteImageManagerImageCompletion)progressImageBlock + progressDownloadBlock:(nullable PINRemoteImageManagerProgressDownload)progressDownloadBlock + withUUID:(nonnull NSUUID *)UUID; + +- (void)removeCallbackWithUUID:(nonnull NSUUID *)UUID; + +- (void)callCompletionsWithImage:(nullable PINImage *)image + alternativeRepresentation:(nullable id)alternativeRepresentation + cached:(BOOL)cached + response:(nullable NSURLResponse *)response + error:(nullable NSError *)error + remove:(BOOL)remove; + +//returns YES if no more attached completionBlocks +- (BOOL)cancelWithUUID:(nonnull NSUUID *)UUID resume:(PINResume * _Nullable * _Nullable)resume; + +- (void)setPriority:(PINRemoteImageManagerPriority)priority; + +- (nonnull PINRemoteImageManagerResult *)imageResultWithImage:(nullable PINImage *)image + alternativeRepresentation:(nullable id)alternativeRepresentation + requestLength:(NSTimeInterval)requestLength + resultType:(PINRemoteImageResultType)resultType + UUID:(nullable NSUUID *)uuid + response:(nullable NSURLResponse *)response + error:(nullable NSError *)error; + +@end diff --git a/Source/Classes/PINRemoteImageTask.m b/Source/Classes/PINRemoteImageTask.m new file mode 100644 index 00000000..043a6280 --- /dev/null +++ b/Source/Classes/PINRemoteImageTask.m @@ -0,0 +1,160 @@ +// +// PINRemoteImageTask.m +// Pods +// +// Created by Garrett Moon on 3/9/15. +// +// + +#import "PINRemoteImageTask.h" + +#import "PINRemoteImageCallbacks.h" +#import "PINRemoteImageManager+Private.h" + +@interface PINRemoteImageTask () +{ + NSMutableDictionary *_callbackBlocks; // We need to copy/retain `NSUUID`, because `PINRemoteImageManager` has a weak table `UUIDs` to store all UUIDs. +} + +@end + +@implementation PINRemoteImageTask + +@synthesize lock = _lock; + +- (instancetype)initWithManager:(PINRemoteImageManager *)manager +{ + if (self = [super init]) { + _lock = [[PINRemoteLock alloc] initWithName:@"Task Lock"]; + _manager = manager; + _callbackBlocks = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"<%@: %p> completionBlocks: %lu", NSStringFromClass([self class]), self, (unsigned long)self.callbackBlocks.count]; +} + +- (void)addCallbacksWithCompletionBlock:(PINRemoteImageManagerImageCompletion)completionBlock + progressImageBlock:(PINRemoteImageManagerImageCompletion)progressImageBlock + progressDownloadBlock:(PINRemoteImageManagerProgressDownload)progressDownloadBlock + withUUID:(NSUUID *)UUID +{ + PINRemoteImageCallbacks *completion = [[PINRemoteImageCallbacks alloc] init]; + completion.completionBlock = completionBlock; + completion.progressImageBlock = progressImageBlock; + completion.progressDownloadBlock = progressDownloadBlock; + + [self.lock lockWithBlock:^{ + [self->_callbackBlocks setObject:completion forKey:UUID]; + }]; +} + +- (void)removeCallbackWithUUID:(NSUUID *)UUID +{ + [self.lock lockWithBlock:^{ + [self l_removeCallbackWithUUID:UUID]; + }]; +} + +- (void)l_removeCallbackWithUUID:(NSUUID *)UUID +{ + [_callbackBlocks removeObjectForKey:UUID]; +} + +- (NSDictionary *)callbackBlocks +{ + __block NSDictionary *callbackBlocks; + [self.lock lockWithBlock:^{ + callbackBlocks = [self->_callbackBlocks copy]; + }]; + return callbackBlocks; +} + +- (void)callCompletionsWithImage:(PINImage *)image + alternativeRepresentation:(id)alternativeRepresentation + cached:(BOOL)cached + response:(NSURLResponse *)response + error:(NSError *)error + remove:(BOOL)remove; +{ + __weak typeof(self) weakSelf = self; + [self.callbackBlocks enumerateKeysAndObjectsUsingBlock:^(NSUUID *UUID, PINRemoteImageCallbacks *callback, BOOL *stop) { + typeof(self) strongSelf = weakSelf; + PINRemoteImageManagerImageCompletion completionBlock = callback.completionBlock; + if (completionBlock != nil) { + PINLog(@"calling completion for UUID: %@ key: %@", UUID, strongSelf.key); + CFTimeInterval requestTime = callback.requestTime; + + dispatch_async(self.manager.callbackQueue, ^ + { + PINRemoteImageResultType result; + if (image || alternativeRepresentation) { + result = cached ? PINRemoteImageResultTypeCache : PINRemoteImageResultTypeDownload; + } else { + result = PINRemoteImageResultTypeNone; + } + completionBlock([self imageResultWithImage:image + alternativeRepresentation:alternativeRepresentation + requestLength:CACurrentMediaTime() - requestTime + resultType:result + UUID:UUID + response:response + error:error]); + }); + } + if (remove) { + [strongSelf removeCallbackWithUUID:UUID]; + } + }]; +} + +- (BOOL)cancelWithUUID:(NSUUID *)UUID resume:(PINResume **)resume +{ + __block BOOL noMoreCompletions; + [self.lock lockWithBlock:^{ + noMoreCompletions = [self l_cancelWithUUID:UUID]; + }]; + return noMoreCompletions; +} + +- (BOOL)l_cancelWithUUID:(NSUUID *)UUID +{ + BOOL noMoreCompletions = NO; + [self l_removeCallbackWithUUID:UUID]; + if ([_callbackBlocks count] == 0) { + noMoreCompletions = YES; + } + return noMoreCompletions; +} + +- (void)setPriority:(PINRemoteImageManagerPriority)priority +{ + +} + +- (nonnull PINRemoteImageManagerResult *)imageResultWithImage:(nullable PINImage *)image + alternativeRepresentation:(nullable id)alternativeRepresentation + requestLength:(NSTimeInterval)requestLength + resultType:(PINRemoteImageResultType)resultType + UUID:(nullable NSUUID *)UUID + response:(NSURLResponse *)response + error:(nullable NSError *)error +{ + return [PINRemoteImageManagerResult imageResultWithImage:image + alternativeRepresentation:alternativeRepresentation + requestLength:requestLength + resultType:resultType + UUID:UUID + response:response + error:error]; +} + +- (NSMutableDictionary *)l_callbackBlocks +{ + return _callbackBlocks; +} + +@end diff --git a/Pod/Classes/PINRemoteLock.h b/Source/Classes/PINRemoteLock.h similarity index 100% rename from Pod/Classes/PINRemoteLock.h rename to Source/Classes/PINRemoteLock.h diff --git a/Pod/Classes/PINRemoteLock.m b/Source/Classes/PINRemoteLock.m similarity index 100% rename from Pod/Classes/PINRemoteLock.m rename to Source/Classes/PINRemoteLock.m diff --git a/Source/Classes/PINRemoteWeakProxy.h b/Source/Classes/PINRemoteWeakProxy.h new file mode 100644 index 00000000..b0abc22e --- /dev/null +++ b/Source/Classes/PINRemoteWeakProxy.h @@ -0,0 +1,16 @@ +// +// PINRemoteWeakProxy.h +// PINRemoteImage +// +// Created by Garrett Moon on 4/24/18. +// Copyright © 2018 Pinterest. All rights reserved. +// + +#import + +@interface PINRemoteWeakProxy : NSProxy + ++ (PINRemoteWeakProxy *)weakProxyWithTarget:(id)target; +- (instancetype)initWithTarget:(id)target; + +@end diff --git a/Source/Classes/PINRemoteWeakProxy.m b/Source/Classes/PINRemoteWeakProxy.m new file mode 100644 index 00000000..a7049328 --- /dev/null +++ b/Source/Classes/PINRemoteWeakProxy.m @@ -0,0 +1,59 @@ +// +// PINRemoteWeakProxy.m +// PINRemoteImage +// +// Created by Garrett Moon on 4/24/18. +// Copyright © 2018 Pinterest. All rights reserved. +// + +#import "PINRemoteWeakProxy.h" + +@interface PINRemoteWeakProxy () +{ + __weak id _target; + Class _targetClass; +} +@end + +@implementation PINRemoteWeakProxy + ++ (PINRemoteWeakProxy *)weakProxyWithTarget:(id)target +{ + return [[PINRemoteWeakProxy alloc] initWithTarget:target]; +} + +- (instancetype)initWithTarget:(id)target +{ + if (self) { + _target = target; + _targetClass = [target class]; + } + return self; +} + +- (BOOL)respondsToSelector:(SEL)aSelector +{ + return [_target respondsToSelector:aSelector]; +} + +- (BOOL)conformsToProtocol:(Protocol *)aProtocol +{ + return [_target conformsToProtocol:aProtocol]; +} + +- (id)forwardingTargetForSelector:(SEL)aSelector +{ + return _target; +} + +- (void)forwardInvocation:(NSInvocation *)invocation +{ + // Drop it since we shouldn't get here if _target is nil +} + +- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel +{ + return _target ? [_target methodSignatureForSelector:sel] : [_targetClass instanceMethodSignatureForSelector:sel]; +} + +@end diff --git a/Source/Classes/PINRequestRetryStrategy.m b/Source/Classes/PINRequestRetryStrategy.m new file mode 100644 index 00000000..71171586 --- /dev/null +++ b/Source/Classes/PINRequestRetryStrategy.m @@ -0,0 +1,69 @@ +// +// PINRequestRetryStrategy.m +// Pods +// +// Created by Hovhannes Safaryan on 9/24/16. +// +// + +#import +#import +#import + +@interface PINRequestExponentialRetryStrategy () + +@property (nonatomic, assign) int retryMaxCount; +@property (nonatomic, assign) int retryCount; +@property (nonatomic, assign) int delayBase; + +@end + +@implementation PINRequestExponentialRetryStrategy + +- (instancetype)initWithRetryMaxCount:(int)retryMaxCount delayBase:(int)delayBase +{ + if (self = [super init]) { + _retryCount = 0; + _retryMaxCount = retryMaxCount; + _delayBase = delayBase; + } + return self; +} + +- (int)numberOfRetries +{ + return self.retryCount; +} + +- (BOOL)shouldRetryWithError:(NSError *)error +{ + if (error == nil || ![[self class] retriableError:error] || + self.retryCount >= self.retryMaxCount) { + return NO; + } + return YES; +} + +- (int)nextDelay +{ + return powf(self.delayBase, self.retryCount); +} + +- (void)incrementRetryCount +{ + self.retryCount++; +} + ++ (BOOL)retriableError:(NSError *)remoteImageError +{ + if ([remoteImageError.domain isEqualToString:PINURLErrorDomain]) { + return remoteImageError.code >= 500; + } else if ([remoteImageError.domain isEqualToString:NSURLErrorDomain] && remoteImageError.code == NSURLErrorUnsupportedURL) { + return NO; + } else if ([remoteImageError.domain isEqualToString:PINRemoteImageManagerErrorDomain]) { + return NO; + } + return YES; +} + +@end diff --git a/Source/Classes/PINResume.h b/Source/Classes/PINResume.h new file mode 100644 index 00000000..7ff2b53b --- /dev/null +++ b/Source/Classes/PINResume.h @@ -0,0 +1,24 @@ +// +// PINResume.h +// PINRemoteImage +// +// Created by Garrett Moon on 3/10/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface PINResume : NSObject + +- (id)init NS_UNAVAILABLE; ++ (PINResume *)resumeData:(NSData *)resumeData ifRange:(NSString *)ifRange totalBytes:(long long)totalBytes; + +@property (nonatomic, strong, readonly) NSData *resumeData; +@property (nonatomic, copy, readonly) NSString *ifRange; +@property (nonatomic, assign, readonly) long long totalBytes; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Source/Classes/PINResume.m b/Source/Classes/PINResume.m new file mode 100644 index 00000000..cfcbd165 --- /dev/null +++ b/Source/Classes/PINResume.m @@ -0,0 +1,51 @@ +// +// PINResume.m +// PINRemoteImage +// +// Created by Garrett Moon on 3/10/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import "PINResume.h" + +@implementation PINResume + +NSString * const kResumeDataKey = @"kResumeDataKey"; +NSString * const kIfRangeKey = @"kIfRangeKey"; +NSString * const kTotalBytesKey = @"kTotalBytesKey"; + +- (instancetype)initWithCoder:(NSCoder *)aDecoder +{ + if (self = [super init]) { + _resumeData = [aDecoder decodeObjectForKey:kResumeDataKey]; + _ifRange = [aDecoder decodeObjectForKey:kIfRangeKey]; + _totalBytes = [aDecoder decodeInt64ForKey:kTotalBytesKey]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder +{ + [aCoder encodeObject:_resumeData forKey:kResumeDataKey]; + [aCoder encodeObject:_ifRange forKey:kIfRangeKey]; + [aCoder encodeInt64:_totalBytes forKey:kTotalBytesKey]; +} + ++ (PINResume *)resumeData:(NSData *)resumeData ifRange:(NSString *)ifRange totalBytes:(long long)totalBytes +{ + PINResume *resume = [[PINResume alloc] initWithResumeData:resumeData ifRange:ifRange totalBytes:totalBytes]; + return resume; +} + +- (PINResume *)initWithResumeData:(NSData *)resumeData ifRange:(NSString *)ifRange totalBytes:(long long)totalBytes +{ + if (self = [super init]) { + NSAssert(resumeData.length > 0 && ifRange.length > 0 && totalBytes > 0, @"PINResume must have all fields non-nil and non-zero length."); + _resumeData = resumeData; + _ifRange = ifRange; + _totalBytes = totalBytes; + } + return self; +} + +@end diff --git a/Source/Classes/PINSpeedRecorder.h b/Source/Classes/PINSpeedRecorder.h new file mode 100644 index 00000000..901002fa --- /dev/null +++ b/Source/Classes/PINSpeedRecorder.h @@ -0,0 +1,51 @@ +// +// PINSpeedRecorder.h +// PINRemoteImage +// +// Created by Garrett Moon on 8/30/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import + +typedef enum : NSUInteger { + PINSpeedRecorderConnectionStatusNotReachable, + PINSpeedRecorderConnectionStatusWWAN, + PINSpeedRecorderConnectionStatusWiFi +} PINSpeedRecorderConnectionStatus; + +@interface PINSpeedRecorder : NSObject + ++ (PINSpeedRecorder *)sharedRecorder; ++ (NSUInteger)appropriateImageIdxForURLsGivenHistoricalNetworkConditions:(NSArray *)urls + lowQualityQPSThreshold:(float)lowQualityQPSThreshold + highQualityQPSThreshold:(float)highQualityQPSThreshold; + +- (void)processMetrics:(NSURLSessionTaskMetrics *)metrics forTask:(NSURLSessionTask *)task; + +/* + Returns a weighted average of the bytes per second of a transfer with the time to first byte subtracted. + More specifically, we get the time to first byte for every task that completes, + subtract it from the total transfer time, calculate bytes per second + and add it to an existing average using exponential weighted average and adjusting + for starting bias. + This is all done on a per host basis. + */ +- (float)weightedAdjustedBytesPerSecondForHost:(NSString *)host; + +/* + Returns a weighted average of time to first byte for the specified host. + More specifically, we get the time to first byte for every task that completes + and add it to an existing average using exponential weighted average and adjusting + for starting bias. + This is all done on a per host basis. + */ +- (NSTimeInterval)weightedTimeToFirstByteForHost:(NSString *)host; + +- (PINSpeedRecorderConnectionStatus)connectionStatus; + +#if DEBUG +- (void)setCurrentBytesPerSecond:(float)currentBPS; +#endif + +@end diff --git a/Source/Classes/PINSpeedRecorder.m b/Source/Classes/PINSpeedRecorder.m new file mode 100644 index 00000000..8e02fb26 --- /dev/null +++ b/Source/Classes/PINSpeedRecorder.m @@ -0,0 +1,265 @@ +// +// PINSpeedRecorder.m +// PINRemoteImage +// +// Created by Garrett Moon on 8/30/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import "PINSpeedRecorder.h" + +#import +#import + +#import "PINRemoteLock.h" + +@interface PINSpeedMeasurement : NSObject + +// Storing the count of each measurement allows for bias adjustment in exponentially +// weighted average. +@property (nonatomic, assign) NSUInteger count; +@property (nonatomic, assign) float bytesPerSecond; +@property (nonatomic, assign) float startAdjustedBytesPerSecond; +@property (nonatomic, assign) CFTimeInterval timeToFirstByte; + +@end + +@interface PINSpeedRecorder () +{ + NSCache *_speedMeasurements; + SCNetworkReachabilityRef _reachability; +#if DEBUG + BOOL _overrideBPS; + float _currentBPS; +#endif +} + +@property (nonatomic, strong) PINRemoteLock *lock; + +@end + +@implementation PINSpeedRecorder + ++ (PINSpeedRecorder *)sharedRecorder +{ + static dispatch_once_t onceToken; + static PINSpeedRecorder *sharedRecorder; + dispatch_once(&onceToken, ^{ + sharedRecorder = [[self alloc] init]; + }); + + return sharedRecorder; +} + +- (instancetype)init +{ + if (self = [super init]) { + _lock = [[PINRemoteLock alloc] initWithName:@"PINSpeedRecorder lock"]; + _speedMeasurements = [[NSCache alloc] init]; + _speedMeasurements.countLimit = 25; + + struct sockaddr_in zeroAddress; + bzero(&zeroAddress, sizeof(zeroAddress)); + zeroAddress.sin_len = sizeof(zeroAddress); + zeroAddress.sin_family = AF_INET; + _reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)&zeroAddress); + } + return self; +} + +- (void)processMetrics:(NSURLSessionTaskMetrics *)metrics forTask:(NSURLSessionTask *)task +{ + NSDate *requestStart = [NSDate distantFuture]; + NSDate *firstByte = [NSDate distantFuture]; + NSDate *requestEnd = [NSDate distantPast]; + int64_t contentLength = task.countOfBytesReceived; + + for (NSURLSessionTaskTransactionMetrics *metric in metrics.transactionMetrics) { + if (metric.requestStartDate == nil || metric.responseStartDate == nil) { + //Only evaluate requests which completed their first byte. + return; + } + + requestStart = [requestStart earlierDate:metric.requestStartDate]; + firstByte = [firstByte earlierDate:metric.responseStartDate]; + requestEnd = [requestEnd laterDate:metric.responseEndDate]; + } + + if ([requestStart isEqual:[NSDate distantFuture]] || [firstByte isEqual:[NSDate distantFuture]] || [requestEnd isEqual:[NSDate distantPast]] || contentLength == 0) { + return; + } + + [self updateSpeedsForHost:task.currentRequest.URL.host + bytesPerSecond:contentLength / [requestEnd timeIntervalSinceDate:requestStart] + startAdjustedBytesPerSecond:contentLength / [requestEnd timeIntervalSinceDate:firstByte] + timeToFirstByte:[firstByte timeIntervalSinceDate:requestStart]]; +} + +- (void)resetMeasurements +{ + [self.lock lockWithBlock:^{ + [self->_speedMeasurements removeAllObjects]; + }]; +} + +- (void)updateSpeedsForHost:(NSString *)host bytesPerSecond:(float)bytesPerSecond startAdjustedBytesPerSecond:(float)startAdjustedBytesPerSecond timeToFirstByte:(float)timeToFirstByte +{ + [self.lock lockWithBlock:^{ + PINSpeedMeasurement *measurement = [self->_speedMeasurements objectForKey:host]; + if (measurement == nil) { + measurement = [[PINSpeedMeasurement alloc] init]; + measurement.count = 0; + measurement.bytesPerSecond = bytesPerSecond; + measurement.startAdjustedBytesPerSecond = startAdjustedBytesPerSecond; + measurement.timeToFirstByte = timeToFirstByte; + [self->_speedMeasurements setObject:measurement forKey:host]; + } else { + const double bpsBeta = 0.8; + const double ttfbBeta = 0.8; + measurement.count++; + measurement.bytesPerSecond = (measurement.bytesPerSecond * bpsBeta) + ((1.0 - bpsBeta) * bytesPerSecond); + measurement.startAdjustedBytesPerSecond = (measurement.startAdjustedBytesPerSecond * bpsBeta) + ((1.0 - bpsBeta) * startAdjustedBytesPerSecond); + measurement.timeToFirstByte = (measurement.timeToFirstByte * ttfbBeta) + ((1.0 - ttfbBeta) * timeToFirstByte); + } + }]; +} + +- (float)weightedAdjustedBytesPerSecondForHost:(NSString *)host +{ + __block float startAdjustedBytesPerSecond = -1; + [self.lock lockWithBlock:^{ +#if DEBUG + if (self->_overrideBPS) { + startAdjustedBytesPerSecond = self->_currentBPS; + return; + } +#endif + PINSpeedMeasurement *measurement = [self->_speedMeasurements objectForKey:host]; + if (measurement == 0) { + startAdjustedBytesPerSecond = -1; + return; + } + startAdjustedBytesPerSecond = measurement.startAdjustedBytesPerSecond; + }]; + return startAdjustedBytesPerSecond; +} + +- (NSTimeInterval)weightedTimeToFirstByteForHost:(NSString *)host +{ + __block NSTimeInterval timeToFirstByte = 0; + [self.lock lockWithBlock:^{ + PINSpeedMeasurement *measurement = [self->_speedMeasurements objectForKey:host]; + timeToFirstByte = measurement.timeToFirstByte; + }]; + return timeToFirstByte; +} + +#if DEBUG +- (void)setCurrentBytesPerSecond:(float)currentBPS +{ + [self.lock lockWithBlock:^{ + if (currentBPS == -1) { + self->_overrideBPS = NO; + } else { + self->_overrideBPS = YES; + } + self->_currentBPS = currentBPS; + }]; +} +#endif + +// Cribbed from Apple's reachability: https://developer.apple.com/library/content/samplecode/Reachability/Listings/Reachability_Reachability_m.html#//apple_ref/doc/uid/DTS40007324-Reachability_Reachability_m-DontLinkElementID_9 + +- (PINSpeedRecorderConnectionStatus)connectionStatus +{ + PINSpeedRecorderConnectionStatus status = PINSpeedRecorderConnectionStatusNotReachable; + SCNetworkReachabilityFlags flags; + + // _reachability is set on init and therefore safe to access outside the lock + if (SCNetworkReachabilityGetFlags(_reachability, &flags)) { + return [self networkStatusForFlags:flags]; + } + return status; +} + +- (PINSpeedRecorderConnectionStatus)networkStatusForFlags:(SCNetworkReachabilityFlags)flags +{ + if ((flags & kSCNetworkReachabilityFlagsReachable) == 0) { + // The target host is not reachable. + return PINSpeedRecorderConnectionStatusNotReachable; + } + + PINSpeedRecorderConnectionStatus connectionStatus = PINSpeedRecorderConnectionStatusNotReachable; + + if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0) { + /* + If the target host is reachable and no connection is required then we'll assume (for now) that you're on Wi-Fi... + */ + connectionStatus = PINSpeedRecorderConnectionStatusWiFi; + } + + if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)) { + /* + ... and the connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs... + */ + + if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0) { + /* + ... and no [user] intervention is needed... + */ + connectionStatus = PINSpeedRecorderConnectionStatusWiFi; + } + } + +#if PIN_TARGET_IOS + if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN) { + /* + ... but WWAN connections are OK if the calling application is using the CFNetwork APIs. + */ + connectionStatus = PINSpeedRecorderConnectionStatusWWAN; + } +#endif + + return connectionStatus; +} + ++ (NSUInteger)appropriateImageIdxForURLsGivenHistoricalNetworkConditions:(NSArray *)urls + lowQualityQPSThreshold:(float)lowQualityQPSThreshold + highQualityQPSThreshold:(float)highQualityQPSThreshold +{ + float currentBytesPerSecond = [[PINSpeedRecorder sharedRecorder] weightedAdjustedBytesPerSecondForHost:[[urls firstObject] host]]; + + NSUInteger desiredImageURLIdx; + + if (currentBytesPerSecond == -1) { + // Base it on reachability + switch ([[PINSpeedRecorder sharedRecorder] connectionStatus]) { + case PINSpeedRecorderConnectionStatusWiFi: + desiredImageURLIdx = urls.count - 1; + break; + + case PINSpeedRecorderConnectionStatusWWAN: + case PINSpeedRecorderConnectionStatusNotReachable: + desiredImageURLIdx = 0; + break; + } + } else { + if (currentBytesPerSecond >= highQualityQPSThreshold) { + desiredImageURLIdx = urls.count - 1; + } else if (currentBytesPerSecond <= lowQualityQPSThreshold) { + desiredImageURLIdx = 0; + } else if (urls.count == 2) { + desiredImageURLIdx = roundf((currentBytesPerSecond - lowQualityQPSThreshold) / ((highQualityQPSThreshold - lowQualityQPSThreshold) / (float)(urls.count - 1))); + } else { + desiredImageURLIdx = ceilf((currentBytesPerSecond - lowQualityQPSThreshold) / ((highQualityQPSThreshold - lowQualityQPSThreshold) / (float)(urls.count - 2))); + } + } + + return desiredImageURLIdx; +} + +@end + +@implementation PINSpeedMeasurement + +@end diff --git a/Source/Classes/PINURLSessionManager.m b/Source/Classes/PINURLSessionManager.m new file mode 100644 index 00000000..a2fb4abb --- /dev/null +++ b/Source/Classes/PINURLSessionManager.m @@ -0,0 +1,250 @@ +// +// PINURLSessionManager.m +// Pods +// +// Created by Garrett Moon on 6/26/15. +// +// + +#import + +#import "PINSpeedRecorder.h" + +NSErrorDomain const PINURLErrorDomain = @"PINURLErrorDomain"; + +@interface PINURLSessionManager () + +@property (nonatomic, strong) NSLock *sessionManagerLock; +@property (nonatomic, strong) NSURLSession *session; +@property (nonatomic, strong) NSOperationQueue *operationQueue; +@property (nonatomic, strong) NSMutableDictionary *delegateQueues; +@property (nonatomic, strong) NSMutableDictionary *completions; + +@end + +@implementation PINURLSessionManager + +- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration +{ + if (self = [super init]) { + self.sessionManagerLock = [[NSLock alloc] init]; + self.sessionManagerLock.name = @"PINURLSessionManager"; + self.operationQueue = [[NSOperationQueue alloc] init]; + self.operationQueue.name = @"PINURLSessionManager Operation Queue"; + + //queue must be serial to ensure proper ordering + [self.operationQueue setMaxConcurrentOperationCount:1]; + self.session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:self.operationQueue]; + self.completions = [[NSMutableDictionary alloc] init]; + self.delegateQueues = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (void)invalidateSessionAndCancelTasks +{ + [self lock]; + [self.session invalidateAndCancel]; + [self unlock]; +} + +- (nonnull NSURLSessionDataTask *)dataTaskWithRequest:(nonnull NSURLRequest *)request + completionHandler:(nonnull PINURLSessionDataTaskCompletion)completionHandler +{ + return [self dataTaskWithRequest:request + priority:PINRemoteImageManagerPriorityDefault + completionHandler:completionHandler]; +} + +- (nonnull NSURLSessionDataTask *)dataTaskWithRequest:(nonnull NSURLRequest *)request + priority:(PINRemoteImageManagerPriority)priority + completionHandler:(nonnull PINURLSessionDataTaskCompletion)completionHandler +{ + [self lock]; + NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:request]; + dataTask.priority = dataTaskPriorityWithImageManagerPriority(priority); + if (completionHandler) { + [self.completions setObject:completionHandler forKey:@(dataTask.taskIdentifier)]; + } + NSString *queueName = [NSString stringWithFormat:@"PINURLSessionManager delegate queue - %ld", (unsigned long)dataTask.taskIdentifier]; + dispatch_queue_t delegateQueue = dispatch_queue_create([queueName UTF8String], DISPATCH_QUEUE_SERIAL); + [self.delegateQueues setObject:delegateQueue forKey:@(dataTask.taskIdentifier)]; + [self unlock]; + return dataTask; +} + +- (void)lock +{ + [self.sessionManagerLock lock]; +} + +- (void)unlock +{ + [self.sessionManagerLock unlock]; +} + +#pragma mark NSURLSessionDataDelegate + +- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)task didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler +{ + [self lock]; + dispatch_queue_t delegateQueue = self.delegateQueues[@(task.taskIdentifier)]; + [self unlock]; + + NSAssert(delegateQueue != nil, @"There seems to be an issue in iOS 9 where this can be nil. If you can reliably reproduce hitting this, *please* open an issue: https://github.com/pinterest/PINRemoteImage/issues"); + if (delegateQueue == nil) { + return; + } + + __weak typeof(self) weakSelf = self; + dispatch_async(delegateQueue, ^{ + typeof(self) strongSelf = weakSelf; + if ([strongSelf.delegate respondsToSelector:@selector(didReceiveResponse:forTask:)]) { + [strongSelf.delegate didReceiveResponse:response forTask:task]; + } + }); + //Even though this is documented to be non-nil, in the wild it sometimes is. + if (completionHandler) { + completionHandler(NSURLSessionResponseAllow); + } +} + +- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler +{ + if ([self.delegate respondsToSelector:@selector(didReceiveAuthenticationChallenge:forTask:completionHandler:)]) { + [self.delegate didReceiveAuthenticationChallenge:challenge forTask:nil completionHandler:completionHandler]; + } else { + //Even though this is documented to be non-nil, in the wild it sometimes is. + if (completionHandler) { + completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); + } + } +} + +- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler +{ + [self lock]; + dispatch_queue_t delegateQueue = self.delegateQueues[@(task.taskIdentifier)]; + [self unlock]; + + NSAssert(delegateQueue != nil, @"There seems to be an issue in iOS 9 where this can be nil. If you can reliably reproduce hitting this, *please* open an issue: https://github.com/pinterest/PINRemoteImage/issues"); + if (delegateQueue == nil) { + return; + } + + __weak typeof(self) weakSelf = self; + dispatch_async(delegateQueue, ^{ + typeof(self) strongSelf = weakSelf; + if ([strongSelf.delegate respondsToSelector:@selector(didReceiveAuthenticationChallenge:forTask:completionHandler:)]) { + [strongSelf.delegate didReceiveAuthenticationChallenge:challenge forTask:task completionHandler:completionHandler]; + } else { + //Even though this is documented to be non-nil, in the wild it sometimes is + if (completionHandler) { + completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); + } + } + }); +} + +- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)task didReceiveData:(NSData *)data +{ + [self lock]; + dispatch_queue_t delegateQueue = self.delegateQueues[@(task.taskIdentifier)]; + [self unlock]; + + NSAssert(delegateQueue != nil, @"There seems to be an issue in iOS 9 where this can be nil. If you can reliably reproduce hitting this, *please* open an issue: https://github.com/pinterest/PINRemoteImage/issues"); + if (delegateQueue == nil) { + return; + } + + __weak typeof(self) weakSelf = self; + dispatch_async(delegateQueue, ^{ + typeof(self) strongSelf = weakSelf; + [strongSelf.delegate didReceiveData:data forTask:task]; + }); +} + +- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error +{ + [self lock]; + dispatch_queue_t delegateQueue = self.delegateQueues[@(task.taskIdentifier)]; + [self unlock]; + + NSAssert(delegateQueue != nil, @"There seems to be an issue in iOS 9 where this can be nil. If you can reliably reproduce hitting this, *please* open an issue: https://github.com/pinterest/PINRemoteImage/issues"); + if (delegateQueue == nil) { + return; + } + + if (!error && [task.response isKindOfClass:[NSHTTPURLResponse class]]) { + NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response; + NSInteger statusCode = [response statusCode]; + //If a 404 response contains an image, we treat it as a successful request and return the image + BOOL recoverable = [self responseRecoverableFrom404:response]; + if (statusCode >= 400 && recoverable == NO) { + error = [NSError errorWithDomain:PINURLErrorDomain + code:statusCode + userInfo:@{NSLocalizedDescriptionKey : @"HTTP Error Response."}]; + } + } + __weak typeof(self) weakSelf = self; + dispatch_async(delegateQueue, ^{ + typeof(self) strongSelf = weakSelf; + + [strongSelf lock]; + PINURLSessionDataTaskCompletion completionHandler = strongSelf.completions[@(task.taskIdentifier)]; + [strongSelf.completions removeObjectForKey:@(task.taskIdentifier)]; + [strongSelf.delegateQueues removeObjectForKey:@(task.taskIdentifier)]; + [strongSelf unlock]; + + if (completionHandler) { + completionHandler(task, error); + } + + if ([strongSelf.delegate respondsToSelector:@selector(didCompleteTask:withError:)]) { + [strongSelf.delegate didCompleteTask:task withError:error]; + } + }); +} + +#pragma mark - session statistics + +- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics +{ + [[PINSpeedRecorder sharedRecorder] processMetrics:metrics forTask:task]; + + [self lock]; + dispatch_queue_t delegateQueue = self.delegateQueues[@(task.taskIdentifier)]; + [self unlock]; + + NSAssert(delegateQueue != nil, @"There seems to be an issue in iOS 9 where this can be nil. If you can reliably reproduce hitting this, *please* open an issue: https://github.com/pinterest/PINRemoteImage/issues"); + if (delegateQueue == nil) { + return; + } + + __weak typeof(self) weakSelf = self; + dispatch_async(delegateQueue, ^{ + typeof(self) strongSelf = weakSelf; + if ([strongSelf.delegate respondsToSelector:@selector(didCollectMetrics:forURL:)]) { + [strongSelf.delegate didCollectMetrics:metrics forURL:task.originalRequest.URL]; + } + }); +} + +- (BOOL)responseRecoverableFrom404:(NSHTTPURLResponse*)response +{ + return response.statusCode == 404 + && [response.allHeaderFields[@"content-type"] rangeOfString:@"image"].location != NSNotFound; +} + +#if DEBUG +- (void)concurrentDownloads:(void (^_Nullable)(NSUInteger concurrentDownloads))concurrentDownloadsCompletion +{ + [self.session getAllTasksWithCompletionHandler:^(NSArray<__kindof NSURLSessionTask *> * _Nonnull tasks) { + concurrentDownloadsCompletion(tasks.count); + }]; +} + +#endif + +@end + diff --git a/Source/Classes/include/PINRemoteImage/NSData+ImageDetectors.h b/Source/Classes/include/PINRemoteImage/NSData+ImageDetectors.h new file mode 100644 index 00000000..2a67cff2 --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/NSData+ImageDetectors.h @@ -0,0 +1,25 @@ +// +// NSData+ImageDetectors.h +// Pods +// +// Created by Garrett Moon on 11/19/14. +// +// + +#import + +#import + +@interface NSData (PINImageDetectors) + +- (BOOL)pin_isGIF; +- (BOOL)pin_isAnimatedGIF; +#if PIN_WEBP +- (BOOL)pin_isWebP; +- (BOOL)pin_isAnimatedWebP; +#endif +#if PIN_APNG +- (BOOL)pin_isAPNG; +#endif + +@end diff --git a/Source/Classes/include/PINRemoteImage/NSHTTPURLResponse+MaxAge.h b/Source/Classes/include/PINRemoteImage/NSHTTPURLResponse+MaxAge.h new file mode 100644 index 00000000..49198e6f --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/NSHTTPURLResponse+MaxAge.h @@ -0,0 +1,14 @@ +// +// NSHTTPURLResponse+MaxAge.h +// +// Created by Kevin Smith on 6/15/18. +// +// + +#import + +@interface NSHTTPURLResponse (MaxAge) + +- (NSNumber *)findMaxAge; + +@end diff --git a/Source/Classes/include/PINRemoteImage/PINAPNGAnimatedImage.h b/Source/Classes/include/PINRemoteImage/PINAPNGAnimatedImage.h new file mode 100644 index 00000000..fb285763 --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINAPNGAnimatedImage.h @@ -0,0 +1,19 @@ +// +// PINAPNGAnimatedImage.h +// PINRemoteImage +// +// Created by SAGESSE on 2020/2/28. +// Copyright © 2020 Pinterest. All rights reserved. +// + +#import +#import +#import + +@interface PINAPNGAnimatedImage : PINAnimatedImage + +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithAnimatedImageData:(NSData *)animatedImageData NS_DESIGNATED_INITIALIZER; + +@end + diff --git a/Source/Classes/include/PINRemoteImage/PINAlternateRepresentationProvider.h b/Source/Classes/include/PINRemoteImage/PINAlternateRepresentationProvider.h new file mode 100644 index 00000000..3442735f --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINAlternateRepresentationProvider.h @@ -0,0 +1,25 @@ +// +// PINAlternateRepresentationProvider.h +// Pods +// +// Created by Garrett Moon on 3/17/16. +// +// + +#import + +#import + +@protocol PINRemoteImageManagerAlternateRepresentationProvider +@required + +/** + @discussion This method will be called with data off the wire or stored in the cache. Return an object to have it returned as the alternativeRepresentation object in the PINRemoteImageManagerResult. @warning this method can be called on the main thread, be careful of doing expensive work. + */ +- (id)alternateRepresentationWithData:(NSData *)data options:(PINRemoteImageManagerDownloadOptions)options; + +@end + +@interface PINAlternateRepresentationProvider : NSObject + +@end diff --git a/Source/Classes/include/PINRemoteImage/PINAnimatedImage.h b/Source/Classes/include/PINRemoteImage/PINAnimatedImage.h new file mode 100644 index 00000000..e1f99b50 --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINAnimatedImage.h @@ -0,0 +1,165 @@ +// +// PINAnimatedImage.h +// PINRemoteImage +// +// Created by Garrett Moon on 9/17/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import +#import + +#if PIN_TARGET_IOS +#import +#elif PIN_TARGET_MAC +#import +#endif + +NS_ASSUME_NONNULL_BEGIN + +extern NSErrorDomain const kPINAnimatedImageErrorDomain; + +/** + PINAnimatedImage decoding and processing errors. + */ +typedef NS_ERROR_ENUM(kPINAnimatedImageErrorDomain, PINAnimatedImageErrorCode) { + /** No error, yay! */ + PINAnimatedImageErrorNoError = 0, + /** Could not create a necessary file. */ + PINAnimatedImageErrorFileCreationError, + /** Could not get a file handle to the necessary file. */ + PINAnimatedImageErrorFileHandleError, + /** Could not decode the image. */ + PINAnimatedImageErrorImageFrameError, + /** Could not memory map the file. */ + PINAnimatedImageErrorMappingError, + /** File write error */ + PINAnimatedImageErrorFileWrite, +}; + +/** + The processing status of the animated image. + */ +typedef NS_ENUM(NSUInteger, PINAnimatedImageStatus) { + /** No work has been done. */ + PINAnimatedImageStatusUnprocessed = 0, + /** Info about the animated image and the cover image are available. */ + PINAnimatedImageStatusInfoProcessed, + /** At least one set of frames has been decoded to a file. It's safe to start playback. */ + PINAnimatedImageStatusFirstFileProcessed, + /** The entire animated image has been processed. */ + PINAnimatedImageStatusProcessed, + /** Processing was canceled. */ + PINAnimatedImageStatusCanceled, + /** There was an error in processing. */ + PINAnimatedImageStatusError, +}; + +extern const Float32 kPINAnimatedImageDefaultDuration; + +/** + Called when the cover image of an animatedImage is ready. + */ +typedef void(^PINAnimatedImageInfoReady)(PINImage * _Nonnull coverImage); + +@protocol PINAnimatedImage; + +@interface PINAnimatedImage : NSObject + +/** + @abstract The maximum number of frames per second supported. + */ ++ (NSInteger)maximumFramesPerSecond; + +/** + @abstract Return the duration at a given index. + + @warning *Must be overridden by subclass + */ +- (CFTimeInterval)durationAtIndex:(NSUInteger)index; + +/** + @abstract Return the total number of frames in the animated image. + + @warning *Must be overridden by subclass + */ +@property (nonatomic, readonly) size_t frameCount; + +/** + @abstract Return the total duration of the animated image's playback. + */ +@property (nonatomic, readonly) CFTimeInterval totalDuration; + +/** + The number of frames to play per second * display refresh rate (defined as 60 which appears to be true on iOS). You probably want to + set this value on a displayLink. + @warning Access to this property before status == PINAnimatedImageStatusInfoProcessed is undefined. + */ +@property (nonatomic, readonly) NSUInteger frameInterval; + +@end + +@protocol PINCachedAnimatedFrameProvider + +@required + +- (nullable CGImageRef)cachedFrameImageAtIndex:(NSUInteger)index; + +@end + +@protocol PINAnimatedImage + +/** + @abstract the underlying data of the animated image if available. + */ +@property (nonatomic, readonly) NSData *data; + +/** + @abstract the native width of the animated image. + */ +@property (nonatomic, readonly) uint32_t width; + +/** + @abstract the native height of the animated image. + */ +@property (nonatomic, readonly) uint32_t height; + +/** + @abstract number of bytes per frame. + */ +@property (nonatomic, readonly) uint32_t bytesPerFrame; + +/** + @abstract Return the total duration of the animated image's playback. + */ +@property (nonatomic, readonly) CFTimeInterval totalDuration; +/** + @abstract Return the interval at which playback should occur. Will be set to a CADisplayLink's frame interval. + */ +@property (nonatomic, readonly) NSUInteger frameInterval; +/** + @abstract Return the total number of loops the animated image should play or 0 to loop infinitely. + */ +@property (nonatomic, readonly) size_t loopCount; +/** + @abstract Return the total number of frames in the animated image. + */ +@property (nonatomic, readonly) size_t frameCount; +/** + @abstract Return any error that has occurred. Playback will be paused if this returns non-nil. + */ +@property (nonatomic, readonly, nullable) NSError *error; + +/** + @abstract Return the image at a given index. + */ +- (nullable CGImageRef)imageAtIndex:(NSUInteger)index cacheProvider:(nullable id)cacheProvider; +/** + + @abstract Return the duration at a given index. + */ +- (CFTimeInterval)durationAtIndex:(NSUInteger)index; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Source/Classes/include/PINRemoteImage/PINAnimatedImageView+PINRemoteImage.h b/Source/Classes/include/PINRemoteImage/PINAnimatedImageView+PINRemoteImage.h new file mode 100644 index 00000000..e8e7eb83 --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINAnimatedImageView+PINRemoteImage.h @@ -0,0 +1,13 @@ +// +// PINAnimatedImageView+PINRemoteImage.h +// Pods +// +// Created by Garrett Moon on 4/19/18. +// + +#import +#import + +@interface PINAnimatedImageView (PINRemoteImage) + +@end diff --git a/Source/Classes/include/PINRemoteImage/PINAnimatedImageView.h b/Source/Classes/include/PINRemoteImage/PINAnimatedImageView.h new file mode 100644 index 00000000..01e6b90a --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINAnimatedImageView.h @@ -0,0 +1,28 @@ +// +// PINAnimatedImageView.h +// Pods +// +// Created by Garrett Moon on 4/17/18. +// + +#import + +#if PIN_TARGET_IOS +#import +#elif PIN_TARGET_MAC +#import +#endif + +#import + +@interface PINAnimatedImageView : PINImageView + +- (nonnull instancetype)initWithAnimatedImage:(nonnull PINCachedAnimatedImage *)animatedImage NS_DESIGNATED_INITIALIZER; +- (nonnull instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +@property (nullable, nonatomic, strong) PINCachedAnimatedImage *animatedImage; +@property (nullable, nonatomic, strong) NSString *animatedImageRunLoopMode; +@property (nonatomic, assign, getter=isPlaybackPaused) BOOL playbackPaused; + +@end diff --git a/Source/Classes/include/PINRemoteImage/PINButton+PINRemoteImage.h b/Source/Classes/include/PINRemoteImage/PINButton+PINRemoteImage.h new file mode 100644 index 00000000..7a492b3a --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINButton+PINRemoteImage.h @@ -0,0 +1,22 @@ +// +// UIButton+PINRemoteImage.h +// Pods +// +// Created by Garrett Moon on 8/18/14. +// +// + +#import + +#if PIN_TARGET_IOS +#import +#elif PIN_TARGET_MAC +#import +#endif + +#import +#import + +@interface PINButton (PINRemoteImage) + +@end diff --git a/Source/Classes/include/PINRemoteImage/PINCache+PINRemoteImageCaching.h b/Source/Classes/include/PINRemoteImage/PINCache+PINRemoteImageCaching.h new file mode 100644 index 00000000..4b1d8335 --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINCache+PINRemoteImageCaching.h @@ -0,0 +1,26 @@ +// +// PINCache+PINRemoteImageCaching.h +// Pods +// +// Created by Aleksei Shevchenko on 7/28/16. +// +// + +#if !__has_include() +#import "PINCache.h" +#else +#import +#endif + +#import +#import + +@interface PINCache (PINRemoteImageCaching) + +@end + +@interface PINRemoteImageManager (PINCache) + +@property (nonatomic, nullable, readonly) PINCache *pinCache; + +@end diff --git a/Source/Classes/include/PINRemoteImage/PINCachedAnimatedImage.h b/Source/Classes/include/PINRemoteImage/PINCachedAnimatedImage.h new file mode 100644 index 00000000..833f896c --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINCachedAnimatedImage.h @@ -0,0 +1,83 @@ +// +// PINCachedAnimatedImage.h +// PINRemoteImage +// +// Created by Garrett Moon on 9/17/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import + +#import +#import + +@interface PINCachedAnimatedImage : NSObject + +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithAnimatedImage:(id )animatedImage NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithAnimatedImageData:(NSData *)animatedImageData; + +/** + @abstract A block which receives the cover image. Should be called when the objects cover image is ready. + */ +@property (nonatomic, readwrite) PINAnimatedImageInfoReady coverImageReadyCallback; + +/** + @abstract Return the objects's cover image. + */ +@property (nonatomic, readonly) PINImage *coverImage; +/** + @abstract Return a boolean to indicate that the cover image is ready. + */ +@property (nonatomic, readonly) BOOL coverImageReady; +/** + @abstract Return the total duration of the animated image's playback. + */ +@property (nonatomic, readonly) CFTimeInterval totalDuration; +/** + @abstract Return the interval at which playback should occur. Will be set to a CADisplayLink's frame interval. + */ +@property (nonatomic, readonly) NSUInteger frameInterval; +/** + @abstract Return the size of the underlying animated image. + */ +@property (nonatomic, readonly) CGSize size; +/** + @abstract Return the total number of loops the animated image should play or 0 to loop infinitely. + */ +@property (nonatomic, readonly) size_t loopCount; +/** + @abstract Return the total number of frames in the animated image. + */ +@property (nonatomic, readonly) size_t frameCount; +/** + @abstract Return the underlying data if available; + */ +@property (nonatomic, readonly) NSData *data; +/** + @abstract Return YES when playback is ready to occur. + */ +@property (nonatomic, readonly) BOOL playbackReady; +/** + @abstract Return any error that has occurred. Playback will be paused if this returns non-nil. + */ +@property (nonatomic, readonly) NSError *error; +/** + @abstract Should be called when playback is ready. + */ +@property (nonatomic, readwrite) dispatch_block_t playbackReadyCallback; + +/** + @abstract Return the image at a given index. + */ +- (CGImageRef)imageAtIndex:(NSUInteger)index; +/** + @abstract Return the duration at a given index. + */ +- (CFTimeInterval)durationAtIndex:(NSUInteger)index; +/** + @abstract Clear any cached data. Called when playback is paused. + */ +- (void)clearAnimatedImageCache; + +@end diff --git a/Source/Classes/include/PINRemoteImage/PINGIFAnimatedImage.h b/Source/Classes/include/PINRemoteImage/PINGIFAnimatedImage.h new file mode 100644 index 00000000..14a87d6c --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINGIFAnimatedImage.h @@ -0,0 +1,18 @@ +// +// PINGIFAnimatedImage.h +// PINRemoteImage +// +// Created by Garrett Moon on 9/17/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import + +#import + +@interface PINGIFAnimatedImage : PINAnimatedImage + +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithAnimatedImageData:(NSData *)animatedImageData NS_DESIGNATED_INITIALIZER; + +@end diff --git a/Source/Classes/include/PINRemoteImage/PINImage+DecodedImage.h b/Source/Classes/include/PINRemoteImage/PINImage+DecodedImage.h new file mode 100644 index 00000000..21326845 --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINImage+DecodedImage.h @@ -0,0 +1,44 @@ +// +// UIImage+DecodedImage.h +// Pods +// +// Created by Garrett Moon on 11/19/14. +// +// + +#import + +#import + +#if PIN_TARGET_IOS +#import +#elif PIN_TARGET_MAC +#import +#endif + +#if !PIN_TARGET_IOS +@interface NSImage (PINiOSMapping) + +@property(nonatomic, readonly, nullable) CGImageRef CGImage; + ++ (nullable NSImage *)imageWithData:(nonnull NSData *)imageData; ++ (nullable NSImage *)imageWithContentsOfFile:(nonnull NSString *)path; ++ (nonnull NSImage *)imageWithCGImage:(nonnull CGImageRef)imageRef; + +@end +#endif + +NSData * __nullable PINImageJPEGRepresentation(PINImage * __nonnull image, CGFloat compressionQuality); +NSData * __nullable PINImagePNGRepresentation(PINImage * __nonnull image); + +@interface PINImage (PINDecodedImage) + ++ (nullable PINImage *)pin_decodedImageWithData:(nonnull NSData *)data; ++ (nullable PINImage *)pin_decodedImageWithData:(nonnull NSData *)data skipDecodeIfPossible:(BOOL)skipDecodeIfPossible; ++ (nullable PINImage *)pin_decodedImageWithCGImageRef:(nonnull CGImageRef)imageRef; +#if PIN_TARGET_IOS ++ (nullable PINImage *)pin_decodedImageWithCGImageRef:(nonnull CGImageRef)imageRef orientation:(UIImageOrientation) orientation; +#endif ++ (nullable CGImageRef)pin_decodedImageRefWithCGImageRef:(nonnull CGImageRef)imageRef; + +@end diff --git a/Source/Classes/include/PINRemoteImage/PINImage+ScaledImage.h b/Source/Classes/include/PINRemoteImage/PINImage+ScaledImage.h new file mode 100644 index 00000000..4dc5070a --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINImage+ScaledImage.h @@ -0,0 +1,24 @@ +// +// UIImage+ScaledImage.h +// Pods +// +// Created by Michael Schneider on 2/9/17. +// +// + +#import + +#import + +#if PIN_TARGET_IOS +#import +#elif PIN_TARGET_MAC +#import +#endif + +@interface PINImage (PINScaledImage) + +- (PINImage *)pin_scaledImageForKey:(NSString *)key; ++ (PINImage *)pin_scaledImageForImage:(PINImage *)image withKey:(NSString *)key; + +@end diff --git a/Source/Classes/include/PINRemoteImage/PINImageView+PINRemoteImage.h b/Source/Classes/include/PINRemoteImage/PINImageView+PINRemoteImage.h new file mode 100644 index 00000000..33d4f1f7 --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINImageView+PINRemoteImage.h @@ -0,0 +1,22 @@ +// +// UIImageView+PINRemoteImage.h +// Pods +// +// Created by Garrett Moon on 8/17/14. +// +// + +#import + +#if PIN_TARGET_IOS +#import +#elif PIN_TARGET_MAC +#import +#endif + +#import +#import + +@interface PINImageView (PINRemoteImage) + +@end diff --git a/Source/Classes/include/PINRemoteImage/PINProgressiveImage.h b/Source/Classes/include/PINRemoteImage/PINProgressiveImage.h new file mode 100644 index 00000000..e5e57b46 --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINProgressiveImage.h @@ -0,0 +1,52 @@ +// +// PINProgressiveImage.h +// Pods +// +// Created by Garrett Moon on 2/9/15. +// +// + +#import + +#import + +#if PIN_TARGET_IOS +#import +#elif PIN_TARGET_MAC +#import +#endif + +@class PINRemoteImageDownloadTask; + +/** An object which store the data of a downloading image and vends progressive scans **/ +@interface PINProgressiveImage : NSObject + +@property (atomic, copy, nonnull) NSArray *progressThresholds; +@property (atomic, assign) CFTimeInterval estimatedRemainingTimeThreshold; +@property (nonatomic, strong, readonly, nonnull) NSURLSessionDataTask * dataTask; +@property (nonatomic, readonly) CFTimeInterval estimatedRemainingTime; + +- (nonnull instancetype)init NS_UNAVAILABLE; +- (nonnull instancetype)initWithDataTask:(nonnull NSURLSessionDataTask *)dataTask; + +- (void)updateProgressiveImageWithData:(nonnull NSData *)data expectedNumberOfBytes:(int64_t)expectedNumberOfBytes isResume:(BOOL)isResume; + +/** + Returns the latest image based on thresholds, returns nil if no new image is generated. + + @param blurred A boolean to indicate if the image should be blurred. + @param maxProgressiveRenderSize The maximum dimensions at which to apply a blur. If an image exceeds either the height. + or width of this dimension, the image will *not* be blurred regardless of the blurred parameter. + @param renderedImageQuality Value between 0 and 1. Computed by dividing the received number of bytes by the expected number of bytes. + @return PINImage A progressive scan of the image or nil if a new one has not been generated. + */ +- (nullable PINImage *)currentImageBlurred:(BOOL)blurred maxProgressiveRenderSize:(CGSize)maxProgressiveRenderSize renderedImageQuality:(nonnull out CGFloat *)renderedImageQuality; + +/** + Returns the current data for the image. + + @return NSData The current data for the image. + */ +- (nullable NSData *)data; + +@end diff --git a/Source/Classes/include/PINRemoteImage/PINRemoteImage.h b/Source/Classes/include/PINRemoteImage/PINRemoteImage.h new file mode 100644 index 00000000..57a7d339 --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINRemoteImage.h @@ -0,0 +1,35 @@ +// +// PINRemoteImage.h +// +// Created by Garrett Moon on 8/17/14. +// +// + +#import + +#if USE_PINCACHE + #import +#endif + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import diff --git a/Source/Classes/include/PINRemoteImage/PINRemoteImageCaching.h b/Source/Classes/include/PINRemoteImage/PINRemoteImageCaching.h new file mode 100644 index 00000000..bfafbdfc --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINRemoteImageCaching.h @@ -0,0 +1,52 @@ +// +// PINRemoteImageCaching.h +// Pods +// +// Created by Aleksei Shevchenko on 7/25/16. +// +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol PINRemoteImageCaching; +typedef void (^PINRemoteImageCachingObjectBlock)(id cache, NSString *key, id __nullable object); + +/** + * Image Cache is responsible for actual image caching. + */ +@protocol PINRemoteImageCaching + +//****************************************************************************************************** +// Memory cache methods +//****************************************************************************************************** +- (nullable id)objectFromMemoryForKey:(NSString *)key; +- (void)setObjectInMemory:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost; + +//****************************************************************************************************** +// Disk cache methods +//****************************************************************************************************** +- (nullable id)objectFromDiskForKey:(NSString *)key; +- (void)objectFromDiskForKey:(NSString *)key completion:(nullable PINRemoteImageCachingObjectBlock)completion; +- (void)setObjectOnDisk:(id)object forKey:(NSString *)key; + + +- (BOOL)objectExistsForKey:(NSString *)key; + +- (void)removeObjectForKey:(NSString *)key; +- (void)removeObjectForKey:(NSString *)key completion:(nullable PINRemoteImageCachingObjectBlock)completion; +- (void)removeAllObjects; + +@optional + +- (void)removeObjectForKeyFromMemory:(NSString *)key; +- (void)setObjectInMemory:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost withAgeLimit:(NSTimeInterval)ageLimit; +- (void)setObjectOnDisk:(id)object forKey:(NSString *)key withAgeLimit:(NSTimeInterval)ageLimit; +- (BOOL)memoryCacheIsTTLCache; +- (BOOL)diskCacheIsTTLCache; + +@end + + +NS_ASSUME_NONNULL_END diff --git a/Source/Classes/include/PINRemoteImage/PINRemoteImageCategoryManager.h b/Source/Classes/include/PINRemoteImage/PINRemoteImageCategoryManager.h new file mode 100644 index 00000000..daf5d7c9 --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINRemoteImageCategoryManager.h @@ -0,0 +1,230 @@ +// +// PINRemoteImageCategoryManager.h +// Pods +// +// Created by Garrett Moon on 11/4/14. +// +// + +#import + +#if PIN_TARGET_IOS +#import +#elif PIN_TARGET_MAC +#import +#endif + +#import + +@protocol PINRemoteImageCategory; + +/** + PINRemoteImageCategoryManager is a class that handles subclassing image display classes. PINImageView+PINRemoteImage, UIButton+PINRemoteImage, etc, all delegate their work to this class. If you'd like to create a category to display an image on a view, you should mimic one of the above categories. + */ + +@interface PINRemoteImageCategoryManager : NSObject + ++ (void)setImageOnView:(nonnull id )view + fromURL:(nullable NSURL *)url; + ++ (void)setImageOnView:(nonnull id )view + fromURL:(nullable NSURL *)url + placeholderImage:(nullable PINImage *)placeholderImage; + ++ (void)setImageOnView:(nonnull id )view + fromURL:(nullable NSURL *)url + placeholderImage:(nullable PINImage *)placeholderImage + completion:(nullable PINRemoteImageManagerImageCompletion)completion; + ++ (void)setImageOnView:(nonnull id )view + fromURL:(nullable NSURL *)url + completion:(nullable PINRemoteImageManagerImageCompletion)completion; + ++ (void)setImageOnView:(nonnull id )view + fromURL:(nullable NSURL *)url + processorKey:(nullable NSString *)processorKey + processor:(nullable PINRemoteImageManagerImageProcessor)processor; + ++ (void)setImageOnView:(nonnull id )view + fromURL:(nullable NSURL *)url + placeholderImage:(nullable PINImage *)placeholderImage + processorKey:(nullable NSString *)processorKey + processor:(nullable PINRemoteImageManagerImageProcessor)processor; + ++ (void)setImageOnView:(nonnull id )view + fromURL:(nullable NSURL *)url + processorKey:(nullable NSString *)processorKey + processor:(nullable PINRemoteImageManagerImageProcessor)processor + completion:(nullable PINRemoteImageManagerImageCompletion)completion; + ++ (void)setImageOnView:(nonnull id )view + fromURLs:(nullable NSArray *)urls + placeholderImage:(nullable PINImage *)placeholderImage + processorKey:(nullable NSString *)processorKey + processor:(nullable PINRemoteImageManagerImageProcessor)processor + completion:(nullable PINRemoteImageManagerImageCompletion)completion; + ++ (void)setImageOnView:(nonnull id )view + fromURLs:(nullable NSArray *)urls; + ++ (void)setImageOnView:(nonnull id )view + fromURLs:(nullable NSArray *)urls + placeholderImage:(nullable PINImage *)placeholderImage; + ++ (void)setImageOnView:(nonnull id )view + fromURLs:(nullable NSArray *)urls + placeholderImage:(nullable PINImage *)placeholderImage + completion:(nullable PINRemoteImageManagerImageCompletion)completion; + ++ (void)cancelImageDownloadOnView:(nonnull id )view; + ++ (nullable NSUUID *)downloadImageOperationUUIDOnView:(nonnull id )view; + ++ (void)setDownloadImageOperationUUID:(nullable NSUUID *)downloadImageOperationUUID onView:(nonnull id )view; + ++ (BOOL)updateWithProgressOnView:(nonnull id )view; + ++ (void)setUpdateWithProgressOnView:(BOOL)updateWithProgress onView:(nonnull id )view; + +@end + +/** + Protocol to implement on UIView subclasses to support PINRemoteImage + */ +@protocol PINRemoteImageCategory + +//Call manager + +/** + Set the image from the given URL. + + @param url NSURL to fetch from. + */ +- (void)pin_setImageFromURL:(nullable NSURL *)url; + +/** + Set the image from the given URL and set placeholder image while image at URL is being retrieved. + + @param url NSURL to fetch from. + @param placeholderImage PINImage to set on the view while the image at URL is being retrieved. + */ +- (void)pin_setImageFromURL:(nullable NSURL *)url placeholderImage:(nullable PINImage *)placeholderImage; + +/** + Set the image from the given URL and call completion when finished. + + @param url NSURL to fetch from. + @param completion Called when url has been retrieved and set on view. + */ +- (void)pin_setImageFromURL:(nullable NSURL *)url completion:(nullable PINRemoteImageManagerImageCompletion)completion; + +/** + Set the image from the given URL, set placeholder while image at url is being retrieved and call completion when finished. + + @param url NSURL to fetch from. + @param placeholderImage PINImage to set on the view while the image at URL is being retrieved. + @param completion Called when url has been retrieved and set on view. + */ +- (void)pin_setImageFromURL:(nullable NSURL *)url placeholderImage:(nullable PINImage *)placeholderImage completion:(nullable PINRemoteImageManagerImageCompletion)completion; + +/** + Retrieve the image from the given URL, process it using the passed in processor block and set result on view. + + @param url NSURL to fetch from. + @param processorKey NSString key to uniquely identify processor. Used in caching. + @param processor PINRemoteImageManagerImageProcessor processor block which should return the processed image. + */ +- (void)pin_setImageFromURL:(nullable NSURL *)url processorKey:(nullable NSString *)processorKey processor:(nullable PINRemoteImageManagerImageProcessor)processor; + +/** + Set placeholder on view and retrieve the image from the given URL, process it using the passed in processor block and set result on view. + + @param url NSURL to fetch from. + @param placeholderImage PINImage to set on the view while the image at URL is being retrieved. + @param processorKey NSString key to uniquely identify processor. Used in caching. + @param processor PINRemoteImageManagerImageProcessor processor block which should return the processed image. + */ +- (void)pin_setImageFromURL:(nullable NSURL *)url placeholderImage:(nullable PINImage *)placeholderImage processorKey:(nullable NSString *)processorKey processor:(nullable PINRemoteImageManagerImageProcessor)processor; + +/** + Retrieve the image from the given URL, process it using the passed in processor block and set result on view. Call completion after image has been fetched, processed and set on view. + + @param url NSURL to fetch from. + @param processorKey NSString key to uniquely identify processor. Used in caching. + @param processor PINRemoteImageManagerImageProcessor processor block which should return the processed image. + @param completion Called when url has been retrieved and set on view. + */ +- (void)pin_setImageFromURL:(nullable NSURL *)url processorKey:(nullable NSString *)processorKey processor:(nullable PINRemoteImageManagerImageProcessor)processor completion:(nullable PINRemoteImageManagerImageCompletion)completion; + +/** + Set placeholder on view and retrieve the image from the given URL, process it using the passed in processor block and set result on view. Call completion after image has been fetched, processed and set on view. + + @param url NSURL to fetch from. + @param placeholderImage PINImage to set on the view while the image at URL is being retrieved. + @param processorKey NSString key to uniquely identify processor. Used in caching. + @param processor PINRemoteImageManagerImageProcessor processor block which should return the processed image. + @param completion Called when url has been retrieved and set on view. + */ +- (void)pin_setImageFromURL:(nullable NSURL *)url placeholderImage:(nullable PINImage *)placeholderImage processorKey:(nullable NSString *)processorKey processor:(nullable PINRemoteImageManagerImageProcessor)processor completion:(nullable PINRemoteImageManagerImageCompletion)completion; + +/** + Retrieve one of the images at the passed in URLs depending on previous network performance and set result on view. + + @param urls NSArray of NSURLs sorted in increasing quality + */ +- (void)pin_setImageFromURLs:(nullable NSArray *)urls; + +/** + Set placeholder on view and retrieve one of the images at the passed in URLs depending on previous network performance and set result on view. + + @param urls NSArray of NSURLs sorted in increasing quality + @param placeholderImage PINImage to set on the view while the image at URL is being retrieved. + */ +- (void)pin_setImageFromURLs:(nullable NSArray *)urls placeholderImage:(nullable PINImage *)placeholderImage; + +/** + Set placeholder on view and retrieve one of the images at the passed in URLs depending on previous network performance and set result on view. Call completion after image has been fetched and set on view. + + @param urls NSArray of NSURLs sorted in increasing quality + @param placeholderImage PINImage to set on the view while the image at URL is being retrieved. + @param completion Called when url has been retrieved and set on view. + */ +- (void)pin_setImageFromURLs:(nullable NSArray *)urls placeholderImage:(nullable PINImage *)placeholderImage completion:(nullable PINRemoteImageManagerImageCompletion)completion; + +/** + Cancels the image download. Guarantees that previous setImage calls will *not* have their results set on the image view after calling this (as opposed to PINRemoteImageManager which does not guarantee cancellation). + */ +- (void)pin_cancelImageDownload; + +/** + Returns the NSUUID associated with any PINRemoteImage task currently running on the view. + + @return NSUUID associated with any PINRemoteImage task currently running on the view. + */ +- (nullable NSUUID *)pin_downloadImageOperationUUID; + +/** + Set the current NSUUID associated with a PINRemoteImage task running on the view. + + @param downloadImageOperationUUID NSUUID associated with a PINRemoteImage task. + */ +- (void)pin_setDownloadImageOperationUUID:(nullable NSUUID *)downloadImageOperationUUID; + +/** + Whether the view should update with progress images (such as those provided by progressive JPEG images). + + @return BOOL value indicating whether the view should update with progress images + */ +@property (nonatomic, assign) BOOL pin_updateWithProgress; + +//Handle +- (void)pin_setPlaceholderWithImage:(nullable PINImage *)image; +- (void)pin_updateUIWithRemoteImageManagerResult:(nonnull PINRemoteImageManagerResult *)result; +- (void)pin_clearImages; +- (BOOL)pin_ignoreGIFs; + +@optional + +- (PINRemoteImageManagerDownloadOptions)pin_defaultOptions; + +@end diff --git a/Source/Classes/include/PINRemoteImage/PINRemoteImageDataConvertible.h b/Source/Classes/include/PINRemoteImage/PINRemoteImageDataConvertible.h new file mode 100644 index 00000000..5953cdb7 --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINRemoteImageDataConvertible.h @@ -0,0 +1,18 @@ +// +// PINRemoteImageDataConvertible.h +// PINRemoteImage +// +// Created by Andy Finnell on 5/23/24. +// Copyright © 2024 Pinterest. All rights reserved. +// + +#import + +/** + Protocol for describing a class that convert into image data. + */ +@protocol PINRemoteImageDataConvertible + +@property (nonatomic, readonly) NSData *data; + +@end diff --git a/Source/Classes/include/PINRemoteImage/PINRemoteImageMacros.h b/Source/Classes/include/PINRemoteImage/PINRemoteImageMacros.h new file mode 100644 index 00000000..5459097d --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINRemoteImageMacros.h @@ -0,0 +1,70 @@ +// +// PINRemoteImageMacros.h +// PINRemoteImage +// + +#import + +#ifndef PINRemoteImageMacros_h +#define PINRemoteImageMacros_h + +#define PIN_TARGET_IOS (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR || TARGET_OS_TV) +#define PIN_TARGET_MAC TARGET_OS_OSX + +#define PINRemoteImageLogging 0 +#if PINRemoteImageLogging +#define PINLog(args...) NSLog(args) +#else +#define PINLog(args...) +#endif + +#ifndef USE_PINCACHE + #if __has_include() || __has_include("PINCache.h") + #define USE_PINCACHE 1 + #else + #define USE_PINCACHE 0 + #endif +#endif + +#ifndef PIN_WEBP + #define PIN_WEBP 1 +#endif + +#ifndef PIN_APNG + #define PIN_APNG 1 +#endif + +#if PIN_TARGET_IOS +#define PINImage UIImage +#define PINImageView UIImageView +#define PINButton UIButton +#define PINNSOperationSupportsBlur (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_8_0) +#elif PIN_TARGET_MAC +#define PINImage NSImage +#define PINImageView NSImageView +#define PINButton NSButton +#define PINNSOperationSupportsBlur (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber10_10) +#define PINNSURLSessionTaskSupportsPriority (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber10_10) +#endif + +#define PINWeakify(var) __weak typeof(var) PINWeak_##var = var; + +#define PINStrongify(var) \ +_Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wshadow\"") __strong typeof(var) var = \ +PINWeak_##var; \ +_Pragma("clang diagnostic pop") + +#define BlockAssert(condition, desc, ...) \ +do { \ +__PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \ +if (!(condition)) { \ +[[NSAssertionHandler currentHandler] handleFailureInMethod:_cmd \ +object:strongSelf file:[NSString stringWithUTF8String:__FILE__] \ +lineNumber:__LINE__ description:(desc), ##__VA_ARGS__]; \ +} \ +__PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \ +} while(0); + +#define PINAssertMain() NSAssert([NSThread isMainThread], @"Expected to be on the main thread."); + +#endif /* PINRemoteImageMacros_h */ diff --git a/Source/Classes/include/PINRemoteImage/PINRemoteImageManager.h b/Source/Classes/include/PINRemoteImage/PINRemoteImageManager.h new file mode 100644 index 00000000..72853e67 --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINRemoteImageManager.h @@ -0,0 +1,713 @@ +// +// PINRemoteImageManager.h +// Pods +// +// Created by Garrett Moon on 8/17/14. +// +// + +#import + +#import + +#if PIN_TARGET_IOS +#import +#elif PIN_TARGET_MAC +#import +#endif + +#import + +#define PINRemoteImageHTTPMaximumConnectionsPerHost UINT16_MAX + +@protocol PINRemoteImageManagerAlternateRepresentationProvider; +@protocol PINRemoteImageCaching; +@protocol PINRequestRetryStrategy; + +@class PINRemoteImageManagerConfiguration; +@class PINRemoteImageManagerResult; + +extern NSErrorDomain _Nonnull const PINRemoteImageManagerErrorDomain; + +/** + Error codes returned by PINRemoteImage + */ +typedef NS_ERROR_ENUM(PINRemoteImageManagerErrorDomain, PINRemoteImageManagerError) { + /** The image failed to decode */ + PINRemoteImageManagerErrorFailedToDecodeImage = 1, + /** The image could not be downloaded and therefore could not be processed */ + PINRemoteImageManagerErrorFailedToFetchImageForProcessing = 2, + /** The image returned by the processor block was nil */ + PINRemoteImageManagerErrorFailedToProcessImage = 3, + /** The image in the cache was invalid */ + PINRemoteImageManagerErrorInvalidItemInCache = 4, + /** The image at the URL was empty */ + PINRemoteImageManagerErrorImageEmpty = 5, +}; + +/** + Options with which to download and process images + */ +typedef NS_OPTIONS(NSUInteger, PINRemoteImageManagerDownloadOptions) { + /** Download and process with default options (no other options set) */ + PINRemoteImageManagerDownloadOptionsNone = 0, + /** Set to disallow any alternate representations such as Animated Images */ + PINRemoteImageManagerDisallowAlternateRepresentations = 1, + /** Skip decoding the image before returning. This means smaller images returned, but images will be decoded on the main thread when set on an image view */ + PINRemoteImageManagerDownloadOptionsSkipDecode = 1 << 1, + /** Skip the early check of the memory cache */ + PINRemoteImageManagerDownloadOptionsSkipEarlyCheck = 1 << 2, + /** Save processed images as JPEGs in the cache. The default is PNG to support transparency */ + PINRemoteImageManagerSaveProcessedImageAsJPEG = 1 << 3, + /** Ignore cache and force download */ + PINRemoteImageManagerDownloadOptionsIgnoreCache = 1 << 4, + /** Skip download retry */ + PINRemoteImageManagerDownloadOptionsSkipRetry = 1 << 5, + /** + * Do not honor HTTP Cache-Control headers + * By default, PINRemoteImage will by default respect 'no-store', 'no-cache', 'max-age', + * 'Expires', and 'must-revalidate'. Set this flag to ignore those headers. + * TODO: Currently PINRemoteImage will re-download images that only must be re-validated. In the + * future this could be improved with revalidation behavior that stores ETag or Last-Modified + * values and only makes HEAD requests to see if these headers are unchanged. + * see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control and + * https://tools.ietf.org/html/rfc7234 + */ + PINRemoteImageManagerDownloadOptionsIgnoreCacheControlHeaders = 1 << 6 +}; + +/** + Priority to download and process image at. + */ +typedef NS_ENUM(NSUInteger, PINRemoteImageManagerPriority) { + /** Low priority */ + PINRemoteImageManagerPriorityLow = 0, + /** Default priority */ + PINRemoteImageManagerPriorityDefault, + /** High priority */ + PINRemoteImageManagerPriorityHigh, + PINRemoteImageManagerPriorityVeryHigh DEPRECATED_ATTRIBUTE = PINRemoteImageManagerPriorityHigh, + PINRemoteImageManagerPriorityVeryLow DEPRECATED_ATTRIBUTE = PINRemoteImageManagerPriorityLow, + PINRemoteImageManagerPriorityMedium DEPRECATED_ATTRIBUTE = PINRemoteImageManagerPriorityDefault, +}; + +float dataTaskPriorityWithImageManagerPriority(PINRemoteImageManagerPriority priority); + +/** + Completion called for many PINRemoteImage tasks as well as progress updates. Passed in a PINRemoteImageManagerResult. + + @param result PINRemoteImageManagerResult which contains the downloaded image. + */ +typedef void (^PINRemoteImageManagerImageCompletion)(PINRemoteImageManagerResult * __nonnull result); + +/** + Processor block to post-process a downloaded image. Passed in a PINRemoteImageManagerResult and a pointer to an NSUInteger which can be updated to indicate the cost of processing the image. + + @param result PINRemoteImageManagerResult which contains the downloaded image. + @param cost NSUInteger point which can be modified to indicate the cost of processing the image. This is used when determining which cache objects to evict on memory pressure. + + @return return the processed UIImage + */ +typedef PINImage * _Nullable(^PINRemoteImageManagerImageProcessor)(PINRemoteImageManagerResult * __nonnull result, NSUInteger * __nonnull cost); + +/** + PINRemoteImageManager is the main workhorse of PINRemoteImage. It is unnecessary to access directly if you simply + wish to download images and have them rendered in a UIImageView, UIButton or PINAnimatedImageView. + + However, if you wish to download images directly, this class is your guy / gal. + + You can use this class to download images, postprocess downloaded images, prefetch images, download images progressively, or download one image in a set of images depending on network performance. + */ + +/** + Completion Handler block which will be forwarded to NSURLSessionTaskDelegate's completion handler + + @param disposition One of several constants that describes how the challenge should be handled. + @param credential The credential that should be used for authentication if disposition is NSURLSessionAuthChallengeUseCredential; otherwise, NULL. + */ +typedef void(^PINRemoteImageManagerAuthenticationChallengeCompletionHandler)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential); + +/** + Authentication challenge handler + + @param task The task whose request requires authentication. + @param challenge An object that contains the request for authentication. + @param aHandler A PINRemoteImageManagerAuthenticationChallengeCompletionHandler, see example for further details. + */ +typedef void(^PINRemoteImageManagerAuthenticationChallenge)(NSURLSessionTask * __nullable task, NSURLAuthenticationChallenge * __nonnull challenge, PINRemoteImageManagerAuthenticationChallengeCompletionHandler __nullable aHandler); + + +/** + Request configuration handler. Used to modify a network request before it is executed. + Useful for adding custom, per-request headers. + + @param request The request about to be executed + */ +typedef NSURLRequest * _Nonnull(^PINRemoteImageManagerRequestConfigurationHandler)(NSURLRequest * __nonnull request); + + +/** + Handler called for many PINRemoteImage tasks providing the progress of the download. + + @param completedBytes Amount of bytes that have been downloaded so far. + @param totalBytes Total amount of bytes in the image being downloaded. + */ +typedef void(^PINRemoteImageManagerProgressDownload)(int64_t completedBytes, int64_t totalBytes); + +/** + Reports NSURLSessionTaskMetrics for download requests + + */ +typedef void(^PINRemoteImageManagerMetrics)(NSURL * __nonnull url, NSURLSessionTaskMetrics * __nonnull metrics); + +/** An image downloading, processing and caching manager. It uses the concept of download and processing tasks to ensure that even if multiple calls to download or process an image are made, it only occurs one time (unless an item is no longer in the cache). PINRemoteImageManager is backed by GCD and safe to access from multiple threads simultaneously. It ensures that images are decoded off the main thread so that animation performance isn't affected. None of its exposed methods allow for synchronous access. However, it is optimized to call completions on the calling thread if an item is in its memory cache. **/ +@interface PINRemoteImageManager : NSObject + +@property (nonatomic, readonly, nonnull) id cache; + +/** + Create and return a PINRemoteImageManager created with the specified configuration. If configuration is nil, [NSURLSessionConfiguration defaultConfiguration] is used. Specify a custom configuration if you need to configure timeout values, cookie policies, additional HTTP headers, etc. + @param sessionConfiguration The session configuration used to create the PINRemoteImageManager. + @return A PINRemoteImageManager with the specified configuration. + @note If you provide your own `sessionConfiguration`, please attention `HTTPMaximumConnectionsPerHost` property, it may causes timeout when in conjunction with `maxNumberOfConcurrentDownloads` if you set a larger number to `maxNumberOfConcurrentDownloads` but smaller number to `HTTPMaximumConnectionsPerHost`. + */ +- (nonnull instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)sessionConfiguration; + +/** + Create and return a PINRemoteImageManager with the specified configuration and alternative representation delegate. If configuration is nil, [NSURLSessionConfiguration defaultConfiguration] is used. Specify a custom configuration if you need to configure timeout values, cookie policies, additional HTTP headers, etc. If alternativeRepresentationProvider is nil, the default is used (and supports PINAnimatedImageView). + @param sessionConfiguration The session configuration used to create the PINRemoteImageManager. + @param alternativeRepresentationProvider a delegate which conforms to the PINRemoteImageManagerAlternateRepresentationProvider protocol. Provide a delegate if you want to have non image results. The manager maintains a weak reference to the delegate. @see PINRemoteImageManagerAlternateRepresentationProvider for an example. + @return A PINRemoteImageManager with the specified configuration. + @note If you provide your own `sessionConfiguration`, please attention `HTTPMaximumConnectionsPerHost` property, it may causes timeout when in conjunction with `maxNumberOfConcurrentDownloads` if you set a larger number to `maxNumberOfConcurrentDownloads` but smaller number to `HTTPMaximumConnectionsPerHost`. + */ +- (nonnull instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)sessionConfiguration + alternativeRepresentationProvider:(nullable id )alternativeRepresentationProvider; + +/** + Create and return a PINRemoteImageManager with the specified configuration and alternative representation delegate. If configuration is nil, [NSURLSessionConfiguration defaultConfiguration] is used. Specify a custom configuration if you need to configure timeout values, cookie policies, additional HTTP headers, etc. If alternativeRepresentationProvider is nil, the default is used (and supports PINAnimatedImageView). + @param sessionConfiguration The session configuration used to create the PINRemoteImageManager. + @param alternateRepDelegate a delegate which conforms to the PINRemoteImageManagerAlternateRepresentationProvider protocol. Provide a delegate if you want to have non image results. The manager maintains a weak reference to the delegate. @see PINRemoteImageManagerAlternateRepresentationProvider for an example. + @param imageCache Optional delegate which conforms to the PINRemoteImageCaching protocol. Provide a delegate if you want to control image caching. By default, image manager will use most appropriate implementation available (based on PINCache or NSCache, depending on subspec)@see PINRemoteImageBasicCache for an example. + @return A PINRemoteImageManager with the specified configuration. + @note If you provide your own `sessionConfiguration`, please attention `HTTPMaximumConnectionsPerHost` property, it may causes timeout when in conjunction with `maxNumberOfConcurrentDownloads` if you set a larger number to `maxNumberOfConcurrentDownloads` but smaller number to `HTTPMaximumConnectionsPerHost`. + */ +- (nonnull instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)sessionConfiguration + alternativeRepresentationProvider:(nullable id )alternateRepDelegate + imageCache:(nullable id)imageCache; + +/** + Create and return a PINRemoteImageManager with the specified configuration and alternative representation delegate. If configuration is nil, [NSURLSessionConfiguration defaultConfiguration] is used. Specify a custom configuration if you need to configure timeout values, cookie policies, additional HTTP headers, etc. If alternativeRepresentationProvider is nil, the default is used (and supports PINAnimatedImageView). + @param sessionConfiguration The session configuration used to create the PINRemoteImageManager. + @param alternateRepDelegate a delegate which conforms to the PINRemoteImageManagerAlternateRepresentationProvider protocol. Provide a delegate if you want to have non image results. The manager maintains a weak reference to the delegate. @see PINRemoteImageManagerAlternateRepresentationProvider for an example. + @param imageCache Optional delegate which conforms to the PINRemoteImageCaching protocol. Provide a delegate if you want to control image caching. By default, image manager will use most appropriate implementation available (based on PINCache or NSCache, depending on subspec)@see PINRemoteImageBasicCache for an example. + @param managerConfiguration The configuration used to create the PINRemoteImageManager. + @return A PINRemoteImageManager with the specified configuration. + @note If you provide your own `sessionConfiguration`, please attention `HTTPMaximumConnectionsPerHost` property, it may causes timeout when in conjunction with `maxNumberOfConcurrentDownloads` if you set a larger number to `maxNumberOfConcurrentDownloads` but smaller number to `HTTPMaximumConnectionsPerHost`. + */ +- (nonnull instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)sessionConfiguration + alternativeRepresentationProvider:(nullable id )alternateRepDelegate + imageCache:(nullable id)imageCache + managerConfiguration:(nullable PINRemoteImageManagerConfiguration *)managerConfiguration NS_DESIGNATED_INITIALIZER; + +/** + Get the shared instance of PINRemoteImageManager + + @return Shared instance of PINRemoteImageManager + */ ++ (nonnull instancetype)sharedImageManager; + +/** + Sets the shared instance of PINRemoteImageManager to an instance with the supplied configuration. If configuration is nil, [NSURLSessionConfiguration ephemeralSessionConfiguration] is used. You specify a custom configuration if you need to configure timeout values, cookie policies, additional HTTP headers, etc. This method should not be used if the shared instance has already been created. + + @param configuration The configuration used to create the PINRemoteImageManager. + @note If you provide your own `sessionConfiguration`, please attention `HTTPMaximumConnectionsPerHost` property, it may causes timeout when in conjunction with `maxNumberOfConcurrentDownloads` if you set a larger number to `maxNumberOfConcurrentDownloads` but smaller number to `HTTPMaximumConnectionsPerHost`. + */ ++ (void)setSharedImageManagerWithConfiguration:(nullable NSURLSessionConfiguration *)configuration; + + +/** + The result of this method is assigned to self.cache in init. If you wish to provide a customized cache to the manager you can subclass PINRemoteImageManager and return a custom object, implementing PINRemoteImageCaching protocol from this method. Same effect could be achieved by using initWithSessionConfiguration:alternativeRepresentationProvider:imageCache: initializer. + @deprecated Use the class method +defaultImageCache + @warning This method is meant only for override. It will be called *once* by an instance of PINRemoteImageManager. The default implementation creates a new cache on every call. If you're looking to access the cache being used by an instance of PINRemoteImageManager, @c cache. + @return An instance of a object, implementing PINRemoteImageCaching protocol. + */ +- (nonnull id)defaultImageCache __attribute__((deprecated)); + +/** + The result of this method is assigned to self.cache in init. If you wish to provide a customized cache to the manager you can subclass PINRemoteImageManager and return a custom object, implementing PINRemoteImageCaching protocol from this method. Same effect could be achieved by using initWithSessionConfiguration:alternativeRepresentationProvider:imageCache: initializer. + @warning This method is meant only for override. It will be called *once* by an instance of PINRemoteImageManager. The default implementation creates a new cache on every call. If you're looking to access the cache being used by an instance of PINRemoteImageManager, @c cache. + @return An instance of a object, implementing PINRemoteImageCaching protocol. + */ ++ (nonnull id)defaultImageCache; + +/** + * If you want a Ttl (maxAge) image cache, you can pass the result of this method explicitly into the initWithSessionConfiguration:alternativeRepresentationProvider:imageCache: initializer. + * @return An instance of a object, implementing PINRemoteImageCaching protocol. + */ ++ (nonnull id)defaultImageTtlCache; + +/** + * Sets a custom header to be included in every request. Headers set from this method will override any header from NSURLSessionConfiguration. + * + * @deprecated Use NSURLSessionConfiguration.HTTPAdditionalHeaders instead + * @param value A value for the header. Pass in nil to remove a previously set value. + * @param header A string field for header. + + */ +- (void)setValue:(nullable NSString *)value forHTTPHeaderField:(nullable NSString *)header __attribute__((deprecated)); + +/** + Sets the Request Configuration Block. + + @param configurationBlock A PINRemoteImageManagerRequestConfigurationHandler block. + */ +- (void)setRequestConfiguration:(nullable PINRemoteImageManagerRequestConfigurationHandler)configurationBlock; + +/** + Sets the Request Configuration Block. + + @param configurationBlock A PINRemoteImageManagerRequestConfigurationHandler block. + @param completion Completion to be called once configurationBlock has been set. + */ +- (void)setRequestConfiguration:(nullable PINRemoteImageManagerRequestConfigurationHandler)configurationBlock + completion:(void (^_Nullable)(void))completion; + +/** + Set the Authentication Challenge Block. + + @param challengeBlock A PINRemoteImageManagerAuthenticationChallenge block. + */ +- (void)setAuthenticationChallenge:(nullable PINRemoteImageManagerAuthenticationChallenge)challengeBlock; + +/** + Set the minimum BPS to download the highest quality image in a set. + @see downloadImageWithURLs:options:progressImage:completion: + + @param highQualityBPSThreshold bytes per second minimum. Defaults to 500000. + @param completion Completion to be called once highQualityBPSThreshold has been set. + */ +- (void)setHighQualityBPSThreshold:(float)highQualityBPSThreshold completion:(nullable dispatch_block_t)completion; + +/** + Set the maximum BPS to download the lowest quality image in a set. + @see downloadImageWithURLs:options:progressImage:completion: + + @param lowQualityBPSThreshold bytes per second maximum. Defaults to 50000. + @param completion Completion to be called once lowQualityBPSThreshold has been set. + */ +- (void)setLowQualityBPSThreshold:(float)lowQualityBPSThreshold + completion:(nullable dispatch_block_t)completion; + +/** + Set whether high quality images should be downloaded when a low quality image is cached if network connectivity has improved. + @see downloadImageWithURLs:options:progressImage:completion: + + @param shouldUpgradeLowQualityImages if YES, low quality images will be 'upgraded'. + @param completion Completion to be called once shouldUpgradeLowQualityImages has been set. + */ +- (void)setShouldUpgradeLowQualityImages:(BOOL)shouldUpgradeLowQualityImages + completion:(nullable dispatch_block_t)completion; + +/** + Set the maximum number of concurrent operations (decompressing images, creating gifs, etc). + + @param maxNumberOfConcurrentOperations The maximum number of concurrent operations. Defaults to NSOperationQueueDefaultMaxConcurrentOperationCount. + @param completion Completion to be called once maxNumberOfConcurrentOperations is set. + */ +- (void)setMaxNumberOfConcurrentOperations:(NSInteger)maxNumberOfConcurrentOperations + completion:(nullable dispatch_block_t)completion; + +/** + Set the maximum number of concurrent downloads. + + @param maxNumberOfConcurrentDownloads The maximum number of concurrent downloads. Defaults to 10, maximum 65535. + @param completion Completion to be called once maxNumberOfConcurrentDownloads is set. + */ +- (void)setMaxNumberOfConcurrentDownloads:(NSInteger)maxNumberOfConcurrentDownloads + completion:(nullable dispatch_block_t)completion; + +/** + Set the estimated time remaining to download threshold at which to generate progressive images. Progressive images previews will only be generated if the estimated remaining time on a download is greater than estimatedTimeRemainingThreshold. If estimatedTimeRemainingThreshold is less than or equal to zero, this check is skipped. + + @param estimatedRemainingTimeThreshold The estimated remaining time threshold used to decide to skip progressive rendering. Defaults to 0.1. + @param completion Completion to be called once estimatedTimeRemainingTimeThreshold is set. + */ +- (void)setEstimatedRemainingTimeThresholdForProgressiveDownloads:(NSTimeInterval)estimatedRemainingTimeThreshold + completion:(nullable dispatch_block_t)completion; + +/** + Sets the progress at which progressive images are generated. By default this is @[@0.00, @0.35, @0.65] which generates at most, 3 progressive images. The first progressive image will only be generated when at least one scan has been completed (so you never see half an image). + + @param progressThresholds an array of progress thresholds at which to generate progressive images. progress thresholds should range from 0.00 - 1.00. Defaults to @[@0.00, @0.35, @0.65] + @param completion Completion to be called once progressThresholds is set. + */ +- (void)setProgressThresholds:(nonnull NSArray *)progressThresholds + completion:(nullable dispatch_block_t)completion; + +/** + Sets whether PINRemoteImage should blur progressive render results + + @param shouldBlur A bool value indicating whether PINRemoteImage should blur progressive render results + @param completion Completion to be called once progressThresholds is set. + */ +- (void)setProgressiveRendersShouldBlur:(BOOL)shouldBlur + completion:(nullable dispatch_block_t)completion; + +/** + Sets the maximum size of an image that PINRemoteImage will render progessively. If the image is too large, progressive rendering is skipped. + + @param maxProgressiveRenderSize A CGSize which indicates the max size PINRemoteImage will render a progressive image. If an image is larger in either dimension, progressive rendering will be skipped + @param completion Completion to be called once maxProgressiveRenderSize is set. + */ +- (void)setProgressiveRendersMaxProgressiveRenderSize:(CGSize)maxProgressiveRenderSize + completion:(nullable dispatch_block_t)completion; + +/** + Sets a metrics callback block to be called when NSURLSessionTaskMetrics are reported for downloads. + + @warning PINRemoteImageManager will hold a strong reference to metricsCallback. Avoid retain cycles by using weak references in the block! + */ +- (void)setMetricsCallback:(nullable PINRemoteImageManagerMetrics)metricsCallback + completion:(nullable dispatch_block_t)completion; + +/** + Prefetch an image at the given URL. + + @param url NSURL where the image to prefetch resides. + */ +- (nullable NSUUID *)prefetchImageWithURL:(nonnull NSURL *)url; + +/** + Prefetch an image at the given URL with given options. + + @param url NSURL where the image to prefetch resides. + @param options PINRemoteImageManagerDownloadOptions options with which to pefetch the image. + */ +- (nullable NSUUID *)prefetchImageWithURL:(nonnull NSURL *)url options:(PINRemoteImageManagerDownloadOptions)options; + +/** + Prefetch an image at the given URL with given options. + + @param url NSURL where the image to prefetch resides. + @param options PINRemoteImageManagerDownloadOptions options with which to prefetch the image. + @param priority PINRemoteImageManagerPriority priority of the operation when to prefetch the image. + */ +- (nullable NSUUID *)prefetchImageWithURL:(nonnull NSURL *)url options:(PINRemoteImageManagerDownloadOptions)options priority:(PINRemoteImageManagerPriority)priority; + +/** + Prefetch images at the given URLs. + + @param urls An array of NSURLs where the images to prefetch reside. + */ +- (nonnull NSArray *)prefetchImagesWithURLs:(nonnull NSArray *)urls; + +/** + Prefetch images at the given URLs with given options. + + @param urls An array of NSURLs where the images to prefetch reside. + @param options PINRemoteImageManagerDownloadOptions options with which to pefetch the image. + */ +- (nonnull NSArray *)prefetchImagesWithURLs:(nonnull NSArray *)urls options:(PINRemoteImageManagerDownloadOptions)options; + +/** + Prefetch images at the given URLs with given options. + + @param urls An array of NSURLs where the images to prefetch reside. + @param options PINRemoteImageManagerDownloadOptions options with which to pefetch the image. + @param priority PINRemoteImageManagerPriority priority of the operation to prefetch the image. + */ +- (nonnull NSArray *)prefetchImagesWithURLs:(nonnull NSArray *)urls options:(PINRemoteImageManagerDownloadOptions)options priority:(PINRemoteImageManagerPriority)priority; + +/** + Download or retrieve from cache the image found at the url. All completions are called on an arbitrary callback queue unless called on the main thread and the result is in the memory cache (this is an optimization to allow synchronous results for the UI when an object is cached in memory). + + @param url NSURL where the image to download resides. + @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache or downloaded. + @return An NSUUID which uniquely identifies this request. To be used for canceling requests and verifying that the callback is for the request you expect (see categories for example). + */ +- (nullable NSUUID *)downloadImageWithURL:(nonnull NSURL *)url completion:(nullable PINRemoteImageManagerImageCompletion)completion; + +/** + Download or retrieve from cache the image found at the url. All completions are called on an arbitrary callback queue unless called on the main thread and the result is in the memory cache (this is an optimization to allow synchronous results for the UI when an object is cached in memory). + + @param url NSURL where the image to download resides. + @param options PINRemoteImageManagerDownloadOptions options with which to fetch the image. + @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache or downloaded. + @return An NSUUID which uniquely identifies this request. To be used for canceling requests and verifying that the callback is for the request you expect (see categories for example). + */ +- (nullable NSUUID *)downloadImageWithURL:(nonnull NSURL *)url + options:(PINRemoteImageManagerDownloadOptions)options + completion:(nullable PINRemoteImageManagerImageCompletion)completion; + +/** + Download or retrieve from cache the image found at the url. All completions are called on an arbitrary callback queue unless called on the main thread and the result is in the memory cache (this is an optimization to allow synchronous results for the UI when an object is cached in memory). + + @param url NSURL where the image to download resides. + @param options PINRemoteImageManagerDownloadOptions options with which to fetch the image. + @param progressImage PINRemoteImageManagerImageCompletion block which will be called to update progress of the image download. + @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache or downloaded. + + @return An NSUUID which uniquely identifies this request. To be used for canceling requests and verifying that the callback is for the request you expect (see categories for example). + */ +- (nullable NSUUID *)downloadImageWithURL:(nonnull NSURL *)url + options:(PINRemoteImageManagerDownloadOptions)options + progressImage:(nullable PINRemoteImageManagerImageCompletion)progressImage + completion:(nullable PINRemoteImageManagerImageCompletion)completion; + +/** + Download or retrieve from cache the image found at the url. All completions are called on an arbitrary callback queue unless called on the main thread and the result is in the memory cache (this is an optimization to allow synchronous results for the UI when an object is cached in memory). + + @param url NSURL where the image to download resides. + @param options PINRemoteImageManagerDownloadOptions options with which to fetch the image. + @param progressDownload PINRemoteImageManagerDownloadProgress block which will be called to update progress in bytes of the image download. NOTE: For performance reasons, this block is not called on the main thread every time, if you need to update your UI ensure that you dispatch to the main thread first. + @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache or downloaded. + + @return An NSUUID which uniquely identifies this request. To be used for canceling requests and verifying that the callback is for the request you expect (see categories for example). + */ +- (nullable NSUUID *)downloadImageWithURL:(nonnull NSURL *)url + options:(PINRemoteImageManagerDownloadOptions)options + progressDownload:(nullable PINRemoteImageManagerProgressDownload)progressDownload + completion:(nullable PINRemoteImageManagerImageCompletion)completion; + +/** + Download or retrieve from cache the image found at the url. All completions are called on an arbitrary callback queue unless called on the main thread and the result is in the memory cache (this is an optimization to allow synchronous results for the UI when an object is cached in memory). + + @param url NSURL where the image to download resides. + @param options PINRemoteImageManagerDownloadOptions options with which to fetch the image. + @param progressImage PINRemoteImageManagerImageCompletion block which will be called to update progress of the image download. + @param progressDownload PINRemoteImageManagerDownloadProgress block which will be called to update progress in bytes of the image download. NOTE: For performance reasons, this block is not called on the main thread every time, if you need to update your UI ensure that you dispatch to the main thread first. + @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache or downloaded. + + @return An NSUUID which uniquely identifies this request. To be used for canceling requests and verifying that the callback is for the request you expect (see categories for example). + */ +- (nullable NSUUID *)downloadImageWithURL:(nonnull NSURL *)url + options:(PINRemoteImageManagerDownloadOptions)options + progressImage:(nullable PINRemoteImageManagerImageCompletion)progressImage + progressDownload:(nullable PINRemoteImageManagerProgressDownload)progressDownload + completion:(nullable PINRemoteImageManagerImageCompletion)completion; + +/** + Download or retrieve from cache the image found at the url and process it before calling completion. All completions are called on an arbitrary callback queue unless called on the main thread and the result is in the memory cache (this is an optimization to allow synchronous results for the UI when an object is cached in memory). + + @param url NSURL where the image to download resides. + @param options PINRemoteImageManagerDownloadOptions options with which to fetch the image. + @param priority PINRemoteImageManagerPriority which indicates the priority of the download task. + @param progressImage PINRemoteImageManagerImageCompletion block which will be called to update progress of the image download. + @param progressDownload PINRemoteImageManagerDownloadProgress block which will be called to update progress in bytes of the image download. NOTE: For performance reasons, this block is not called on the main thread every time, if you need to update your UI ensure that you dispatch to the main thread first. + @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache or downloaded. + + @return An NSUUID which uniquely identifies this request. To be used for canceling requests and verifying that the callback is for the request you expect (see categories for example). + */ +- (nullable NSUUID *)downloadImageWithURL:(nonnull NSURL *)url + options:(PINRemoteImageManagerDownloadOptions)options + priority:(PINRemoteImageManagerPriority)priority + progressImage:(nullable PINRemoteImageManagerImageCompletion)progressImage + progressDownload:(nullable PINRemoteImageManagerProgressDownload)progressDownload + completion:(nullable PINRemoteImageManagerImageCompletion)completion; + +/** + Download or retrieve from cache the image found at the url and process it before calling completion. All completions are called on an arbitrary callback queue unless called on the main thread and the result is in the memory cache (this is an optimization to allow synchronous results for the UI when an object is cached in memory). + + @param url NSURL where the image to download resides. + @param options PINRemoteImageManagerDownloadOptions options with which to fetch the image. + @param processorKey NSString key to uniquely identify processor and process. Will be used for caching processed images. + @param processor PINRemoteImageManagerImageProcessor block which will be called to post-process downloaded image. + @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache or downloaded. + + @return An NSUUID which uniquely identifies this request. To be used for canceling requests and verifying that the callback is for the request you expect (see categories for example). + */ +- (nullable NSUUID *)downloadImageWithURL:(nonnull NSURL *)url + options:(PINRemoteImageManagerDownloadOptions)options + processorKey:(nullable NSString *)processorKey + processor:(nullable PINRemoteImageManagerImageProcessor)processor + completion:(nullable PINRemoteImageManagerImageCompletion)completion; + +/** + Download or retrieve from cache the image found at the url and process it before calling completion. All completions are called on an arbitrary callback queue unless called on the main thread and the result is in the memory cache (this is an optimization to allow synchronous results for the UI when an object is cached in memory). + + @param url NSURL where the image to download resides. + @param options PINRemoteImageManagerDownloadOptions options with which to fetch the image. + @param processorKey NSString key to uniquely identify processor and process. Will be used for caching processed images. + @param progressDownload PINRemoteImageManagerDownloadProgress block which will be called to update progress in bytes of the image download. NOTE: For performance reasons, this block is not called on the main thread every time, if you need to update your UI ensure that you dispatch to the main thread first. + @param processor PINRemoteImageManagerImageProcessor block which will be called to post-process downloaded image. + @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache or downloaded. + + @return An NSUUID which uniquely identifies this request. To be used for canceling requests and verifying that the callback is for the request you expect (see categories for example). + */ +- (nullable NSUUID *)downloadImageWithURL:(nonnull NSURL *)url + options:(PINRemoteImageManagerDownloadOptions)options + processorKey:(nullable NSString *)processorKey + processor:(nullable PINRemoteImageManagerImageProcessor)processor + progressDownload:(nullable PINRemoteImageManagerProgressDownload)progressDownload + completion:(nullable PINRemoteImageManagerImageCompletion)completion; + +/** + Download or retrieve from cache one of the images found at the urls in the passed in array based on current network performance. URLs should be sorted from lowest quality image URL to highest. All completions are called on an arbitrary callback queue unless called on the main thread and the result is in the memory cache (this is an optimization to allow synchronous results for the UI when an object is cached in memory). + + Unless setShouldUpgradeLowQualityImages is set to YES, this method checks the cache for all URLs and returns the highest quality version stored. It is possible though unlikely for a cached image to not be returned if it is still being cached while a call is made to this method and if network conditions have changed. See source for more details. + + @param urls An array of NSURLs of increasing cost to download. + @param options PINRemoteImageManagerDownloadOptions options with which to fetch the image. + @param progressImage PINRemoteImageManagerImageCompletion block which will be called to update progress of the image download. + @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache or downloaded. + + @return An NSUUID which uniquely identifies this request. To be used for canceling requests and verifying that the callback is for the request you expect (see categories for example). + */ +- (nullable NSUUID *)downloadImageWithURLs:(nonnull NSArray *)urls + options:(PINRemoteImageManagerDownloadOptions)options + progressImage:(nullable PINRemoteImageManagerImageCompletion)progressImage + completion:(nullable PINRemoteImageManagerImageCompletion)completion; + +/** + Download or retrieve from cache one of the images found at the urls in the passed in array based on current network performance. URLs should be sorted from lowest quality image URL to highest. All completions are called on an arbitrary callback queue unless called on the main thread and the result is in the memory cache (this is an optimization to allow synchronous results for the UI when an object is cached in memory). + + Unless setShouldUpgradeLowQualityImages is set to YES, this method checks the cache for all URLs and returns the highest quality version stored. It is possible though unlikely for a cached image to not be returned if it is still being cached while a call is made to this method and if network conditions have changed. See source for more details. + + @param urls An array of NSURLs of increasing cost to download. + @param options PINRemoteImageManagerDownloadOptions options with which to fetch the image. + @param progressImage PINRemoteImageManagerImageCompletion block which will be called to update progress of the image download. + @param progressDownload PINRemoteImageManagerDownloadProgress block which will be called to update progress in bytes of the image download. NOTE: For performance reasons, this block is not called on the main thread every time, if you need to update your UI ensure that you dispatch to the main thread first. + @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache or downloaded. + + @return An NSUUID which uniquely identifies this request. To be used for canceling requests and verifying that the callback is for the request you expect (see categories for example). + */ +- (nullable NSUUID *)downloadImageWithURLs:(nonnull NSArray *)urls + options:(PINRemoteImageManagerDownloadOptions)options + progressImage:(nullable PINRemoteImageManagerImageCompletion)progressImage + progressDownload:(nullable PINRemoteImageManagerProgressDownload)progressDownload + completion:(nullable PINRemoteImageManagerImageCompletion)completion; + + +/** + Adds an image manually into the memory and disk cache. + + @param data NSData with the raw image data. + @param url NSURL where the image resides. + @param processorKey NSString key to uniquely identify processor and process. Will be used for caching processed images. + @param additionalCost NSUInteger the additional cost (for cache eviction purposes) to generate the processed image + + @return A BOOL indicating if the image was successfully added to the cache. + */ +- (BOOL) insertImageDataIntoCache:(nonnull NSData*)data + withURL:(nonnull NSURL *)url + processorKey:(nullable NSString *)processorKey + additionalCost:(NSUInteger)additionalCost; + +/** + Returns the cacheKey for a given URL and processorKey. Exposed to be overridden if necessary or to be used with imageFromCacheWithCacheKey + @see imageFromCacheWithCacheKey:completion: + + @param url NSURL that was used to download image + @param processorKey An optional key to uniquely identify the processor used to post-process the downloaded image. + + @return returns an NSString which is the key used for caching. + */ +- (nonnull NSString *)cacheKeyForURL:(nonnull NSURL *)url processorKey:(nullable NSString *)processorKey; + +/** + @see imageFromCacheWithURL:processorKey:options:completion: + @deprecated + + @param cacheKey NSString key to look up image in the cache. + @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache. + */ +- (void)imageFromCacheWithCacheKey:(nonnull NSString *)cacheKey completion:(nonnull PINRemoteImageManagerImageCompletion)completion __attribute__((deprecated)); + +/** + @see imageFromCacheWithURL:processorKey:options:completion: + @deprecated + + @param cacheKey NSString key to look up image in the cache. + @param options options will be used to determine if the cached image should be decompressed or PINCachedAnimatedImages should be returned. + @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache. + */ +- (void)imageFromCacheWithCacheKey:(nonnull NSString *)cacheKey options:(PINRemoteImageManagerDownloadOptions)options completion:(nonnull PINRemoteImageManagerImageCompletion)completion __attribute__((deprecated)); + +/** + Directly get an image from the underlying cache. + + @param url NSURL that was used to download image + @param processorKey An optional key to uniquely identify the processor used to post-process the downloaded image. + @param options options will be used to determine if the cached image should be decompressed or PINCachedAnimatedImages should be returned. + @param completion PINRemoteImageManagerImageCompletion block to call when image has been fetched from the cache. + */ +- (void)imageFromCacheWithURL:(nonnull NSURL *)url processorKey:(nullable NSString *)processorKey options:(PINRemoteImageManagerDownloadOptions)options completion:(nonnull PINRemoteImageManagerImageCompletion)completion; + +/** + @deprecated + @see synchronousImageFromCacheWithURL:processorKey:options: + + @param cacheKey NSString obtained from @c cacheKeyForURL:processorKey + @param options options will be used to determine if the cached image should be decompressed or PINCachedAnimatedImages should be returned. + + @return A PINRemoteImageManagerResult + */ +- (nonnull PINRemoteImageManagerResult *)synchronousImageFromCacheWithCacheKey:(nonnull NSString *)cacheKey options:(PINRemoteImageManagerDownloadOptions)options __attribute__((deprecated)); + +/** + Directly get an image from the underlying memory cache synchronously. + + @param url NSURL that was used to download image + @param processorKey An optional key to uniquely identify the processor used to post-process the downloaded image. + @param options options will be used to determine if the cached image should be decompressed or PINCachedAnimatedImages should be returned. + + @return A PINRemoteImageManagerResult + */ +- (nonnull PINRemoteImageManagerResult *)synchronousImageFromCacheWithURL:(nonnull NSURL *)url processorKey:(nullable NSString *)processorKey options:(PINRemoteImageManagerDownloadOptions)options; + +/** + Cancel a download. Canceling will only cancel the download if all other downloads are also canceled with their associated UUIDs. + Canceling *does not* guarantee that your completion will not be called. You can use the UUID provided on the result object to verify + the completion you want called is being called. + @see PINRemoteImageCategoryManager + + @param UUID NSUUID of the task to cancel. + */ +- (void)cancelTaskWithUUID:(nonnull NSUUID *)UUID; + +/** + Cancel a download. Canceling will only cancel the download if all other downloads are also canceled with their associated UUIDs. + Canceling *does not* guarantee that your completion will not be called. You can use the UUID provided on the result object to verify + the completion you want called is being called. + @param storeResumeData if YES and the server indicates it supports resuming downloads, downloaded data will be stored in the disk + cache and used to resume the download if the same URL is attempted to be downloaded in the future. + PINRemoteImageBasicCache does not support disk caching, use PINCache. + */ +- (void)cancelTaskWithUUID:(nonnull NSUUID *)UUID storeResumeData:(BOOL)storeResumeData; + +/** + Cancel all tasks. + */ +- (void)cancelAllTasks; + +/** + Cancel all tasks and store resume data if any task has. + */ +- (void)cancelAllTasksAndStoreResumeData:(BOOL)storeResumeData; + +/** + Set the priority of a download task. Since there is only one task per download, the priority of the download task will always be the last priority this method was called with. + + @param priority priority to set on the task. + @param UUID NSUUID of the task to set the priority on. + */ +- (void)setPriority:(PINRemoteImageManagerPriority)priority ofTaskWithUUID:(nonnull NSUUID *)UUID; + +/** + * @abstract set the progress callback on a download task. You can use this to add progress callbacks or remove them for in flight downloads + * + * @param progressImageCallback a PINRemoteImageManagerImageCompletion block to be called with a progress update + * @param UUID NSUUID of the task to set the priority on. + */ +- (void)setProgressImageCallback:(nullable PINRemoteImageManagerImageCompletion)progressImageCallback ofTaskWithUUID:(nonnull NSUUID *)UUID; + +/** + Set retry strategy for all requests + + @param retryStrategyCreationBlock a block which should create new instance of PINRequestRetryStrategy when called. + */ +- (void)setRetryStrategyCreationBlock:(_Nonnull id (^_Nonnull)(void))retryStrategyCreationBlock; + +@property (nonatomic, readonly) _Nonnull id (^_Nonnull retryStrategyCreationBlock)(void); + +@end diff --git a/Source/Classes/include/PINRemoteImage/PINRemoteImageManagerConfiguration.h b/Source/Classes/include/PINRemoteImage/PINRemoteImageManagerConfiguration.h new file mode 100644 index 00000000..20b0746c --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINRemoteImageManagerConfiguration.h @@ -0,0 +1,46 @@ +// +// PINRemoteImageManagerConfiguration.h +// Pods +// +// Created by Ryan Quan on 2/22/19. +// +// + +#import + +#import + +#if PIN_TARGET_IOS +#import +#elif PIN_TARGET_MAC +#import +#endif + +/** A configuration object used to customize a PINRemoteImageManager instance **/ +@interface PINRemoteImageManagerConfiguration : NSObject + +/** The maximum number of concurrent operations. Defaults to NSOperationQueueDefaultMaxConcurrentOperationCount. */ +@property (nonatomic, readwrite, assign) NSUInteger maxConcurrentOperations; + +/** The maximum number of concurrent downloads. Defaults to 10, maximum 65535. */ +@property (nonatomic, readwrite, assign) NSUInteger maxConcurrentDownloads; + +/** The estimated remaining time threshold used to decide to skip progressive rendering. Defaults to 0.1. */ +@property (nonatomic, readwrite, assign) NSTimeInterval estimatedRemainingTimeThreshold; + +/** A bool value indicating whether PINRemoteImage should blur progressive render results */ +@property (nonatomic, readwrite, assign) BOOL shouldBlurProgressive; + +/** A CGSize which indicates the max size PINRemoteImage will render a progressive image. If an image is larger in either dimension, progressive rendering will be skipped */ +@property (nonatomic, readwrite, assign) CGSize maxProgressiveRenderSize; + +/** The minimum BPS to download the highest quality image in a set. */ +@property (nonatomic, readwrite, assign) float highQualityBPSThreshold; + +/** The maximum BPS to download the lowest quality image in a set. */ +@property (nonatomic, readwrite, assign) float lowQualityBPSThreshold; + +/** Whether high quality images should be downloaded when a low quality image is cached if network connectivity has improved. */ +@property (nonatomic, readwrite, assign) BOOL shouldUpgradeLowQualityImages; + +@end diff --git a/Source/Classes/include/PINRemoteImage/PINRemoteImageManagerResult.h b/Source/Classes/include/PINRemoteImage/PINRemoteImageManagerResult.h new file mode 100644 index 00000000..f4ea820a --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINRemoteImageManagerResult.h @@ -0,0 +1,71 @@ +// +// PINRemoteImageManagerResult.h +// Pods +// +// Created by Garrett Moon on 3/9/15. +// +// + +#import + +#import + +#if PIN_TARGET_IOS +#import +#elif PIN_TARGET_MAC +#import +#endif + +/** How the image was fetched. */ +typedef NS_ENUM(NSUInteger, PINRemoteImageResultType) { + /** Returned if no image is returned */ + PINRemoteImageResultTypeNone = 0, + /** Image was fetched from the memory cache */ + PINRemoteImageResultTypeMemoryCache, + /** Image was fetched from the disk cache */ + PINRemoteImageResultTypeCache, + /** Image was downloaded */ + PINRemoteImageResultTypeDownload, + /** Image is progress */ + PINRemoteImageResultTypeProgress, +}; + +@interface PINRemoteImageManagerResult : NSObject + +@property (nonatomic, readonly, strong, nullable) PINImage *image; +@property (nonatomic, readonly, strong, nullable) id alternativeRepresentation; +@property (nonatomic, readonly, assign) NSTimeInterval requestDuration; +@property (nonatomic, readonly, strong, nullable) NSError *error; +@property (nonatomic, readonly, assign) PINRemoteImageResultType resultType; +@property (nonatomic, readonly, strong, nullable) NSUUID *UUID; +@property (nonatomic, readonly, assign) CGFloat renderedImageQuality; +@property (nonatomic, readonly, assign) NSUInteger bytesSavedByResuming; +@property (nonatomic, readonly, strong, nullable) NSURLResponse *response; + ++ (nonnull instancetype)imageResultWithImage:(nullable PINImage *)image + alternativeRepresentation:(nullable id)alternativeRepresentation + requestLength:(NSTimeInterval)requestLength + resultType:(PINRemoteImageResultType)resultType + UUID:(nullable NSUUID *)uuid + response:(nullable NSURLResponse *)response + error:(nullable NSError *)error; + ++ (nonnull instancetype)imageResultWithImage:(nullable PINImage *)image + alternativeRepresentation:(nullable id)alternativeRepresentation + requestLength:(NSTimeInterval)requestLength + resultType:(PINRemoteImageResultType)resultType + UUID:(nullable NSUUID *)uuid + response:(nullable NSURLResponse *)response + error:(nullable NSError *)error + bytesSavedByResuming:(NSUInteger)bytesSavedByResuming; + ++ (nonnull instancetype)imageResultWithImage:(nullable PINImage *)image + alternativeRepresentation:(nullable id)alternativeRepresentation + requestLength:(NSTimeInterval)requestLength + resultType:(PINRemoteImageResultType)resultType + UUID:(nullable NSUUID *)uuid + response:(nullable NSURLResponse *)response + error:(nullable NSError *)error + renderedImageQuality:(CGFloat)renderedImageQuality; + +@end diff --git a/Source/Classes/include/PINRemoteImage/PINRequestRetryStrategy.h b/Source/Classes/include/PINRemoteImage/PINRequestRetryStrategy.h new file mode 100644 index 00000000..448ec8d5 --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINRequestRetryStrategy.h @@ -0,0 +1,28 @@ +// +// PINRequestRetryStrategy.h +// Pods +// +// Created by Hovhannes Safaryan on 9/24/16. +// +// + +#import + +/* + Decide whether request should be retried based on the error. + **/ + +@protocol PINRequestRetryStrategy + +- (BOOL)shouldRetryWithError:(NSError *)error; +- (int)nextDelay; +- (void)incrementRetryCount; +- (int)numberOfRetries; + +@end + +@interface PINRequestExponentialRetryStrategy : NSObject + +- (instancetype)initWithRetryMaxCount:(int)retryMaxCount delayBase:(int)delayBase; + +@end diff --git a/Source/Classes/include/PINRemoteImage/PINURLSessionManager.h b/Source/Classes/include/PINRemoteImage/PINURLSessionManager.h new file mode 100644 index 00000000..308412f0 --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINURLSessionManager.h @@ -0,0 +1,51 @@ +// +// PINURLSessionManager.h +// Pods +// +// Created by Garrett Moon on 6/26/15. +// +// + +#import + +#import + +extern NSErrorDomain _Nonnull const PINURLErrorDomain; + +@protocol PINURLSessionManagerDelegate + +@required +- (void)didReceiveData:(nonnull NSData *)data forTask:(nonnull NSURLSessionTask *)task; + +@optional +- (void)didCollectMetrics:(nonnull NSURLSessionTaskMetrics *)metrics forURL:(nonnull NSURL *)url; +- (void)didReceiveResponse:(nonnull NSURLResponse *)response forTask:(nonnull NSURLSessionTask *)task; +- (void)didReceiveAuthenticationChallenge:(nonnull NSURLAuthenticationChallenge *)challenge forTask:(nullable NSURLSessionTask *)task completionHandler:(nonnull void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler; +- (void)didCompleteTask:(nonnull NSURLSessionTask *)task withError:(nullable NSError *)error; + +@end + +typedef void (^PINURLSessionDataTaskCompletion)(NSURLSessionTask * _Nonnull task, NSError * _Nullable error); + +@interface PINURLSessionManager : NSObject + +- (nonnull instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)configuration; + +- (nonnull NSURLSessionDataTask *)dataTaskWithRequest:(nonnull NSURLRequest *)request + completionHandler:(nonnull PINURLSessionDataTaskCompletion)completionHandler; + +- (nonnull NSURLSessionDataTask *)dataTaskWithRequest:(nonnull NSURLRequest *)request + priority:(PINRemoteImageManagerPriority)priority + completionHandler:(nonnull PINURLSessionDataTaskCompletion)completionHandler; + +- (void)invalidateSessionAndCancelTasks; + +- (void)URLSession:(nonnull NSURLSession *)session task:(nonnull NSURLSessionTask *)task didFinishCollectingMetrics:(nonnull NSURLSessionTaskMetrics *)metrics; + +@property (atomic, weak, nullable) id delegate; + +#if DEBUG +- (void)concurrentDownloads:(void (^_Nullable)(NSUInteger concurrentDownloads))concurrentDownloadsCompletion; +#endif + +@end diff --git a/Source/Classes/include/PINRemoteImage/PINWebPAnimatedImage.h b/Source/Classes/include/PINRemoteImage/PINWebPAnimatedImage.h new file mode 100644 index 00000000..5f3d9567 --- /dev/null +++ b/Source/Classes/include/PINRemoteImage/PINWebPAnimatedImage.h @@ -0,0 +1,19 @@ +// +// PINWebPAnimatedImage.h +// PINRemoteImage +// +// Created by Garrett Moon on 9/14/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import +#import + +#import + +@interface PINWebPAnimatedImage : PINAnimatedImage + +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithAnimatedImageData:(NSData *)animatedImageData NS_DESIGNATED_INITIALIZER; + +@end diff --git a/PINRemoteImage/PINRemoteImage/Info.plist b/Source/Info.plist similarity index 100% rename from PINRemoteImage/PINRemoteImage/Info.plist rename to Source/Info.plist diff --git a/Source/PINRemoteImage.modulemap b/Source/PINRemoteImage.modulemap new file mode 100644 index 00000000..7c739d4d --- /dev/null +++ b/Source/PINRemoteImage.modulemap @@ -0,0 +1,11 @@ +framework module PINRemoteImage { + umbrella header "PINRemoteImage.h" + + textual header "PINRemoteImageMacros.h" + header "PINAnimatedImageView+PINRemoteImage.h" + header "PINButton+PINRemoteImage.h" + header "PINImageView+PINRemoteImage.h" + + export * + module * { export * } +} diff --git a/Source/PrivacyInfo.xcprivacy b/Source/PrivacyInfo.xcprivacy new file mode 100644 index 00000000..7beabeb1 --- /dev/null +++ b/Source/PrivacyInfo.xcprivacy @@ -0,0 +1,23 @@ + + + + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + NSPrivacyCollectedDataTypes + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPITypeReasons + + C56D.1 + + + + + diff --git a/Tests/Info.plist b/Tests/Info.plist new file mode 100644 index 00000000..6c6c23c4 --- /dev/null +++ b/Tests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Tests/Media.xcassets/Contents.json b/Tests/Media.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/Tests/Media.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tests/Media.xcassets/DynamicImage.imageset/Contents.json b/Tests/Media.xcassets/DynamicImage.imageset/Contents.json new file mode 100644 index 00000000..9006b23f --- /dev/null +++ b/Tests/Media.xcassets/DynamicImage.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "filename" : "Light.png", + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "Dark.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tests/Media.xcassets/DynamicImage.imageset/Dark.png b/Tests/Media.xcassets/DynamicImage.imageset/Dark.png new file mode 100644 index 00000000..a55e5145 Binary files /dev/null and b/Tests/Media.xcassets/DynamicImage.imageset/Dark.png differ diff --git a/Tests/Media.xcassets/DynamicImage.imageset/Light.png b/Tests/Media.xcassets/DynamicImage.imageset/Light.png new file mode 100644 index 00000000..68c023f3 Binary files /dev/null and b/Tests/Media.xcassets/DynamicImage.imageset/Light.png differ diff --git a/Tests/NSDate+PINCacheTests.h b/Tests/NSDate+PINCacheTests.h new file mode 100644 index 00000000..e11033d0 --- /dev/null +++ b/Tests/NSDate+PINCacheTests.h @@ -0,0 +1,15 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSDate (PINCacheTests) + +/** Swizzles +[NSDate date] to always return the specified date. */ ++ (void)startMockingDateWithDate:(NSDate *)date; + +/** Stops swizzling +[NSDate date] and returns to original implementation */ ++ (void)stopMockingDate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Tests/NSDate+PINCacheTests.m b/Tests/NSDate+PINCacheTests.m new file mode 100644 index 00000000..1133c2b0 --- /dev/null +++ b/Tests/NSDate+PINCacheTests.m @@ -0,0 +1,50 @@ +#import "NSDate+PINCacheTests.h" + +#import + +static NSDate *PINCacheTestsSwizzedDate = nil; + +@implementation NSDate (PINCacheTests) + ++ (void)startMockingDateWithDate:(NSDate *)date +{ + // If already swizzled, just replace the static date. + BOOL alreadySwizzled = (PINCacheTestsSwizzedDate != nil); + PINCacheTestsSwizzedDate = date; + if (alreadySwizzled) { return; } + + SEL originalSelector = @selector(date); + SEL swizzledSelector = @selector(swizzled_date); + + Method originalMethod = class_getClassMethod(self, originalSelector); + Method swizzledMethod = class_getClassMethod(self, swizzledSelector); + + Class class = object_getClass((id)self); + + if (class_addMethod(class, + originalSelector, + method_getImplementation(swizzledMethod), + method_getTypeEncoding(swizzledMethod))) { + class_replaceMethod(class, + swizzledSelector, + method_getImplementation(originalMethod), + method_getTypeEncoding(originalMethod)); + } else { + method_exchangeImplementations(originalMethod, swizzledMethod); + } +} + ++ (void)stopMockingDate +{ + Method originalMethod = class_getClassMethod(self, @selector(date)); + Method swizzledMethod = class_getClassMethod(self, @selector(swizzled_date)); + method_exchangeImplementations(swizzledMethod, originalMethod); + PINCacheTestsSwizzedDate = nil; +} + ++ (instancetype)swizzled_date +{ + return PINCacheTestsSwizzedDate; +} + +@end diff --git a/Tests/PINAnimatedImage+PINAnimatedImageTesting.h b/Tests/PINAnimatedImage+PINAnimatedImageTesting.h new file mode 100644 index 00000000..82359d53 --- /dev/null +++ b/Tests/PINAnimatedImage+PINAnimatedImageTesting.h @@ -0,0 +1,22 @@ +// +// PINAnimatedImage+PINAnimatedImageTesting.h +// PINRemoteImageTests +// +// Created by Garrett Moon on 10/16/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import +#import + +@interface PINAnimatedImage (PINAnimatedImageTesting) + ++ (NSUInteger)greatestCommonDivisorOfA:(NSUInteger)a andB:(NSUInteger)b; + +@end + +@interface PINAnimatedImageView (PINAnimatedImageViewTesting) + +- (NSUInteger)frameIndexAtPlayHeadPosition:(CFTimeInterval)playHead; + +@end diff --git a/Tests/PINAnimatedImage+PINAnimatedImageTesting.m b/Tests/PINAnimatedImage+PINAnimatedImageTesting.m new file mode 100644 index 00000000..6410d119 --- /dev/null +++ b/Tests/PINAnimatedImage+PINAnimatedImageTesting.m @@ -0,0 +1,9 @@ +// +// PINAnimatedImage+PINAnimatedImageTesting.m +// PINRemoteImageTests +// +// Created by Garrett Moon on 10/16/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +#import "PINAnimatedImage+PINAnimatedImageTesting.h" diff --git a/Tests/PINAnimatedImageTests.swift b/Tests/PINAnimatedImageTests.swift new file mode 100644 index 00000000..5eb4cfe5 --- /dev/null +++ b/Tests/PINAnimatedImageTests.swift @@ -0,0 +1,295 @@ +// +// PINAnimatedImageTests.swift +// PINRemoteImageTests +// +// Created by Garrett Moon on 9/16/17. +// Copyright © 2017 Pinterest. All rights reserved. +// + +import XCTest +import PINRemoteImage + +class PINAnimatedImageTests: XCTestCase, PINRemoteImageManagerAlternateRepresentationProvider { + + override func setUp() { + super.setUp() + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + + func timeoutInterval() -> TimeInterval { + return 30 + } + + // MARK: - Animated Images + func animatedWebPURL() -> URL? { + return URL.init(string: "https://res.cloudinary.com/demo/image/upload/fl_awebp/bored_animation.webp") + } + + func slowAnimatedGIFURL() -> URL? { + return URL.init(string: "https://i.pinimg.com/originals/1d/65/00/1d650041ad356b248139800bc84b7bce.gif") + } + + func nonAnimatedGIFURL() -> URL? { + return URL.init(string: "http://ak-cache.legacy.net/legacy/images/fhlogo/7630fhlogo.gif") + } + + func APNGURL() -> URL? { + return URL.init(string: "https://upload.wikimedia.org/wikipedia/commons/1/14/Animated_PNG_example_bouncing_beach_ball.png") + } + + func nonAPNGURL() -> URL? { + return URL.init(string: "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png") + } + + func testMinimumFrameInterval() { + let expectation = self.expectation(description: "Result should be downloaded") + let imageManager = PINRemoteImageManager.init(sessionConfiguration: nil, alternativeRepresentationProvider: self) + imageManager.downloadImage(with: self.slowAnimatedGIFURL()!) { (result : PINRemoteImageManagerResult) in + guard let animatedData = result.alternativeRepresentation as? Data else { + XCTAssert(false, "alternativeRepresentation should be able to be coerced into data") + return + } + + guard let animatedImage = PINGIFAnimatedImage.init(animatedImageData: animatedData) else { + XCTAssert(false, "could not create GIF image") + return + } + + XCTAssert(animatedImage.frameInterval == 12, "Frame interval should be 12 because each frame is 0.2 seconds long. 60 / 12 = 5; 1 / 5 of a second is 0.2.") + expectation.fulfill() + } + self.waitForExpectations(timeout: self.timeoutInterval(), handler: nil) + } + + func testWebpAnimatedImages() { + let expectation = self.expectation(description: "Result should be downloaded") + let imageManager = PINRemoteImageManager.init(sessionConfiguration: nil, alternativeRepresentationProvider: self) + imageManager.downloadImage(with: self.animatedWebPURL()!) { (result : PINRemoteImageManagerResult) in + XCTAssertNotNil(result.alternativeRepresentation, "alternative representation should be non-nil.") + XCTAssertNil(result.image, "image should not be returned") + + guard let animatedData = result.alternativeRepresentation as? Data else { + XCTAssert(false, "alternativeRepresentation should be able to be coerced into data") + return + } + + guard let animatedImage = PINWebPAnimatedImage.init(animatedImageData: animatedData) else { + XCTAssert(false, "could not create webp image") + return + } + + let frameCount = animatedImage.frameCount + var totalDuration : CFTimeInterval = 0 + XCTAssert(frameCount > 1, "Frame count should be greater than 1") + for frameIdx in 0 ..< frameCount { + XCTAssertNotNil(animatedImage.image(at: UInt(frameIdx), cacheProvider: nil)) + totalDuration += animatedImage.duration(at: UInt(frameIdx)) + } + XCTAssert(animatedImage.totalDuration > 0, "Total duration should be greater than 0") + XCTAssertEqual(totalDuration, animatedImage.totalDuration, "Total duration should be equal to the sum of each frames duration") + + expectation.fulfill() + } + + self.waitForExpectations(timeout: self.timeoutInterval(), handler: nil) + } + + func testGreatestCommonDivisor() { + XCTAssert(PINAnimatedImage.greatestCommonDivisor(ofA: 1, andB: 1) == 1) + XCTAssert(PINAnimatedImage.greatestCommonDivisor(ofA: 2, andB: 4) == 2) + XCTAssert(PINAnimatedImage.greatestCommonDivisor(ofA: 4, andB: 2) == 2) + XCTAssert(PINAnimatedImage.greatestCommonDivisor(ofA: 18, andB: 15) == 3) + XCTAssert(PINAnimatedImage.greatestCommonDivisor(ofA: 42, andB: 56) == 14) + XCTAssert(PINAnimatedImage.greatestCommonDivisor(ofA: 12, andB: 120) == 12) + } + + func alternateRepresentation(with data: Data!, options: PINRemoteImageManagerDownloadOptions = []) -> Any! { + guard let nsdata = data as NSData? else { + return nil + } + if nsdata.pin_isAnimatedWebP() || nsdata.pin_isAnimatedGIF() || nsdata.pin_isAPNG() { + return data + } + return nil + } + + func testIsAnimatedGIF() { + let animatedExpectation = self.expectation(description: "Animated image should be downloaded") + let imageManager = PINRemoteImageManager.init(sessionConfiguration: nil, alternativeRepresentationProvider: self) + imageManager.downloadImage(with: self.slowAnimatedGIFURL()!) { (result : PINRemoteImageManagerResult) in + XCTAssert(result.image == nil) + guard let animatedData = result.alternativeRepresentation as? NSData else { + XCTAssert(false, "alternativeRepresentation should be able to be coerced into data") + return + } + + XCTAssert(animatedData.pin_isGIF() && animatedData.pin_isAnimatedGIF()) + + animatedExpectation.fulfill() + } + + let nonAnimatedExpectation = self.expectation(description: "Non animated image should be downloaded") + imageManager.downloadImage(with: self.nonAnimatedGIFURL()!) { (result : PINRemoteImageManagerResult) in + XCTAssert(result.image != nil && result.alternativeRepresentation == nil) + nonAnimatedExpectation.fulfill() + } + self.waitForExpectations(timeout: self.timeoutInterval(), handler: nil) + } + + func testIsAPNG() { + let animatedExpectation = self.expectation(description: "Animated image should be downloaded") + let imageManager = PINRemoteImageManager.init(sessionConfiguration: nil, alternativeRepresentationProvider: self) + imageManager.downloadImage(with: self.APNGURL()!) { (result : PINRemoteImageManagerResult) in + XCTAssert(result.image == nil) + guard let animatedData = result.alternativeRepresentation as? NSData else { + XCTAssert(false, "alternativeRepresentation should be able to be coerced into data") + return + } + + XCTAssert(animatedData.pin_isAPNG()) + + animatedExpectation.fulfill() + } + + let nonAnimatedExpectation = self.expectation(description: "Non animated image should be downloaded") + imageManager.downloadImage(with: self.nonAPNGURL()!) { (result : PINRemoteImageManagerResult) in + XCTAssert(result.image != nil && result.alternativeRepresentation == nil) + nonAnimatedExpectation.fulfill() + } + self.waitForExpectations(timeout: self.timeoutInterval(), handler: nil) + } + + func testAnimatedImageViewInitializer() { + let animatedExpectation = self.expectation(description: "Animated image should be downloaded") + let imageManager = PINRemoteImageManager.init(sessionConfiguration: nil, alternativeRepresentationProvider: self) + imageManager.downloadImage(with: self.slowAnimatedGIFURL()!) { (result : PINRemoteImageManagerResult) in + XCTAssert(result.image == nil) + guard let animatedData = result.alternativeRepresentation as? NSData else { + XCTAssert(false, "alternativeRepresentation should be able to be coerced into data") + return + } + + XCTAssert(animatedData.pin_isGIF() && animatedData.pin_isAnimatedGIF()) + + DispatchQueue.main.async { + let pinCachedAnimatedImage = PINCachedAnimatedImage(animatedImageData: animatedData as Data) + + let gifImageView = PINAnimatedImageView(animatedImage: pinCachedAnimatedImage!) + XCTAssert(gifImageView.animatedImage?.coverImageReadyCallback != nil) + + animatedExpectation.fulfill() + } + } + + self.waitForExpectations(timeout: self.timeoutInterval(), handler: nil) + } + + func testGIFBytes() { + let animatedExpectation = self.expectation(description: "Animated image should be downloaded") + let imageManager = PINRemoteImageManager.init(sessionConfiguration: nil, alternativeRepresentationProvider: self) + imageManager.downloadImage(with: self.slowAnimatedGIFURL()!) { (result : PINRemoteImageManagerResult) in + XCTAssert(result.image == nil) + guard let animatedData = result.alternativeRepresentation as? NSData else { + XCTAssert(false, "alternativeRepresentation should be able to be coerced into data") + return + } + + XCTAssert(animatedData.pin_isGIF() && animatedData.pin_isAnimatedGIF()) + + let pinCachedAnimatedImage = PINGIFAnimatedImage(animatedImageData: animatedData as Data)! + let bytesSize = UInt32((pinCachedAnimatedImage.image(at: 0, cacheProvider: nil)!.takeUnretainedValue() as CGImage).bytesPerRow) * pinCachedAnimatedImage.height + + XCTAssert(pinCachedAnimatedImage.bytesPerFrame == bytesSize) + + animatedExpectation.fulfill() + } + + self.waitForExpectations(timeout: self.timeoutInterval(), handler: nil) + } + + func testInvalidAnimatedData() { + let data = "AA".data(using: .ascii) + let gifAnimatedImage = PINGIFAnimatedImage(animatedImageData: data) + XCTAssert(gifAnimatedImage == nil) + + let webpAnimatedImage = PINWebPAnimatedImage(animatedImageData: data) + XCTAssert(webpAnimatedImage == nil) + } + + func testRetainCycle() { + weak var weakCachedAnimatedImage : PINCachedAnimatedImage? + autoreleasepool { + let animatedImage = TestAnimatedImage.init() + let cachedAnimatedImage = PINCachedAnimatedImage.init(animatedImage: animatedImage) + weakCachedAnimatedImage = cachedAnimatedImage + } + + // PINCachedAnimatedImage kicks off a block on init which grabs a strong + // reference to itself. Wait for the work to complete. This test would be + // more reliable if we made a separate API for testing to *not* kick off + // the work, but then it wouldn't *really* be testing what we want it to + // test. + sleep(1); + + let cachedAnimatedImage : PINCachedAnimatedImage? = weakCachedAnimatedImage + XCTAssertNil(cachedAnimatedImage) + } + + func testFrameIndex() { + let bundle = Bundle(for: type(of: self)) + let path = bundle.path(forResource: "fireworks", ofType: "gif")! + let gifData = NSData(contentsOfFile: path) + let cachedAnimatedImage = PINCachedAnimatedImage(animatedImageData: gifData! as Data)! + + let gifAnimatedImageView = PINAnimatedImageView(animatedImage: cachedAnimatedImage) + + // Test left bounds + var index = gifAnimatedImageView.frameIndex(atPlayHeadPosition: 0.1) + XCTAssert(index == 0) + + // Test right bounds + index = gifAnimatedImageView.frameIndex(atPlayHeadPosition: 1.1) + XCTAssert(index == 9) + + // Test random index + index = gifAnimatedImageView.frameIndex(atPlayHeadPosition: 0.41) + XCTAssert(index == 4) + } + + @available(iOS 13.0, tvOS 10.0, *) + func testDynamicPlaceholderImages() { + let bundle = Bundle(for: type(of: self)) + let dynamicImage = UIImage(named: "DynamicImage", in: bundle, with: nil) + XCTAssertNotNil(dynamicImage, "Unable to read image") + + let lightTraitCollection = UITraitCollection(traitsFrom: [.current, .init(userInterfaceStyle: .light)]) + let darkTraitCollection = UITraitCollection(traitsFrom: [.current, .init(userInterfaceStyle: .dark)]) + + let lightImage = dynamicImage?.imageAsset?.image(with: lightTraitCollection).cgImage + let darkImage = dynamicImage?.imageAsset?.image(with: darkTraitCollection).cgImage + + let imageView = PINAnimatedImageView() + imageView.image = dynamicImage + + let layer = CALayer() + + imageView.overrideUserInterfaceStyle = .light + if #available(iOS 17.0, *) { + imageView.updateTraitsIfNeeded() + } + imageView.display(layer) + XCTAssert(lightImage === (layer.contents as! CGImage), "Placeholder image should be using light mode version") + + imageView.overrideUserInterfaceStyle = .dark + if #available(iOS 17.0, *) { + imageView.updateTraitsIfNeeded() + } + imageView.display(layer) + XCTAssert(darkImage === (layer.contents as! CGImage), "Placeholder image should be using dark mode version") + } +} diff --git a/Tests/PINRemoteImageTests-Bridging-Header.h b/Tests/PINRemoteImageTests-Bridging-Header.h new file mode 100644 index 00000000..c6510991 --- /dev/null +++ b/Tests/PINRemoteImageTests-Bridging-Header.h @@ -0,0 +1,6 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import "PINAnimatedImage+PINAnimatedImageTesting.h" +#import "TestAnimatedImage.h" diff --git a/Tests/PINRemoteImageTests.m b/Tests/PINRemoteImageTests.m new file mode 100644 index 00000000..4d56e181 --- /dev/null +++ b/Tests/PINRemoteImageTests.m @@ -0,0 +1,1713 @@ +// +// PINRemoteImage_Tests.m +// PINRemoteImage Tests +// +// Created by Garrett Moon on 11/6/14. +// Copyright (c) 2014 Garrett Moon. All rights reserved. +// + +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import "NSDate+PINCacheTests.h" +#import "PINResume.h" +#import "PINRemoteImageDownloadTask.h" +#import "PINSpeedRecorder.h" + +#import + +static BOOL requestRetried = NO; +extern NSString * const PINRemoteImageWeakTaskKey; +static NSInteger canceledCount = 0; + +static inline BOOL PINImageAlphaInfoIsOpaque(CGImageAlphaInfo info) { + switch (info) { + case kCGImageAlphaNone: + case kCGImageAlphaNoneSkipLast: + case kCGImageAlphaNoneSkipFirst: + return YES; + default: + return NO; + } +} + +@interface PINRemoteImageDownloadTask (Private) + +- (void)scheduleDownloadWithRequest:(NSURLRequest *)request + resume:(PINResume *)resume + skipRetry:(BOOL)skipRetry + priority:(PINRemoteImageManagerPriority)priority + isRetry:(BOOL)isRetry + completionHandler:(PINRemoteImageManagerDataCompletion)completionHandler; + +@end + +@interface PINRemoteImageDownloadTask (Swizzled) + +- (void)swizzled_scheduleDownloadWithRequest:(NSURLRequest *)request + resume:(PINResume *)resume + skipRetry:(BOOL)skipRetry + priority:(PINRemoteImageManagerPriority)priority + isRetry:(BOOL)isRetry + completionHandler:(PINRemoteImageManagerDataCompletion)completionHandler; + +@end + +@interface PINImage (Private) + ++ (nullable PINImage *)pin_decodedImageWithCGImageRef:(nonnull CGImageRef)imageRef orientation:(UIImageOrientation) orientation; + +@end + +#if DEBUG + +@interface PINRemoteImageWeakTask : NSObject + +@property (nonatomic, readonly, weak) PINRemoteImageTask *task; + +@end + +@interface PINRemoteImageManager () + +@property (nonatomic, strong) PINURLSessionManager *sessionManager; +@property (nonatomic, readonly) NSUInteger totalDownloads; +@property (nonatomic, strong) NSMapTable *UUIDToTask; + +- (NSString *)resumeCacheKeyForURL:(NSURL *)url; + +@end + +@interface PINRemoteImageManager (Swizzled) + +- (void)swizzled_cancelTaskWithUUID:(nonnull NSUUID *)UUID storeResumeData:(BOOL)storeResumeData; + +@end + +@interface PINURLSessionManager () + +@property (nonatomic, strong) NSURLSession *session; +- (void)storeTimeToFirstByte:(NSTimeInterval)timeToFirstByte forHost:(NSString *)host; + +@end +#endif + +@interface PINRemoteImage_Tests : XCTestCase + +@property (nonatomic, strong) PINRemoteImageManager *imageManager; +@property (nonatomic, strong) NSMutableData *data; +@property (nonatomic, strong) NSURLSessionTask *task; +@property (nonatomic, strong) PINRemoteImageDownloadTask *firstDownloadTask; +@property (nonatomic, strong) PINRemoteImageDownloadTask *secondDownloadTask; +@property (nonatomic, strong) NSError *error; +@property (nonatomic, strong) dispatch_semaphore_t semaphore; +@property (nonatomic, strong) dispatch_semaphore_t sessionDidCompleteDelegateSemaphore; + +@end + +@interface PINSpeedRecorder () + +- (void)resetMeasurements; +- (void)updateSpeedsForHost:(NSString *)host bytesPerSecond:(float)bytesPerSecond startAdjustedBytesPerSecond:(float)startAdjustedBytesPerSecond timeToFirstByte:(float)timeToFirstByte; + +@end + +@implementation PINRemoteImage_Tests + +- (NSTimeInterval)timeoutTimeInterval { + return 30.0; +} + +- (dispatch_time_t)timeoutWithInterval:(NSTimeInterval)interval { + return dispatch_time(DISPATCH_TIME_NOW, (int64_t)(interval * NSEC_PER_SEC)); +} + +- (dispatch_time_t)timeout { + return [self timeoutWithInterval:[self timeoutTimeInterval]]; +} + +- (NSURL *)GIFURL +{ + return [NSURL URLWithString:@"https://i.pinimg.com/originals/90/f5/77/90f577fc6abcd24f9a5f9f55b2d7482b.jpg"]; +} + +- (NSURL *)emptyURL +{ + return [NSURL URLWithString:@""]; +} + +- (NSURL *)fourZeroFourURL +{ + return [NSURL URLWithString:@"https://google.com/404"]; +} + +- (NSURL *)headersURL +{ + return [NSURL URLWithString:@"https://httpbin.org/headers"]; +} + +- (NSURL *)JPEGURL_Small +{ + return [NSURL URLWithString:@"https://i.pinimg.com/345x/1b/bc/c2/1bbcc264683171eb3815292d2f546e92.jpg"]; +} + +- (NSURL *)JPEGURL_Medium +{ + return [NSURL URLWithString:@"https://i.pinimg.com/600x/1b/bc/c2/1bbcc264683171eb3815292d2f546e92.jpg"]; +} + +- (NSURL *)JPEGURL_Large +{ + return [NSURL URLWithString:@"https://i.pinimg.com/736x/1b/bc/c2/1bbcc264683171eb3815292d2f546e92.jpg"]; +} + +- (NSURL *)JPEGURL +{ + return [self JPEGURL_Medium]; +} + +- (NSURL *)BASE64URL +{ + return [NSURL URLWithString:@"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD///+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4Ug9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC"]; +} + +- (NSURL *)transparentPNGURL +{ + return [NSURL URLWithString:@"https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png"]; +} + +- (NSURL *)nonTransparentWebPURL +{ + return [NSURL URLWithString:@"https://www.gstatic.com/webp/gallery/5.webp"]; +} + +- (NSURL *)transparentWebPURL +{ + return [NSURL URLWithString:@"https://www.gstatic.com/webp/gallery3/4_webp_ll.webp"]; +} + +- (NSURL *)grayscalePNGURL +{ + return [NSURL URLWithString:@"https://upload.wikimedia.org/wikipedia/commons/f/fa/Grayscale_8bits_palette_sample_image.png"]; +} + +- (NSURL *)veryLongURL +{ + return [NSURL URLWithString:@"https://loremflickr.com/200/301?longarg=helloMomHowAreYouDoing.IamFineJustMovedToLiveWithANiceChapWeTravelTogetherInHisBlueBoxThroughSpaceAndTimeMaybeYouveMetHimAlready.YesterdayWeMetACultureOfPeopleWithTentaclesWhoSingWithAVeryCelestialVoice.SoGood.SeeYouSoon.MaybeYesterday.WhoKnows.XOXO"]; +} + +- (NSURL *)progressiveURL +{ + return [NSURL URLWithString:@"https://performancedemo.vir2al.ch/assets/img/progressive/thumb/spiez_sunset.jpg"]; +} + +- (NSURL *)progressiveURL2 +{ + return [NSURL URLWithString:@"https://performancedemo.vir2al.ch/assets/img/baseline/thumb/balkon.jpg"]; +} + +- (NSArray *)bigURLs +{ + static dispatch_once_t onceToken; + static NSArray *bigURLs; + dispatch_once(&onceToken, ^{ + bigURLs = @[[NSURL URLWithString:@"https://images.unsplash.com/photo-1483388381485-344c3a9ded7f"], + [NSURL URLWithString:@"https://images.unsplash.com/photo-1483279745275-2a5d5a1074d2"], + [NSURL URLWithString:@"https://images.unsplash.com/photo-1483127140828-af66a3429184"], + [NSURL URLWithString:@"https://images.unsplash.com/photo-1482160310982-3adf8b38daef"], + ]; + }); + + return bigURLs; +} + +- (NSURL *)imageFrom404URL +{ + NSString *base64EncodedUrl = @"aHR0cHM6Ly9pLnl0aW1nLmNvbS92aS9PRzlRbW9jNGVZcy9tcWRlZmF1bHQuanBn"; + NSData *nsdataFromBase64String = [[NSData alloc] initWithBase64EncodedString:base64EncodedUrl options:0]; + NSString *base64Decoded = [[NSString alloc] initWithData:nsdataFromBase64String encoding:NSUTF8StringEncoding]; + return [[NSURL alloc] initWithString:base64Decoded]; +} + +#pragma mark - + +- (void)didReceiveData:(NSData *)data forTask:(NSURLSessionTask *)task +{ + self.task = task; + // Used for DownloadTaskWhenReDownload test + if (self.semaphore) { + PINRemoteImageWeakTask *weakTask = [NSURLProtocol propertyForKey:PINRemoteImageWeakTaskKey inRequest:task.originalRequest]; + PINRemoteImageTask *task = (PINRemoteImageDownloadTask *)weakTask.task; + if (!self.firstDownloadTask) { + self.firstDownloadTask = (PINRemoteImageDownloadTask *)task; + dispatch_semaphore_signal(self.semaphore); + } + if (self.firstDownloadTask && self.firstDownloadTask != task && !self.secondDownloadTask) { + self.secondDownloadTask = (PINRemoteImageDownloadTask *)task; + dispatch_semaphore_signal(self.semaphore); + } + } +} + +- (void)didCompleteTask:(NSURLSessionTask *)task withError:(NSError *)error +{ + self.task = task; + self.error = error; + // Used for URLSessionDidCompleteDelegate test + if (self.sessionDidCompleteDelegateSemaphore) { + dispatch_semaphore_signal(self.sessionDidCompleteDelegateSemaphore); + } +} + +- (void)setUp +{ + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.imageManager = [[PINRemoteImageManager alloc] init]; + [self.imageManager.cache removeAllObjects]; +} + +- (void)tearDown +{ + // Put teardown code here. This method is called after the invocation of each test method in the class. + //clear disk cache + self.imageManager = nil; + [[PINSpeedRecorder sharedRecorder] setCurrentBytesPerSecond:-1]; + [[PINSpeedRecorder sharedRecorder] resetMeasurements]; + + if (self.semaphore) { + self.semaphore = nil; + self.firstDownloadTask = nil; + self.secondDownloadTask = nil; + } + if (self.sessionDidCompleteDelegateSemaphore) { + self.sessionDidCompleteDelegateSemaphore = nil; + } + [super tearDown]; +} + +- (void)testGIFDownload +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Download animatedImage"]; + [self.imageManager downloadImageWithURL:[self GIFURL] + options:PINRemoteImageManagerDownloadOptionsNone + completion:^(PINRemoteImageManagerResult *result) + { + UIImage *outImage = result.image; + id outAnimatedImage = result.alternativeRepresentation; + + XCTAssert(outAnimatedImage && [outAnimatedImage isKindOfClass:[PINCachedAnimatedImage class]], @"Failed downloading animatedImage or animatedImage is not a PINCachedAnimatedImage."); + XCTAssert(outImage == nil, @"Image is not nil."); + + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testInitWithNilConfiguration +{ + self.imageManager = [[PINRemoteImageManager alloc] initWithSessionConfiguration:nil]; + XCTAssertNotNil(self.imageManager.sessionManager.session.configuration); +} + +- (void)testInitWithConfiguration +{ + NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; + configuration.HTTPAdditionalHeaders = @{ @"Authorization" : @"Pinterest 123456" }; + self.imageManager = [[PINRemoteImageManager alloc] initWithSessionConfiguration:configuration]; + XCTAssert([self.imageManager.sessionManager.session.configuration.HTTPAdditionalHeaders isEqualToDictionary:@{ @"Authorization" : @"Pinterest 123456" }]); +} + +- (void)testSessionConfigurationOfHTTPMaximumConnectionsPerHost +{ + { + // User has custom `HTTPMaximumConnectionsPerHost` + NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; + configuration.HTTPMaximumConnectionsPerHost = 5; + self.imageManager = [[PINRemoteImageManager alloc] initWithSessionConfiguration:configuration]; + NSURLSessionConfiguration *sessionManagerConfiguration = self.imageManager.sessionManager.session.configuration; + XCTAssert(configuration.HTTPMaximumConnectionsPerHost == sessionManagerConfiguration.HTTPMaximumConnectionsPerHost); + } + + { + // Using image manager provided `HTTPMaximumConnectionsPerHost` value + self.imageManager = [[PINRemoteImageManager alloc] initWithSessionConfiguration:nil]; + NSURLSessionConfiguration *sessionManagerConfiguration = self.imageManager.sessionManager.session.configuration; + XCTAssert(sessionManagerConfiguration.HTTPMaximumConnectionsPerHost == PINRemoteImageHTTPMaximumConnectionsPerHost); + } +} + +- (void)testURLSessionManagerDeallocated +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"URLSessionManager should be deallocated"]; + __block __weak PINURLSessionManager *sessionManager = nil; + dispatch_async(dispatch_get_main_queue(), ^{ + PINRemoteImageManager *manager = [[PINRemoteImageManager alloc] initWithSessionConfiguration:nil]; + sessionManager = manager.sessionManager; + }); + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + XCTAssert(sessionManager == nil); + [expectation fulfill]; + }); + + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testCustomHeaderIsAddedToImageRequests +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Custom header was added to image request"]; + NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; + configuration.HTTPAdditionalHeaders = @{ @"X-Custom-Header" : @"Custom Header Value" }; + self.imageManager = [[PINRemoteImageManager alloc] initWithSessionConfiguration:configuration]; + self.imageManager.sessionManager.delegate = self; + + //sleep for a moment so values have a chance to asynchronously set. + usleep(10000); + + [self.imageManager downloadImageWithURL:[self headersURL] + options:PINRemoteImageManagerDownloadOptionsNone + completion:^(PINRemoteImageManagerResult *result) + { + NSDictionary *headers = [self.task.currentRequest allHTTPHeaderFields]; + + XCTAssert([headers[@"X-Custom-Header"] isEqualToString:@"Custom Header Value"]); + + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testImageRequestIgnoresLocalData +{ + XCTestExpectation *cacheExpectation = [self expectationWithDescription:@"Verify cache policy of request"]; + XCTestExpectation *setRequestConfigExpectation = [self expectationWithDescription:@"Verify request configuration is set"]; + + self.imageManager = [[PINRemoteImageManager alloc] initWithSessionConfiguration:nil]; + self.imageManager.sessionManager.delegate = self; + + [self.imageManager setRequestConfiguration:^NSURLRequest * _Nonnull(NSURLRequest * _Nonnull request) { + XCTAssertEqual(request.cachePolicy, NSURLRequestReloadIgnoringLocalCacheData); + [cacheExpectation fulfill]; + return request; + } completion:^{ + [setRequestConfigExpectation fulfill]; + }]; + + [self waitForExpectations:@[setRequestConfigExpectation] timeout:[self timeoutTimeInterval]]; + + [self.imageManager downloadImageWithURL:[self headersURL] + options:PINRemoteImageManagerDownloadOptionsIgnoreCache + completion:nil]; + + [self waitForExpectations:@[cacheExpectation] timeout:[self timeoutTimeInterval]]; +} + +- (void)testRequestConfigurationIsUsedForImageRequest +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Requestion configuration block was called image request"]; + NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; + configuration.HTTPAdditionalHeaders = @{ @"X-Custom-Header" : @"Custom Header Value" }; + + self.imageManager = [[PINRemoteImageManager alloc] initWithSessionConfiguration:configuration]; + [self.imageManager setRequestConfiguration:^NSURLRequest * _Nonnull(NSURLRequest * _Nonnull request) { + NSMutableURLRequest *mutableRequest = [request mutableCopy]; + [mutableRequest setValue:@"Custom Header 2 Value" forHTTPHeaderField:@"X-Custom-Header-2"]; + return mutableRequest; + }]; + + //sleep for a moment so values have a chance to asynchronously set. + usleep(10000); + + self.imageManager.sessionManager.delegate = self; + [self.imageManager downloadImageWithURL:[self headersURL] + options:PINRemoteImageManagerDownloadOptionsNone + completion:^(PINRemoteImageManagerResult *result) + { + NSDictionary *headers = [self.task.currentRequest allHTTPHeaderFields]; + XCTAssert([headers[@"X-Custom-Header"] isEqualToString:@"Custom Header Value"]); + XCTAssert([headers[@"X-Custom-Header-2"] isEqualToString:@"Custom Header 2 Value"]); + + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testResponseHeadersReturned +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Headers returned in image download result"]; + [self.imageManager downloadImageWithURL:[self JPEGURL] completion:^(PINRemoteImageManagerResult * _Nonnull result) { + NSDictionary *headers = [(NSHTTPURLResponse *)result.response allHeaderFields]; + XCTAssert(headers != nil, @"Expected headers back"); + + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testSkipPINAnimatedImageDownload +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Download animated image"]; + [self.imageManager downloadImageWithURL:[self GIFURL] + options:PINRemoteImageManagerDisallowAlternateRepresentations + completion:^(PINRemoteImageManagerResult *result) + { + UIImage *outImage = result.image; + id outAnimatedImage = result.alternativeRepresentation; + + XCTAssert(outImage && [outImage isKindOfClass:[UIImage class]], @"Failed downloading image or image is not a UIImage."); + XCTAssert(outAnimatedImage == nil, @"Animated image is not nil."); + + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testIgnoreCache +{ + [self.imageManager downloadImageWithURL:[self JPEGURL] completion:nil]; + [self waitForImageWithURLToBeCached:[self JPEGURL]]; + + XCTestExpectation *expectation = [self expectationWithDescription:@"Download ignoring cache"]; + [self.imageManager downloadImageWithURL:[self JPEGURL] + options:PINRemoteImageManagerDownloadOptionsIgnoreCache + completion:^(PINRemoteImageManagerResult *result) + { + XCTAssert(result.resultType == PINRemoteImageResultTypeDownload, @"Image was fetched from cache"); + + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testJPEGDownload +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Downloading JPEG image"]; + [self.imageManager downloadImageWithURL:[self JPEGURL] + options:PINRemoteImageManagerDownloadOptionsNone + completion:^(PINRemoteImageManagerResult *result) + { + UIImage *outImage = result.image; + id outAnimatedImage = result.alternativeRepresentation; + + XCTAssert(outImage && [outImage isKindOfClass:[UIImage class]], @"Failed downloading image or image is not a UIImage."); + XCTAssert(outAnimatedImage == nil, @"Animated image is not nil."); + + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testBase64 +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Decoding base64 image"]; + [self.imageManager downloadImageWithURL:[self BASE64URL] + options:PINRemoteImageManagerDownloadOptionsNone + completion:^(PINRemoteImageManagerResult *result) + { + UIImage *outImage = result.image; + PINCachedAnimatedImage *outAnimatedImage = result.alternativeRepresentation; + + XCTAssert(outImage && [outImage isKindOfClass:[UIImage class]], @"Failed downloading image or image is not a UIImage."); + XCTAssert(CGSizeEqualToSize(outImage.size, CGSizeMake(16,16)), @"Failed decoding image, image size is wrong."); + XCTAssert(outAnimatedImage == nil, @"Animated image is not nil."); + + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testHTTPResponse404WithData +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"image from 404 response should set correctly"]; + PINRemoteImageManager *manager = [[PINRemoteImageManager alloc] init]; + NSURL *url = [self imageFrom404URL]; + [manager downloadImageWithURL:url completion:^(PINRemoteImageManagerResult * _Nonnull result) { + XCTAssertNotNil(result.image); + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:^(NSError * _Nullable error) { + XCTAssertNil(error); + }]; +} + +- (void)testErrorOnNilURLDownload +{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnonnull" + XCTestExpectation *expectation = [self expectationWithDescription:@"Error on nil image url download"]; + [self.imageManager downloadImageWithURL:nil + options:PINRemoteImageManagerDownloadOptionsNone + completion:^(PINRemoteImageManagerResult *result) +#pragma clang diagnostic pop + { + NSError *outError = result.error; + + XCTAssert([outError.domain isEqualToString:NSURLErrorDomain]); + XCTAssert(outError.code == NSURLErrorUnsupportedURL); + XCTAssert([outError.localizedDescription isEqualToString:@"unsupported URL"]); + + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testErrorOnEmptyURLDownload +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Error on empty image url download"]; + [self.imageManager downloadImageWithURL:[self emptyURL] + options:PINRemoteImageManagerDownloadOptionsNone + completion:^(PINRemoteImageManagerResult *result) + { + NSError *outError = result.error; + + XCTAssert([outError.domain isEqualToString:NSURLErrorDomain]); + XCTAssert(outError.code == NSURLErrorUnsupportedURL); + // iOS8 (and presumably 10.10) returns NSURLErrorUnsupportedURL which means the HTTP NSURLProtocol does not accept it + NSArray *validErrorMessages = @[ @"unsupported URL", @"The operation couldn’t be completed. (NSURLErrorDomain error -1002.)"]; + XCTAssert([validErrorMessages containsObject:outError.localizedDescription], @"%@", outError.localizedDescription); + + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testErrorOn404Response +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Error on 404 response"]; + [self.imageManager downloadImageWithURL:[self fourZeroFourURL] + options:PINRemoteImageManagerDownloadOptionsNone + completion:^(PINRemoteImageManagerResult *result) + { + NSError *outError = result.error; + + XCTAssert([outError.domain isEqualToString:PINURLErrorDomain]); + XCTAssert(outError.code == 404); + + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testDecoding +{ + dispatch_group_t group = dispatch_group_create(); + __block UIImage *outImageDecoded = nil; + __block UIImage *outImageEncoded = nil; + PINRemoteImageManager *encodedManager = [[PINRemoteImageManager alloc] init]; + + dispatch_group_enter(group); + [self.imageManager downloadImageWithURL:[self JPEGURL] + options:PINRemoteImageManagerDownloadOptionsNone + completion:^(PINRemoteImageManagerResult *result) + { + outImageDecoded = result.image; + dispatch_group_leave(group); + }]; + + dispatch_group_wait(group, DISPATCH_TIME_FOREVER); + + dispatch_group_enter(group); + [encodedManager downloadImageWithURL:[self JPEGURL] + options:PINRemoteImageManagerDownloadOptionsSkipDecode + completion:^(PINRemoteImageManagerResult *result) + { + outImageEncoded = result.image; + dispatch_group_leave(group); + }]; + + dispatch_group_wait(group, DISPATCH_TIME_FOREVER); + + CFTimeInterval before = CACurrentMediaTime(); + [self drawImage:outImageEncoded]; + CFTimeInterval after = CACurrentMediaTime(); + CFTimeInterval encodedDrawTime = after - before; + + before = CACurrentMediaTime(); + [self drawImage:outImageDecoded]; + after = CACurrentMediaTime(); + CFTimeInterval decodedDrawTime = after - before; + + XCTAssert(outImageEncoded && [outImageEncoded isKindOfClass:[UIImage class]], @"Failed downloading image or image is not a UIImage."); + XCTAssert(outImageDecoded && [outImageDecoded isKindOfClass:[UIImage class]], @"Failed downloading image or image is not a UIImage."); + XCTAssert(encodedDrawTime / decodedDrawTime > 2, @"Drawing decoded image should be much faster"); +} + +- (void)drawImage:(UIImage *)image +{ + UIGraphicsBeginImageContext(image.size); + + [image drawAtPoint:CGPointZero]; + + UIGraphicsEndImageContext(); +} + +- (void)waitForImageWithURLToBeCached:(NSURL *)URL +{ + NSString *key = [self.imageManager cacheKeyForURL:URL processorKey:nil]; + for (NSUInteger idx = 0; idx < 100; idx++) { + if ([[self.imageManager cache] objectExistsForKey:key]) { + break; + } + if (idx == 99) { + XCTAssert(NO, @"image never set to cache."); + } + usleep(50000); + } +} + +- (void)testTransparentWebPDownload +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Download transparent WebP image"]; + [self.imageManager downloadImageWithURL:[self transparentWebPURL] + options:PINRemoteImageManagerDownloadOptionsNone + completion:^(PINRemoteImageManagerResult *result) + { + XCTAssert(result.error == nil, @"error is non-nil: %@", result.error); + + UIImage *outImage = result.image; + id outAnimatedImage = result.alternativeRepresentation; + + XCTAssert(outImage && [outImage isKindOfClass:[UIImage class]], @"Failed downloading image or image is not a UIImage."); + + CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(outImage.CGImage); + BOOL opaque = alphaInfo == kCGImageAlphaNone || alphaInfo == kCGImageAlphaNoneSkipFirst || alphaInfo == kCGImageAlphaNoneSkipLast; + + XCTAssert(opaque == NO, @"transparent WebP image is opaque."); + XCTAssert(outAnimatedImage == nil, @"Animated image is not nil."); + + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testNonTransparentWebPDownload +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Download non transparent WebP image"]; + [self.imageManager downloadImageWithURL:[self nonTransparentWebPURL] + options:PINRemoteImageManagerDownloadOptionsNone + completion:^(PINRemoteImageManagerResult *result) + { + UIImage *outImage = result.image; + id outAnimatedImage = result.alternativeRepresentation; + + XCTAssert(outImage && [outImage isKindOfClass:[UIImage class]], @"Failed downloading image or image is not a UIImage."); + + CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(outImage.CGImage); + BOOL opaque = alphaInfo == kCGImageAlphaNone || alphaInfo == kCGImageAlphaNoneSkipFirst || alphaInfo == kCGImageAlphaNoneSkipLast; + + XCTAssert(opaque == YES, @"non transparent WebP image is not opaque."); + XCTAssert(outAnimatedImage == nil, @"Animated image is not nil."); + + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testPrefetchImage +{ + id key = [self.imageManager cacheKeyForURL:[self JPEGURL] processorKey:nil]; + + id object = [[self.imageManager cache] objectFromMemoryForKey:key]; + XCTAssert(object == nil, @"image should not be in cache"); + + [self.imageManager prefetchImageWithURL:[self JPEGURL]]; + + XCTestExpectation *expectation = [self expectationWithDescription:@"image was prefetched into cache"]; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + while ([[self.imageManager cache] objectFromMemoryForKey:key] == nil) { + usleep(10000); + } + [expectation fulfill]; + }); + + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testUIImageView +{ + XCTestExpectation *imageSetExpectation = [self expectationWithDescription:@"imageView did not have image set"]; + UIImageView *imageView = [[UIImageView alloc] init]; + __weak UIImageView *weakImageView = imageView; + [imageView pin_setImageFromURL:[self JPEGURL] + completion:^(PINRemoteImageManagerResult *result) + { + if (weakImageView.image) + [imageSetExpectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testPINAnimatedImageView +{ + XCTestExpectation *imageSetExpectation = [self expectationWithDescription:@"animatedImageView did not have animated image set"]; + PINAnimatedImageView *imageView = [[PINAnimatedImageView alloc] init]; + __weak PINAnimatedImageView *weakImageView = imageView; + [imageView pin_setImageFromURL:[self GIFURL] + completion:^(PINRemoteImageManagerResult *result) + { + if (weakImageView.animatedImage) + [imageSetExpectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testEarlyReturn +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Download JPEG image"]; + [self.imageManager downloadImageWithURL:[self JPEGURL] completion:^(PINRemoteImageManagerResult *result) { + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; + + // callback can occur *before* image is stored in cache this is an optimization to avoid waiting on the cache to write. + // So, wait until it's actually in the cache. + [self waitForImageWithURLToBeCached:[self JPEGURL]]; + + __block UIImage *image = nil; + [self.imageManager downloadImageWithURL:[self JPEGURL] completion:^(PINRemoteImageManagerResult *result) { + image = result.image; + }]; + XCTAssert(image != nil, @"image callback did not occur synchronously."); +} + +- (void)testload +{ + srand([[NSDate date] timeIntervalSince1970]); + dispatch_group_t group = dispatch_group_create(); + __block NSInteger count = 0; + const NSInteger numIntervals = 10000; + NSLock *countLock = [[NSLock alloc] init]; + for (NSUInteger idx = 0; idx < numIntervals; idx++) { + dispatch_group_enter(group); + NSURL *url = nil; + if (rand() % 2 == 0) { + url = [self JPEGURL]; + } else { + url = [self GIFURL]; + } + [self.imageManager downloadImageWithURL:url + options:PINRemoteImageManagerDownloadOptionsNone + completion:^(PINRemoteImageManagerResult *result) + { + [countLock lock]; + count++; + XCTAssert(count <= numIntervals, @"callback called too many times"); + [countLock unlock]; + XCTAssert((result.image && !result.alternativeRepresentation) || (result.alternativeRepresentation && !result.image), @"image or alternativeRepresentation not downloaded"); + if (rand() % 2) { + [[self.imageManager cache] removeObjectForKey:[self.imageManager cacheKeyForURL:url processorKey:nil]]; + } + dispatch_group_leave(group); + }]; + } + XCTAssert(dispatch_group_wait(group, [self timeoutWithInterval:100]) == 0, @"Group timed out."); +} + +- (void)testInvalidObject +{ + NSString * const kPINRemoteImageDiskCacheName = @"PINRemoteImageManagerCache"; + NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]; + + PINDiskCache *tempDiskCache = [[PINDiskCache alloc] initWithName:kPINRemoteImageDiskCacheName rootPath:cachePath serializer:^NSData * _Nonnull(id _Nonnull object, NSString * _Nonnull key) { + return [NSKeyedArchiver archivedDataWithRootObject:object requiringSecureCoding:NO error:nil]; + } deserializer:^id _Nonnull(NSData * _Nonnull data, NSString * _Nonnull key) { + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data error:nil]; + unarchiver.requiresSecureCoding = NO; + return [unarchiver decodeObjectForKey:NSKeyedArchiveRootObjectKey]; + }]; + + [tempDiskCache setObject:@"invalid" forKey:[self.imageManager cacheKeyForURL:[self JPEGURL] processorKey:nil]]; + + XCTestExpectation *expectation = [self expectationWithDescription:@"Download JPEG image"]; + [self.imageManager downloadImageWithURL:[self JPEGURL] completion:^(PINRemoteImageManagerResult *result) { + UIImage *image = result.image; + + XCTAssert([image isKindOfClass:[UIImage class]], @"image should be UIImage"); + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; + +} + +- (void)testImageFromCacheReturnsNilErrorForCacheMiss +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Image from cache"]; + + [self.imageManager imageFromCacheWithURL:[self JPEGURL] processorKey:nil options:PINRemoteImageManagerDownloadOptionsNone completion:^(PINRemoteImageManagerResult * _Nonnull result) { + XCTAssert(result.image == nil, @"Image was found in cache"); + XCTAssert(result.error == nil, @"Error was returned in cache miss"); + + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testProcessingLoad +{ + dispatch_group_t group = dispatch_group_create(); + + __block UIImage *image = nil; + const NSUInteger numIntervals = 1000; + __block NSInteger processCount = 0; + __block UIImage *processedImage = nil; + NSLock *processCountLock = [[NSLock alloc] init]; + for (NSUInteger idx = 0; idx < numIntervals; idx++) { + dispatch_group_enter(group); + [self.imageManager downloadImageWithURL:[self JPEGURL] options:PINRemoteImageManagerDownloadOptionsNone + processorKey:@"process" + processor:^UIImage *(PINRemoteImageManagerResult *result, NSUInteger *cost) + { + [processCountLock lock]; + processCount++; + [processCountLock unlock]; + + UIImage *inputImage = result.image; + XCTAssert(inputImage, @"no input image"); + UIGraphicsBeginImageContextWithOptions(inputImage.size, NO, 0); + CGContextRef context = UIGraphicsGetCurrentContext(); + + CGRect destRect = CGRectMake(0, 0, inputImage.size.width, inputImage.size.height); + [[UIColor clearColor] set]; + CGContextFillRect(context, destRect); + + CGRect pathRect = CGRectMake(0, 0, inputImage.size.width, inputImage.size.height); + UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:pathRect + cornerRadius:MIN(inputImage.size.width, inputImage.size.height) / 2.0]; + CGContextAddPath(context, path.CGPath); + CGContextClosePath(context); + CGContextClip(context); + + [inputImage drawInRect:CGRectMake(0, 0, inputImage.size.width, inputImage.size.height)]; + + UIImage *roundedImage = nil; + roundedImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + processedImage = roundedImage; + + return roundedImage; + } + completion:^(PINRemoteImageManagerResult *result) + { + image = result.image; + XCTAssert([image isKindOfClass:[UIImage class]] && image == processedImage, @"result image is not a UIImage"); + dispatch_group_leave(group); + }]; + } + + XCTAssert(dispatch_group_wait(group, [self timeout]) == 0, @"Group timed out."); + + XCTAssert(processCount <= 1, @"image processed too many times"); + XCTAssert([image isKindOfClass:[UIImage class]], @"result image is not a UIImage"); +} + +- (void)testNumberDownloads +{ + dispatch_group_t group = dispatch_group_create(); + + __block UIImage *image = nil; + const NSUInteger numIntervals = 1000; + + for (NSUInteger idx = 0; idx < numIntervals; idx++) { + dispatch_group_enter(group); + [self.imageManager downloadImageWithURL:[self JPEGURL] completion:^(PINRemoteImageManagerResult *result) { + XCTAssert([result.image isKindOfClass:[UIImage class]], @"result image is not a UIImage"); + image = result.image; + dispatch_group_leave(group); + }]; + } + + XCTAssert(dispatch_group_wait(group, [self timeout]) == 0, @"Group timed out."); + + XCTAssert(self.imageManager.totalDownloads <= 1, @"image downloaded too many times: %lu", (unsigned long)self.imageManager.totalDownloads); + XCTAssert([image isKindOfClass:[UIImage class]], @"result image is not a UIImage"); +} + +- (BOOL)isFloat:(float)one equalToFloat:(float)two +{ + if (fabsf(one - two) < FLT_EPSILON) { + return YES; + } + return NO; +} + +- (void)testBytesPerSecond +{ + NSString *host = @"none.com"; + + XCTAssert([[PINSpeedRecorder sharedRecorder] weightedAdjustedBytesPerSecondForHost:host] == -1, @"Without any tasks added, should be -1"); + [[PINSpeedRecorder sharedRecorder] updateSpeedsForHost:host bytesPerSecond:100 startAdjustedBytesPerSecond:100 timeToFirstByte:0]; + XCTAssert([self isFloat:[[PINSpeedRecorder sharedRecorder] weightedAdjustedBytesPerSecondForHost:host] equalToFloat:100.0f], @"One task should be same as added task"); + [[PINSpeedRecorder sharedRecorder] updateSpeedsForHost:host bytesPerSecond:50 startAdjustedBytesPerSecond:50 timeToFirstByte:0]; + XCTAssert([self isFloat:[[PINSpeedRecorder sharedRecorder] weightedAdjustedBytesPerSecondForHost:host] equalToFloat:90.0], @"Last task should be weighted"); +} + +- (void)testQOS +{ + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + [self.imageManager setHighQualityBPSThreshold:10 completion:^{ + dispatch_semaphore_signal(semaphore); + }]; + XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); + + [self.imageManager setLowQualityBPSThreshold:5 completion:^{ + dispatch_semaphore_signal(semaphore); + }]; + XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); + + [self.imageManager setShouldUpgradeLowQualityImages:NO completion:^{ + dispatch_semaphore_signal(semaphore); + }]; + XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); + __block UIImage *image; + [self.imageManager downloadImageWithURLs:@[[self JPEGURL_Small], [self JPEGURL_Medium], [self JPEGURL_Large]] + options:PINRemoteImageManagerDownloadOptionsNone + progressImage:nil + completion:^(PINRemoteImageManagerResult *result) + { + image = result.image; + XCTAssertEqual(image.size.width, 736, @"Large image should be downloaded. result.image: %@, result.error: %@", result.image, result.error); + dispatch_semaphore_signal(semaphore); + }]; + XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); + + // callback can occur *before* image is stored in cache this is an optimization to avoid waiting on the cache to write. + // So, wait until it's actually in the cache. + [self waitForImageWithURLToBeCached:[self JPEGURL_Large]]; + + [[PINSpeedRecorder sharedRecorder] setCurrentBytesPerSecond:5]; + [self.imageManager downloadImageWithURLs:@[[self JPEGURL_Small], [self JPEGURL_Medium], [self JPEGURL_Large]] + options:PINRemoteImageManagerDownloadOptionsNone + progressImage:nil + completion:^(PINRemoteImageManagerResult *result) + { + image = result.image; + XCTAssertEqual(image.size.width, 736, @"Large image should be found in cache"); + dispatch_semaphore_signal(semaphore); + }]; + XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); + + [self.imageManager.cache removeAllObjects]; + [self.imageManager downloadImageWithURLs:@[[self JPEGURL_Small], [self JPEGURL_Medium], [self JPEGURL_Large]] + options:PINRemoteImageManagerDownloadOptionsNone + progressImage:nil + completion:^(PINRemoteImageManagerResult *result) + { + image = result.image; + XCTAssert(image.size.width == 345, @"Small image should be downloaded at low bps"); + dispatch_semaphore_signal(semaphore); + }]; + XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); + + [self waitForImageWithURLToBeCached:[self JPEGURL_Small]]; + + [[PINSpeedRecorder sharedRecorder] setCurrentBytesPerSecond:100]; + [self.imageManager downloadImageWithURLs:@[[self JPEGURL_Small], [self JPEGURL_Medium], [self JPEGURL_Large]] + options:PINRemoteImageManagerDownloadOptionsNone + progressImage:nil + completion:^(PINRemoteImageManagerResult *result) + { + image = result.image; + XCTAssert(image.size.width == 345, @"Small image should be found in cache"); + dispatch_semaphore_signal(semaphore); + }]; + XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); + + [self.imageManager setShouldUpgradeLowQualityImages:YES completion:^{ + dispatch_semaphore_signal(semaphore); + }]; + XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); + + [[PINSpeedRecorder sharedRecorder] setCurrentBytesPerSecond:7]; + [self.imageManager downloadImageWithURLs:@[[self JPEGURL_Small], [self JPEGURL_Medium], [self JPEGURL_Large]] + options:PINRemoteImageManagerDownloadOptionsNone + progressImage:nil + completion:^(PINRemoteImageManagerResult *result) + { + image = result.image; + XCTAssert(image.size.width == 564, @"Medium image should be now downloaded"); + dispatch_semaphore_signal(semaphore); + }]; + XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); + + //small image should have been removed from cache + NSString *key = [self.imageManager cacheKeyForURL:[self JPEGURL_Small] processorKey:nil]; + for (NSUInteger idx = 0; idx < 100; idx++) { + if ([[self.imageManager cache] objectFromMemoryForKey:key] == nil) { + break; + } + usleep(100); + } + XCTAssert( + [[self.imageManager cache] objectFromMemoryForKey:[self.imageManager cacheKeyForURL:[self JPEGURL_Small] processorKey:nil]] == nil, @"Small image should have been removed from cache"); + + [self.imageManager.cache removeAllObjects]; + [self.imageManager setShouldUpgradeLowQualityImages:NO completion:^{ + dispatch_semaphore_signal(semaphore); + }]; + XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); + + [[PINSpeedRecorder sharedRecorder] setCurrentBytesPerSecond:7]; + [self.imageManager downloadImageWithURLs:@[[self JPEGURL_Small], [self JPEGURL_Large]] + options:PINRemoteImageManagerDownloadOptionsNone + progressImage:nil + completion:^(PINRemoteImageManagerResult *result) + { + image = result.image; + XCTAssert(image.size.width == 345, @"Small image should be now downloaded"); + dispatch_semaphore_signal(semaphore); + }]; + XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); +} + +- (void)testCacheControlSupport +{ + self.imageManager = [[PINRemoteImageManager alloc] initWithSessionConfiguration:nil alternativeRepresentationProvider:nil imageCache:[PINRemoteImageManager defaultImageTtlCache] managerConfiguration:nil]; + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + id cache = self.imageManager.cache; + XCTAssert([cache isKindOfClass:[PINCache class]]); + PINCache *pinCache = (PINCache *)cache; + pinCache.diskCache.ageLimit = 0; // forever, which is more than 31536000 (which is about a yr fwiw) + XCTAssert(pinCache.diskCache.isTTLCache, @"Default imageManager did not use a ttl cache"); + + // JPEGURL_Small includes the header "Cache-Control: max-age=31536000, immutable" + // Looks like it adds about 13 years right now + // If that ever changes, this might start failing + [self.imageManager downloadImageWithURL:[self JPEGURL_Small] completion:^(PINRemoteImageManagerResult *result) { + XCTAssert(result.resultType == PINRemoteImageResultTypeDownload, @"Expected PINRemoteImageResultTypeDownload(3), got %lu", (unsigned long)result.resultType); + dispatch_semaphore_signal(semaphore); + }]; + XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); + + NSString *key = [self.imageManager cacheKeyForURL:[self JPEGURL_Small] processorKey:nil]; + id diskCachedObj = [cache objectFromDiskForKey:key]; + XCTAssert(diskCachedObj != nil, @"Image was not found in the disk cache"); + [self.imageManager downloadImageWithURL:[self JPEGURL_Small] completion:^(PINRemoteImageManagerResult *result) { + XCTAssert(result.resultType == PINRemoteImageResultTypeMemoryCache, @"Expected PINRemoteImageResultTypeCache(2), got %lu", (unsigned long)result.resultType); + dispatch_semaphore_signal(semaphore); + }]; + XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); + + [NSDate startMockingDateWithDate:[NSDate dateWithTimeIntervalSinceNow:448000000]]; + diskCachedObj = [cache objectFromDiskForKey:key]; + XCTAssert(diskCachedObj == nil, @"Image was not discarded from the disk cache"); + [self.imageManager downloadImageWithURL:[self JPEGURL_Small] completion:^(PINRemoteImageManagerResult *result) { + XCTAssertEqual(result.resultType, PINRemoteImageResultTypeDownload, @"Expected PINRemoteImageResultTypeDownload(3), got %lu", (unsigned long)result.resultType); + dispatch_semaphore_signal(semaphore); + }]; + XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); + [NSDate stopMockingDate]; + + + // nonTransparentWebPURL includes the header "expires: " + // If that ever changes, this might start failing + [self.imageManager downloadImageWithURL:[self nonTransparentWebPURL] completion:^(PINRemoteImageManagerResult *result) { + XCTAssert(result.resultType == PINRemoteImageResultTypeDownload, @"Expected PINRemoteImageResultTypeDownload(3), got %lu", (unsigned long)result.resultType); + dispatch_semaphore_signal(semaphore); + }]; + XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); + + key = [self.imageManager cacheKeyForURL:[self nonTransparentWebPURL] processorKey:nil]; + diskCachedObj = [cache objectFromDiskForKey:key]; + XCTAssert(diskCachedObj != nil, @"Image was not found in the disk cache"); + [self.imageManager downloadImageWithURL:[self nonTransparentWebPURL] completion:^(PINRemoteImageManagerResult *result) { + XCTAssert(result.resultType == PINRemoteImageResultTypeMemoryCache, @"Expected PINRemoteImageResultTypeCache(2), got %lu", (unsigned long)result.resultType); + dispatch_semaphore_signal(semaphore); + }]; + XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); + + [NSDate startMockingDateWithDate:[NSDate dateWithTimeIntervalSinceNow:32000000]]; + diskCachedObj = [cache objectFromDiskForKey:key]; + XCTAssert(diskCachedObj == nil, @"Image was not discarded from the disk cache"); + [self.imageManager downloadImageWithURL:[self nonTransparentWebPURL] completion:^(PINRemoteImageManagerResult *result) { + XCTAssert(result.resultType == PINRemoteImageResultTypeDownload, @"Expected PINRemoteImageResultTypeDownload(3), got %lu", (unsigned long)result.resultType); + dispatch_semaphore_signal(semaphore); + }]; + XCTAssert(dispatch_semaphore_wait(semaphore, [self timeout]) == 0, @"Semaphore timed out."); + [NSDate stopMockingDate]; + +} + +- (void)testAuthentication +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Authentification challenge was called"]; + __block BOOL authHit = NO; + [self.imageManager setAuthenticationChallenge:^(NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, PINRemoteImageManagerAuthenticationChallengeCompletionHandler aHandler) { + aHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); + authHit = YES; + [expectation fulfill]; + }]; + + //Wait for async authentication challenge setter to complete + sleep(1); + + [self.imageManager downloadImageWithURL:[NSURL URLWithString:@"https://i.pinimg.com/600x/1b/bc/c2/1bbcc264683171eb3815292d2f546e92.jpg"] + options:PINRemoteImageManagerDownloadOptionsNone + completion:^(PINRemoteImageManagerResult * _Nonnull result) { + XCTAssert(authHit, @"should not complete without hitting auth challenge."); + }]; + + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testDiskCacheOnLongURLs +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Image is available in the disk cache"]; + id cache = self.imageManager.cache; + NSURL *longURL = [self veryLongURL]; + NSString *key = [self.imageManager cacheKeyForURL:longURL processorKey:nil]; + [self.imageManager downloadImageWithURL:longURL + options:PINRemoteImageManagerDownloadOptionsNone + completion:^(PINRemoteImageManagerResult *result) + { + XCTAssertNotNil(result.image, @"Image should not be nil"); + id diskCachedObj = [cache objectFromDiskForKey:key]; + XCTAssertNotNil(diskCachedObj); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testLongCacheKeyCreationPerformance +{ + [self measureBlock:^{ + NSURL *longURL = [self veryLongURL]; + for (NSUInteger i = 0; i < 10000; i++) { + __unused NSString *key = [self.imageManager cacheKeyForURL:longURL processorKey:nil]; + } + }]; +} + +- (void)testDefaultCacheKeyCreationPerformance +{ + [self measureBlock:^{ + NSURL *defaultURL = [self JPEGURL]; + for (NSUInteger i = 0; i < 10000; i++) { + __unused NSString *key = [self.imageManager cacheKeyForURL:defaultURL processorKey:nil]; + } + }]; +} + +- (void)testThatNondecodedJPEGImageHasNoAlpha +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Downloading JPEG image"]; + [self.imageManager downloadImageWithURL:[self JPEGURL] + options:PINRemoteImageManagerDownloadOptionsSkipDecode + completion:^(PINRemoteImageManagerResult *result) + { + UIImage *outImage = result.image; + + XCTAssert(outImage && [outImage isKindOfClass:[UIImage class]], @"Failed downloading image or image is not a UIImage."); + XCTAssert(PINImageAlphaInfoIsOpaque(CGImageGetAlphaInfo(outImage.CGImage)), @"Opaque image has an alpha channel."); + + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testThatDecodedJPEGImageHasNoAlpha +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Downloading JPEG image"]; + [self.imageManager downloadImageWithURL:[self JPEGURL] + options:PINRemoteImageManagerDownloadOptionsNone + completion:^(PINRemoteImageManagerResult *result) + { + UIImage *outImage = result.image; + + XCTAssert(outImage && [outImage isKindOfClass:[UIImage class]], @"Failed downloading image or image is not a UIImage."); + XCTAssert(PINImageAlphaInfoIsOpaque(CGImageGetAlphaInfo(outImage.CGImage)), @"Opaque image has an alpha channel."); + + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + + +- (void)testThatNondecodedTransparentPNGImageHasAlpha +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Downloading PNG image"]; + [self.imageManager downloadImageWithURL:[self transparentPNGURL] + options:PINRemoteImageManagerDownloadOptionsSkipDecode + completion:^(PINRemoteImageManagerResult *result) + { + UIImage *outImage = result.image; + + XCTAssert(outImage && [outImage isKindOfClass:[UIImage class]], @"Failed downloading image or image is not a UIImage."); + XCTAssertFalse(PINImageAlphaInfoIsOpaque(CGImageGetAlphaInfo(outImage.CGImage)), @"Transparent image has no alpha."); + + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testThatDecodedTransparentPNGImageHasAlpha +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Downloading PNG image"]; + [self.imageManager downloadImageWithURL:[self transparentPNGURL] + options:PINRemoteImageManagerDownloadOptionsNone + completion:^(PINRemoteImageManagerResult *result) + { + UIImage *outImage = result.image; + + XCTAssert(outImage && [outImage isKindOfClass:[UIImage class]], @"Failed downloading image or image is not a UIImage."); + XCTAssertFalse(PINImageAlphaInfoIsOpaque(CGImageGetAlphaInfo(outImage.CGImage)), @"Transparent image has no alpha."); + + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testThatGrayscalePNGImageIsEightBPP +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Downloading grayscale PNG image"]; + [self.imageManager downloadImageWithURL:[self grayscalePNGURL] + options:PINRemoteImageManagerDownloadOptionsNone + completion:^(PINRemoteImageManagerResult *result) + { + UIImage *outImage = result.image; + + XCTAssertEqual(CGImageGetBitsPerPixel(outImage.CGImage), 8, @"This grayscale image should've been decoded as a 8 bit per pixel image."); + XCTAssert(PINImageAlphaInfoIsOpaque(CGImageGetAlphaInfo(outImage.CGImage)), @"Opaque image has an alpha channel."); + + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testImageRendererOrientation +{ + dispatch_group_t group = dispatch_group_create(); + __block CGImageRef imageRefEncoded = nil; + + dispatch_group_enter(group); + [self.imageManager downloadImageWithURL:[self JPEGURL] + options:PINRemoteImageManagerDownloadOptionsSkipDecode + completion:^(PINRemoteImageManagerResult *result) + { + imageRefEncoded = CGImageCreateCopy(result.image.CGImage); + dispatch_group_leave(group); + }]; + + dispatch_group_wait(group, DISPATCH_TIME_FOREVER); + + // All image orientations (copied from `UIImage.h`) + UIImageOrientation allOrientations[] = { + UIImageOrientationUp, // default orientation + UIImageOrientationDown, // 180 deg rotation + UIImageOrientationLeft, // 90 deg CCW + UIImageOrientationRight, // 90 deg CW + UIImageOrientationUpMirrored, // as above but image mirrored along other axis. horizontal flip + UIImageOrientationDownMirrored, // horizontal flip + UIImageOrientationLeftMirrored, // vertical flip + UIImageOrientationRightMirrored, // vertical flip + }; + + // iOS or tvOS versions below 10.0 use the traditional `+[UIImage imageWithCGImage:]` API that doesn't translate orientation. + // For iOS/tvOS 10.0+ we manually convert the `UIImageOrientation` in `UIGraphicsImageRenderer`, and therefore, + // the following test is meant to solidify that behavior + // Loop over all orientations and compare each element respective to one-another + for (NSInteger i = 0; i < sizeof(allOrientations)/sizeof(allOrientations[0]); i++) { + + // Rotate the reference image by the given orientation + UIImage *referenceImage = [UIImage pin_decodedImageWithCGImageRef:imageRefEncoded orientation:allOrientations[i]]; + + // Compare the reference image to each element + for (NSInteger j = 0; j < sizeof(allOrientations)/sizeof(allOrientations[0]); j++) { + + // Rotate the image by the given orientation + UIImage *rotatedImage = [UIImage pin_decodedImageWithCGImageRef:imageRefEncoded orientation:allOrientations[j]]; + + // equal images must succeed + if (i == j) { + XCTAssert([UIImageJPEGRepresentation(referenceImage, 1.0) isEqualToData:UIImageJPEGRepresentation(rotatedImage, 1.0)], + @"Unsuccessful transformation. The `referenceImage` and `rotatedImage` are not the same."); + } + // unequal images must fail + else { + XCTAssertFalse([UIImageJPEGRepresentation(referenceImage, 1.0) isEqualToData:UIImageJPEGRepresentation(rotatedImage, 1.0)], + @"Unsuccessful transformation. The `referenceImage` and `rotatedImage` are the same."); + } + } + } + + CGImageRelease(imageRefEncoded); +} + +- (void)testExponentialRetryStrategy +{ + PINRequestExponentialRetryStrategy *exponentialRetryStrategy = [[PINRequestExponentialRetryStrategy alloc] initWithRetryMaxCount:3 delayBase:2]; + + NSError *retryableError = [NSError errorWithDomain:PINURLErrorDomain code:501 userInfo:@{}]; + NSError *nonRetryableError1 = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorUnsupportedURL userInfo:@{}]; + NSError *nonRetryableError2 = [NSError errorWithDomain:PINRemoteImageManagerErrorDomain code:0 userInfo:@{}]; + XCTAssertTrue([exponentialRetryStrategy shouldRetryWithError:retryableError], @"Retryable error"); + XCTAssertFalse([exponentialRetryStrategy shouldRetryWithError:nonRetryableError1], @"Non retryable error"); + XCTAssertFalse([exponentialRetryStrategy shouldRetryWithError:nonRetryableError2], @"Non retryable error"); + + + XCTAssertTrue([exponentialRetryStrategy shouldRetryWithError:retryableError], @"Original request failed"); + [exponentialRetryStrategy incrementRetryCount]; + XCTAssertEqual([exponentialRetryStrategy nextDelay], 2, @"First delay, exponential strategy"); + + XCTAssertTrue([exponentialRetryStrategy shouldRetryWithError:retryableError], @"First retry failed"); + [exponentialRetryStrategy incrementRetryCount]; + XCTAssertEqual([exponentialRetryStrategy nextDelay], 4, @"Second delay, exponential strategy"); + + XCTAssertTrue([exponentialRetryStrategy shouldRetryWithError:retryableError], @"Second retry failed"); + [exponentialRetryStrategy incrementRetryCount]; + XCTAssertEqual([exponentialRetryStrategy nextDelay], 8, @"Third delay, exponential strategy"); + + XCTAssertFalse([exponentialRetryStrategy shouldRetryWithError:retryableError], @"Third retry failed"); +} + +- (void)testMaximumNumberOfDownloads +{ + __block NSInteger count = 0; + NSUInteger totalDownloads = [self bigURLs].count; + static NSUInteger maxNumberOfConcurrentDownloads = 2; + NSLock *countLock = [[NSLock alloc] init]; + XCTestExpectation *expectation = [self expectationWithDescription:@"All images downloaded"]; + + void (^imageCompletion) (PINRemoteImageManagerResult* _Nonnull result) = ^(PINRemoteImageManagerResult * _Nonnull result) { + [countLock lock]; + count++; + if (count == totalDownloads) { + [expectation fulfill]; + } + [countLock unlock]; + }; + + __weak typeof(self) weakSelf = self; + [self.imageManager setMaxNumberOfConcurrentDownloads:maxNumberOfConcurrentDownloads completion:^{ + for (NSUInteger idx = 0; idx < totalDownloads; idx++) { + [weakSelf.imageManager downloadImageWithURL:[weakSelf bigURLs][idx] completion:imageCompletion]; + } + }]; + + //I want this retain cycle +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + __block void (^checkConcurrentDownloads) (void); + checkConcurrentDownloads = ^{ + usleep(10000); + [self.imageManager.sessionManager concurrentDownloads:^(NSUInteger concurrentDownloads) { + XCTAssert(concurrentDownloads <= maxNumberOfConcurrentDownloads, @"concurrent downloads: %lu", (unsigned long)concurrentDownloads); + checkConcurrentDownloads(); + }]; + }; +#pragma clang diagnostic pop + + checkConcurrentDownloads(); + + //Give this one a bit longer since these are big images. + [self waitForExpectationsWithTimeout:120 handler:nil]; +} + +- (void)testResume +{ + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + + PINWeakify(self); + [self.imageManager setEstimatedRemainingTimeThresholdForProgressiveDownloads:0.001 completion:^{ + PINStrongify(self); + [self.imageManager setProgressiveRendersMaxProgressiveRenderSize:CGSizeMake(10000, 10000) completion:^{ + dispatch_semaphore_signal(semaphore); + }]; + }]; + dispatch_semaphore_wait(semaphore, [self timeout]); + + __block BOOL renderedImageQualityGreater = NO; + [self.imageManager downloadImageWithURL:[self progressiveURL] + options:PINRemoteImageManagerDownloadOptionsNone + progressImage:^(PINRemoteImageManagerResult * _Nonnull result) { + [self.imageManager cancelTaskWithUUID:result.UUID storeResumeData:YES]; + //Wait a second for cancelation. + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + dispatch_semaphore_signal(semaphore); + }); + } + completion:^(PINRemoteImageManagerResult * _Nonnull result) { + XCTAssert(result.image == nil, @"should not complete download: %@", result); + }]; + + dispatch_semaphore_wait(semaphore, [self timeout]); + + PINResume *resume = [self.imageManager.cache objectFromDiskForKey:[self.imageManager resumeCacheKeyForURL:[self progressiveURL]]]; + XCTAssert(resume.resumeData.length > 0, @"Resume should have > 0 data length"); + + //Shorten resume data to improve reliability of test (expect to get progressive render callback before download completes. + resume = [PINResume resumeData:[resume.resumeData subdataWithRange:NSMakeRange(0, 10)] ifRange:resume.ifRange totalBytes:resume.totalBytes]; + [self.imageManager.cache setObjectOnDisk:resume forKey:[self.imageManager resumeCacheKeyForURL:[self progressiveURL]]]; + + [self.imageManager downloadImageWithURL:[self progressiveURL] + options:PINRemoteImageManagerDownloadOptionsNone + progressImage:^(PINRemoteImageManagerResult * _Nonnull result) { + // We expect renderedImageQualitySame to be true because we want an initial progress callback on a resumed + // download. Otherwise, a canceled download which had already rendered progress, may not render progress again + // until completed. + XCTAssert(result.renderedImageQuality + FLT_EPSILON >= ((CGFloat)resume.resumeData.length / resume.totalBytes), @"expected renderedImageQuality (%f) to be greater or equal to progress (%f)", result.renderedImageQuality, (CGFloat)resume.resumeData.length / resume.totalBytes); + renderedImageQualityGreater = YES; + } + completion:^(PINRemoteImageManagerResult * _Nonnull result) { + XCTAssert(renderedImageQualityGreater, @"Rendered image quality should non-zero and be greater than resume length. resume data length: %lu total: %lld", (unsigned long)resume.resumeData.length, resume.totalBytes); + XCTAssert(result.image && result.error == nil, @"Image not downloaded"); + //Wait a second for disk storage. + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + dispatch_semaphore_signal(semaphore); + }); + }]; + + dispatch_semaphore_wait(semaphore, [self timeout]); + + NSData *resumedImageData = [self.imageManager.cache objectFromDiskForKey:[self.imageManager cacheKeyForURL:[self progressiveURL] processorKey:nil]]; + + [self.imageManager.cache removeAllObjects]; + + [self.imageManager downloadImageWithURL:[self progressiveURL] completion:^(PINRemoteImageManagerResult * _Nonnull result) { + //Wait a second for disk storage. + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + dispatch_semaphore_signal(semaphore); + }); + }]; + + dispatch_semaphore_wait(semaphore, [self timeout]); + + NSData *nonResumedImageData = [self.imageManager.cache objectFromDiskForKey:[self.imageManager cacheKeyForURL:[self progressiveURL] processorKey:nil]]; + + XCTAssert([nonResumedImageData isEqualToData:resumedImageData], @"Resumed image data and non resumed image data should be the same."); +} + +- (void)testResumeSkipCancelation +{ + //Test that images aren't canceled if the cost of resuming is high (i.e. time to first byte is longer than the time left to download) + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + + PINWeakify(self); + [self.imageManager setEstimatedRemainingTimeThresholdForProgressiveDownloads:0.001 completion:^{ + PINStrongify(self); + [self.imageManager setProgressiveRendersMaxProgressiveRenderSize:CGSizeMake(10000, 10000) completion:^{ + dispatch_semaphore_signal(semaphore); + }]; + }]; + dispatch_semaphore_wait(semaphore, [self timeout]); + + XCTestExpectation *progressExpectation = [self expectationWithDescription:@"progress is rendered"]; + + [[PINSpeedRecorder sharedRecorder] updateSpeedsForHost:[[self progressiveURL] host] bytesPerSecond:0 startAdjustedBytesPerSecond:0 timeToFirstByte:0]; + + __block BOOL canceled = NO; + [self.imageManager downloadImageWithURL:[self progressiveURL] + options:PINRemoteImageManagerDownloadOptionsNone + progressImage:^(PINRemoteImageManagerResult * _Nonnull result) { + if (canceled == NO) { + canceled = YES; + [self.imageManager cancelTaskWithUUID:result.UUID storeResumeData:YES]; + [progressExpectation fulfill]; + dispatch_semaphore_signal(semaphore); + } + } + completion:^(PINRemoteImageManagerResult * _Nonnull result) { + XCTAssert(result.image == nil, @"should not complete download: %@", result); + }]; + + dispatch_semaphore_wait(semaphore, [self timeout]); + + //Remove any progress + [self.imageManager.cache removeObjectForKey:[self.imageManager resumeCacheKeyForURL:[self progressiveURL]]]; + + XCTestExpectation *progress2Expectation = [self expectationWithDescription:@"progress 2 is rendered"]; + XCTestExpectation *completedExpectation = [self expectationWithDescription:@"image is completed"]; + + [[PINSpeedRecorder sharedRecorder] resetMeasurements]; + [[PINSpeedRecorder sharedRecorder] updateSpeedsForHost:[[self progressiveURL] host] bytesPerSecond:100000 startAdjustedBytesPerSecond:100000 timeToFirstByte:10]; + + canceled = NO; + [self.imageManager downloadImageWithURL:[self progressiveURL] + options:PINRemoteImageManagerDownloadOptionsNone + progressImage:^(PINRemoteImageManagerResult * _Nonnull result) { + if (canceled == NO) { + canceled = YES; + [self.imageManager cancelTaskWithUUID:result.UUID storeResumeData:YES]; + [progress2Expectation fulfill]; + } + } + completion:^(PINRemoteImageManagerResult * _Nonnull result) { + [completedExpectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testRetry +{ + NSURLSessionConfiguration *config = [NSURLSessionConfiguration ephemeralSessionConfiguration]; + PINRemoteImageManager *manager = [[PINRemoteImageManager alloc] initWithSessionConfiguration:config]; + + //Do nasty swizzling to test this + SEL originalSelector = @selector(scheduleDownloadWithRequest:resume:skipRetry:priority:isRetry:completionHandler:); + SEL swizzledSelector = @selector(swizzled_scheduleDownloadWithRequest:resume:skipRetry:priority:isRetry:completionHandler:); + + Method originalMethod = class_getInstanceMethod([PINRemoteImageDownloadTask class], originalSelector); + Method swizzledMethod = class_getInstanceMethod([PINRemoteImageDownloadTask class], swizzledSelector); + + BOOL added = class_addMethod([PINRemoteImageDownloadTask class], originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); + if (added) { + class_replaceMethod([PINRemoteImageDownloadTask class], swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); + } else { + method_exchangeImplementations(originalMethod, swizzledMethod); + } + + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + __block BOOL requestFinished = NO; + [manager downloadImageWithURL:[self progressiveURL] completion:^(PINRemoteImageManagerResult * _Nonnull result) { + XCTAssert(result.image && result.error == nil, @"Should not have resulted in an error"); + requestFinished = YES; + dispatch_semaphore_signal(semaphore); + }]; + + dispatch_semaphore_wait(semaphore, [self timeout]); + + XCTAssert(requestFinished, @"Request should have finished before timeout"); + XCTAssert(requestRetried, @"Request should have been retried."); + + method_exchangeImplementations(originalMethod, swizzledMethod); +} + + +- (void)testDownloadTaskWhenReDownload +{ + self.semaphore = dispatch_semaphore_create(0); + self.imageManager = [[PINRemoteImageManager alloc] init]; + self.imageManager.sessionManager.delegate = self; + + PINRemoteImageTask *firstTask = nil; + NSUUID *firstUUID = [self.imageManager downloadImageWithURL:[self transparentPNGURL] options:0 progressDownload:nil completion:nil]; + dispatch_semaphore_wait(self.semaphore, [self timeout]); + firstTask = self.firstDownloadTask; + + [self.imageManager cancelTaskWithUUID:firstUUID]; + + PINRemoteImageTask *secondTask = nil; + [self.imageManager downloadImageWithURL:[self transparentPNGURL] options:0 progressDownload:nil completion:nil]; + dispatch_semaphore_wait(self.semaphore, [self timeout]); + secondTask = self.secondDownloadTask; + + XCTAssert(firstTask != secondTask); +} + +- (void)testURLSessionDidCompleteDelegate +{ + self.imageManager = [[PINRemoteImageManager alloc] init]; + self.imageManager.sessionManager.delegate = self; + self.sessionDidCompleteDelegateSemaphore = dispatch_semaphore_create(0); + [self.imageManager downloadImageWithURL:[self transparentPNGURL] completion:nil]; + long result = dispatch_semaphore_wait(self.sessionDidCompleteDelegateSemaphore, [self timeout]); + XCTAssert(result == 0); +} + +- (void)testCancelAllTasks +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Cancel all tasks"]; + dispatch_group_t group = dispatch_group_create(); + + dispatch_group_enter(group); + [self.imageManager downloadImageWithURL:[self progressiveURL2] options:0 progressDownload:^(int64_t completedBytes, int64_t totalBytes) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + dispatch_group_leave(group); + }); + } completion:nil]; + + dispatch_group_enter(group); + [self.imageManager downloadImageWithURL:[self progressiveURL] options:0 progressDownload:^(int64_t completedBytes, int64_t totalBytes) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + dispatch_group_leave(group); + }); + } completion:nil]; + + dispatch_group_notify(group, dispatch_get_main_queue(), ^{ + SEL originalSelector = @selector(cancelTaskWithUUID:storeResumeData:); + SEL swizzledSelector = @selector(swizzled_cancelTaskWithUUID:storeResumeData:); + + Method originalMethod = class_getInstanceMethod([PINRemoteImageManager class], originalSelector); + Method swizzledMethod = class_getInstanceMethod([PINRemoteImageManager class], swizzledSelector); + + method_exchangeImplementations(originalMethod, swizzledMethod); + + [self.imageManager cancelAllTasks]; + + // Give manager 2 seconds to cancel all tasks + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + XCTAssert(canceledCount == 2); + [expectation fulfill]; + }); + }); + dispatch_group_wait(group, [self timeout]); + [self waitForExpectationsWithTimeout:[self timeoutTimeInterval] handler:nil]; +} + +- (void)testImageDownloadUUIDs +{ + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + __weak PINRemoteImageManager *weakImageManager = self.imageManager; + __block NSUUID *uuid = [self.imageManager downloadImageWithURL:[self progressiveURL2] options:0 progressDownload:^(int64_t completedBytes, int64_t totalBytes) { + PINRemoteImageDownloadTask *task = (PINRemoteImageDownloadTask *)[weakImageManager.UUIDToTask objectForKey:uuid]; + XCTAssert([task.URL isEqual:[self progressiveURL2]]); + } completion:^(PINRemoteImageManagerResult *result) { + dispatch_async(dispatch_get_main_queue(), ^{ + PINRemoteImageDownloadTask *task = (PINRemoteImageDownloadTask *)[weakImageManager.UUIDToTask objectForKey:uuid]; + XCTAssert(!task); + dispatch_semaphore_signal(semaphore); + }); + }]; + + dispatch_semaphore_wait(semaphore, [self timeout]); +} + +@end + +@implementation PINRemoteImageManager (Swizzled) + +- (void)swizzled_cancelTaskWithUUID:(nonnull NSUUID *)UUID storeResumeData:(BOOL)storeResumeData +{ + canceledCount++; + [self swizzled_cancelTaskWithUUID:UUID storeResumeData:storeResumeData]; +} + +@end + +@implementation PINRemoteImageDownloadTask (Swizzled) + +- (void)swizzled_scheduleDownloadWithRequest:(NSURLRequest *)request + resume:(PINResume *)resume + skipRetry:(BOOL)skipRetry + priority:(PINRemoteImageManagerPriority)priority + isRetry:(BOOL)isRetry + completionHandler:(PINRemoteImageManagerDataCompletion)completionHandler +{ + static BOOL requestModified = NO; + NSMutableURLRequest *modifiedRequest = nil; + if (requestModified == NO) { + requestModified = YES; + modifiedRequest = [request mutableCopy]; + [modifiedRequest setTimeoutInterval:0.00001]; + } else { + modifiedRequest = [request mutableCopy]; + [modifiedRequest setTimeoutInterval:30]; + requestRetried = YES; + } + [self swizzled_scheduleDownloadWithRequest:modifiedRequest resume:resume skipRetry:skipRetry priority:priority isRetry:isRetry completionHandler:completionHandler]; +} + +@end diff --git a/Tests/TestAnimatedImage.h b/Tests/TestAnimatedImage.h new file mode 100644 index 00000000..8771e576 --- /dev/null +++ b/Tests/TestAnimatedImage.h @@ -0,0 +1,17 @@ +// +// TestAnimatedImage.h +// PINRemoteImage +// +// Created by Greg Bolsinga on 3/10/20. +// Copyright © 2020 Pinterest. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TestAnimatedImage : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/Tests/TestAnimatedImage.m b/Tests/TestAnimatedImage.m new file mode 100644 index 00000000..2154c387 --- /dev/null +++ b/Tests/TestAnimatedImage.m @@ -0,0 +1,39 @@ +// +// TestAnimatedImage.m +// PINRemoteImage +// +// Created by Greg Bolsinga on 3/10/20. +// Copyright © 2020 Pinterest. All rights reserved. +// + +#import "TestAnimatedImage.h" + +@implementation TestAnimatedImage + +@synthesize bytesPerFrame; + +@synthesize data; + +@synthesize error; + +@synthesize frameCount; + +@synthesize frameInterval; + +@synthesize height; + +@synthesize loopCount; + +@synthesize totalDuration; + +@synthesize width; + +- (CFTimeInterval)durationAtIndex:(NSUInteger)index { + return 0; +} + +- (nullable CGImageRef)imageAtIndex:(NSUInteger)index cacheProvider:(nullable id)cacheProvider { + return nil; +} + +@end diff --git a/Tests/fireworks.gif b/Tests/fireworks.gif new file mode 100644 index 00000000..067e887f Binary files /dev/null and b/Tests/fireworks.gif differ diff --git a/docs/html/Classes/PINRemoteImageManager.html b/docs/html/Classes/PINRemoteImageManager.html index 2d6d88d3..4deb87ee 100644 --- a/docs/html/Classes/PINRemoteImageManager.html +++ b/docs/html/Classes/PINRemoteImageManager.html @@ -1134,7 +1134,7 @@

Parameters

options -

PINRemoteImageManagerDownloadOptions options with which to pefetch the image.

+

PINRemoteImageManagerDownloadOptions options with which to prefetch the image.

@@ -1245,7 +1245,7 @@

Parameters

options -

PINRemoteImageManagerDownloadOptions options with which to pefetch the image.

+

PINRemoteImageManagerDownloadOptions options with which to prefetch the image.

@@ -2354,4 +2354,4 @@

Declared In

- \ No newline at end of file +