├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── build.gradle ├── docs ├── images │ ├── demo.gif │ └── google_play.png ├── issue_template.md └── javadoc │ ├── allclasses-frame.html │ ├── allclasses-noframe.html │ ├── com │ └── davemorrissey │ │ └── labs │ │ └── subscaleview │ │ ├── ImageSource.html │ │ ├── ImageViewState.html │ │ ├── SubsamplingScaleImageView.AnimationBuilder.html │ │ ├── SubsamplingScaleImageView.DefaultOnAnimationEventListener.html │ │ ├── SubsamplingScaleImageView.DefaultOnImageEventListener.html │ │ ├── SubsamplingScaleImageView.DefaultOnStateChangedListener.html │ │ ├── SubsamplingScaleImageView.OnAnimationEventListener.html │ │ ├── SubsamplingScaleImageView.OnImageEventListener.html │ │ ├── SubsamplingScaleImageView.OnStateChangedListener.html │ │ ├── SubsamplingScaleImageView.html │ │ ├── decoder │ │ ├── CompatDecoderFactory.html │ │ ├── DecoderFactory.html │ │ ├── ImageDecoder.html │ │ ├── ImageRegionDecoder.html │ │ ├── SkiaImageDecoder.html │ │ ├── SkiaImageRegionDecoder.html │ │ ├── SkiaPooledImageRegionDecoder.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ └── package-tree.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ └── package-tree.html │ ├── constant-values.html │ ├── deprecated-list.html │ ├── help-doc.html │ ├── index-all.html │ ├── index.html │ ├── overview-frame.html │ ├── overview-summary.html │ ├── overview-tree.html │ ├── package-list │ ├── script.js │ ├── serialized-form.html │ └── stylesheet.css ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── build.gradle ├── proguard-rules.txt └── src │ └── main │ ├── AndroidManifest.xml │ └── kotlin │ └── com │ └── davemorrissey │ └── labs │ └── subscaleview │ ├── CompatDecoderFactory.kt │ ├── DecoderFactory.kt │ ├── GestureDetectorListener.java │ ├── ImageDecoder.kt │ ├── ImageRegionDecoder.kt │ ├── SkiaImageDecoder.kt │ ├── SkiaImageRegionDecoder.kt │ ├── SkiaPooledImageRegionDecoder.kt │ └── SubsamplingScaleImageView.kt ├── sample ├── assets │ ├── card.png │ ├── sanmartino.jpg │ └── swissroad.jpg ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── kotlin │ └── com │ │ └── davemorrissey │ │ └── labs │ │ └── subscaleview │ │ └── test │ │ └── BasicFeaturesActivity.kt │ └── res │ ├── drawable-nodpi │ ├── button_standout_inactive.xml │ ├── button_standout_pressed.xml │ ├── button_transparent_pressed.xml │ ├── buttonstate_standout.xml │ ├── buttonstate_transparent.xml │ ├── pushpin_blue.png │ └── transparent.xml │ ├── drawable-xhdpi │ ├── next.png │ ├── play.png │ ├── previous.png │ ├── reset.png │ └── rotate.png │ ├── layout │ └── pages_activity.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── style.xml └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Gradle files 2 | .gradle/ 3 | build/ 4 | 5 | # Local configuration file (sdk path, etc) 6 | local.properties 7 | 8 | # Android Studio generated folders 9 | .navigation/ 10 | captures/ 11 | .externalNativeBuild 12 | 13 | # IntelliJ project files 14 | *.iml 15 | .idea/ 16 | 17 | # Misc 18 | .DS_Store 19 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | 3 | before_cache: 4 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock 5 | - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ 6 | 7 | before_install: 8 | - yes | sdkmanager "platforms;android-27" 9 | 10 | cache: 11 | directories: 12 | - $HOME/.gradle/caches/ 13 | - $HOME/.gradle/wrapper/ 14 | - $HOME/.android/build-cache 15 | 16 | android: 17 | components: 18 | - tools 19 | - build-tools-26.0.2 20 | - android-27 21 | - platform-tools 22 | licenses: 23 | - 'android-sdk-license-.+' 24 | 25 | script: 26 | ./gradlew build 27 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Before raising a new issue, please check the following places for an answer to your question! 2 | 3 | * Read through [the wiki](https://github.com/davemorrissey/subsampling-scale-image-view/wiki) for a comprehensive guide to using the view. 4 | * Search through [open and closed issues](https://github.com/davemorrissey/subsampling-scale-image-view/issues?utf8=%E2%9C%93&q=is%3Aissue) 5 | * Check examples in [the sample project](https://github.com/davemorrissey/subsampling-scale-image-view/tree/master/sample/src/com/davemorrissey/labs/subscaleview/sample) - most common uses are covered. 6 | * See if there's an answer to your question on [StackOverflow](http://stackoverflow.com/). 7 | 8 | If you get stuck adding the view in your project or need help extending it for your requirements, please consider asking for help on StackOverflow instead of raising an issue. This issue tracker is intended for reporting bugs and raising feature requests. 9 | 10 | Thanks for reading! 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, and 10 | distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by the copyright 13 | owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all other entities 16 | that control, are controlled by, or are under common control with that entity. 17 | For the purposes of this definition, "control" means (i) the power, direct or 18 | indirect, to cause the direction or management of such entity, whether by 19 | contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the 20 | outstanding shares, or (iii) beneficial ownership of such entity. 21 | 22 | "You" (or "Your") shall mean an individual or Legal Entity exercising 23 | permissions granted by this License. 24 | 25 | "Source" form shall mean the preferred form for making modifications, including 26 | but not limited to software source code, documentation source, and configuration 27 | files. 28 | 29 | "Object" form shall mean any form resulting from mechanical transformation or 30 | translation of a Source form, including but not limited to compiled object code, 31 | generated documentation, and conversions to other media types. 32 | 33 | "Work" shall mean the work of authorship, whether in Source or Object form, made 34 | available under the License, as indicated by a copyright notice that is included 35 | in or attached to the work (an example is provided in the Appendix below). 36 | 37 | "Derivative Works" shall mean any work, whether in Source or Object form, that 38 | is based on (or derived from) the Work and for which the editorial revisions, 39 | annotations, elaborations, or other modifications represent, as a whole, an 40 | original work of authorship. For the purposes of this License, Derivative Works 41 | shall not include works that remain separable from, or merely link (or bind by 42 | name) to the interfaces of, the Work and Derivative Works thereof. 43 | 44 | "Contribution" shall mean any work of authorship, including the original version 45 | of the Work and any modifications or additions to that Work or Derivative Works 46 | thereof, that is intentionally submitted to Licensor for inclusion in the Work 47 | by the copyright owner or by an individual or Legal Entity authorized to submit 48 | on behalf of the copyright owner. For the purposes of this definition, 49 | "submitted" means any form of electronic, verbal, or written communication sent 50 | to the Licensor or its representatives, including but not limited to 51 | communication on electronic mailing lists, source code control systems, and 52 | issue tracking systems that are managed by, or on behalf of, the Licensor for 53 | the purpose of discussing and improving the Work, but excluding communication 54 | that is conspicuously marked or otherwise designated in writing by the copyright 55 | owner as "Not a Contribution." 56 | 57 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf 58 | of whom a Contribution has been received by Licensor and subsequently 59 | incorporated within the Work. 60 | 61 | 2. Grant of Copyright License. 62 | 63 | Subject to the terms and conditions of this License, each Contributor hereby 64 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, 65 | irrevocable copyright license to reproduce, prepare Derivative Works of, 66 | publicly display, publicly perform, sublicense, and distribute the Work and such 67 | Derivative Works in Source or Object form. 68 | 69 | 3. Grant of Patent License. 70 | 71 | Subject to the terms and conditions of this License, each Contributor hereby 72 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, 73 | irrevocable (except as stated in this section) patent license to make, have 74 | made, use, offer to sell, sell, import, and otherwise transfer the Work, where 75 | such license applies only to those patent claims licensable by such Contributor 76 | that are necessarily infringed by their Contribution(s) alone or by combination 77 | of their Contribution(s) with the Work to which such Contribution(s) was 78 | submitted. If You institute patent litigation against any entity (including a 79 | cross-claim or counterclaim in a lawsuit) alleging that the Work or a 80 | Contribution incorporated within the Work constitutes direct or contributory 81 | patent infringement, then any patent licenses granted to You under this License 82 | for that Work shall terminate as of the date such litigation is filed. 83 | 84 | 4. Redistribution. 85 | 86 | You may reproduce and distribute copies of the Work or Derivative Works thereof 87 | in any medium, with or without modifications, and in Source or Object form, 88 | provided that You meet the following conditions: 89 | 90 | You must give any other recipients of the Work or Derivative Works a copy of 91 | this License; and 92 | You must cause any modified files to carry prominent notices stating that You 93 | changed the files; and 94 | You must retain, in the Source form of any Derivative Works that You distribute, 95 | all copyright, patent, trademark, and attribution notices from the Source form 96 | of the Work, excluding those notices that do not pertain to any part of the 97 | Derivative Works; and 98 | If the Work includes a "NOTICE" text file as part of its distribution, then any 99 | Derivative Works that You distribute must include a readable copy of the 100 | attribution notices contained within such NOTICE file, excluding those notices 101 | that do not pertain to any part of the Derivative Works, in at least one of the 102 | following places: within a NOTICE text file distributed as part of the 103 | Derivative Works; within the Source form or documentation, if provided along 104 | with the Derivative Works; or, within a display generated by the Derivative 105 | Works, if and wherever such third-party notices normally appear. The contents of 106 | the NOTICE file are for informational purposes only and do not modify the 107 | License. You may add Your own attribution notices within Derivative Works that 108 | You distribute, alongside or as an addendum to the NOTICE text from the Work, 109 | provided that such additional attribution notices cannot be construed as 110 | modifying the License. 111 | You may add Your own copyright statement to Your modifications and may provide 112 | additional or different license terms and conditions for use, reproduction, or 113 | distribution of Your modifications, or for any such Derivative Works as a whole, 114 | provided Your use, reproduction, and distribution of the Work otherwise complies 115 | with the conditions stated in this License. 116 | 117 | 5. Submission of Contributions. 118 | 119 | Unless You explicitly state otherwise, any Contribution intentionally submitted 120 | for inclusion in the Work by You to the Licensor shall be under the terms and 121 | conditions of this License, without any additional terms or conditions. 122 | Notwithstanding the above, nothing herein shall supersede or modify the terms of 123 | any separate license agreement you may have executed with Licensor regarding 124 | such Contributions. 125 | 126 | 6. Trademarks. 127 | 128 | This License does not grant permission to use the trade names, trademarks, 129 | service marks, or product names of the Licensor, except as required for 130 | reasonable and customary use in describing the origin of the Work and 131 | reproducing the content of the NOTICE file. 132 | 133 | 7. Disclaimer of Warranty. 134 | 135 | Unless required by applicable law or agreed to in writing, Licensor provides the 136 | Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, 137 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, 138 | including, without limitation, any warranties or conditions of TITLE, 139 | NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are 140 | solely responsible for determining the appropriateness of using or 141 | redistributing the Work and assume any risks associated with Your exercise of 142 | permissions under this License. 143 | 144 | 8. Limitation of Liability. 145 | 146 | In no event and under no legal theory, whether in tort (including negligence), 147 | contract, or otherwise, unless required by applicable law (such as deliberate 148 | and grossly negligent acts) or agreed to in writing, shall any Contributor be 149 | liable to You for damages, including any direct, indirect, special, incidental, 150 | or consequential damages of any character arising as a result of this License or 151 | out of the use or inability to use the Work (including but not limited to 152 | damages for loss of goodwill, work stoppage, computer failure or malfunction, or 153 | any and all other commercial damages or losses), even if such Contributor has 154 | been advised of the possibility of such damages. 155 | 156 | 9. Accepting Warranty or Additional Liability. 157 | 158 | While redistributing the Work or Derivative Works thereof, You may choose to 159 | offer, and charge a fee for, acceptance of support, warranty, indemnity, or 160 | other liability obligations and/or rights consistent with this License. However, 161 | in accepting such obligations, You may act only on Your own behalf and on Your 162 | sole responsibility, not on behalf of any other Contributor, and only if You 163 | agree to indemnify, defend, and hold each Contributor harmless for any liability 164 | incurred by, or claims asserted against, such Contributor by reason of your 165 | accepting any such warranty or additional liability. 166 | 167 | END OF TERMS AND CONDITIONS 168 | 169 | APPENDIX: How to apply the Apache License to your work 170 | 171 | To apply the Apache License to your work, attach the following boilerplate 172 | notice, with the fields enclosed by brackets "[]" replaced with your own 173 | identifying information. (Don't include the brackets!) The text should be 174 | enclosed in the appropriate comment syntax for the file format. We also 175 | recommend that a file or class name and description of purpose be included on 176 | the same "printed page" as the copyright notice for easier identification within 177 | third-party archives. 178 | 179 | Copyright [yyyy] [name of copyright owner] 180 | 181 | Licensed under the Apache License, Version 2.0 (the "License"); 182 | you may not use this file except in compliance with the License. 183 | You may obtain a copy of the License at 184 | 185 | http://www.apache.org/licenses/LICENSE-2.0 186 | 187 | Unless required by applicable law or agreed to in writing, software 188 | distributed under the License is distributed on an "AS IS" BASIS, 189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 190 | See the License for the specific language governing permissions and 191 | limitations under the License. 192 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Subsampling Scale Image View 2 | =========================== 3 | 4 | [![Build Status](https://travis-ci.org/davemorrissey/subsampling-scale-image-view.svg?branch=master)](https://travis-ci.org/davemorrissey/subsampling-scale-image-view) 5 | 6 | A custom image view for Android, designed for photo galleries and displaying huge images (e.g. maps and building plans) without `OutOfMemoryError`s. Includes pinch to zoom, panning, rotation and animation support, and allows easy extension so you can add your own overlays and touch event detection. 7 | 8 | The view optionally uses subsampling and tiles to support very large images - a low resolution base layer is loaded and as you zoom in, it is overlaid with smaller high resolution tiles for the visible area. This avoids holding too much data in memory. It's ideal for displaying large images while allowing you to zoom in to the high resolution details. You can disable tiling for smaller images and when displaying a bitmap object. There are some advantages and disadvantages to disabling tiling so to decide which is best, see [the wiki](https://github.com/davemorrissey/subsampling-scale-image-view/wiki/02.-Displaying-images). 9 | 10 | #### Guides 11 | 12 | * [Releases & downloads](https://github.com/davemorrissey/subsampling-scale-image-view/releases) 13 | * [Installation and setup](https://github.com/davemorrissey/subsampling-scale-image-view/wiki/01.-Setup) 14 | * [Image display notes & limitations](https://github.com/davemorrissey/subsampling-scale-image-view/wiki/02.-Displaying-images) 15 | * [Using preview images](https://github.com/davemorrissey/subsampling-scale-image-view/wiki/03.-Preview-images) 16 | * [Handling orientation changes](https://github.com/davemorrissey/subsampling-scale-image-view/wiki/05.-Orientation-changes) 17 | * [Advanced configuration](https://github.com/davemorrissey/subsampling-scale-image-view/wiki/07.-Configuration) 18 | * [Event handling](https://github.com/davemorrissey/subsampling-scale-image-view/wiki/09.-Events) 19 | * [Animation](https://github.com/davemorrissey/subsampling-scale-image-view/wiki/08.-Animation) 20 | * [Extension](https://github.com/davemorrissey/subsampling-scale-image-view/wiki/10.-Extension) 21 | * [Reference (JavaDocs)](http://davemorrissey.github.io/subsampling-scale-image-view/javadoc/) 22 | 23 | #### Migration guides 24 | 25 | Versions 3.9.0, 3.8.0 and 3.0.0 contain breaking changes. Migration instructions can be found [in the wiki](https://github.com/davemorrissey/subsampling-scale-image-view/wiki/X.--Migration-guides). 26 | 27 | #### Download the sample app 28 | 29 | [![Get it on Google Play](docs/images/google_play.png)](https://play.google.com/store/apps/details?id=com.davemorrissey.labs.subscaleview.sample) 30 | 31 | [Kotlin Sample App on GitHub](https://github.com/davemorrissey/ssiv-kotlin-sample) 32 | 33 | #### Demo 34 | 35 | ![Demo](docs/images/demo.gif) 36 | 37 | ## Features 38 | 39 | #### Image display 40 | 41 | * Display images from assets, resources, the file system or bitmaps 42 | * Automatically rotate images from the file system (e.g. the camera or gallery) according to EXIF 43 | * Manually rotate images in 90° increments 44 | * Display a region of the source image 45 | * Use a preview image while large images load 46 | * Swap images at runtime 47 | * Use a custom bitmap decoder 48 | 49 | *With tiling enabled:* 50 | 51 | * Display huge images, larger than can be loaded into memory 52 | * Show high resolution detail on zooming in 53 | * Tested up to 20,000x20,000px, though larger images are slower 54 | 55 | #### Gesture detection 56 | 57 | * One finger pan 58 | * Two finger pinch to zoom 59 | * Quick scale (one finger zoom) 60 | * Pan while zooming 61 | * Seamless switch between pan and zoom 62 | * Fling momentum after panning 63 | * Double tap to zoom in and out 64 | * Options to disable pan and/or zoom gestures 65 | 66 | #### Animation 67 | 68 | * Public methods for animating the scale and center 69 | * Customisable duration and easing 70 | * Optional uninterruptible animations 71 | 72 | #### Overridable event detection 73 | * Supports `OnClickListener` and `OnLongClickListener` 74 | * Supports interception of events using `GestureDetector` and `OnTouchListener` 75 | * Extend to add your own gestures 76 | 77 | #### Easy integration 78 | * Use within a `ViewPager` to create a photo gallery 79 | * Easily restore scale, center and orientation after screen rotation 80 | * Can be extended to add overlay graphics that move and scale with the image 81 | * Handles view resizing and `wrap_content` layout 82 | 83 | ## Quick start 84 | 85 | **1)** Add this library as a dependency in your app's build.gradle file. 86 | 87 | dependencies { 88 | implementation 'com.davemorrissey.labs:subsampling-scale-image-view:3.10.0' 89 | } 90 | 91 | **2)** Add the view to your layout XML. 92 | 93 | 96 | 97 | 101 | 102 | 103 | 104 | **3a)** Now, in your fragment or activity, set the image resource, asset name or file path. 105 | 106 | SubsamplingScaleImageView imageView = (SubsamplingScaleImageView)findViewById(id.imageView); 107 | imageView.setImage(ImageSource.resource(R.drawable.monkey)); 108 | // ... or ... 109 | imageView.setImage(ImageSource.asset("map.png")) 110 | // ... or ... 111 | imageView.setImage(ImageSource.uri("/sdcard/DCIM/DSCM00123.JPG")); 112 | 113 | **3b)** Or, if you have a `Bitmap` object in memory, load it into the view. This is unsuitable for large images because it bypasses subsampling - you may get an `OutOfMemoryError`. 114 | 115 | SubsamplingScaleImageView imageView = (SubsamplingScaleImageView)findViewById(id.imageView); 116 | imageView.setImage(ImageSource.bitmap(bitmap)); 117 | 118 | ## Photo credits 119 | 120 | * San Martino by Luca Bravo, via [unsplash.com](https://unsplash.com/photos/lWAOc0UuJ-A) 121 | * Swiss Road by Ludovic Fremondiere, via [unsplash.com](https://unsplash.com/photos/3XN-BNRDUyY) 122 | 123 | ## About 124 | 125 | Copyright 2018 David Morrissey, and licensed under the Apache License, Version 2.0. No attribution is necessary but it's very much appreciated. Star this project if you like it! 126 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext.kotlin_version = '1.7.10' 5 | 6 | repositories { 7 | google() 8 | jcenter() 9 | } 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:7.3.1' 12 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 13 | } 14 | } 15 | 16 | allprojects { 17 | repositories { 18 | google() 19 | jcenter() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /docs/images/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FossifyOrg/subsampling-scale-image-view/fc9559cae264a1928a9fa39116e019e29126da1a/docs/images/demo.gif -------------------------------------------------------------------------------- /docs/images/google_play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FossifyOrg/subsampling-scale-image-view/fc9559cae264a1928a9fa39116e019e29126da1a/docs/images/google_play.png -------------------------------------------------------------------------------- /docs/issue_template.md: -------------------------------------------------------------------------------- 1 | *Please provide as much of the following information as possible. Please do not raise issues to ask for help developing your app.* 2 | 3 | ### Expected behaviour 4 | 5 | ### Actual behaviour 6 | 7 | ### Steps to reproduce 8 | 9 | (Include your setup code, and where relevant, your layout XML) 10 | 11 | ### Affected devices 12 | 13 | (Specific devices, screen densities, SDK versions) 14 | 15 | ### Affected images 16 | 17 | (Attach images you have problems with) 18 | -------------------------------------------------------------------------------- /docs/javadoc/allclasses-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | All Classes (library 3.10.0 API) 7 | 8 | 9 | 10 | 11 |

All Classes

12 |
13 | 31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /docs/javadoc/allclasses-noframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | All Classes (library 3.10.0 API) 7 | 8 | 9 | 10 | 11 |

All Classes

12 |
13 | 31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /docs/javadoc/com/davemorrissey/labs/subscaleview/SubsamplingScaleImageView.OnAnimationEventListener.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SubsamplingScaleImageView.OnAnimationEventListener (library 3.10.0 API) 7 | 8 | 9 | 10 | 11 | 27 | 30 | 31 |
32 | 33 | 34 |
Skip navigation links
35 | 36 | 37 | 38 | 47 |
48 | 90 | 91 | 92 |
93 |
com.davemorrissey.labs.subscaleview
94 |

Interface SubsamplingScaleImageView.OnAnimationEventListener

95 |
96 |
97 |
98 | 117 |
118 |
119 | 156 |
157 |
158 | 200 |
201 |
202 | 203 | 204 |
205 | 206 | 207 |
Skip navigation links
208 | 209 | 210 | 211 | 220 |
221 | 263 | 264 | 265 | 266 | -------------------------------------------------------------------------------- /docs/javadoc/com/davemorrissey/labs/subscaleview/SubsamplingScaleImageView.OnStateChangedListener.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SubsamplingScaleImageView.OnStateChangedListener (library 3.10.0 API) 7 | 8 | 9 | 10 | 11 | 27 | 30 | 31 |
32 | 33 | 34 |
Skip navigation links
35 | 36 | 37 | 38 | 47 |
48 | 90 | 91 | 92 |
93 |
com.davemorrissey.labs.subscaleview
94 |

Interface SubsamplingScaleImageView.OnStateChangedListener

95 |
96 |
97 |
98 | 117 |
118 |
119 | 152 |
153 |
154 | 199 |
200 |
201 | 202 | 203 |
204 | 205 | 206 |
Skip navigation links
207 | 208 | 209 | 210 | 219 |
220 | 262 | 263 | 264 | 265 | -------------------------------------------------------------------------------- /docs/javadoc/com/davemorrissey/labs/subscaleview/decoder/DecoderFactory.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | DecoderFactory (library 3.10.0 API) 7 | 8 | 9 | 10 | 11 | 27 | 30 | 31 |
32 | 33 | 34 |
Skip navigation links
35 | 36 | 37 | 38 | 47 |
48 | 90 | 91 | 92 |
93 |
com.davemorrissey.labs.subscaleview.decoder
94 |

Interface DecoderFactory<T>

95 |
96 |
97 |
98 | 114 |
115 |
116 | 141 |
142 |
143 | 179 |
180 |
181 | 182 | 183 |
184 | 185 | 186 |
Skip navigation links
187 | 188 | 189 | 190 | 199 |
200 | 242 | 243 | 244 | 245 | -------------------------------------------------------------------------------- /docs/javadoc/com/davemorrissey/labs/subscaleview/decoder/ImageDecoder.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ImageDecoder (library 3.10.0 API) 7 | 8 | 9 | 10 | 11 | 27 | 30 | 31 |
32 | 33 | 34 |
Skip navigation links
35 | 36 | 37 | 38 | 47 |
48 | 90 | 91 | 92 |
93 |
com.davemorrissey.labs.subscaleview.decoder
94 |

Interface ImageDecoder

95 |
96 |
97 |
98 | 111 |
112 |
113 | 139 |
140 |
141 | 182 |
183 |
184 | 185 | 186 |
187 | 188 | 189 |
Skip navigation links
190 | 191 | 192 | 193 | 202 |
203 | 245 | 246 | 247 | 248 | -------------------------------------------------------------------------------- /docs/javadoc/com/davemorrissey/labs/subscaleview/decoder/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.davemorrissey.labs.subscaleview.decoder (library 3.10.0 API) 7 | 8 | 9 | 10 | 11 |

com.davemorrissey.labs.subscaleview.decoder

12 |
13 |

Interfaces

14 | 19 |

Classes

20 | 26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /docs/javadoc/com/davemorrissey/labs/subscaleview/decoder/package-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.davemorrissey.labs.subscaleview.decoder (library 3.10.0 API) 7 | 8 | 9 | 10 | 11 | 21 | 24 | 25 |
26 | 27 | 28 |
Skip navigation links
29 | 30 | 31 | 32 | 41 |
42 | 69 | 70 |
71 |

Package com.davemorrissey.labs.subscaleview.decoder

72 |
73 |
74 | 146 |
147 | 148 |
149 | 150 | 151 |
Skip navigation links
152 | 153 | 154 | 155 | 164 |
165 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /docs/javadoc/com/davemorrissey/labs/subscaleview/decoder/package-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.davemorrissey.labs.subscaleview.decoder Class Hierarchy (library 3.10.0 API) 7 | 8 | 9 | 10 | 11 | 21 | 24 | 25 |
26 | 27 | 28 |
Skip navigation links
29 | 30 | 31 | 32 | 41 |
42 | 69 | 70 |
71 |

Hierarchy For Package com.davemorrissey.labs.subscaleview.decoder

72 | Package Hierarchies: 73 | 76 |
77 |
78 |

Class Hierarchy

79 | 89 |

Interface Hierarchy

90 | 95 |
96 | 97 |
98 | 99 | 100 |
Skip navigation links
101 | 102 | 103 | 104 | 113 |
114 | 141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /docs/javadoc/com/davemorrissey/labs/subscaleview/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.davemorrissey.labs.subscaleview (library 3.10.0 API) 7 | 8 | 9 | 10 | 11 |

com.davemorrissey.labs.subscaleview

12 |
13 |

Interfaces

14 | 19 |

Classes

20 | 28 |
29 | 30 | 31 | -------------------------------------------------------------------------------- /docs/javadoc/com/davemorrissey/labs/subscaleview/package-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.davemorrissey.labs.subscaleview (library 3.10.0 API) 7 | 8 | 9 | 10 | 11 | 21 | 24 | 25 |
26 | 27 | 28 |
Skip navigation links
29 | 30 | 31 | 32 | 41 |
42 | 69 | 70 |
71 |

Package com.davemorrissey.labs.subscaleview

72 |
73 |
74 | 154 |
155 | 156 |
157 | 158 | 159 |
Skip navigation links
160 | 161 | 162 | 163 | 172 |
173 | 200 | 201 | 202 | 203 | -------------------------------------------------------------------------------- /docs/javadoc/com/davemorrissey/labs/subscaleview/package-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.davemorrissey.labs.subscaleview Class Hierarchy (library 3.10.0 API) 7 | 8 | 9 | 10 | 11 | 21 | 24 | 25 |
26 | 27 | 28 |
Skip navigation links
29 | 30 | 31 | 32 | 41 |
42 | 69 | 70 |
71 |

Hierarchy For Package com.davemorrissey.labs.subscaleview

72 | Package Hierarchies: 73 | 76 |
77 |
78 |

Class Hierarchy

79 | 96 |

Interface Hierarchy

97 | 102 |
103 | 104 |
105 | 106 | 107 |
Skip navigation links
108 | 109 | 110 | 111 | 120 |
121 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /docs/javadoc/constant-values.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Constant Field Values (library 3.10.0 API) 7 | 8 | 9 | 10 | 11 | 21 | 24 | 25 |
26 | 27 | 28 |
Skip navigation links
29 | 30 | 31 | 32 | 41 |
42 | 69 | 70 |
71 |

Constant Field Values

72 |

Contents

73 | 76 |
77 |
78 | 79 | 80 |

com.davemorrissey.*

81 | 249 |
250 | 251 |
252 | 253 | 254 |
Skip navigation links
255 | 256 | 257 | 258 | 267 |
268 | 295 | 296 | 297 | 298 | -------------------------------------------------------------------------------- /docs/javadoc/deprecated-list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Deprecated List (library 3.10.0 API) 7 | 8 | 9 | 10 | 11 | 21 | 24 | 25 |
26 | 27 | 28 |
Skip navigation links
29 | 30 | 31 | 32 | 41 |
42 | 69 | 70 |
71 |

Deprecated API

72 |

Contents

73 |
74 | 75 |
76 | 77 | 78 |
Skip navigation links
79 | 80 | 81 | 82 | 91 |
92 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /docs/javadoc/help-doc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | API Help (library 3.10.0 API) 7 | 8 | 9 | 10 | 11 | 21 | 24 | 25 |
26 | 27 | 28 |
Skip navigation links
29 | 30 | 31 | 32 | 41 |
42 | 69 | 70 |
71 |

How This API Document Is Organized

72 |
This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.
73 |
74 |
75 | 174 | This help file applies to API documentation generated using the standard doclet.
175 | 176 |
177 | 178 | 179 |
Skip navigation links
180 | 181 | 182 | 183 | 192 |
193 | 220 | 221 | 222 | 223 | -------------------------------------------------------------------------------- /docs/javadoc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | library 3.10.0 API 7 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | <noscript> 68 | <div>JavaScript is disabled on your browser.</div> 69 | </noscript> 70 | <h2>Frame Alert</h2> 71 | <p>This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. Link to <a href="overview-summary.html">Non-frame version</a>.</p> 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /docs/javadoc/overview-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Overview List (library 3.10.0 API) 7 | 8 | 9 | 10 | 11 |
All Classes
12 |
13 |

Packages

14 | 18 |
19 |

 

20 | 21 | 22 | -------------------------------------------------------------------------------- /docs/javadoc/overview-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Overview (library 3.10.0 API) 7 | 8 | 9 | 10 | 11 | 21 | 24 | 25 |
26 | 27 | 28 |
Skip navigation links
29 | 30 | 31 | 32 | 41 |
42 | 69 | 70 |
71 |

library 3.10.0 API

72 |
73 |
74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 |
Packages 
PackageDescription
com.davemorrissey.labs.subscaleview 
com.davemorrissey.labs.subscaleview.decoder 
91 |
92 | 93 |
94 | 95 | 96 |
Skip navigation links
97 | 98 | 99 | 100 | 109 |
110 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /docs/javadoc/overview-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Class Hierarchy (library 3.10.0 API) 7 | 8 | 9 | 10 | 11 | 21 | 24 | 25 |
26 | 27 | 28 |
Skip navigation links
29 | 30 | 31 | 32 | 41 |
42 | 69 | 70 |
71 |

Hierarchy For All Packages

72 | Package Hierarchies: 73 | 77 |
78 |
79 |

Class Hierarchy

80 | 101 |

Interface Hierarchy

102 | 110 |
111 | 112 |
113 | 114 | 115 |
Skip navigation links
116 | 117 | 118 | 119 | 128 |
129 | 156 | 157 | 158 | 159 | -------------------------------------------------------------------------------- /docs/javadoc/package-list: -------------------------------------------------------------------------------- 1 | com.davemorrissey.labs.subscaleview 2 | com.davemorrissey.labs.subscaleview.decoder 3 | -------------------------------------------------------------------------------- /docs/javadoc/script.js: -------------------------------------------------------------------------------- 1 | function show(type) 2 | { 3 | count = 0; 4 | for (var key in methods) { 5 | var row = document.getElementById(key); 6 | if ((methods[key] & type) != 0) { 7 | row.style.display = ''; 8 | row.className = (count++ % 2) ? rowColor : altColor; 9 | } 10 | else 11 | row.style.display = 'none'; 12 | } 13 | updateTabs(type); 14 | } 15 | 16 | function updateTabs(type) 17 | { 18 | for (var value in tabs) { 19 | var sNode = document.getElementById(tabs[value][0]); 20 | var spanNode = sNode.firstChild; 21 | if (value == type) { 22 | sNode.className = activeTableTab; 23 | spanNode.innerHTML = tabs[value][1]; 24 | } 25 | else { 26 | sNode.className = tableTab; 27 | spanNode.innerHTML = "" + tabs[value][1] + ""; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /docs/javadoc/serialized-form.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Serialized Form (library 3.10.0 API) 7 | 8 | 9 | 10 | 11 | 21 | 24 | 25 |
26 | 27 | 28 |
Skip navigation links
29 | 30 | 31 | 32 | 41 |
42 | 69 | 70 |
71 |

Serialized Form

72 |
73 |
74 | 109 |
110 | 111 |
112 | 113 | 114 |
Skip navigation links
115 | 116 | 117 | 118 | 127 |
128 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | android.enableJetifier=true 13 | android.useAndroidX=true 14 | org.gradle.jvmargs=-Xmx1536m 15 | 16 | # When configured, Gradle will run in incubating parallel mode. 17 | # This option should only be used with decoupled projects. More details, visit 18 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 19 | # org.gradle.parallel=true 20 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FossifyOrg/subsampling-scale-image-view/fc9559cae264a1928a9fa39116e019e29126da1a/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Feb 18 21:28:48 CET 2021 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /library/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | 4 | android { 5 | compileSdkVersion 33 6 | 7 | defaultConfig { 8 | minSdkVersion 23 9 | consumerProguardFiles 'proguard-rules.txt' 10 | } 11 | 12 | sourceSets { 13 | main.java.srcDirs += 'src/main/kotlin' 14 | } 15 | } 16 | 17 | dependencies { 18 | implementation 'androidx.annotation:annotation:1.5.0' 19 | implementation 'androidx.exifinterface:exifinterface:1.3.5' 20 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 21 | } 22 | 23 | repositories { 24 | google() 25 | } 26 | -------------------------------------------------------------------------------- /library/proguard-rules.txt: -------------------------------------------------------------------------------- 1 | -keep class com.davemorrissey.labs.subscaleview.** { *; } 2 | -------------------------------------------------------------------------------- /library/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /library/src/main/kotlin/com/davemorrissey/labs/subscaleview/CompatDecoderFactory.kt: -------------------------------------------------------------------------------- 1 | package com.davemorrissey.labs.subscaleview 2 | 3 | import android.graphics.Bitmap 4 | 5 | class CompatDecoderFactory constructor(private val clazz: Class, private val bitmapConfig: Bitmap.Config? = null) : DecoderFactory { 6 | constructor(clazz: Class) : this(clazz, null) 7 | 8 | override fun make(): T { 9 | return if (bitmapConfig == null) { 10 | clazz.newInstance() 11 | } else { 12 | clazz.getConstructor(Bitmap.Config::class.java).newInstance(bitmapConfig) 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /library/src/main/kotlin/com/davemorrissey/labs/subscaleview/DecoderFactory.kt: -------------------------------------------------------------------------------- 1 | package com.davemorrissey.labs.subscaleview 2 | 3 | interface DecoderFactory { 4 | fun make(): T 5 | } 6 | -------------------------------------------------------------------------------- /library/src/main/kotlin/com/davemorrissey/labs/subscaleview/GestureDetectorListener.java: -------------------------------------------------------------------------------- 1 | package com.davemorrissey.labs.subscaleview; 2 | 3 | import android.view.GestureDetector; 4 | import android.view.MotionEvent; 5 | 6 | import androidx.annotation.Nullable; 7 | 8 | public class GestureDetectorListener extends GestureDetector.SimpleOnGestureListener { 9 | @Override 10 | public boolean onFling(@Nullable MotionEvent e1, @Nullable MotionEvent e2, float velocityX, float velocityY) { 11 | return super.onFling(e1, e2, velocityX, velocityY); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /library/src/main/kotlin/com/davemorrissey/labs/subscaleview/ImageDecoder.kt: -------------------------------------------------------------------------------- 1 | package com.davemorrissey.labs.subscaleview 2 | 3 | import android.content.Context 4 | import android.graphics.Bitmap 5 | import android.net.Uri 6 | 7 | interface ImageDecoder { 8 | fun decode(context: Context, uri: Uri): Bitmap 9 | } 10 | -------------------------------------------------------------------------------- /library/src/main/kotlin/com/davemorrissey/labs/subscaleview/ImageRegionDecoder.kt: -------------------------------------------------------------------------------- 1 | package com.davemorrissey.labs.subscaleview 2 | 3 | import android.content.Context 4 | import android.graphics.Bitmap 5 | import android.graphics.Point 6 | import android.graphics.Rect 7 | import android.net.Uri 8 | 9 | interface ImageRegionDecoder { 10 | fun isReady(): Boolean 11 | 12 | fun init(context: Context, uri: Uri): Point 13 | 14 | fun decodeRegion(sRect: Rect, sampleSize: Int): Bitmap 15 | 16 | fun recycle() 17 | } 18 | -------------------------------------------------------------------------------- /library/src/main/kotlin/com/davemorrissey/labs/subscaleview/SkiaImageDecoder.kt: -------------------------------------------------------------------------------- 1 | package com.davemorrissey.labs.subscaleview 2 | 3 | import android.content.Context 4 | import android.graphics.Bitmap 5 | import android.graphics.BitmapFactory 6 | import android.net.Uri 7 | import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView.Companion.ASSET_PREFIX 8 | import java.io.InputStream 9 | 10 | class SkiaImageDecoder : ImageDecoder { 11 | override fun decode(context: Context, uri: Uri): Bitmap { 12 | val uriString = uri.toString() 13 | val options = BitmapFactory.Options() 14 | val bitmap: Bitmap? 15 | options.inPreferredConfig = Bitmap.Config.RGB_565 16 | when { 17 | uriString.startsWith(ASSET_PREFIX) -> { 18 | val assetName = uriString.substring(ASSET_PREFIX.length) 19 | bitmap = BitmapFactory.decodeStream(context.assets.open(assetName), null, options) 20 | } 21 | else -> { 22 | var inputStream: InputStream? = null 23 | try { 24 | val contentResolver = context.contentResolver 25 | inputStream = contentResolver.openInputStream(uri) 26 | bitmap = BitmapFactory.decodeStream(inputStream, null, options) 27 | } finally { 28 | try { 29 | inputStream?.close() 30 | } catch (e: Exception) { 31 | } 32 | } 33 | } 34 | } 35 | 36 | if (bitmap == null) { 37 | throw RuntimeException("Skia image region decoder returned null bitmap - image format may not be supported") 38 | } 39 | return bitmap 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /library/src/main/kotlin/com/davemorrissey/labs/subscaleview/SkiaImageRegionDecoder.kt: -------------------------------------------------------------------------------- 1 | package com.davemorrissey.labs.subscaleview 2 | 3 | import android.content.Context 4 | import android.content.res.AssetManager 5 | import android.graphics.* 6 | import android.net.Uri 7 | import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView.Companion.ASSET_PREFIX 8 | import java.io.InputStream 9 | import java.util.concurrent.locks.ReentrantReadWriteLock 10 | 11 | class SkiaImageRegionDecoder : ImageRegionDecoder { 12 | private var decoder: BitmapRegionDecoder? = null 13 | private val decoderLock = ReentrantReadWriteLock(true) 14 | 15 | @Synchronized 16 | override fun isReady() = decoder?.isRecycled == false 17 | 18 | override fun init(context: Context, uri: Uri): Point { 19 | val uriString = uri.toString() 20 | when { 21 | uriString.startsWith(ASSET_PREFIX) -> { 22 | val assetName = uriString.substring(ASSET_PREFIX.length) 23 | decoder = BitmapRegionDecoder.newInstance(context.assets.open(assetName, AssetManager.ACCESS_RANDOM), false) 24 | } 25 | else -> { 26 | var inputStream: InputStream? = null 27 | try { 28 | val contentResolver = context.contentResolver 29 | inputStream = contentResolver.openInputStream(uri)!! 30 | decoder = BitmapRegionDecoder.newInstance(inputStream, false) 31 | } finally { 32 | try { 33 | inputStream?.close() 34 | } catch (e: Exception) { 35 | } 36 | } 37 | } 38 | } 39 | return Point(decoder!!.width, decoder!!.height) 40 | } 41 | 42 | override fun decodeRegion(sRect: Rect, sampleSize: Int): Bitmap { 43 | decoderLock.readLock().lock() 44 | try { 45 | if (decoder?.isRecycled == false) { 46 | val options = BitmapFactory.Options() 47 | options.inSampleSize = sampleSize 48 | options.inPreferredConfig = Bitmap.Config.RGB_565 49 | return decoder!!.decodeRegion(sRect, options) 50 | ?: throw RuntimeException("Skia image decoder returned null bitmap - image format may not be supported") 51 | } else { 52 | throw IllegalStateException("Cannot decode region after decoder has been recycled") 53 | } 54 | } finally { 55 | decoderLock.readLock().unlock() 56 | } 57 | } 58 | 59 | @Synchronized 60 | override fun recycle() { 61 | decoderLock.writeLock().lock() 62 | try { 63 | decoder?.recycle() 64 | decoder = null 65 | } finally { 66 | decoderLock.writeLock().unlock() 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /library/src/main/kotlin/com/davemorrissey/labs/subscaleview/SkiaPooledImageRegionDecoder.kt: -------------------------------------------------------------------------------- 1 | package com.davemorrissey.labs.subscaleview 2 | 3 | import android.app.ActivityManager 4 | import android.content.Context 5 | import android.content.Context.ACTIVITY_SERVICE 6 | import android.content.res.AssetManager 7 | import android.graphics.* 8 | import android.net.Uri 9 | import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView.Companion.ASSET_PREFIX 10 | import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView.Companion.FILE_SCHEME 11 | import java.io.File 12 | import java.io.InputStream 13 | import java.util.concurrent.ConcurrentHashMap 14 | import java.util.concurrent.Semaphore 15 | import java.util.concurrent.atomic.AtomicBoolean 16 | import java.util.concurrent.locks.ReentrantReadWriteLock 17 | 18 | class SkiaPooledImageRegionDecoder : ImageRegionDecoder { 19 | private var decoderPool: DecoderPool? = DecoderPool() 20 | private val decoderLock = ReentrantReadWriteLock(true) 21 | 22 | private var context: Context? = null 23 | private var uri: Uri? = null 24 | 25 | private var fileLength = Long.MAX_VALUE 26 | private val imageDimensions = Point(0, 0) 27 | private val lazyInited = AtomicBoolean(false) 28 | 29 | @Synchronized 30 | override fun isReady() = decoderPool?.getIsEmpty() == false 31 | 32 | private fun getNumberOfCores() = Runtime.getRuntime().availableProcessors() 33 | 34 | private fun getIsLowMemory(): Boolean { 35 | val activityManager = context!!.getSystemService(ACTIVITY_SERVICE) as ActivityManager 36 | val memoryInfo = ActivityManager.MemoryInfo() 37 | activityManager.getMemoryInfo(memoryInfo) 38 | return memoryInfo.lowMemory 39 | } 40 | 41 | override fun init(context: Context, uri: Uri): Point { 42 | this.context = context 43 | this.uri = uri 44 | initialiseDecoder() 45 | return imageDimensions 46 | } 47 | 48 | private fun lazyInit() { 49 | if (lazyInited.compareAndSet(false, true) && fileLength < Long.MAX_VALUE) { 50 | Thread { 51 | while (decoderPool != null && allowAdditionalDecoder(decoderPool!!.size(), fileLength)) { 52 | try { 53 | if (decoderPool != null) { 54 | initialiseDecoder() 55 | } 56 | } catch (e: Exception) { 57 | } 58 | } 59 | }.start() 60 | } 61 | } 62 | 63 | private fun initialiseDecoder() { 64 | val uriString = uri!!.toString() 65 | val decoder: BitmapRegionDecoder 66 | var fileLength = Long.MAX_VALUE 67 | when { 68 | uriString.startsWith(ASSET_PREFIX) -> { 69 | val assetName = uriString.substring(ASSET_PREFIX.length) 70 | try { 71 | val descriptor = context!!.assets.openFd(assetName) 72 | fileLength = descriptor.length 73 | } catch (e: Exception) { 74 | } 75 | 76 | decoder = BitmapRegionDecoder.newInstance(context!!.assets.open(assetName, AssetManager.ACCESS_RANDOM), false)!! 77 | } 78 | uriString.startsWith(FILE_SCHEME) -> { 79 | decoder = BitmapRegionDecoder.newInstance(uriString.substring(FILE_SCHEME.length), false) 80 | try { 81 | val file = File(uriString) 82 | if (file.exists()) { 83 | fileLength = file.length() 84 | } 85 | } catch (e: Exception) { 86 | } 87 | } 88 | else -> { 89 | var inputStream: InputStream? = null 90 | try { 91 | val contentResolver = context!!.contentResolver 92 | inputStream = contentResolver.openInputStream(uri!!)!! 93 | decoder = BitmapRegionDecoder.newInstance(inputStream, false)!! 94 | try { 95 | val descriptor = contentResolver.openAssetFileDescriptor(uri!!, "r") 96 | if (descriptor != null) { 97 | fileLength = descriptor.length 98 | } 99 | } catch (e: Exception) { 100 | } 101 | } finally { 102 | try { 103 | inputStream?.close() 104 | } catch (e: Exception) { 105 | } 106 | } 107 | } 108 | } 109 | 110 | this.fileLength = fileLength 111 | imageDimensions.set(decoder.width, decoder.height) 112 | decoderLock.writeLock().lock() 113 | try { 114 | decoderPool?.add(decoder) 115 | } finally { 116 | decoderLock.writeLock().unlock() 117 | } 118 | } 119 | 120 | override fun decodeRegion(sRect: Rect, sampleSize: Int): Bitmap { 121 | if (sRect.width() < imageDimensions.x || sRect.height() < imageDimensions.y) { 122 | lazyInit() 123 | } 124 | 125 | decoderLock.readLock().lock() 126 | try { 127 | if (decoderPool != null) { 128 | val decoder = decoderPool!!.acquire() 129 | try { 130 | if (decoder?.isRecycled == false) { 131 | val options = BitmapFactory.Options() 132 | options.inSampleSize = sampleSize 133 | options.inPreferredConfig = Bitmap.Config.RGB_565 134 | return decoder.decodeRegion(sRect, options) 135 | ?: throw RuntimeException("Skia image decoder returned null bitmap - image format may not be supported") 136 | } 137 | } finally { 138 | if (decoder != null) { 139 | decoderPool!!.release(decoder) 140 | } 141 | } 142 | } 143 | throw IllegalStateException("Cannot decode region after decoder has been recycled") 144 | } finally { 145 | decoderLock.readLock().unlock() 146 | } 147 | } 148 | 149 | @Synchronized 150 | override fun recycle() { 151 | decoderLock.writeLock().lock() 152 | try { 153 | decoderPool?.recycle() 154 | decoderPool = null 155 | context = null 156 | uri = null 157 | } finally { 158 | decoderLock.writeLock().unlock() 159 | } 160 | } 161 | 162 | private fun allowAdditionalDecoder(numberOfDecoders: Int, fileLength: Long): Boolean { 163 | return when { 164 | numberOfDecoders >= 4 -> false 165 | numberOfDecoders * fileLength > 20 * 1024 * 1024 -> false 166 | numberOfDecoders >= getNumberOfCores() -> false 167 | getIsLowMemory() -> false 168 | else -> true 169 | } 170 | } 171 | 172 | class DecoderPool { 173 | private val available = Semaphore(0, true) 174 | private val decoders = ConcurrentHashMap() 175 | 176 | @Synchronized 177 | fun getIsEmpty() = decoders.isEmpty() 178 | 179 | private val nextAvailable: BitmapRegionDecoder? 180 | @Synchronized get() { 181 | for (entry in decoders.entries) { 182 | if (!entry.value) { 183 | entry.setValue(true) 184 | return entry.key 185 | } 186 | } 187 | return null 188 | } 189 | 190 | @Synchronized 191 | fun size() = decoders.size 192 | 193 | fun acquire(): BitmapRegionDecoder? { 194 | available.acquireUninterruptibly() 195 | return nextAvailable 196 | } 197 | 198 | fun release(decoder: BitmapRegionDecoder) { 199 | if (markAsUnused(decoder)) { 200 | available.release() 201 | } 202 | } 203 | 204 | @Synchronized 205 | fun add(decoder: BitmapRegionDecoder) { 206 | decoders[decoder] = false 207 | available.release() 208 | } 209 | 210 | @Synchronized 211 | fun recycle() { 212 | while (!decoders.isEmpty()) { 213 | val decoder = acquire() 214 | decoder!!.recycle() 215 | decoders.remove(decoder) 216 | } 217 | } 218 | 219 | @Synchronized 220 | fun markAsUnused(decoder: BitmapRegionDecoder): Boolean { 221 | for (entry in decoders.entries) { 222 | if (decoder == entry.key) { 223 | return if (entry.value) { 224 | entry.setValue(false) 225 | true 226 | } else { 227 | false 228 | } 229 | } 230 | } 231 | return false 232 | } 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /sample/assets/card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FossifyOrg/subsampling-scale-image-view/fc9559cae264a1928a9fa39116e019e29126da1a/sample/assets/card.png -------------------------------------------------------------------------------- /sample/assets/sanmartino.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FossifyOrg/subsampling-scale-image-view/fc9559cae264a1928a9fa39116e019e29126da1a/sample/assets/sanmartino.jpg -------------------------------------------------------------------------------- /sample/assets/swissroad.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FossifyOrg/subsampling-scale-image-view/fc9559cae264a1928a9fa39116e019e29126da1a/sample/assets/swissroad.jpg -------------------------------------------------------------------------------- /sample/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android-extensions' 3 | apply plugin: 'kotlin-android' 4 | 5 | android { 6 | compileSdkVersion 33 7 | 8 | defaultConfig { 9 | minSdkVersion 23 10 | applicationId "com.davemorrissey.labs.subscaleview.test" 11 | versionCode 4 12 | versionName "3.1.0" 13 | } 14 | 15 | sourceSets { 16 | main { 17 | assets.srcDirs = ['assets'] 18 | } 19 | } 20 | 21 | sourceSets { 22 | main.java.srcDirs += 'src/main/kotlin' 23 | } 24 | } 25 | 26 | dependencies { 27 | implementation project(':library') 28 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 29 | api 'androidx.appcompat:appcompat:1.5.1' 30 | } 31 | -------------------------------------------------------------------------------- /sample/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | 14 | 17 | 18 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /sample/src/main/kotlin/com/davemorrissey/labs/subscaleview/test/BasicFeaturesActivity.kt: -------------------------------------------------------------------------------- 1 | package com.davemorrissey.labs.subscaleview.test 2 | 3 | import android.os.Bundle 4 | import androidx.appcompat.app.AppCompatActivity 5 | import kotlinx.android.synthetic.main.pages_activity.* 6 | 7 | class BasicFeaturesActivity : AppCompatActivity() { 8 | override fun onCreate(savedInstanceState: Bundle?) { 9 | super.onCreate(savedInstanceState) 10 | setContentView(R.layout.pages_activity) 11 | actionBar?.title = getString(R.string.basic_title) 12 | imageView.setImage("/android_asset/sanmartino.jpg") 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable-nodpi/button_standout_inactive.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable-nodpi/button_standout_pressed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable-nodpi/button_transparent_pressed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable-nodpi/buttonstate_standout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable-nodpi/buttonstate_transparent.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable-nodpi/pushpin_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FossifyOrg/subsampling-scale-image-view/fc9559cae264a1928a9fa39116e019e29126da1a/sample/src/main/res/drawable-nodpi/pushpin_blue.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-nodpi/transparent.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FossifyOrg/subsampling-scale-image-view/fc9559cae264a1928a9fa39116e019e29126da1a/sample/src/main/res/drawable-xhdpi/next.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FossifyOrg/subsampling-scale-image-view/fc9559cae264a1928a9fa39116e019e29126da1a/sample/src/main/res/drawable-xhdpi/play.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/previous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FossifyOrg/subsampling-scale-image-view/fc9559cae264a1928a9fa39116e019e29126da1a/sample/src/main/res/drawable-xhdpi/previous.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/reset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FossifyOrg/subsampling-scale-image-view/fc9559cae264a1928a9fa39116e019e29126da1a/sample/src/main/res/drawable-xhdpi/reset.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/rotate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FossifyOrg/subsampling-scale-image-view/fc9559cae264a1928a9fa39116e019e29126da1a/sample/src/main/res/drawable-xhdpi/rotate.png -------------------------------------------------------------------------------- /sample/src/main/res/layout/pages_activity.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FossifyOrg/subsampling-scale-image-view/fc9559cae264a1928a9fa39116e019e29126da1a/sample/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FossifyOrg/subsampling-scale-image-view/fc9559cae264a1928a9fa39116e019e29126da1a/sample/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FossifyOrg/subsampling-scale-image-view/fc9559cae264a1928a9fa39116e019e29126da1a/sample/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FossifyOrg/subsampling-scale-image-view/fc9559cae264a1928a9fa39116e019e29126da1a/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FossifyOrg/subsampling-scale-image-view/fc9559cae264a1928a9fa39116e019e29126da1a/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #111111 4 | #282828 5 | 6 | -------------------------------------------------------------------------------- /sample/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | SSIV Test App 4 | 5 | Subsampling Scale Image View 6 | 7 | View on GitHub 8 | 9 | Animate 10 | Next 11 | Previous 12 | Rotate 13 | Reset 14 | 15 | Basic features 16 | Basic features 17 | Pinch to zoom 18 | 19 | Use a two finger pinch to zoom in and out. The zoom is centred on the pinch gesture, and you can pan at the same time. 20 | 21 | Quick scale 22 | 23 | Double tap and swipe up or down to zoom in or out. The zoom is centred where you tapped. 24 | 25 | Drag 26 | Use one finger to drag the image around. 27 | Fling 28 | 29 | If you drag quickly and let go, fling momentum keeps the image moving. 30 | 31 | Double tap 32 | 33 | Double tap the image to zoom in to that spot. Double tap again to zoom out. 34 | 35 | 36 | Image display 37 | Image display 38 | Large images 39 | 40 | This image is 7,800 x 6,240 pixels. On most devices it will be subsampled, and higher quality tiles are loaded as you zoom in. 41 | 42 | Rotation 43 | 44 | This image has been rotated 90 degrees. Tap the button to rotate it. EXIF rotation is supported for external files. 45 | 46 | Display region 47 | Set the region to display instead of the whole image. 48 | 49 | Event handling 50 | Event handling 51 | Simple events 52 | 53 | Touch handling by the image view doesn\'t prevent normal events from working. 54 | 55 | OnClickListener 56 | 57 | This view has an OnClickListener. Tap once to activate the click. 58 | 59 | OnLongClickListener 60 | 61 | This view has an OnLongClickListener. Press and hold to activate it. 62 | 63 | 64 | Advanced event handling 65 | Advanced event handling 66 | Overriding gestures 67 | Some gestures can be overridden with your own 68 | GestureDetector without affecting the image view. This allows you to get the coordinates of 69 | the event. 70 | 71 | onSingleTapConfirmed 72 | onSingleTapConfirmed has been overridden. Tap the image to 73 | see coordinates. 74 | 75 | onDoubleTap 76 | onDoubleTap has been overridden. Tap the image to see 77 | coordinates. This overrides the default zoom in behaviour. 78 | 79 | onLongPress 80 | onLongPress has been overridden. Press and hold the image 81 | to see coordinates. 82 | 83 | Other events 84 | You can override any event you want, but customising swipe, 85 | fling and zoom gestures will stop the view working normally. 86 | 87 | 88 | 89 | View pager galleries 90 | View pager gallery 91 | Horizontal 92 | 93 | This gallery has two images in a ViewPager. Swipe to move to the 94 | next image. If you\'re zoomed in on an image, you need to pan to the right of it, then swipe 95 | again to activate the pager. 96 | 97 | Vertical 98 | 99 | Vertical view pagers are also supported. Swipe up to move to the 100 | next image. If you\'re zoomed in on an image, you need to pan to the bottom of it, then 101 | swipe again to activate the pager. 102 | 103 | 104 | Animation 105 | Animation 106 | A demo 107 | 108 | Tap the play button. The image will scale and zoom to a random point, shown by a marker. 109 | 110 | Limited pan 111 | 112 | If the target point is near the edge of the image, it will be moved as near to the center as possible. 113 | 114 | Unlimited pan 115 | 116 | With unlimited or center-limited pan, the target point can always be animated to the center. 117 | 118 | Customisation 119 | 120 | Duration and easing are configurable. You can also make animations non-interruptible. 121 | 122 | 123 | Extension 124 | Extension 125 | Location pin 126 | 127 | This view class extends the image view, and adds a pin anchored to a point on the image. 128 | 129 | Overlaid circle 130 | 131 | A slightly more advanced example, this shows a circle that will 132 | move and scale with the image. (Due to a limitation in Android, this circle may disappear 133 | when it\'s larger than 2048px.) 134 | 135 | Freehand drawing 136 | 137 | This subclass adds event detection. Draw a freehand line; it 138 | will move with the image. (Due to a limitation in Android, your drawing may disappear when 139 | it\'s larger than 2048px.) 140 | 141 | 142 | Configuration 143 | Configuration 144 | Maximum scale 145 | 146 | The maximum scale has been set to 50dpi. You can zoom in until the image is very pixellated. 147 | 148 | Minimum tile DPI 149 | 150 | The minimum tile DPI has been set to 50dpi, to reduce 151 | memory usage. The next layer of tiles will not be loaded until the image is very pixellated. 152 | 153 | Pan disabled 154 | 155 | Dragging has been disabled. You can only zoom in to the centre point. 156 | 157 | Zoom disabled 158 | 159 | Zooming has been disabled. You can drag the image around. 160 | 161 | Double tap style 162 | 163 | On double tap, the tapped point is now zoomed to the center of the screen instead of remaining in the same place. 164 | 165 | Double tap style 166 | On double tap, the zoom now happens immediately. 167 | Double tap scale 168 | The double tap zoom scale has been set to 240dpi. 169 | Pan limit center 170 | 171 | The pan limit has been changed to PAN_LIMIT_CENTER. Panning stops when a corner reaches the centre of the screen. 172 | 173 | Pan limit outside 174 | 175 | The pan limit has been changed to PAN_LIMIT_OUTSIDE. Panning stops when the image is just off screen. 176 | 177 | Debug 178 | 179 | Debug has been enabled. This shows the tile boundaries and sizes. 180 | 181 | 182 | 183 | -------------------------------------------------------------------------------- /sample/src/main/res/values/style.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |