├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── builtin-decoder-common ├── pixelcomposer.cpp ├── pixelcomposer.h ├── sampler.cpp └── sampler.h ├── gradle-mvn-push.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── jpeg-decoder ├── .gitignore ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── jni │ ├── jpegdecoder.cpp │ ├── jpgd.cpp │ └── jpgd.h ├── library ├── .gitignore ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── rapid │ └── decoder │ ├── AssetBitmapLoader.java │ ├── BackgroundTask.java │ ├── BackgroundTaskManager.java │ ├── BitmapDecoder.java │ ├── BitmapLoader.java │ ├── BitmapMeta.java │ ├── BitmapPostProcessor.java │ ├── BitmapTransformer.java │ ├── BitmapUtils.java │ ├── ByteArrayBitmapLoader.java │ ├── CloneUtils.java │ ├── Decodable.java │ ├── FileBitmapLoader.java │ ├── FileDescriptorBitmapLoader.java │ ├── ForInternalUse.java │ ├── IntegerMaker.java │ ├── LazyInputStream.java │ ├── NextLayoutInspector.java │ ├── NullBitmapLoader.java │ ├── Quality.java │ ├── Queriable.java │ ├── ResourceBitmapLoader.java │ ├── StreamBitmapLoader.java │ ├── StreamOpener.java │ ├── TransitionDrawable.java │ ├── TwiceReadableInputStream.java │ ├── ViewFrameBuilder.java │ ├── binder │ ├── DrawableCreator.java │ ├── DrawableInflater.java │ ├── Effect.java │ ├── ImageViewBinder.java │ ├── TextViewBinder.java │ ├── ViewBackgroundBinder.java │ └── ViewBinder.java │ ├── builtin │ ├── BuiltInDecoder.java │ ├── JpegDecoder.java │ └── PngDecoder.java │ ├── cache │ ├── BitmapLruCache.java │ ├── CacheSource.java │ ├── DiskLruCache.java │ ├── DiskLruCacheEngine.java │ ├── LruCache.java │ ├── ResourcePool.java │ └── TransactionOutputStream.java │ ├── compat │ ├── DisplayCompat.java │ ├── ImageViewCompat.java │ └── ViewCompat.java │ └── frame │ ├── AspectRatioCalculator.java │ ├── CenterCropFramedDecoder.java │ ├── CenterFramedDecoder.java │ ├── CenterInsideFramedDecoder.java │ ├── FitGravityFramedDecoder.java │ ├── FitXYFramedDecoder.java │ ├── FramedDecoder.java │ ├── FramingMethod.java │ ├── MatrixFramedDecoder.java │ └── ScaleTypeFraming.java ├── png-decoder ├── .gitignore ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── jni │ ├── libpng │ ├── png.c │ ├── png.h │ ├── pngconf.h │ ├── pngdebug.h │ ├── pngerror.c │ ├── pngget.c │ ├── pnginfo.h │ ├── pnglibconf.h │ ├── pngmem.c │ ├── pngpread.c │ ├── pngpriv.h │ ├── pngread.c │ ├── pngrio.c │ ├── pngrtran.c │ ├── pngrutil.c │ ├── pngset.c │ ├── pngstruct.h │ └── pngtrans.c │ ├── pngdecoder.cpp │ └── pngdecoder.h ├── repository └── rapid │ └── decoder │ ├── jpeg-decoder │ ├── 0.3.0 │ │ ├── jpeg-decoder-0.3.0-sources.jar │ │ ├── jpeg-decoder-0.3.0-sources.jar.md5 │ │ ├── jpeg-decoder-0.3.0-sources.jar.sha1 │ │ ├── jpeg-decoder-0.3.0.aar │ │ ├── jpeg-decoder-0.3.0.aar.md5 │ │ ├── jpeg-decoder-0.3.0.aar.sha1 │ │ ├── jpeg-decoder-0.3.0.pom │ │ ├── jpeg-decoder-0.3.0.pom.md5 │ │ └── jpeg-decoder-0.3.0.pom.sha1 │ ├── maven-metadata.xml │ ├── maven-metadata.xml.md5 │ └── maven-metadata.xml.sha1 │ ├── library │ ├── 0.3.0 │ │ ├── library-0.3.0-sources.jar │ │ ├── library-0.3.0-sources.jar.md5 │ │ ├── library-0.3.0-sources.jar.sha1 │ │ ├── library-0.3.0.aar │ │ ├── library-0.3.0.aar.md5 │ │ ├── library-0.3.0.aar.sha1 │ │ ├── library-0.3.0.pom │ │ ├── library-0.3.0.pom.md5 │ │ └── library-0.3.0.pom.sha1 │ ├── maven-metadata.xml │ ├── maven-metadata.xml.md5 │ └── maven-metadata.xml.sha1 │ └── png-decoder │ ├── 0.3.0 │ ├── png-decoder-0.3.0-sources.jar │ ├── png-decoder-0.3.0-sources.jar.md5 │ ├── png-decoder-0.3.0-sources.jar.sha1 │ ├── png-decoder-0.3.0.aar │ ├── png-decoder-0.3.0.aar.md5 │ ├── png-decoder-0.3.0.aar.sha1 │ ├── png-decoder-0.3.0.pom │ ├── png-decoder-0.3.0.pom.md5 │ └── png-decoder-0.3.0.pom.sha1 │ ├── maven-metadata.xml │ ├── maven-metadata.xml.md5 │ └── maven-metadata.xml.sha1 ├── sample ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── squirrel.jpg │ ├── java │ └── rapid │ │ └── decoder │ │ └── sample │ │ ├── ContactsFragment.java │ │ ├── FrameFragment.java │ │ ├── GalleryFragment.java │ │ ├── MainActivity.java │ │ ├── MutableDecodingFragment.java │ │ ├── RegionalDecodingFragment.java │ │ ├── ResetFragment.java │ │ ├── ScaledDecodingFragment.java │ │ ├── WrapContentFragment.java │ │ └── widget │ │ └── SquaredImageView.java │ └── res │ ├── drawable-hdpi │ ├── ic_launcher.png │ └── ic_navigation_drawer.png │ ├── drawable-mdpi │ ├── ic_launcher.png │ ├── ic_navigation_drawer.png │ └── transparent_background_base.png │ ├── drawable-nodpi │ ├── amanda.jpg │ ├── amanda2.png │ ├── horizontal_reflex_848.jpg │ ├── ribbon.png │ └── vertical_panorama02.jpg │ ├── drawable-xhdpi │ ├── ic_launcher.png │ └── ic_navigation_drawer.png │ ├── drawable-xxhdpi │ └── ic_navigation_drawer.png │ ├── drawable │ ├── contacts_profile_image_placeholder.xml │ └── transparent_background.xml │ ├── layout │ ├── activity_main.xml │ ├── fragment_contacts.xml │ ├── fragment_frame.xml │ ├── fragment_gallery.xml │ ├── fragment_mutable_decoding.xml │ ├── fragment_regional_decoding.xml │ ├── fragment_reset.xml │ ├── fragment_scaled_decoding.xml │ ├── fragment_wrap_content.xml │ ├── item_contacts.xml │ └── item_gallery.xml │ └── values │ ├── arrays.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── settings.gradle └── test ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src ├── androidTest └── java │ └── rapid │ └── decoder │ ├── BasicUnitTest.java │ └── DecodeFromUriTest.java └── main ├── AndroidManifest.xml └── res ├── drawable-nodpi └── android.jpg └── drawable-xhdpi └── pond.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | .DS_Store 4 | 5 | .classpath 6 | .project 7 | .settings 8 | eclipsebin 9 | 10 | bin 11 | gen 12 | build 13 | out 14 | lib 15 | jniLibs 16 | 17 | target 18 | pom.xml.* 19 | release.properties 20 | 21 | .idea 22 | *.iml 23 | classes 24 | 25 | obj 26 | 27 | .DS_Store 28 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.0.0' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /builtin-decoder-common/pixelcomposer.cpp: -------------------------------------------------------------------------------- 1 | #include "pixelcomposer.h" 2 | 3 | typedef unsigned char uint8; 4 | typedef unsigned short uint16; 5 | typedef unsigned long uint32; 6 | 7 | void rgb565_composer(uint8*& dest, uint8 a, uint8 r, uint8 g, uint8 b) 8 | { 9 | uint16* p = (uint16*)dest; 10 | *p = (uint16)(((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3)); 11 | dest += 2; 12 | } 13 | 14 | void rgba4444_composer(uint8*& dest, uint8 a, uint8 r, uint8 g, uint8 b) 15 | { 16 | uint16* p = (uint16*)dest; 17 | *p = (uint16)(((r & 0xf0) << 8) | ((g & 0xf0) << 4) | (b & 0xf0) | (a >> 4)); 18 | dest += 2; 19 | } 20 | 21 | void rgb888_composer(uint8*& dest, uint8 a, uint8 r, uint8 g, uint8 b) 22 | { 23 | dest[0] = r; 24 | dest[1] = g; 25 | dest[2] = b; 26 | dest += 3; 27 | } 28 | 29 | void argb_composer(uint8*& dest, uint8 a, uint8 r, uint8 g, uint8 b) 30 | { 31 | uint32* p = (uint32*)dest; 32 | *p = (b << 24) | (g << 16) | (r << 8) | a; 33 | dest += 4; 34 | } 35 | 36 | void rgba_composer(uint8*& dest, uint8 a, uint8 r, uint8 g, uint8 b) 37 | { 38 | uint32* p = (uint32*)dest; 39 | *p = (a << 24) | (b << 16) | (g << 8) | r; 40 | dest += 4; 41 | } 42 | 43 | pixel_format RGB565(rgb565_composer, 2, false); 44 | pixel_format RGBA4444(rgba4444_composer, 2, true); 45 | pixel_format RGB888(rgb888_composer, 3, false); 46 | pixel_format ARGB8888(argb_composer, 4, true); 47 | pixel_format RGBA8888(rgba_composer, 4, true); -------------------------------------------------------------------------------- /builtin-decoder-common/pixelcomposer.h: -------------------------------------------------------------------------------- 1 | #ifndef PIXELCOMPOSER_H 2 | #define PIXELCOMPOSER_H 3 | 4 | typedef void (*pixel_composer)(unsigned char*& dest, unsigned char a, unsigned char r, unsigned char g, unsigned char b); 5 | 6 | class pixel_format 7 | { 8 | public: 9 | pixel_composer composer; 10 | int bytes_per_pixel; 11 | bool alpha; 12 | 13 | inline pixel_format() 14 | { 15 | composer = 0; 16 | bytes_per_pixel = 0; 17 | alpha = false; 18 | } 19 | 20 | inline pixel_format(pixel_composer composer, int bytes_per_pixel, bool alpha) 21 | { 22 | this->composer = composer; 23 | this->bytes_per_pixel = bytes_per_pixel; 24 | this->alpha = alpha; 25 | } 26 | 27 | inline bool operator==(const pixel_format& rhs) const 28 | { 29 | return composer == rhs.composer; 30 | } 31 | }; 32 | 33 | extern pixel_format RGB565; 34 | extern pixel_format RGBA4444; 35 | extern pixel_format RGB888; 36 | extern pixel_format ARGB8888; 37 | extern pixel_format RGBA8888; 38 | 39 | #endif // PIXELCOMPOSER_H -------------------------------------------------------------------------------- /builtin-decoder-common/sampler.h: -------------------------------------------------------------------------------- 1 | #ifndef SAMPLER_H 2 | #define SAMPLER_H 3 | 4 | #include "pixelcomposer.h" 5 | 6 | class opaque_sampler 7 | { 8 | public: 9 | opaque_sampler(int width, int sampled_width, unsigned int sample_size, bool filter, const pixel_format& format); 10 | virtual ~opaque_sampler(); 11 | 12 | virtual bool sample(const unsigned char* pixels, int offset, unsigned char* out); 13 | void finish(unsigned char* out); 14 | 15 | protected: 16 | unsigned int* m_red; 17 | unsigned int* m_green; 18 | unsigned int* m_blue; 19 | unsigned int m_sample_size; 20 | unsigned int m_shift_count_2; 21 | unsigned int m_shift_count; 22 | int m_width; 23 | int m_sampled_width; 24 | int m_remainder; 25 | int m_rows; 26 | bool m_filter; 27 | pixel_composer m_composer; 28 | 29 | virtual int get_bytes_per_pixel(); 30 | virtual void emit_square(unsigned char* out); 31 | virtual void emit(unsigned char* out); 32 | 33 | static unsigned int get_shift_count(unsigned int n); 34 | }; 35 | 36 | class sampler : public opaque_sampler 37 | { 38 | public: 39 | sampler(int width, int sampled_width, unsigned int sample_size, bool filter, const pixel_format& format); 40 | ~sampler(); 41 | 42 | bool sample(const unsigned char* pixels, int offset, unsigned char* out); 43 | 44 | protected: 45 | unsigned int* m_alpha; 46 | 47 | int get_bytes_per_pixel(); 48 | void emit_square(unsigned char* out); 49 | void emit(unsigned char* out); 50 | }; 51 | 52 | #endif // SAMPLER_H -------------------------------------------------------------------------------- /gradle-mvn-push.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Chris Banes 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | apply plugin: 'maven' 18 | apply plugin: 'signing' 19 | 20 | def isReleaseBuild() { 21 | return VERSION_NAME.contains("SNAPSHOT") == false 22 | } 23 | 24 | def getReleaseRepositoryUrl() { 25 | return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL 26 | : "https://oss.sonatype.org/service/local/staging/deploy/maven2/" 27 | } 28 | 29 | def getSnapshotRepositoryUrl() { 30 | return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL 31 | : "https://oss.sonatype.org/content/repositories/snapshots/" 32 | } 33 | 34 | def getRepositoryUsername() { 35 | return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : "" 36 | } 37 | 38 | def getRepositoryPassword() { 39 | return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : "" 40 | } 41 | 42 | afterEvaluate { project -> 43 | uploadArchives { 44 | repositories { 45 | mavenDeployer { 46 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } 47 | 48 | pom.groupId = GROUP 49 | pom.artifactId = POM_ARTIFACT_ID 50 | pom.version = VERSION_NAME 51 | 52 | repository(url: getReleaseRepositoryUrl()) { 53 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) 54 | } 55 | snapshotRepository(url: getSnapshotRepositoryUrl()) { 56 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) 57 | } 58 | 59 | pom.project { 60 | name POM_NAME 61 | packaging POM_PACKAGING 62 | description POM_DESCRIPTION 63 | url POM_URL 64 | 65 | scm { 66 | url POM_SCM_URL 67 | connection POM_SCM_CONNECTION 68 | developerConnection POM_SCM_DEV_CONNECTION 69 | } 70 | 71 | licenses { 72 | license { 73 | name POM_LICENCE_NAME 74 | url POM_LICENCE_URL 75 | distribution POM_LICENCE_DIST 76 | } 77 | } 78 | 79 | developers { 80 | developer { 81 | id POM_DEVELOPER_ID 82 | name POM_DEVELOPER_NAME 83 | } 84 | } 85 | } 86 | } 87 | } 88 | } 89 | 90 | signing { 91 | required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") } 92 | sign configurations.archives 93 | } 94 | 95 | task androidJavadocs(type: Javadoc) { 96 | source = android.sourceSets.main.java.srcDirs 97 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 98 | } 99 | 100 | task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { 101 | classifier = 'javadoc' 102 | from androidJavadocs.destinationDir 103 | } 104 | 105 | task androidSourcesJar(type: Jar) { 106 | classifier = 'sources' 107 | from android.sourceSets.main.java.sourceFiles 108 | } 109 | 110 | artifacts { 111 | archives androidSourcesJar 112 | // archives androidJavadocsJar 113 | } 114 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Settings specified in this file will override any Gradle settings 5 | # configured through the IDE. 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 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | RELEASE_REPOSITORY_URL=.//repository 21 | 22 | VERSION_NAME=0.3.0 23 | VERSION_CODE=12 24 | GROUP=rapid.decoder 25 | 26 | POM_DESCRIPTION= 27 | POM_URL=https://github.com/suckgamony/RapidDecoder 28 | POM_SCM_URL=https://github.com/suckgamony/RapidDecoder 29 | POM_SCM_CONNECTION=scm:git@github.com:suckgamony/RapidDecoder.git 30 | POM_SCM_DEV_CONNECTION=scm:git@github.com:suckgamony/RapidDecoder.git 31 | POM_LICENCE_NAME=The Apache Software License, Version 2.0 32 | POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt 33 | POM_LICENCE_DIST=repo 34 | POM_DEVELOPER_ID=suckgamony 35 | POM_DEVELOPER_NAME=suckgamony -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Nov 26 09:01:19 KST 2014 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-2.2-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 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 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /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 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 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 Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /jpeg-decoder/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /jpeg-decoder/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 21 5 | buildToolsVersion "21.1.2" 6 | 7 | sourceSets.main { 8 | jni.srcDirs += ['../builtin-decoder-common'] 9 | } 10 | defaultConfig { 11 | ndk { 12 | abiFilters "armeabi", "armeabi-v7a", "x86" 13 | moduleName "jpeg-decoder" 14 | ldLibs "jnigraphics" 15 | cFlags "-ffunction-sections -fdata-sections -fvisibility=hidden -Wl,--gc-sections " + 16 | "-Ibuiltin-decoder-common" 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | } 23 | 24 | apply from: '../gradle-mvn-push.gradle' -------------------------------------------------------------------------------- /jpeg-decoder/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_NAME=RapidDecoder jpeg decoder 2 | POM_ARTIFACT_ID=jpeg-decoder 3 | POM_PACKAGING=aar -------------------------------------------------------------------------------- /jpeg-decoder/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /opt/android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /jpeg-decoder/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /jpeg-decoder/src/main/jni/jpegdecoder.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "jpgd.h" 6 | 7 | using namespace jpgd; 8 | 9 | #define min(a, b) ((a) < (b) ? (a) : (b)) 10 | 11 | static jclass Bitmap; 12 | static jmethodID Bitmap_createBitmap1; 13 | static jmethodID Bitmap_recycle; 14 | 15 | static jfieldID Options_inSampleSize; 16 | static jfieldID Options_mCancel; 17 | 18 | // Java apis 19 | 20 | extern "C" JNIEXPORT 21 | void JNICALL Java_rapid_decoder_builtin_JpegDecoder_init(JNIEnv* env, jclass clazz) 22 | { 23 | Bitmap = (jclass) env->NewGlobalRef(env->FindClass("android/graphics/Bitmap")); 24 | Bitmap_createBitmap1 = env->GetStaticMethodID(Bitmap, "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;"); 25 | Bitmap_recycle = env->GetMethodID(Bitmap, "recycle", "()V"); 26 | 27 | jclass Options = env->FindClass("android/graphics/BitmapFactory$Options"); 28 | Options_inSampleSize = env->GetFieldID(Options, "inSampleSize", "I"); 29 | Options_mCancel = env->GetFieldID(Options, "mCancel", "Z"); 30 | } 31 | 32 | // JpegDecoder 33 | 34 | extern "C" JNIEXPORT 35 | jlong JNICALL Java_rapid_decoder_builtin_JpegDecoder_createNativeDecoder(JNIEnv* env, jclass clazz, 36 | jobject in) 37 | { 38 | jpeg_decoder* decoder = new jpeg_decoder(env, in); 39 | return (jlong)decoder; 40 | } 41 | 42 | extern "C" JNIEXPORT 43 | void JNICALL Java_rapid_decoder_builtin_JpegDecoder_destroyNativeDecoder(JNIEnv* env, jclass clazz, 44 | jlong decoderPtr) 45 | { 46 | jpeg_decoder* decoder = (jpeg_decoder*)decoderPtr; 47 | delete decoder; 48 | } 49 | 50 | extern "C" JNIEXPORT 51 | jboolean JNICALL Java_rapid_decoder_builtin_JpegDecoder_nativeBegin(JNIEnv* env, jclass clazz, 52 | jlong decoderPtr) 53 | { 54 | jpeg_decoder* decoder = (jpeg_decoder*)decoderPtr; 55 | return decoder->begin_decoding() == JPGD_SUCCESS; 56 | } 57 | 58 | extern "C" JNIEXPORT 59 | jint JNICALL Java_rapid_decoder_builtin_JpegDecoder_nativeGetWidth(JNIEnv* env, jclass clazz, 60 | jlong decoderPtr) 61 | { 62 | jpeg_decoder* decoder = (jpeg_decoder*)decoderPtr; 63 | return decoder->get_width(); 64 | } 65 | 66 | extern "C" JNIEXPORT 67 | jint JNICALL Java_rapid_decoder_builtin_JpegDecoder_nativeGetHeight(JNIEnv* env, jclass clazz, 68 | jlong decoderPtr) 69 | { 70 | jpeg_decoder* decoder = (jpeg_decoder*)decoderPtr; 71 | return decoder->get_height(); 72 | } 73 | 74 | extern "C" JNIEXPORT 75 | jobject JNICALL Java_rapid_decoder_builtin_JpegDecoder_nativeDecode(JNIEnv* env, jclass clazz, 76 | jlong decoderPtr, jint left, jint top, jint right, jint bottom, jboolean filter, jobject config, jobject opts) 77 | { 78 | jpeg_decoder* decoder = (jpeg_decoder*)decoderPtr; 79 | 80 | if (left < 0) 81 | { 82 | left = top = 0; 83 | right = decoder->get_width(); 84 | bottom = decoder->get_height(); 85 | } 86 | 87 | int w = right - left; 88 | int h = bottom - top; 89 | 90 | jint sample_size = env->GetIntField(opts, Options_inSampleSize); 91 | int sampled_width = (sample_size > 1 ? (w + sample_size - 1) / sample_size : w); 92 | int sampled_height = (sample_size > 1 ? (h + sample_size - 1) / sample_size : h); 93 | 94 | jobject bitmap = env->CallStaticObjectMethod(Bitmap, Bitmap_createBitmap1, sampled_width, sampled_height, config); 95 | 96 | AndroidBitmapInfo info; 97 | AndroidBitmap_getInfo(env, bitmap, &info); 98 | 99 | pixel_format format; 100 | 101 | switch (info.format) 102 | { 103 | case ANDROID_BITMAP_FORMAT_RGBA_8888: format = RGBA8888; break; 104 | case ANDROID_BITMAP_FORMAT_RGBA_4444: format = RGBA4444; break; 105 | case ANDROID_BITMAP_FORMAT_RGB_565: format = RGB565; break; 106 | default: 107 | env->CallVoidMethod(bitmap, Bitmap_recycle); 108 | return NULL; 109 | } 110 | 111 | opaque_sampler* sampler = NULL; 112 | 113 | if (sample_size > 1) 114 | { 115 | sampler = new opaque_sampler(w, sampled_width, sample_size, filter, format); 116 | decoder->set_pixel_format(RGB888); 117 | } 118 | else 119 | { 120 | decoder->set_pixel_format(format); 121 | } 122 | 123 | uint8* pixels; 124 | AndroidBitmap_lockPixels(env, bitmap, (void**)&pixels); 125 | 126 | decoder->set_column_offset(left); 127 | decoder->set_column_length(w); 128 | 129 | const void* buffer; 130 | uint bytes_read; 131 | 132 | int dest_bypp = decoder->get_bytes_per_pixel(); 133 | uint scan_line_length = w * dest_bypp; 134 | 135 | for (int i = 0; i < top; ++i) 136 | { 137 | int ret = decoder->skip(&bytes_read); 138 | if (ret == JPGD_DONE || ret == JPGD_FAILED || 139 | bytes_read < scan_line_length || 140 | env->GetBooleanField(opts, Options_mCancel)) goto canceled; 141 | } 142 | 143 | for (int i = top; i < bottom; ++i) 144 | { 145 | int ret = decoder->decode(&buffer, &bytes_read); 146 | if (ret == JPGD_DONE || ret == JPGD_FAILED || 147 | bytes_read < scan_line_length || 148 | env->GetBooleanField(opts, Options_mCancel)) goto canceled; 149 | 150 | if (sample_size > 1) 151 | { 152 | if (sampler->sample((const uint8*)buffer, 0, pixels)) 153 | { 154 | pixels += info.stride; 155 | } 156 | } 157 | else 158 | { 159 | memcpy(pixels, buffer, scan_line_length); 160 | pixels += info.stride; 161 | } 162 | } 163 | 164 | if (sample_size > 1) 165 | { 166 | sampler->finish(pixels); 167 | delete sampler; 168 | } 169 | AndroidBitmap_unlockPixels(env, bitmap); 170 | 171 | return bitmap; 172 | 173 | canceled: 174 | if (sample_size > 1) 175 | { 176 | delete sampler; 177 | } 178 | 179 | AndroidBitmap_unlockPixels(env, bitmap); 180 | env->CallVoidMethod(bitmap, Bitmap_recycle); 181 | return NULL; 182 | } -------------------------------------------------------------------------------- /library/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /library/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 21 5 | buildToolsVersion "21.1.2" 6 | 7 | defaultConfig { 8 | minSdkVersion 8 9 | targetSdkVersion 21 10 | versionCode 12 11 | versionName "0.3.0" 12 | } 13 | lintOptions { 14 | abortOnError false 15 | } 16 | } 17 | 18 | dependencies { 19 | //noinspection GradleDynamicVersion 20 | compile 'com.android.support:support-annotations:+' 21 | //noinspection GradleDynamicVersion 22 | provided 'com.android.support:support-v4:+' 23 | } 24 | 25 | //apply from: 'https://raw.github.com/chrisbanes/gradle-mvn-push/master/gradle-mvn-push.gradle' 26 | apply from: '../gradle-mvn-push.gradle' -------------------------------------------------------------------------------- /library/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_NAME=RapidDecoder library 2 | POM_ARTIFACT_ID=library 3 | POM_PACKAGING=aar -------------------------------------------------------------------------------- /library/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /opt/android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /library/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/AssetBitmapLoader.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.annotation.TargetApi; 4 | import android.content.Context; 5 | import android.content.res.AssetManager; 6 | import android.graphics.Bitmap; 7 | import android.graphics.BitmapFactory; 8 | import android.graphics.BitmapFactory.Options; 9 | import android.graphics.BitmapRegionDecoder; 10 | import android.os.Build; 11 | import android.support.annotation.NonNull; 12 | 13 | import java.io.IOException; 14 | import java.io.InputStream; 15 | 16 | class AssetBitmapLoader extends BitmapLoader { 17 | private AssetManager mAssetManager; 18 | private String mPath; 19 | 20 | public AssetBitmapLoader(Context context, @NonNull String path) { 21 | mAssetManager = context.getAssets(); 22 | mPath = path; 23 | } 24 | 25 | protected AssetBitmapLoader(AssetBitmapLoader other) { 26 | super(other); 27 | } 28 | 29 | @Override 30 | protected Bitmap decode(Options opts) { 31 | return BitmapFactory.decodeStream(openInputStream(), null, opts); 32 | } 33 | 34 | @Override 35 | protected InputStream openInputStream() { 36 | try { 37 | return new TwiceReadableInputStream(mAssetManager.open(mPath)); 38 | } catch (IOException ignored) { 39 | } 40 | return null; 41 | } 42 | 43 | @TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1) 44 | @Override 45 | protected BitmapRegionDecoder createBitmapRegionDecoder() { 46 | try { 47 | InputStream in = openInputStream(); 48 | if (in == null) { 49 | return null; 50 | } 51 | return BitmapRegionDecoder.newInstance(in, false); 52 | } catch (IOException e) { 53 | return null; 54 | } 55 | } 56 | 57 | @NonNull 58 | @Override 59 | public BitmapLoader fork() { 60 | return new AssetBitmapLoader(this); 61 | } 62 | 63 | @Override 64 | public boolean equals(Object o) { 65 | return o == this || o instanceof AssetBitmapLoader && super.equals(o); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/BackgroundTask.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.graphics.Bitmap; 4 | import android.os.AsyncTask; 5 | import android.os.Build; 6 | 7 | import java.lang.ref.WeakReference; 8 | 9 | import rapid.decoder.cache.CacheSource; 10 | 11 | class BackgroundTask extends AsyncTask { 12 | public static class Result { 13 | public Bitmap bitmap; 14 | public CacheSource cacheSource; 15 | 16 | public Result(Bitmap bitmap, CacheSource cacheSource) { 17 | this.bitmap = bitmap; 18 | this.cacheSource = cacheSource; 19 | } 20 | } 21 | 22 | private Decodable mDecodable; 23 | private Decodable.OnBitmapDecodedListener mListener; 24 | private ViewFrameBuilder mFrameBuilder; 25 | private Object mKey; 26 | 27 | public BackgroundTask(Object key) { 28 | mKey = key; 29 | } 30 | 31 | public void setDecodable(Decodable decodable) { 32 | mDecodable = decodable; 33 | } 34 | 35 | public void setOnBitmapDecodedListener(Decodable.OnBitmapDecodedListener listener) { 36 | mListener = listener; 37 | } 38 | 39 | private boolean removeKey() { 40 | if (mKey == null) return false; 41 | if (mKey instanceof WeakReference) { 42 | return BackgroundTaskManager.removeWeak(((WeakReference) mKey).get()) != null; 43 | } else { 44 | return BackgroundTaskManager.removeStrong(mKey) != null; 45 | } 46 | } 47 | 48 | @Override 49 | protected void onPostExecute(Result result) { 50 | if (removeKey()) { 51 | if (mListener != null) { 52 | if (result == null) { 53 | mListener.onBitmapDecoded(null, null); 54 | } else { 55 | mListener.onBitmapDecoded(result.bitmap, result.cacheSource); 56 | } 57 | mListener = null; 58 | } 59 | } else { 60 | dispatchCancel(); 61 | } 62 | } 63 | 64 | @Override 65 | protected Result doInBackground(Object... params) { 66 | Decodable d = null; 67 | if (mFrameBuilder != null) { 68 | d = mFrameBuilder.getFramedDecoder(false); 69 | } 70 | if (d == null) { 71 | d = mDecodable; 72 | } 73 | 74 | Bitmap bitmap = d.decode(); 75 | if (bitmap == null || isCancelled()) return null; 76 | 77 | CacheSource cacheSource = d.cacheSource(); 78 | return new Result(bitmap, cacheSource); 79 | } 80 | 81 | protected void onCancelled() { 82 | dispatchCancel(); 83 | } 84 | 85 | private void dispatchCancel() { 86 | if (mListener != null) { 87 | mListener.onCancel(); 88 | mListener = null; 89 | } 90 | } 91 | 92 | public void cancel() { 93 | cancel(false); 94 | if (mDecodable != null) { 95 | mDecodable.cancel(); 96 | } 97 | removeKey(); 98 | dispatchCancel(); 99 | } 100 | 101 | public void setFrameBuilder(ViewFrameBuilder builder) { 102 | mFrameBuilder = builder; 103 | } 104 | 105 | public void start() { 106 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 107 | executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 108 | } else { 109 | execute(); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/BackgroundTaskManager.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.app.Activity; 4 | import android.app.Fragment; 5 | import android.os.Build; 6 | import android.support.annotation.NonNull; 7 | import android.view.View; 8 | 9 | import java.lang.ref.WeakReference; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | import java.util.WeakHashMap; 13 | 14 | class BackgroundTaskManager { 15 | private static Boolean sHasSupportLibraryV4; 16 | 17 | private static WeakHashMap sWeakTasks; 18 | private static HashMap sStrongTasks; 19 | 20 | @NonNull 21 | public static BackgroundTask register(@NonNull Object key) { 22 | BackgroundTask task; 23 | if (shouldBeWeak(key)) { 24 | task = new BackgroundTask(new WeakReference(key)); 25 | if (sWeakTasks == null) { 26 | sWeakTasks = new WeakHashMap(); 27 | } else { 28 | cancelTask(sWeakTasks, key); 29 | } 30 | sWeakTasks.put(key, task); 31 | } else { 32 | task = new BackgroundTask(key); 33 | if (sStrongTasks == null) { 34 | sStrongTasks = new HashMap(); 35 | } else { 36 | cancelTask(sStrongTasks, key); 37 | } 38 | sStrongTasks.put(key, task); 39 | } 40 | return task; 41 | } 42 | 43 | public static BackgroundTask removeWeak(Object key) { 44 | if (key == null) return null; 45 | if (sWeakTasks != null) { 46 | return sWeakTasks.remove(key); 47 | } 48 | return null; 49 | } 50 | 51 | public static BackgroundTask removeStrong(Object key) { 52 | if (key == null) return null; 53 | if (sStrongTasks != null) { 54 | return sStrongTasks.remove(key); 55 | } 56 | return null; 57 | } 58 | 59 | public static boolean cancelStrong(Object key) { 60 | return sStrongTasks != null && cancelTask(sStrongTasks, key); 61 | } 62 | 63 | public static boolean cancelWeak(Object key) { 64 | return sWeakTasks != null && cancelTask(sWeakTasks, key); 65 | } 66 | 67 | private static boolean cancelTask(Map map, Object key) { 68 | BackgroundTask task = map.remove(key); 69 | if (task != null) { 70 | task.cancel(); 71 | return true; 72 | } else { 73 | return false; 74 | } 75 | } 76 | 77 | private static boolean hasSupportLibraryV4() { 78 | if (sHasSupportLibraryV4 == null) { 79 | try { 80 | Class.forName("android.support.v4.app.Fragment"); 81 | sHasSupportLibraryV4 = true; 82 | } catch (ClassNotFoundException e) { 83 | sHasSupportLibraryV4 = false; 84 | } 85 | } 86 | return sHasSupportLibraryV4; 87 | } 88 | 89 | static boolean shouldBeWeak(Object o) { 90 | return o instanceof View || 91 | o instanceof Activity || 92 | Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB && o instanceof Fragment || 93 | hasSupportLibraryV4() && o instanceof android.support.v4.app.Fragment; 94 | } 95 | 96 | public static boolean hasAnyTasks() { 97 | return sWeakTasks != null && !sWeakTasks.isEmpty() || 98 | sStrongTasks != null && !sStrongTasks.isEmpty(); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/BitmapMeta.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | public interface BitmapMeta { 4 | int width(); 5 | int height(); 6 | } 7 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/BitmapPostProcessor.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.graphics.Bitmap; 4 | 5 | public interface BitmapPostProcessor { 6 | Bitmap process(Bitmap bitmap); 7 | } 8 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/BitmapUtils.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Canvas; 5 | import android.graphics.PixelFormat; 6 | import android.graphics.Bitmap.Config; 7 | import android.graphics.drawable.BitmapDrawable; 8 | import android.graphics.drawable.Drawable; 9 | import android.os.Build; 10 | 11 | import static rapid.decoder.cache.ResourcePool.*; 12 | 13 | public final class BitmapUtils { 14 | @SuppressWarnings("UnusedDeclaration") 15 | public static Bitmap getBitmap(Drawable d) { 16 | if (d instanceof BitmapDrawable) { 17 | return ((BitmapDrawable) d).getBitmap(); 18 | } else { 19 | final boolean opaque = (d.getOpacity() == PixelFormat.OPAQUE); 20 | 21 | final Bitmap bitmap = Bitmap.createBitmap(d.getIntrinsicWidth(), d.getIntrinsicHeight(), 22 | opaque ? Config.RGB_565 : Config.ARGB_8888); 23 | d.setDither(opaque); 24 | d.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight()); 25 | 26 | Canvas cv = CANVAS.obtain(bitmap); 27 | d.draw(cv); 28 | CANVAS.recycle(cv); 29 | 30 | return bitmap; 31 | } 32 | } 33 | 34 | public static int getByteCount(Bitmap bitmap) { 35 | if (Build.VERSION.SDK_INT >= 19) { 36 | return bitmap.getAllocationByteCount(); 37 | } else if (Build.VERSION.SDK_INT >= 12) { 38 | return bitmap.getByteCount(); 39 | } else { 40 | return getByteCount(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig()); 41 | } 42 | } 43 | 44 | public static int getByteCount(int width, int height, Config config) { 45 | final int bytesPerPixel = (config.equals(Config.ARGB_8888) ? 4 : 2); 46 | return width * height * bytesPerPixel; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/ByteArrayBitmapLoader.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.annotation.TargetApi; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.graphics.BitmapFactory.Options; 7 | import android.graphics.BitmapRegionDecoder; 8 | import android.os.Build; 9 | import android.support.annotation.NonNull; 10 | 11 | import java.io.ByteArrayInputStream; 12 | import java.io.IOException; 13 | import java.io.InputStream; 14 | import java.util.Arrays; 15 | 16 | class ByteArrayBitmapLoader extends BitmapLoader { 17 | private byte[] data; 18 | private int offset; 19 | private int length; 20 | 21 | public ByteArrayBitmapLoader(byte[] data, int offset, int length) { 22 | if (data == null) { 23 | throw new NullPointerException(); 24 | } 25 | 26 | this.data = data; 27 | this.offset = offset; 28 | this.length = length; 29 | } 30 | 31 | protected ByteArrayBitmapLoader(ByteArrayBitmapLoader other) { 32 | super(other); 33 | data = other.data; 34 | offset = other.offset; 35 | length = other.length; 36 | } 37 | 38 | @Override 39 | protected Bitmap decode(Options opts) { 40 | return BitmapFactory.decodeByteArray(data, offset, length, opts); 41 | } 42 | 43 | @Override 44 | protected InputStream openInputStream() { 45 | return new ByteArrayInputStream(data, offset, length); 46 | } 47 | 48 | @TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1) 49 | @Override 50 | protected BitmapRegionDecoder createBitmapRegionDecoder() { 51 | try { 52 | return BitmapRegionDecoder.newInstance(data, offset, length, false); 53 | } catch (IOException e) { 54 | return null; 55 | } 56 | } 57 | 58 | @NonNull 59 | @Override 60 | public BitmapLoader fork() { 61 | return new ByteArrayBitmapLoader(this); 62 | } 63 | 64 | @Override 65 | public int hashCode() { 66 | if (mHashCode == 0) { 67 | mHashCode = super.hashCode() + 31 * (Arrays.hashCode(data) + 31 * (offset + 31 * length)); 68 | } 69 | return mHashCode; 70 | } 71 | 72 | @Override 73 | public boolean equals(Object o) { 74 | if (o == this) return true; 75 | if (!super.equals(o) || !(o instanceof ByteArrayBitmapLoader)) return false; 76 | 77 | final ByteArrayBitmapLoader d = (ByteArrayBitmapLoader) o; 78 | return Arrays.equals(data, d.data) && 79 | offset == d.offset && 80 | length == d.length; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/CloneUtils.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.graphics.BitmapFactory.Options; 5 | import android.os.Build; 6 | 7 | import static rapid.decoder.cache.ResourcePool.*; 8 | 9 | public final class CloneUtils { 10 | @SuppressLint("NewApi") 11 | public static Options clone(Options other) { 12 | final Options opts = OPTIONS.obtainNotReset(); 13 | 14 | opts.inDensity = other.inDensity; 15 | opts.inDither = other.inDither; 16 | opts.inInputShareable = other.inInputShareable; 17 | opts.inJustDecodeBounds = other.inJustDecodeBounds; 18 | opts.inPreferredConfig = other.inPreferredConfig; 19 | opts.inPurgeable = other.inPurgeable; 20 | opts.inSampleSize = other.inSampleSize; 21 | opts.inScaled = other.inScaled; 22 | opts.inScreenDensity = other.inScreenDensity; 23 | opts.inTargetDensity = other.inTargetDensity; 24 | opts.inTempStorage = other.inTempStorage; 25 | opts.mCancel = other.mCancel; 26 | opts.outHeight = other.outHeight; 27 | opts.outMimeType = other.outMimeType; 28 | opts.outWidth = other.outWidth; 29 | 30 | final int ver = Build.VERSION.SDK_INT; 31 | if (ver >= 10) { 32 | opts.inPreferQualityOverSpeed = other.inPreferQualityOverSpeed; 33 | 34 | if (ver >= 11) { 35 | opts.inBitmap = other.inBitmap; 36 | opts.inMutable = other.inMutable; 37 | 38 | if (ver >= 19) { 39 | opts.inPremultiplied = other.inPremultiplied; 40 | } 41 | } 42 | } 43 | 44 | return opts; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/Decodable.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Canvas; 5 | import android.graphics.Rect; 6 | import android.support.annotation.NonNull; 7 | import android.support.annotation.Nullable; 8 | import android.view.View; 9 | import android.widget.ImageView; 10 | 11 | import rapid.decoder.binder.ImageViewBinder; 12 | import rapid.decoder.binder.ViewBackgroundBinder; 13 | import rapid.decoder.binder.ViewBinder; 14 | import rapid.decoder.cache.CacheSource; 15 | import rapid.decoder.frame.FramedDecoder; 16 | import rapid.decoder.frame.FramingMethod; 17 | import rapid.decoder.frame.ScaleTypeFraming; 18 | 19 | public abstract class Decodable implements BitmapMeta { 20 | public interface OnBitmapDecodedListener { 21 | void onBitmapDecoded(@Nullable Bitmap bitmap, @Nullable CacheSource cacheSource); 22 | 23 | void onCancel(); 24 | } 25 | 26 | private boolean mIsMemoryCacheEnabled = true; 27 | 28 | public void into(final ViewBinder binder) { 29 | into(binder, null); 30 | } 31 | 32 | public void into(final ViewBinder binder, final OnBitmapDecodedListener listener) { 33 | View v = binder.getView(); 34 | if (v == null) return; 35 | 36 | final BackgroundTask task = BackgroundTaskManager.register(v); 37 | binder.runAfterReady(new ViewBinder.OnReadyListener() { 38 | @Override 39 | public void onReady(View v, boolean async) { 40 | if (task.isCancelled()) return; 41 | loadBitmapWhenReady(task, binder, async, listener); 42 | } 43 | }); 44 | if (!task.isCancelled()) { 45 | binder.showPlaceholder(); 46 | } 47 | } 48 | 49 | void loadBitmapWhenReady(BackgroundTask task, final ViewBinder binder, boolean async, 50 | final OnBitmapDecodedListener listener) { 51 | ViewFrameBuilder frameBuilder; 52 | FramingMethod framing = binder.framing(); 53 | if (framing == null) { 54 | framing = new ScaleTypeFraming(ImageView.ScaleType.CENTER_CROP); 55 | } 56 | frameBuilder = setupFrameBuilder(binder, framing); 57 | if (frameBuilder != null) { 58 | frameBuilder.prepareFraming(); 59 | if (!async) { 60 | FramedDecoder framedDecoder = frameBuilder.getFramedDecoder(true); 61 | if (framedDecoder != null) { 62 | Bitmap bitmap = framedDecoder.getCachedBitmap(); 63 | if (bitmap != null) { 64 | task.cancel(); 65 | binder.bind(bitmap, false); 66 | if (listener != null) { 67 | listener.onBitmapDecoded(bitmap, CacheSource.MEMORY); 68 | } 69 | return; 70 | } 71 | } 72 | } 73 | } 74 | 75 | task.setDecodable(this); 76 | task.setOnBitmapDecodedListener(new OnBitmapDecodedListener() { 77 | @Override 78 | public void onBitmapDecoded(@Nullable Bitmap bitmap, 79 | @Nullable CacheSource cacheSource) { 80 | if (bitmap == null) { 81 | binder.showErrorImage(); 82 | if (listener != null) { 83 | listener.onBitmapDecoded(null, null); 84 | } 85 | } else { 86 | binder.bind(bitmap, true); 87 | if (listener != null) { 88 | listener.onBitmapDecoded(bitmap, cacheSource); 89 | } 90 | } 91 | } 92 | 93 | @Override 94 | public void onCancel() { 95 | binder.recycle(); 96 | if (listener != null) { 97 | listener.onCancel(); 98 | } 99 | } 100 | }); 101 | task.setFrameBuilder(frameBuilder); 102 | task.start(); 103 | } 104 | 105 | protected ViewFrameBuilder setupFrameBuilder(ViewBinder binder, FramingMethod framing) { 106 | return null; 107 | } 108 | 109 | public void into(View v) { 110 | into(v, null); 111 | } 112 | 113 | public void into(View v, OnBitmapDecodedListener listener) { 114 | if (v instanceof ImageView) { 115 | into(ImageViewBinder.obtain((ImageView) v), listener); 116 | } else { 117 | into(ViewBackgroundBinder.obtain(v), listener); 118 | } 119 | } 120 | 121 | public void decode(@NonNull OnBitmapDecodedListener listener) { 122 | decode(this, listener); 123 | } 124 | 125 | public void decode(@NonNull Object key, @NonNull OnBitmapDecodedListener listener) { 126 | BackgroundTask task = BackgroundTaskManager.register(key); 127 | task.setDecodable(this); 128 | task.setOnBitmapDecodedListener(listener); 129 | task.start(); 130 | } 131 | 132 | public boolean isMemoryCacheEnabled() { 133 | return mIsMemoryCacheEnabled; 134 | } 135 | 136 | public Decodable useMemoryCache(boolean useCache) { 137 | this.mIsMemoryCacheEnabled = useCache; 138 | return this; 139 | } 140 | 141 | public Bitmap getCachedBitmap() { 142 | return null; 143 | } 144 | 145 | public BitmapMeta getCachedMeta() { 146 | return null; 147 | } 148 | 149 | public abstract CacheSource cacheSource(); 150 | 151 | public abstract void cancel(); 152 | 153 | @Nullable 154 | public abstract Bitmap decode(); 155 | 156 | @SuppressWarnings("UnusedDeclaration") 157 | public abstract void draw(Canvas cv, Rect bounds); 158 | 159 | public abstract Decodable fork(); 160 | 161 | public abstract boolean isCancelled(); 162 | 163 | public abstract int width(); 164 | 165 | public abstract int height(); 166 | } 167 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/FileBitmapLoader.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.annotation.TargetApi; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.graphics.BitmapFactory.Options; 7 | import android.graphics.BitmapRegionDecoder; 8 | import android.os.Build; 9 | import android.support.annotation.NonNull; 10 | 11 | import java.io.FileInputStream; 12 | import java.io.FileNotFoundException; 13 | import java.io.IOException; 14 | import java.io.InputStream; 15 | 16 | class FileBitmapLoader extends BitmapLoader { 17 | public FileBitmapLoader(String pathName) { 18 | if (pathName == null) { 19 | throw new NullPointerException(); 20 | } 21 | mId = pathName; 22 | } 23 | 24 | protected FileBitmapLoader(FileBitmapLoader other) { 25 | super(other); 26 | } 27 | 28 | @Override 29 | protected Bitmap decode(Options opts) { 30 | return BitmapFactory.decodeFile((String) mId, opts); 31 | } 32 | 33 | @Override 34 | protected InputStream openInputStream() { 35 | try { 36 | return new FileInputStream((String) mId); 37 | } catch (FileNotFoundException e) { 38 | return null; 39 | } 40 | } 41 | 42 | @TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1) 43 | @Override 44 | protected BitmapRegionDecoder createBitmapRegionDecoder() { 45 | try { 46 | return BitmapRegionDecoder.newInstance((String) mId, false); 47 | } catch (IOException e) { 48 | return null; 49 | } 50 | } 51 | 52 | @NonNull 53 | @Override 54 | public BitmapLoader fork() { 55 | return new FileBitmapLoader(this); 56 | } 57 | 58 | @Override 59 | public boolean equals(Object o) { 60 | return o == this || o instanceof FileBitmapLoader && super.equals(o); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/FileDescriptorBitmapLoader.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.annotation.TargetApi; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.graphics.BitmapFactory.Options; 7 | import android.graphics.BitmapRegionDecoder; 8 | import android.os.Build; 9 | import android.support.annotation.NonNull; 10 | 11 | import java.io.FileDescriptor; 12 | import java.io.FileInputStream; 13 | import java.io.IOException; 14 | import java.io.InputStream; 15 | 16 | class FileDescriptorBitmapLoader extends BitmapLoader { 17 | private FileDescriptor fd; 18 | 19 | public FileDescriptorBitmapLoader(FileDescriptor fd) { 20 | this.fd = fd; 21 | } 22 | 23 | protected FileDescriptorBitmapLoader(FileDescriptorBitmapLoader other) { 24 | super(other); 25 | fd = other.fd; 26 | } 27 | 28 | @Override 29 | protected Bitmap decode(Options opts) { 30 | return BitmapFactory.decodeFileDescriptor(fd, null, opts); 31 | } 32 | 33 | @Override 34 | protected InputStream openInputStream() { 35 | return new FileInputStream(fd); 36 | } 37 | 38 | @TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1) 39 | @Override 40 | protected BitmapRegionDecoder createBitmapRegionDecoder() { 41 | try { 42 | return BitmapRegionDecoder.newInstance(fd, false); 43 | } catch (IOException e) { 44 | return null; 45 | } 46 | } 47 | 48 | @NonNull 49 | @Override 50 | public BitmapLoader fork() { 51 | return new FileDescriptorBitmapLoader(this); 52 | } 53 | 54 | @Override 55 | public int hashCode() { 56 | if (mHashCode == 0) { 57 | mHashCode = super.hashCode() + 31 * fd.hashCode(); 58 | } 59 | return mHashCode; 60 | } 61 | 62 | @Override 63 | public boolean equals(Object o) { 64 | if (o == this) return true; 65 | if (!(o instanceof FileDescriptorBitmapLoader) || !super.equals(o)) return false; 66 | 67 | final FileDescriptorBitmapLoader fdd = (FileDescriptorBitmapLoader) o; 68 | return fd.equals(fdd.fd); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/ForInternalUse.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target(ElementType.METHOD) 9 | @Retention(RetentionPolicy.CLASS) 10 | public @interface ForInternalUse { 11 | } 12 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/IntegerMaker.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | public enum IntegerMaker { 4 | ROUND { 5 | @Override 6 | public int toInteger(float f) { 7 | return Math.round(f); 8 | } 9 | }, 10 | CEIL { 11 | @Override 12 | public int toInteger(float f) { 13 | return (int) Math.ceil(f); 14 | } 15 | }; 16 | 17 | public abstract int toInteger(float f); 18 | } 19 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/LazyInputStream.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import java.io.ByteArrayInputStream; 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | 9 | class LazyInputStream extends InputStream { 10 | private StreamOpener mOpener; 11 | protected InputStream mIn; 12 | 13 | public LazyInputStream(StreamOpener opener) { 14 | mOpener = opener; 15 | } 16 | 17 | public StreamOpener getStreamOpener() { 18 | return mOpener; 19 | } 20 | 21 | @Override 22 | public int read() throws IOException { 23 | return getStream().read(); 24 | } 25 | 26 | @Override 27 | public int available() throws IOException { 28 | return getStream().available(); 29 | } 30 | 31 | @Override 32 | public void close() throws IOException { 33 | if (mIn != null) { 34 | mIn.close(); 35 | } 36 | } 37 | 38 | @Override 39 | public void mark(int readlimit) { 40 | getStream().mark(readlimit); 41 | } 42 | 43 | @Override 44 | public boolean markSupported() { 45 | return getStream().markSupported(); 46 | } 47 | 48 | @Override 49 | public int read(@NonNull byte[] buffer) throws IOException { 50 | return getStream().read(buffer); 51 | } 52 | 53 | @Override 54 | public int read(@NonNull byte[] buffer, int byteOffset, int byteCount) 55 | throws IOException { 56 | 57 | return getStream().read(buffer, byteOffset, byteCount); 58 | } 59 | 60 | @Override 61 | public synchronized void reset() throws IOException { 62 | getStream().reset(); 63 | } 64 | 65 | @Override 66 | public long skip(long byteCount) throws IOException { 67 | return getStream().skip(byteCount); 68 | } 69 | 70 | protected InputStream getStream() { 71 | if (mIn == null) { 72 | mIn = mOpener.openInputStream(); 73 | if (mIn == null) { 74 | mIn = new ByteArrayInputStream(new byte[0]); 75 | } 76 | } 77 | return mIn; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/NextLayoutInspector.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.os.Build; 5 | import android.view.View; 6 | import android.view.ViewTreeObserver; 7 | 8 | import java.lang.ref.WeakReference; 9 | 10 | public class NextLayoutInspector { 11 | private static final boolean TEST_COMPAT = false; 12 | 13 | public interface OnNextLayoutListener { 14 | void onNextLayout(View v); 15 | } 16 | 17 | @SuppressLint("NewApi") 18 | public static void inspectNextLayout(View v, final OnNextLayoutListener listener) { 19 | //noinspection ConstantConditions,PointlessBooleanExpression 20 | if (TEST_COMPAT || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { 21 | new LayoutChangeInspector(v, listener).startInspect(); 22 | } else { 23 | v.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { 24 | @Override 25 | public void onLayoutChange(View v, int left, int top, int right, int bottom, 26 | int oldLeft, int oldTop, int oldRight, int oldBottom) { 27 | v.removeOnLayoutChangeListener(this); 28 | listener.onNextLayout(v); 29 | } 30 | }); 31 | } 32 | } 33 | 34 | private static class LayoutChangeInspector implements Runnable, 35 | ViewTreeObserver.OnGlobalLayoutListener { 36 | private WeakReference mViewRef; 37 | private int mLeft; 38 | private int mTop; 39 | private int mRight; 40 | private int mBottom; 41 | private OnNextLayoutListener mListener; 42 | 43 | public LayoutChangeInspector(View v, OnNextLayoutListener listener) { 44 | mViewRef = new WeakReference(v); 45 | mLeft = v.getLeft(); 46 | mTop = v.getTop(); 47 | mRight = v.getRight(); 48 | mBottom = v.getBottom(); 49 | mListener = listener; 50 | } 51 | 52 | public void startInspect() { 53 | View v = mViewRef.get(); 54 | if (v == null) return; 55 | 56 | if (!v.isLayoutRequested()) { 57 | mListener.onNextLayout(v); 58 | } else { 59 | v.post(this); 60 | v.getViewTreeObserver().addOnGlobalLayoutListener(this); 61 | } 62 | } 63 | 64 | @Override 65 | public void run() { 66 | View v = mViewRef.get(); 67 | if (v == null) return; 68 | 69 | if (!v.isLayoutRequested() || 70 | v.getLeft() != mLeft || 71 | v.getTop() != mTop || 72 | v.getRight() != mRight || 73 | v.getBottom() != mBottom) { 74 | 75 | removeOnGlobalLayoutListener(v); 76 | mListener.onNextLayout(v); 77 | } else { 78 | v.post(this); 79 | } 80 | } 81 | 82 | @Override 83 | public void onGlobalLayout() { 84 | View v = mViewRef.get(); 85 | if (v == null) return; 86 | 87 | removeOnGlobalLayoutListener(v); 88 | v.removeCallbacks(this); 89 | mListener.onNextLayout(v); 90 | } 91 | 92 | @SuppressWarnings("deprecation") 93 | private void removeOnGlobalLayoutListener(View v) { 94 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 95 | v.getViewTreeObserver().removeOnGlobalLayoutListener(this); 96 | } else { 97 | v.getViewTreeObserver().removeGlobalOnLayoutListener(this); 98 | } 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/NullBitmapLoader.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.BitmapFactory; 5 | import android.graphics.BitmapRegionDecoder; 6 | import android.graphics.Canvas; 7 | import android.graphics.Rect; 8 | import android.graphics.drawable.Drawable; 9 | import android.support.annotation.NonNull; 10 | import android.support.annotation.Nullable; 11 | 12 | import java.io.InputStream; 13 | 14 | import rapid.decoder.cache.CacheSource; 15 | 16 | public class NullBitmapLoader extends BitmapLoader { 17 | @Override 18 | public int sourceWidth() { 19 | return 0; 20 | } 21 | 22 | @Override 23 | public int sourceHeight() { 24 | return 0; 25 | } 26 | 27 | @Override 28 | public void draw(Canvas cv, Rect rectDest) { 29 | 30 | } 31 | 32 | @Override 33 | public BitmapLoader config(Bitmap.Config config) { 34 | return null; 35 | } 36 | 37 | @Override 38 | public Bitmap.Config config() { 39 | return null; 40 | } 41 | 42 | @Override 43 | public Bitmap createAndDraw(int width, int height, @NonNull Rect rectDest, @Nullable Drawable 44 | background) { 45 | return null; 46 | } 47 | 48 | @Override 49 | public BitmapLoader useBuiltInDecoder(boolean force) { 50 | return null; 51 | } 52 | 53 | @Override 54 | public BitmapLoader filterBitmap(boolean filter) { 55 | return null; 56 | } 57 | 58 | @Override 59 | public CacheSource cacheSource() { 60 | return null; 61 | } 62 | 63 | @Override 64 | public void cancel() { 65 | 66 | } 67 | 68 | @Override 69 | public Bitmap decode() { 70 | return null; 71 | } 72 | 73 | @NonNull 74 | @Override 75 | public BitmapDecoder fork() { 76 | return this; 77 | } 78 | 79 | @Override 80 | public boolean isCancelled() { 81 | return false; 82 | } 83 | 84 | @Override 85 | public BitmapLoader mutable(boolean mutable) { 86 | return null; 87 | } 88 | 89 | @Nullable 90 | @Override 91 | protected Bitmap decode(BitmapFactory.Options opts) { 92 | return null; 93 | } 94 | 95 | @Nullable 96 | @Override 97 | protected InputStream openInputStream() { 98 | return null; 99 | } 100 | 101 | @Override 102 | protected BitmapRegionDecoder createBitmapRegionDecoder() { 103 | return null; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/Quality.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.BitmapFactory; 5 | import android.os.Build; 6 | 7 | public enum Quality { 8 | @SuppressWarnings("UnusedDeclaration") 9 | UNDEFINED { 10 | @Override 11 | void applyTo(BitmapFactory.Options options) { 12 | options.inPreferredConfig = null; 13 | options.inDither = false; 14 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD_MR1) { 15 | options.inPreferQualityOverSpeed = false; 16 | } 17 | } 18 | }, 19 | HIGH { 20 | @Override 21 | void applyTo(BitmapFactory.Options options) { 22 | options.inPreferredConfig = Bitmap.Config.ARGB_8888; 23 | options.inDither = false; 24 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD_MR1) { 25 | options.inPreferQualityOverSpeed = false; 26 | } 27 | } 28 | }, 29 | @SuppressWarnings("UnusedDeclaration") 30 | HIGH_OPAQUE { 31 | @Override 32 | void applyTo(BitmapFactory.Options options) { 33 | HIGH.applyTo(options); 34 | } 35 | 36 | @Override 37 | boolean shouldConvertToOpaqueOnScale() { 38 | return true; 39 | } 40 | }, 41 | @SuppressWarnings("UnusedDeclaration") 42 | MID { 43 | @Override 44 | void applyTo(BitmapFactory.Options options) { 45 | options.inPreferredConfig = Bitmap.Config.ARGB_4444; 46 | options.inDither = true; 47 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD_MR1) { 48 | options.inPreferQualityOverSpeed = true; 49 | } 50 | } 51 | }, 52 | @SuppressWarnings("UnusedDeclaration") 53 | MID_OPAQUE { 54 | @Override 55 | void applyTo(BitmapFactory.Options options) { 56 | options.inPreferredConfig = Bitmap.Config.RGB_565; 57 | options.inDither = true; 58 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD_MR1) { 59 | options.inPreferQualityOverSpeed = true; 60 | } 61 | } 62 | }, 63 | @SuppressWarnings("UnusedDeclaration") 64 | LOW { 65 | @Override 66 | void applyTo(BitmapFactory.Options options) { 67 | options.inPreferredConfig = Bitmap.Config.ARGB_4444; 68 | options.inDither = true; 69 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD_MR1) { 70 | options.inPreferQualityOverSpeed = false; 71 | } 72 | } 73 | }, 74 | @SuppressWarnings("UnusedDeclaration") 75 | LOW_OPAQUE { 76 | @Override 77 | void applyTo(BitmapFactory.Options options) { 78 | options.inPreferredConfig = Bitmap.Config.RGB_565; 79 | options.inDither = true; 80 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD_MR1) { 81 | options.inPreferQualityOverSpeed = false; 82 | } 83 | } 84 | }, 85 | @SuppressWarnings("UnusedDeclaration") 86 | LOWEST { 87 | @Override 88 | void applyTo(BitmapFactory.Options options) { 89 | options.inPreferredConfig = Bitmap.Config.ARGB_4444; 90 | options.inDither = false; 91 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD_MR1) { 92 | options.inPreferQualityOverSpeed = false; 93 | } 94 | } 95 | }, 96 | @SuppressWarnings("UnusedDeclaration") 97 | LOWEST_OPAQUE { 98 | @Override 99 | void applyTo(BitmapFactory.Options options) { 100 | options.inPreferredConfig = Bitmap.Config.RGB_565; 101 | options.inDither = false; 102 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD_MR1) { 103 | options.inPreferQualityOverSpeed = false; 104 | } 105 | } 106 | }; 107 | 108 | abstract void applyTo(BitmapFactory.Options options); 109 | 110 | boolean shouldConvertToOpaqueOnScale() { 111 | return false; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/Queriable.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.database.Cursor; 4 | 5 | public interface Queriable { 6 | Cursor query(); 7 | } 8 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/ResourceBitmapLoader.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.annotation.TargetApi; 4 | import android.content.res.Resources; 5 | import android.graphics.Bitmap; 6 | import android.graphics.BitmapFactory; 7 | import android.graphics.BitmapFactory.Options; 8 | import android.graphics.BitmapRegionDecoder; 9 | import android.os.Build; 10 | import android.support.annotation.NonNull; 11 | 12 | import java.io.IOException; 13 | import java.io.InputStream; 14 | 15 | class ResourceBitmapLoader extends BitmapLoader { 16 | private static class Identifier { 17 | public Resources res; 18 | public int id; 19 | 20 | private Identifier(Resources res, int id) { 21 | this.res = res; 22 | this.id = id; 23 | } 24 | 25 | @Override 26 | public int hashCode() { 27 | return res.hashCode() + 31 * id; 28 | } 29 | 30 | @Override 31 | public boolean equals(Object o) { 32 | if (this == o) return true; 33 | if (!(o instanceof Identifier)) return false; 34 | 35 | Identifier id2 = (Identifier) o; 36 | return res.equals(id2.res) && id == id2.id; 37 | } 38 | } 39 | 40 | private float densityRatio; 41 | 42 | public ResourceBitmapLoader(Resources res, int id) { 43 | mId = new Identifier(res, id); 44 | } 45 | 46 | protected ResourceBitmapLoader(ResourceBitmapLoader other) { 47 | super(other); 48 | densityRatio = other.densityRatio; 49 | } 50 | 51 | @Override 52 | protected Bitmap decode(Options opts) { 53 | Identifier id = (Identifier) mId; 54 | return BitmapFactory.decodeResource(id.res, id.id, opts); 55 | } 56 | 57 | @Override 58 | protected InputStream openInputStream() { 59 | Identifier id = (Identifier) mId; 60 | return id.res.openRawResource(id.id); 61 | } 62 | 63 | @TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1) 64 | @Override 65 | protected BitmapRegionDecoder createBitmapRegionDecoder() { 66 | try { 67 | InputStream in = openInputStream(); 68 | if (in == null) { 69 | return null; 70 | } 71 | return BitmapRegionDecoder.newInstance(in, false); 72 | } catch (IOException e) { 73 | return null; 74 | } 75 | } 76 | 77 | @Override 78 | protected float densityRatio() { 79 | if (densityRatio == 0) { 80 | decodeBounds(); 81 | 82 | if (mOptions.inDensity != 0 && mOptions.inTargetDensity != 0) { 83 | densityRatio = (float) mOptions.inTargetDensity / mOptions.inDensity; 84 | } else { 85 | densityRatio = 1; 86 | } 87 | } 88 | return densityRatio; 89 | } 90 | 91 | @NonNull 92 | @Override 93 | public BitmapLoader fork() { 94 | return new ResourceBitmapLoader(this); 95 | } 96 | 97 | @Override 98 | public int hashCode() { 99 | if (mHashCode == 0) { 100 | Identifier id = (Identifier) mId; 101 | mHashCode = super.hashCode() + 31 * (id.res.hashCode() + 31 * id.id); 102 | } 103 | return mHashCode; 104 | } 105 | 106 | @Override 107 | public boolean equals(Object o) { 108 | if (o == this) return true; 109 | if (!(o instanceof ResourceBitmapLoader) || !super.equals(o)) return false; 110 | 111 | final ResourceBitmapLoader d = (ResourceBitmapLoader) o; 112 | Identifier id = (Identifier) mId; 113 | return id.equals(d.mId); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/StreamBitmapLoader.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.annotation.TargetApi; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.graphics.BitmapFactory.Options; 7 | import android.graphics.BitmapRegionDecoder; 8 | import android.os.Build; 9 | import android.support.annotation.NonNull; 10 | 11 | import java.io.IOException; 12 | import java.io.InputStream; 13 | 14 | import rapid.decoder.cache.TransactionOutputStream; 15 | 16 | class StreamBitmapLoader extends BitmapLoader { 17 | private TwiceReadableInputStream mIn; 18 | 19 | public StreamBitmapLoader(InputStream is) { 20 | if (is instanceof TwiceReadableInputStream && 21 | !((TwiceReadableInputStream) is).isSecondReading()) { 22 | mIn = (TwiceReadableInputStream) is; 23 | } else { 24 | mIn = new TwiceReadableInputStream(is); 25 | } 26 | } 27 | 28 | protected StreamBitmapLoader(StreamBitmapLoader other) { 29 | super(other); 30 | 31 | InputStream is = other.mIn.getStream(); 32 | if (is instanceof LazyInputStream) { 33 | is = new LazyInputStream(((LazyInputStream) is).getStreamOpener()); 34 | } 35 | mIn = new TwiceReadableInputStream(is); 36 | } 37 | 38 | @Override 39 | protected void finalize() throws Throwable { 40 | try { 41 | mIn.close(); 42 | } finally { 43 | super.finalize(); 44 | } 45 | } 46 | 47 | void setCacheOutputStream(TransactionOutputStream out) { 48 | mIn.setCacheOutputStream(out); 49 | } 50 | 51 | @Override 52 | protected Bitmap decode(Options opts) { 53 | try { 54 | return BitmapFactory.decodeStream(mIn, null, opts); 55 | } catch (Throwable ignored) { 56 | mIn.setTransactionSucceeded(false); 57 | return null; 58 | } 59 | } 60 | 61 | @Override 62 | public void cancel() { 63 | super.cancel(); 64 | try { 65 | mIn.close(); 66 | } catch (IOException ignored) { 67 | } 68 | } 69 | 70 | @Override 71 | protected InputStream openInputStream() { 72 | return mIn; 73 | } 74 | 75 | @Override 76 | protected void onDecodingStarted(boolean builtInDecoder) { 77 | if (!builtInDecoder) { 78 | mIn.startSecondRead(); 79 | } 80 | mIn.seekToBeginning(); 81 | } 82 | 83 | @TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1) 84 | @Override 85 | protected BitmapRegionDecoder createBitmapRegionDecoder() { 86 | try { 87 | return BitmapRegionDecoder.newInstance(mIn, false); 88 | } catch (IOException e) { 89 | return null; 90 | } 91 | } 92 | 93 | @NonNull 94 | @Override 95 | public BitmapLoader fork() { 96 | return new StreamBitmapLoader(this); 97 | } 98 | 99 | @Override 100 | public BitmapLoader reset() { 101 | throw new UnsupportedOperationException(); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/StreamOpener.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.support.annotation.Nullable; 4 | 5 | import java.io.InputStream; 6 | 7 | interface StreamOpener { 8 | @Nullable 9 | InputStream openInputStream(); 10 | } 11 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/TransitionDrawable.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.ColorFilter; 5 | import android.graphics.PixelFormat; 6 | import android.graphics.Rect; 7 | import android.graphics.drawable.Drawable; 8 | import android.os.SystemClock; 9 | import android.support.annotation.NonNull; 10 | import android.support.annotation.Nullable; 11 | 12 | public class TransitionDrawable extends Drawable { 13 | private static final int TRANSITION_NONE = 0; 14 | private static final int TRANSITION_STARTING = 1; 15 | private static final int TRANSITION_RUNNING = 2; 16 | private static final int TRANSITION_FINISHED = 3; 17 | 18 | private int mTransitionState = TRANSITION_NONE; 19 | 20 | private Drawable mDrawableBack; 21 | private Drawable mDrawableFront; 22 | private long mStartTimeMillis = -1; 23 | private int mDuration; 24 | private int mAlpha = 0xff; 25 | private Runnable mEndAction; 26 | 27 | public TransitionDrawable(@Nullable Drawable back, @NonNull Drawable front) { 28 | mDrawableBack = back; 29 | mDrawableFront = front; 30 | } 31 | 32 | public void startTransition(int durationMillis) { 33 | mDuration = durationMillis; 34 | mTransitionState = TRANSITION_STARTING; 35 | invalidateSelf(); 36 | } 37 | 38 | @Override 39 | public void draw(Canvas canvas) { 40 | boolean done = false; 41 | int alpha = 0; 42 | 43 | if (mTransitionState == TRANSITION_NONE) { 44 | if (mDrawableBack != null) { 45 | mDrawableBack.draw(canvas); 46 | } 47 | return; 48 | } else if (mTransitionState == TRANSITION_FINISHED) { 49 | mDrawableFront.draw(canvas); 50 | return; 51 | } else if (mTransitionState == TRANSITION_STARTING) { 52 | mStartTimeMillis = SystemClock.uptimeMillis(); 53 | alpha = 0; 54 | mTransitionState = TRANSITION_RUNNING; 55 | } else { 56 | if (mStartTimeMillis >= 0) { 57 | float normalized = (float) 58 | (SystemClock.uptimeMillis() - mStartTimeMillis) / mDuration; 59 | done = normalized >= 1.0f; 60 | normalized = Math.min(normalized, 1.0f); 61 | alpha = (int) (0xff * normalized); 62 | } 63 | } 64 | 65 | if (done) { 66 | mTransitionState = TRANSITION_FINISHED; 67 | mDrawableFront.draw(canvas); 68 | if (mEndAction != null) { 69 | scheduleSelf(mEndAction, 0); 70 | } 71 | return; 72 | } 73 | 74 | final Drawable d = mDrawableBack; 75 | if (d != null) { 76 | d.setAlpha(0xff - alpha); 77 | d.draw(canvas); 78 | d.setAlpha(mAlpha); 79 | } 80 | 81 | if (alpha != 0) { 82 | final Drawable front = mDrawableFront; 83 | front.setAlpha(alpha); 84 | front.draw(canvas); 85 | front.setAlpha(mAlpha); 86 | } 87 | 88 | invalidateSelf(); 89 | } 90 | 91 | @Override 92 | public void setAlpha(int alpha) { 93 | if (mAlpha != alpha) { 94 | mAlpha = alpha; 95 | if (mDrawableBack != null) { 96 | mDrawableBack.setAlpha(alpha); 97 | } 98 | mDrawableFront.setAlpha(alpha); 99 | invalidateSelf(); 100 | } 101 | } 102 | 103 | @Override 104 | public void setColorFilter(ColorFilter cf) { 105 | } 106 | 107 | @Override 108 | public int getOpacity() { 109 | return PixelFormat.TRANSLUCENT; 110 | } 111 | 112 | public void setEndAction(Runnable r) { 113 | mEndAction = r; 114 | } 115 | 116 | @Override 117 | protected void onBoundsChange(Rect bounds) { 118 | super.onBoundsChange(bounds); 119 | if (mDrawableBack != null) { 120 | mDrawableBack.setBounds(bounds); 121 | } 122 | mDrawableFront.setBounds(bounds); 123 | } 124 | 125 | @Override 126 | public int getIntrinsicWidth() { 127 | if (mDrawableBack == null) { 128 | return mDrawableFront.getIntrinsicWidth(); 129 | } else { 130 | return Math.max(mDrawableBack.getIntrinsicWidth(), mDrawableFront.getIntrinsicWidth()); 131 | } 132 | } 133 | 134 | @Override 135 | public int getIntrinsicHeight() { 136 | if (mDrawableBack == null) { 137 | return mDrawableFront.getIntrinsicHeight(); 138 | } else { 139 | return Math.max(mDrawableBack.getIntrinsicHeight(), mDrawableFront.getIntrinsicHeight()); 140 | } 141 | } 142 | } -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/TwiceReadableInputStream.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | 8 | import rapid.decoder.cache.TransactionOutputStream; 9 | 10 | public class TwiceReadableInputStream extends InputStream { 11 | private static final int INITIAL_BUFFER_CAPACITY = 1024; 12 | 13 | private InputStream mIn; 14 | private byte[] mBuffer = new byte [INITIAL_BUFFER_CAPACITY]; 15 | private int mBufferLength = 0; 16 | private int mBufferOffset; 17 | private int mMarkOffset = 0; 18 | private boolean mBufferExpandable = true; 19 | private boolean mSecondPhase = false; 20 | 21 | private TransactionOutputStream mCacheOutputStream; 22 | private boolean mTransactionSucceeded; 23 | 24 | public static TwiceReadableInputStream getInstanceFrom(InputStream in) { 25 | if (in instanceof TwiceReadableInputStream && 26 | !((TwiceReadableInputStream) in).isSecondReading()) { 27 | 28 | return (TwiceReadableInputStream) in; 29 | } else { 30 | return new TwiceReadableInputStream(in); 31 | } 32 | } 33 | 34 | public TwiceReadableInputStream(InputStream in) { 35 | mIn = in; 36 | } 37 | 38 | public InputStream getStream() { 39 | return mIn; 40 | } 41 | 42 | public void setCacheOutputStream(TransactionOutputStream out) { 43 | mCacheOutputStream = out; 44 | mTransactionSucceeded = true; 45 | } 46 | 47 | @Override 48 | public void mark(int readlimit) { 49 | mMarkOffset = mBufferOffset; 50 | 51 | if (mSecondPhase && mBufferOffset + readlimit > mBufferLength) { 52 | mBufferExpandable = true; 53 | if (mBuffer == null) { 54 | mBuffer = new byte [INITIAL_BUFFER_CAPACITY]; 55 | mBufferLength = mBufferOffset = mMarkOffset = 0; 56 | } 57 | } 58 | } 59 | 60 | @Override 61 | public void reset() throws IOException { 62 | mBufferOffset = mMarkOffset; 63 | } 64 | 65 | private void ensureCapacity(int extraLength) { 66 | int requiredLength = mBufferLength + extraLength; 67 | if (requiredLength > mBuffer.length) { 68 | byte[] newBuffer = new byte [requiredLength * 2]; 69 | System.arraycopy(mBuffer, 0, newBuffer, 0, mBufferLength); 70 | mBuffer = newBuffer; 71 | } 72 | } 73 | 74 | @Override 75 | public int read() throws IOException { 76 | if (mBuffer != null) { 77 | if (mBufferOffset < mBufferLength) { 78 | return mBuffer[mBufferOffset++]; 79 | } else if (mBufferExpandable) { 80 | int oneByte = mIn.read(); 81 | if (oneByte >= 0) { 82 | ensureCapacity(1); 83 | mBuffer[mBufferLength++] = (byte) oneByte; 84 | mBufferOffset = mBufferLength; 85 | } 86 | 87 | return oneByte; 88 | } 89 | } 90 | 91 | int oneByte = mIn.read(); 92 | if (mCacheOutputStream != null) { 93 | if (oneByte == -1) { 94 | try { mCacheOutputStream.close(); } catch (IOException ignored) {} 95 | mCacheOutputStream = null; 96 | } else { 97 | mCacheOutputStream.write(oneByte); 98 | } 99 | } 100 | 101 | return oneByte; 102 | } 103 | 104 | @Override 105 | public boolean markSupported() { 106 | return true; 107 | } 108 | 109 | @Override 110 | public int read(@NonNull byte[] buffer, int byteOffset, int byteCount) 111 | throws IOException { 112 | 113 | if (mBuffer != null) { 114 | int totalBytesRead = 0; 115 | 116 | if (mBufferOffset < mBufferLength) { 117 | int bytesToRead = Math.min(mBufferLength - mBufferOffset, byteCount); 118 | System.arraycopy(mBuffer, mBufferOffset, buffer, byteOffset, bytesToRead); 119 | 120 | mBufferOffset += bytesToRead; 121 | byteOffset += bytesToRead; 122 | byteCount -= bytesToRead; 123 | totalBytesRead += bytesToRead; 124 | } 125 | 126 | if (byteCount > 0) { 127 | int bytesRead = readFromStream(buffer, byteOffset, byteCount); 128 | if (bytesRead == -1) { 129 | return totalBytesRead != 0 ? totalBytesRead : -1; 130 | } 131 | 132 | if (mBufferExpandable) { 133 | ensureCapacity(bytesRead); 134 | System.arraycopy(buffer, byteOffset, mBuffer, mBufferLength, bytesRead); 135 | 136 | mBufferLength += bytesRead; 137 | mBufferOffset = mBufferLength; 138 | } else { 139 | mBuffer = null; 140 | if (mSecondPhase) { 141 | mBufferExpandable = false; 142 | } 143 | } 144 | 145 | return totalBytesRead + bytesRead; 146 | } else { 147 | return totalBytesRead; 148 | } 149 | } else { 150 | return readFromStream(buffer, byteOffset, byteCount); 151 | } 152 | } 153 | 154 | private int readFromStream(byte[] bytes, int offset, int count) throws IOException { 155 | int bytesRead = mIn.read(bytes, offset, count); 156 | if (mCacheOutputStream != null) { 157 | if (bytesRead == -1) { 158 | try { mCacheOutputStream.close(); } catch (IOException ignored) {} 159 | mCacheOutputStream = null; 160 | } else { 161 | mCacheOutputStream.write(bytes, offset, bytesRead); 162 | } 163 | } 164 | return bytesRead; 165 | } 166 | 167 | @Override 168 | public void close() throws IOException { 169 | if (mCacheOutputStream != null) { 170 | try { 171 | if (mTransactionSucceeded) { 172 | mCacheOutputStream.close(); 173 | } else { 174 | mCacheOutputStream.rollback(); 175 | } 176 | } catch (IOException ignored) { 177 | } 178 | mCacheOutputStream = null; 179 | } 180 | mIn.close(); 181 | } 182 | 183 | public void startSecondRead() { 184 | mBufferExpandable = false; 185 | mSecondPhase = true; 186 | } 187 | 188 | public boolean isSecondReading() { 189 | return mSecondPhase; 190 | } 191 | 192 | public void seekToBeginning() { 193 | mBufferOffset = mMarkOffset = 0; 194 | } 195 | 196 | public void setTransactionSucceeded(boolean succeeded) { 197 | mTransactionSucceeded = succeeded; 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/ViewFrameBuilder.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.annotation.Nullable; 5 | import android.view.ViewGroup; 6 | 7 | import rapid.decoder.binder.ViewBinder; 8 | import rapid.decoder.frame.AspectRatioCalculator; 9 | import rapid.decoder.frame.FramedDecoder; 10 | import rapid.decoder.frame.FramingMethod; 11 | 12 | class ViewFrameBuilder { 13 | private static final int AUTOSIZE_NONE = 0; 14 | private static final int AUTOSIZE_WIDTH = 1; 15 | private static final int AUTOSIZE_HEIGHT = 2; 16 | private static final int AUTOSIZE_BOTH = 3; 17 | 18 | private BitmapDecoder mDecoder; 19 | private ViewBinder mViewBinder; 20 | private FramingMethod mFraming; 21 | private int mAutoSizeMode = AUTOSIZE_NONE; 22 | private int mMinWidth; 23 | private int mMinHeight; 24 | private int mMaxWidth; 25 | private int mMaxHeight; 26 | private FramedDecoder mFramedDecoder; 27 | 28 | public ViewFrameBuilder(@NonNull BitmapDecoder decoder, @NonNull ViewBinder binder, 29 | @NonNull FramingMethod framing) { 30 | mDecoder = decoder; 31 | mViewBinder = binder; 32 | mFraming = framing; 33 | } 34 | 35 | public void prepareFraming() { 36 | if (mViewBinder.getLayoutWidth() == ViewGroup.LayoutParams.WRAP_CONTENT) { 37 | if (mViewBinder.getLayoutHeight() == ViewGroup.LayoutParams.WRAP_CONTENT) { 38 | mAutoSizeMode = AUTOSIZE_BOTH; 39 | mMinWidth = mViewBinder.getMinWidth(); 40 | mMaxWidth = mViewBinder.getMaxWidth(); 41 | mMinHeight = mViewBinder.getMinHeight(); 42 | mMaxHeight = mViewBinder.getMaxHeight(); 43 | } else { 44 | mAutoSizeMode = AUTOSIZE_WIDTH; 45 | mMinWidth = mViewBinder.getMinWidth(); 46 | mMaxWidth = mViewBinder.getMaxWidth(); 47 | mMinHeight = mViewBinder.getHeight(); 48 | } 49 | } else if (mViewBinder.getLayoutHeight() == ViewGroup.LayoutParams.WRAP_CONTENT) { 50 | mAutoSizeMode = AUTOSIZE_HEIGHT; 51 | mMinWidth = mViewBinder.getWidth(); 52 | mMinHeight = mViewBinder.getMinHeight(); 53 | mMaxHeight = mViewBinder.getMaxHeight(); 54 | } else { 55 | mAutoSizeMode = AUTOSIZE_NONE; 56 | mMinWidth = mViewBinder.getWidth(); 57 | mMinHeight = mViewBinder.getHeight(); 58 | } 59 | } 60 | 61 | @Nullable 62 | public FramedDecoder getFramedDecoder(boolean fromCache) { 63 | if (mFramedDecoder != null) { 64 | return mFramedDecoder; 65 | } 66 | 67 | int frameWidth, frameHeight; 68 | if (mAutoSizeMode == AUTOSIZE_NONE) { 69 | frameWidth = mMinWidth; 70 | frameHeight = mMinHeight; 71 | } else { 72 | int width, height; 73 | 74 | BitmapMeta meta = mDecoder.getCachedMeta(); 75 | if (meta == null) { 76 | if (fromCache) { 77 | return null; 78 | } else { 79 | width = mDecoder.width(); 80 | height = mDecoder.height(); 81 | } 82 | } else { 83 | width = meta.width(); 84 | height = meta.height(); 85 | } 86 | 87 | switch (mAutoSizeMode) { 88 | case AUTOSIZE_WIDTH: 89 | frameHeight = mMinHeight; 90 | frameWidth = AspectRatioCalculator.getWidth(width, height, frameHeight); 91 | frameWidth = Math.max(mMinWidth, Math.min(frameWidth, mMaxWidth)); 92 | break; 93 | 94 | case AUTOSIZE_HEIGHT: 95 | frameWidth = mMinWidth; 96 | frameHeight = AspectRatioCalculator.getHeight(width, height, frameWidth); 97 | frameHeight = Math.max(mMinHeight, Math.min(frameHeight, mMaxHeight)); 98 | break; 99 | 100 | case AUTOSIZE_BOTH: 101 | frameWidth = Math.max(mMinWidth, Math.min(width, mMaxWidth)); 102 | frameHeight = Math.max(mMinHeight, Math.min(height, mMaxHeight)); 103 | 104 | for (int j = Math.min(width, mMaxWidth); j >= mMinWidth; --j) { 105 | int i = AspectRatioCalculator.getHeight(width, height, j); 106 | if (i >= mMinHeight && i <= mMaxHeight) { 107 | frameWidth = j; 108 | frameHeight = i; 109 | break; 110 | } 111 | } 112 | break; 113 | 114 | default: 115 | throw new IllegalStateException(); 116 | } 117 | } 118 | 119 | if (frameWidth != 0 && frameHeight != 0) { 120 | mFramedDecoder = mFraming.createFramedDecoder(mDecoder, frameWidth, frameHeight); 121 | return mFramedDecoder; 122 | } else { 123 | return null; 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/binder/DrawableCreator.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.binder; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.drawable.Drawable; 6 | import android.support.annotation.NonNull; 7 | import android.support.annotation.Nullable; 8 | 9 | public interface DrawableCreator { 10 | @Nullable 11 | Drawable createDrawable(@NonNull Context context, @NonNull Bitmap d); 12 | } 13 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/binder/DrawableInflater.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.binder; 2 | 3 | import android.content.Context; 4 | import android.graphics.drawable.Drawable; 5 | import android.support.annotation.Nullable; 6 | 7 | public interface DrawableInflater { 8 | @Nullable 9 | Drawable inflate(Context context); 10 | } 11 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/binder/Effect.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.binder; 2 | 3 | import android.content.Context; 4 | import android.graphics.drawable.Drawable; 5 | 6 | import rapid.decoder.TransitionDrawable; 7 | 8 | public abstract class Effect { 9 | public interface EffectTarget { 10 | int getDrawableCount(); 11 | 12 | boolean isDrawableEnabled(int index); 13 | 14 | Drawable getDrawable(int index); 15 | 16 | void setDrawable(int index, Drawable d); 17 | 18 | void dispose(); 19 | } 20 | 21 | private static final int DURATION_ID = android.R.integer.config_mediumAnimTime; 22 | 23 | public abstract void apply(Context context, EffectTarget target, Drawable newDrawable, 24 | boolean isAsync); 25 | 26 | public static Effect NO_EFFECT = new Effect() { 27 | @Override 28 | public void apply(Context context, EffectTarget target, Drawable newDrawable, 29 | boolean isAsync) { 30 | int count = target.getDrawableCount(); 31 | for (int i = 0; i < count; ++i) { 32 | if (!target.isDrawableEnabled(i)) continue; 33 | target.setDrawable(i, newDrawable); 34 | } 35 | target.dispose(); 36 | } 37 | }; 38 | 39 | public static Effect FADE_IN = new Effect() { 40 | @Override 41 | public void apply(Context context, final EffectTarget target, final Drawable newDrawable, 42 | boolean isAsync) { 43 | int count = target.getDrawableCount(); 44 | int duration = context.getResources().getInteger(DURATION_ID); 45 | for (int i = 0; i < count; ++i) { 46 | if (!target.isDrawableEnabled(i)) continue; 47 | Drawable oldDrawable = target.getDrawable(i); 48 | final TransitionDrawable d = new TransitionDrawable(oldDrawable, newDrawable); 49 | d.startTransition(duration); 50 | target.setDrawable(i, d); 51 | final int finalI = i; 52 | d.setEndAction(new Runnable() { 53 | @Override 54 | public void run() { 55 | if (target.getDrawable(finalI) == d) { 56 | target.setDrawable(finalI, newDrawable); 57 | } 58 | target.dispose(); 59 | } 60 | }); 61 | } 62 | } 63 | }; 64 | 65 | public static Effect FADE_IN_IF_SYNC = new Effect() { 66 | @Override 67 | public void apply(Context context, EffectTarget target, Drawable newDrawable, 68 | boolean isAsync) { 69 | if (!isAsync) { 70 | NO_EFFECT.apply(context, target, newDrawable, false); 71 | } else { 72 | FADE_IN.apply(context, target, newDrawable, true); 73 | } 74 | } 75 | }; 76 | } 77 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/binder/ImageViewBinder.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.binder; 2 | 3 | import android.graphics.drawable.Drawable; 4 | import android.widget.ImageView; 5 | 6 | import rapid.decoder.cache.ResourcePool; 7 | import rapid.decoder.frame.FramingMethod; 8 | import rapid.decoder.frame.ScaleTypeFraming; 9 | 10 | public class ImageViewBinder extends ViewBinder { 11 | private static final ResourcePool POOL = new Pool() { 12 | @Override 13 | protected ImageViewBinder newInstance() { 14 | return new ImageViewBinder(); 15 | } 16 | }; 17 | 18 | public static ImageViewBinder obtain(ImageView v) { 19 | ImageViewBinder binder = POOL.obtainNotReset(); 20 | binder.init(v); 21 | return binder; 22 | } 23 | 24 | private ImageViewBinder() { 25 | } 26 | 27 | @SuppressWarnings("UnusedDeclaration") 28 | public ImageViewBinder(ImageView v) { 29 | init(v); 30 | } 31 | 32 | @Override 33 | public void recycle() { 34 | POOL.recycle(this); 35 | } 36 | 37 | @Override 38 | public int getDrawableCount() { 39 | return 1; 40 | } 41 | 42 | @Override 43 | public boolean isDrawableEnabled(int index) { 44 | return true; 45 | } 46 | 47 | @Override 48 | public Drawable getDrawable(int index) { 49 | ImageView v = getView(); 50 | return v != null ? v.getDrawable() : null; 51 | } 52 | 53 | @Override 54 | public void setDrawable(int index, Drawable d) { 55 | ImageView v = getView(); 56 | if (v != null) { 57 | v.setImageDrawable(d); 58 | } 59 | } 60 | 61 | @Override 62 | public FramingMethod framing() { 63 | FramingMethod framing = super.framing(); 64 | if (framing == null) { 65 | ImageView v = getView(); 66 | if (v != null) { 67 | return new ScaleTypeFraming(v.getScaleType()); 68 | } 69 | } 70 | return framing; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/binder/ViewBackgroundBinder.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.binder; 2 | 3 | import android.graphics.drawable.Drawable; 4 | import android.os.Build; 5 | import android.view.View; 6 | 7 | import rapid.decoder.cache.ResourcePool; 8 | 9 | public class ViewBackgroundBinder extends ViewBinder { 10 | private static final ResourcePool POOL = new Pool 11 | () { 12 | @Override 13 | protected ViewBackgroundBinder newInstance() { 14 | return new ViewBackgroundBinder(); 15 | } 16 | }; 17 | 18 | public static ViewBackgroundBinder obtain(View v) { 19 | ViewBackgroundBinder binder = POOL.obtainNotReset(); 20 | binder.init(v); 21 | return binder; 22 | } 23 | 24 | private ViewBackgroundBinder() { 25 | } 26 | 27 | @SuppressWarnings("UnusedDeclaration") 28 | public ViewBackgroundBinder(View v) { 29 | init(v); 30 | } 31 | 32 | @Override 33 | public void recycle() { 34 | POOL.recycle(this); 35 | } 36 | 37 | @Override 38 | public Drawable getDrawable(int index) { 39 | View v = getView(); 40 | return v != null ? v.getBackground() : null; 41 | } 42 | 43 | @SuppressWarnings("deprecation") 44 | @Override 45 | public void setDrawable(int index, Drawable d) { 46 | View v = getView(); 47 | if (v != null) { 48 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 49 | v.setBackground(d); 50 | } else { 51 | v.setBackgroundDrawable(d); 52 | } 53 | } 54 | } 55 | 56 | @Override 57 | public int getDrawableCount() { 58 | return 1; 59 | } 60 | 61 | @Override 62 | public boolean isDrawableEnabled(int index) { 63 | return true; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/builtin/BuiltInDecoder.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.builtin; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Bitmap.Config; 5 | import android.graphics.BitmapFactory.Options; 6 | import android.graphics.Rect; 7 | import android.os.Build; 8 | 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | 12 | import rapid.decoder.TwiceReadableInputStream; 13 | 14 | public class BuiltInDecoder { 15 | private static final String MESSAGE_INVALID_REGION = "rectangle is outside the image"; 16 | 17 | private TwiceReadableInputStream in; 18 | private Rect region; 19 | private boolean useFilter = true; 20 | 21 | public BuiltInDecoder(InputStream in) { 22 | this.in = TwiceReadableInputStream.getInstanceFrom(in); 23 | } 24 | 25 | @SuppressWarnings("UnusedDeclaration") 26 | public InputStream getInputStream() { 27 | return in; 28 | } 29 | 30 | public void setRegion(Rect region) { 31 | this.region = region; 32 | } 33 | 34 | public void setUseFilter(boolean filter) { 35 | useFilter = filter; 36 | } 37 | 38 | public Bitmap decode(Options opts) { 39 | final String mimeType = opts.outMimeType; 40 | Bitmap bitmap = null; 41 | if (mimeType == null) { 42 | bitmap = decodePng(opts); 43 | if (bitmap == null && !opts.mCancel) { 44 | in.seekToBeginning(); 45 | bitmap = decodeJpeg(opts); 46 | } 47 | } else if (mimeType.equals("image/png")) { 48 | in.seekToBeginning(); 49 | bitmap = decodePng(opts); 50 | } else if (mimeType.equals("image/jpeg")) { 51 | in.seekToBeginning(); 52 | bitmap = decodeJpeg(opts); 53 | } 54 | 55 | return bitmap; 56 | } 57 | 58 | private static Config getDefaultConfig(boolean hasAlpha) { 59 | if (hasAlpha) { 60 | return Config.ARGB_8888; 61 | } else { 62 | return (Build.VERSION.SDK_INT >= 9 ? Config.ARGB_8888 : Config.RGB_565); 63 | } 64 | } 65 | 66 | private void validateRegion(int width, int height) { 67 | if (region != null && 68 | (region.left < 0 || region.top < 0 || region.right > width || region.bottom > height)) { 69 | 70 | throw new IllegalArgumentException(MESSAGE_INVALID_REGION); 71 | } 72 | } 73 | 74 | private Bitmap decodeJpeg(Options opts) { 75 | JpegDecoder.initDecoder(); 76 | final JpegDecoder d = new JpegDecoder(in); 77 | try { 78 | if (!d.begin()) { 79 | return null; 80 | } 81 | 82 | if (opts.mCancel) return null; 83 | 84 | in.startSecondRead(); 85 | 86 | final int width = d.getWidth(); 87 | final int height = d.getHeight(); 88 | 89 | validateRegion(width, height); 90 | 91 | final Config config = (opts.inPreferredConfig != null ? opts.inPreferredConfig : getDefaultConfig(false)); 92 | 93 | return d.decode(region, useFilter, config, opts); 94 | } finally { 95 | d.close(); 96 | } 97 | } 98 | 99 | private Bitmap decodePng(Options opts) { 100 | PngDecoder.initDecoder(); 101 | final PngDecoder d = new PngDecoder(in); 102 | try { 103 | if (!d.begin()) { 104 | return null; 105 | } 106 | 107 | if (opts.mCancel) return null; 108 | 109 | in.startSecondRead(); 110 | 111 | final int width = d.getWidth(); 112 | final int height = d.getHeight(); 113 | 114 | validateRegion(width, height); 115 | 116 | final Config config = (opts.inPreferredConfig != null ? opts.inPreferredConfig : getDefaultConfig(d.hasAlpha())); 117 | 118 | return d.decode(region, useFilter, config, opts); 119 | } finally { 120 | d.close(); 121 | } 122 | } 123 | 124 | public void close() { 125 | try { in.close(); } catch (IOException ignored) {} 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/builtin/JpegDecoder.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.builtin; 2 | import android.graphics.Bitmap; 3 | import android.graphics.Bitmap.Config; 4 | import android.graphics.BitmapFactory.Options; 5 | import android.graphics.Rect; 6 | 7 | import java.io.InputStream; 8 | 9 | public class JpegDecoder { 10 | private static boolean sInitialized; 11 | private static boolean sHasLibrary; 12 | public static void initDecoder() { 13 | if (!sInitialized) { 14 | sInitialized = true; 15 | System.loadLibrary("jpeg-decoder"); 16 | init(); 17 | sHasLibrary = true; 18 | } else if (!sHasLibrary) { 19 | throw new UnsatisfiedLinkError(); 20 | } 21 | } 22 | 23 | private static native void init(); 24 | private static native long createNativeDecoder(InputStream in); 25 | private static native void destroyNativeDecoder(long decoder); 26 | private static native boolean nativeBegin(long decoder); 27 | private static native int nativeGetWidth(long decoder); 28 | private static native int nativeGetHeight(long decoder); 29 | private static native Bitmap nativeDecode(long decoder, int left, int top, int right, int bottom, boolean filter, 30 | Config config, Options opts); 31 | 32 | private long decoder; 33 | 34 | public JpegDecoder(InputStream in) { 35 | decoder = createNativeDecoder(in); 36 | } 37 | 38 | public void close() { 39 | if (decoder == 0) return; 40 | 41 | destroyNativeDecoder(decoder); 42 | decoder = 0; 43 | } 44 | 45 | public boolean begin() { 46 | if (decoder == 0) { 47 | throw new IllegalStateException(); 48 | } 49 | 50 | return nativeBegin(decoder); 51 | } 52 | 53 | public int getWidth() { 54 | if (decoder == 0) { 55 | throw new IllegalStateException(); 56 | } 57 | 58 | return nativeGetWidth(decoder); 59 | } 60 | 61 | public int getHeight() { 62 | if (decoder == 0) { 63 | throw new IllegalStateException(); 64 | } 65 | 66 | return nativeGetHeight(decoder); 67 | } 68 | 69 | public Bitmap decode(Rect bounds, boolean filter, Config config, Options opts) { 70 | if (decoder == 0) { 71 | throw new IllegalStateException(); 72 | } 73 | 74 | if (bounds == null) { 75 | return nativeDecode(decoder, -1, -1, -1, -1, filter, config, opts); 76 | } else { 77 | return nativeDecode(decoder, 78 | bounds.left, bounds.top, bounds.right, bounds.bottom, 79 | filter, config, opts); 80 | } 81 | } 82 | 83 | @Override 84 | protected void finalize() throws Throwable { 85 | close(); 86 | super.finalize(); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/builtin/PngDecoder.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.builtin; 2 | import android.graphics.Bitmap; 3 | import android.graphics.Bitmap.Config; 4 | import android.graphics.BitmapFactory.Options; 5 | import android.graphics.Rect; 6 | 7 | import java.io.InputStream; 8 | 9 | public class PngDecoder { 10 | private static boolean sInitialized; 11 | private static boolean sHasLibrary; 12 | public static void initDecoder() { 13 | if (!sInitialized) { 14 | sInitialized = true; 15 | System.loadLibrary("png-decoder"); 16 | init(); 17 | sHasLibrary = true; 18 | } else if (!sHasLibrary) { 19 | throw new UnsatisfiedLinkError(); 20 | } 21 | } 22 | 23 | private static native void init(); 24 | private static native long createNativeDecoder(InputStream in); 25 | private static native void destroyNativeDecoder(long decoder); 26 | private static native boolean nativeBegin(long decoder); 27 | private static native int nativeGetWidth(long decoder); 28 | private static native int nativeGetHeight(long decoder); 29 | private static native boolean nativeHasAlpha(long decoder); 30 | private static native Bitmap nativeDecode(long decoder, int left, int top, int right, int bottom, boolean filter, 31 | Config config, Options opts); 32 | 33 | private long decoder; 34 | 35 | public PngDecoder(InputStream in) { 36 | decoder = createNativeDecoder(in); 37 | } 38 | 39 | public void close() { 40 | if (decoder == 0) return; 41 | 42 | destroyNativeDecoder(decoder); 43 | decoder = 0; 44 | } 45 | 46 | public boolean begin() { 47 | if (decoder == 0) { 48 | throw new IllegalStateException(); 49 | } 50 | 51 | return nativeBegin(decoder); 52 | } 53 | 54 | public int getWidth() { 55 | if (decoder == 0) { 56 | throw new IllegalStateException(); 57 | } 58 | 59 | return nativeGetWidth(decoder); 60 | } 61 | 62 | public int getHeight() { 63 | if (decoder == 0) { 64 | throw new IllegalStateException(); 65 | } 66 | 67 | return nativeGetHeight(decoder); 68 | } 69 | 70 | public Bitmap decode(Rect bounds, boolean filter, Config config, Options opts) { 71 | if (decoder == 0) { 72 | throw new IllegalStateException(); 73 | } 74 | 75 | if (bounds == null) { 76 | return nativeDecode(decoder, -1, -1, -1, -1, filter, config, opts); 77 | } else { 78 | return nativeDecode(decoder, 79 | bounds.left, bounds.top, bounds.right, bounds.bottom, 80 | filter, config, opts); 81 | } 82 | } 83 | 84 | @Override 85 | protected void finalize() throws Throwable { 86 | close(); 87 | super.finalize(); 88 | } 89 | 90 | public boolean hasAlpha() { 91 | if (decoder == 0) { 92 | throw new IllegalStateException(); 93 | } 94 | 95 | return nativeHasAlpha(decoder); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/cache/BitmapLruCache.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.cache; 2 | 3 | import android.graphics.Bitmap; 4 | 5 | import java.lang.ref.WeakReference; 6 | import java.util.HashMap; 7 | import java.util.Iterator; 8 | import java.util.Map; 9 | import java.util.WeakHashMap; 10 | 11 | import rapid.decoder.BitmapLoader; 12 | import rapid.decoder.BitmapMeta; 13 | import rapid.decoder.BitmapUtils; 14 | 15 | public class BitmapLruCache extends LruCache { 16 | private static class CachedMeta implements BitmapMeta { 17 | public int width; 18 | public int height; 19 | public WeakHashMap bitmaps = new WeakHashMap(); 20 | 21 | @Override 22 | public int width() { 23 | return width; 24 | } 25 | 26 | @Override 27 | public int height() { 28 | return height; 29 | } 30 | } 31 | 32 | private HashMap> mEvictedBitmap = 33 | new HashMap>(); 34 | private HashMap mMetaCache = new HashMap(); 35 | 36 | public BitmapLruCache(int maxSize) { 37 | super(maxSize); 38 | } 39 | 40 | @Override 41 | protected int sizeOf(BitmapLoader key, Bitmap value) { 42 | return BitmapUtils.getByteCount(value); 43 | } 44 | 45 | @Override 46 | protected void entryRemoved(boolean evicted, BitmapLoader key, Bitmap oldValue, 47 | Bitmap newValue) { 48 | if (!oldValue.isRecycled()) { 49 | mEvictedBitmap.put(key, new WeakReference(oldValue)); 50 | } 51 | } 52 | 53 | @Override 54 | public Bitmap put(BitmapLoader key, Bitmap value) { 55 | Bitmap bitmap = super.put(key, value); 56 | Object id = key.a(); 57 | if (id != null) { 58 | CachedMeta info = mMetaCache.get(id); 59 | if (info == null) { 60 | info = new CachedMeta(); 61 | mMetaCache.put(id, info); 62 | } 63 | info.width = key.sourceWidth(); 64 | info.height = key.sourceHeight(); 65 | info.bitmaps.put(value, null); 66 | } 67 | return bitmap; 68 | } 69 | 70 | @Override 71 | public Bitmap get(BitmapLoader key) { 72 | Bitmap bitmap = super.get(key); 73 | if (bitmap != null) { 74 | if (bitmap.isRecycled()) { 75 | remove(key); 76 | } else { 77 | return bitmap; 78 | } 79 | } 80 | 81 | WeakReference ref = mEvictedBitmap.get(key); 82 | if (ref == null) { 83 | if (Math.random() <= 0.2) { 84 | gcEvictedBitmaps(); 85 | } 86 | return null; 87 | } 88 | 89 | bitmap = ref.get(); 90 | if (bitmap == null || bitmap.isRecycled()) { 91 | mEvictedBitmap.remove(key); 92 | return null; 93 | } else { 94 | return bitmap; 95 | } 96 | } 97 | 98 | public BitmapMeta getMeta(Object id) { 99 | CachedMeta meta = mMetaCache.get(id); 100 | if (meta == null) { 101 | if (Math.random() <= 0.2) { 102 | gcMetaCache(); 103 | } 104 | return null; 105 | } 106 | 107 | if (meta.bitmaps.isEmpty()) { 108 | mMetaCache.remove(id); 109 | return null; 110 | } 111 | 112 | return meta; 113 | } 114 | 115 | private void gcEvictedBitmaps() { 116 | Iterator>> it = mEvictedBitmap.entrySet() 117 | .iterator(); 118 | while (it.hasNext()) { 119 | Map.Entry> entry = it.next(); 120 | Bitmap bitmap = entry.getValue().get(); 121 | if (bitmap == null || bitmap.isRecycled()) { 122 | it.remove(); 123 | } 124 | } 125 | } 126 | 127 | private void gcMetaCache() { 128 | Iterator> it = mMetaCache.entrySet().iterator(); 129 | while (it.hasNext()) { 130 | Map.Entry entry = it.next(); 131 | if (entry.getValue().bitmaps.isEmpty()) { 132 | it.remove(); 133 | } 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/cache/CacheSource.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.cache; 2 | 3 | public enum CacheSource { 4 | MEMORY, 5 | DISK, 6 | NOT_CACHED 7 | } 8 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/cache/TransactionOutputStream.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.cache; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import java.io.IOException; 6 | import java.io.OutputStream; 7 | 8 | import rapid.decoder.cache.DiskLruCacheEngine.Editor; 9 | 10 | @SuppressWarnings("UnusedDeclaration") 11 | public class TransactionOutputStream extends OutputStream { 12 | private Editor mEditor; 13 | private OutputStream mOut; 14 | private DiskLruCache mCache; 15 | 16 | public TransactionOutputStream(DiskLruCache cache, Editor editor, OutputStream out) { 17 | mCache = cache; 18 | mEditor = editor; 19 | mOut = out; 20 | } 21 | 22 | @Override 23 | public void close() throws IOException { 24 | mOut.close(); 25 | mEditor.commit(); 26 | mCache.flush(); 27 | } 28 | 29 | public void rollback() throws IOException { 30 | mOut.close(); 31 | mEditor.abort(); 32 | mCache.flush(); 33 | } 34 | 35 | @Override 36 | public void flush() throws IOException { 37 | mOut.flush(); 38 | } 39 | 40 | @Override 41 | public void write(@NonNull byte[] buffer, int offset, int count) 42 | throws IOException { 43 | 44 | mOut.write(buffer, offset, count); 45 | } 46 | 47 | @Override 48 | public void write(int oneByte) throws IOException { 49 | mOut.write(oneByte); 50 | } 51 | 52 | @Override 53 | public void write(@NonNull byte[] buffer) throws IOException { 54 | mOut.write(buffer); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/compat/DisplayCompat.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.compat; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.graphics.Point; 5 | import android.os.Build; 6 | import android.view.Display; 7 | 8 | import static rapid.decoder.cache.ResourcePool.*; 9 | 10 | @SuppressWarnings("UnusedDeclaration") 11 | public class DisplayCompat { 12 | @SuppressLint("NewApi") 13 | @SuppressWarnings("deprecation") 14 | public static int getWidth(Display display) { 15 | if (Build.VERSION.SDK_INT >= 13) { 16 | final Point size = POINT.obtain(); 17 | display.getSize(size); 18 | final int width = size.x; 19 | POINT.recycle(size); 20 | 21 | return width; 22 | } else { 23 | return display.getWidth(); 24 | } 25 | } 26 | 27 | @SuppressLint("NewApi") 28 | @SuppressWarnings("deprecation") 29 | public static int getHeight(Display display) { 30 | if (Build.VERSION.SDK_INT >= 13) { 31 | final Point size = POINT.obtain(); 32 | display.getSize(size); 33 | final int height = size.y; 34 | POINT.recycle(size); 35 | 36 | return height; 37 | } else { 38 | return display.getHeight(); 39 | } 40 | } 41 | 42 | @SuppressLint("NewApi") 43 | @SuppressWarnings("deprecation") 44 | public static void getSize(Display display, Point outSize) { 45 | if (Build.VERSION.SDK_INT >= 13) { 46 | display.getSize(outSize); 47 | } else { 48 | outSize.x = display.getWidth(); 49 | outSize.y = display.getHeight(); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/compat/ImageViewCompat.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.compat; 2 | 3 | import android.os.Build; 4 | import android.widget.ImageView; 5 | 6 | import java.lang.reflect.Field; 7 | 8 | public final class ImageViewCompat { 9 | private static Field sFieldMaxWidth; 10 | private static Field sFieldMaxHeight; 11 | 12 | public static int getMaxWidth(ImageView v) { 13 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 14 | return v.getMaxWidth(); 15 | } else { 16 | try { 17 | if (sFieldMaxWidth == null) { 18 | sFieldMaxWidth = ImageView.class.getDeclaredField("mMaxWidth"); 19 | } 20 | sFieldMaxWidth.setAccessible(true); 21 | return sFieldMaxWidth.getInt(v); 22 | } catch (Exception e) { 23 | return Integer.MAX_VALUE; 24 | } 25 | } 26 | } 27 | 28 | public static int getMaxHeight(ImageView v) { 29 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 30 | return v.getMaxHeight(); 31 | } else { 32 | try { 33 | if (sFieldMaxHeight == null) { 34 | sFieldMaxHeight = ImageView.class.getDeclaredField("mMaxHeight"); 35 | } 36 | sFieldMaxHeight.setAccessible(true); 37 | return sFieldMaxHeight.getInt(v); 38 | } catch (Exception e) { 39 | return Integer.MAX_VALUE; 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/compat/ViewCompat.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.compat; 2 | 3 | import android.os.Build; 4 | import android.view.View; 5 | 6 | import java.lang.reflect.Field; 7 | 8 | public final class ViewCompat { 9 | private static Field sFieldMinWidth; 10 | private static Field sFieldMinHeight; 11 | 12 | public static int getMinimumWidth(View v) { 13 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 14 | return v.getMinimumWidth(); 15 | } else { 16 | try { 17 | if (sFieldMinWidth == null) { 18 | sFieldMinWidth = View.class.getDeclaredField("mMinWidth"); 19 | } 20 | sFieldMinWidth.setAccessible(true); 21 | return sFieldMinWidth.getInt(v); 22 | } catch (Exception e) { 23 | return 0; 24 | } 25 | } 26 | } 27 | 28 | public static int getMinimumHeight(View v) { 29 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 30 | return v.getMinimumHeight(); 31 | } else { 32 | try { 33 | if (sFieldMinHeight == null) { 34 | sFieldMinHeight = View.class.getDeclaredField("mMinHeight"); 35 | } 36 | sFieldMinHeight.setAccessible(true); 37 | return sFieldMinHeight.getInt(v); 38 | } catch (Exception e) { 39 | return 0; 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/frame/AspectRatioCalculator.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.frame; 2 | 3 | public class AspectRatioCalculator { 4 | @SuppressWarnings("UnusedDeclaration") 5 | public static int getHeight(int width, int height, int targetWidth) { 6 | final double ratio = (double) height / width; 7 | return (int) Math.round(ratio * targetWidth); 8 | } 9 | 10 | @SuppressWarnings("UnusedDeclaration") 11 | public static int getWidth(int width, int height, int targetHeight) { 12 | final double ratio = (double) width / height; 13 | return (int) Math.round(ratio * targetHeight); 14 | } 15 | 16 | public static float getHeight(float width, float height, float targetWidth) { 17 | return (height / width) * targetWidth; 18 | } 19 | 20 | public static float getWidth(float width, float height, float targetHeight) { 21 | return (width / height) * targetHeight; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/frame/CenterCropFramedDecoder.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.frame; 2 | 3 | import android.graphics.Rect; 4 | import android.support.annotation.Nullable; 5 | 6 | import rapid.decoder.BitmapDecoder; 7 | import rapid.decoder.BitmapMeta; 8 | 9 | class CenterCropFramedDecoder extends FramedDecoder { 10 | public CenterCropFramedDecoder(BitmapDecoder decoder, int frameWidth, int frameHeight) { 11 | super(decoder, frameWidth, frameHeight); 12 | } 13 | 14 | protected CenterCropFramedDecoder(CenterCropFramedDecoder other) { 15 | super(other); 16 | } 17 | 18 | @Override 19 | protected void getBounds(BitmapMeta meta, int frameWidth, int frameHeight, 20 | @Nullable Rect outSrc, @Nullable Rect outDest) { 21 | 22 | int width = meta.width(); 23 | int height = meta.height(); 24 | 25 | int targetWidth; 26 | int targetHeight = AspectRatioCalculator.getHeight(width, height, frameWidth); 27 | if (targetHeight >= frameHeight) { 28 | targetWidth = frameWidth; 29 | } else { 30 | targetWidth = AspectRatioCalculator.getWidth(width, height, frameHeight); 31 | targetHeight = frameHeight; 32 | } 33 | 34 | int targetLeft = (frameWidth - targetWidth) / 2; 35 | int targetTop = (frameHeight - targetHeight) / 2; 36 | 37 | float ratioWidth = (float) targetWidth / width; 38 | float ratioHeight = (float) targetHeight / height; 39 | 40 | if (outSrc != null) { 41 | outSrc.left = Math.round(-targetLeft / ratioWidth); 42 | outSrc.top = Math.round(-targetTop / ratioHeight); 43 | outSrc.right = outSrc.left + Math.round(frameWidth / ratioWidth); 44 | outSrc.bottom = outSrc.top + Math.round(frameHeight / ratioHeight); 45 | } 46 | if (outDest != null) { 47 | outDest.set(0, 0, frameWidth, frameHeight); 48 | } 49 | } 50 | 51 | @Override 52 | public FramedDecoder fork() { 53 | return new CenterCropFramedDecoder(this); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/frame/CenterFramedDecoder.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.frame; 2 | 3 | import android.graphics.Rect; 4 | import android.support.annotation.Nullable; 5 | 6 | import rapid.decoder.BitmapDecoder; 7 | import rapid.decoder.BitmapMeta; 8 | 9 | @SuppressWarnings("UnusedDeclaration") 10 | class CenterFramedDecoder extends FramedDecoder { 11 | public CenterFramedDecoder(BitmapDecoder decoder, int frameWidth, int frameHeight) { 12 | super(decoder, frameWidth, frameHeight); 13 | } 14 | 15 | protected CenterFramedDecoder(CenterFramedDecoder other) { 16 | super(other); 17 | } 18 | 19 | @Override 20 | protected void getBounds(BitmapMeta meta, int frameWidth, int frameHeight, 21 | @Nullable Rect outSrc, @Nullable Rect outDest) { 22 | int width = meta.width(); 23 | int height = meta.height(); 24 | if (width > frameWidth) { 25 | if (outSrc != null) { 26 | outSrc.left = (width - frameWidth) / 2; 27 | outSrc.right = outSrc.left + frameWidth; 28 | } 29 | if (outDest != null) { 30 | outDest.left = 0; 31 | outDest.right = frameWidth; 32 | } 33 | } else { 34 | if (outSrc != null) { 35 | outSrc.left = 0; 36 | outSrc.right = width; 37 | } 38 | if (outDest != null) { 39 | outDest.left = (frameWidth - width) / 2; 40 | outDest.right = outDest.left + width; 41 | } 42 | } 43 | if (height > frameHeight) { 44 | if (outSrc != null) { 45 | outSrc.top = (height - frameHeight) / 2; 46 | outSrc.bottom = outSrc.top + frameHeight; 47 | } 48 | if (outDest != null) { 49 | outDest.top = 0; 50 | outDest.bottom = frameHeight; 51 | } 52 | } else { 53 | if (outSrc != null) { 54 | outSrc.top = 0; 55 | outSrc.bottom = height; 56 | } 57 | if (outDest != null) { 58 | outDest.top = (frameHeight - height) / 2; 59 | outDest.bottom = outDest.top + height; 60 | } 61 | } 62 | } 63 | 64 | @Override 65 | public FramedDecoder fork() { 66 | return new CenterFramedDecoder(this); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/frame/CenterInsideFramedDecoder.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.frame; 2 | 3 | import android.graphics.Rect; 4 | import android.support.annotation.Nullable; 5 | 6 | import rapid.decoder.BitmapDecoder; 7 | import rapid.decoder.BitmapMeta; 8 | 9 | @SuppressWarnings("UnusedDeclaration") 10 | class CenterInsideFramedDecoder extends FramedDecoder { 11 | public CenterInsideFramedDecoder(BitmapDecoder decoder, int frameWidth, int frameHeight) { 12 | super(decoder, frameWidth, frameHeight); 13 | } 14 | 15 | protected CenterInsideFramedDecoder(CenterInsideFramedDecoder other) { 16 | super(other); 17 | } 18 | 19 | @Override 20 | protected void getBounds(BitmapMeta meta, int frameWidth, int frameHeight, 21 | @Nullable Rect outSrc, @Nullable Rect outDest) { 22 | 23 | int width = meta.width(); 24 | int height = meta.height(); 25 | if (outSrc != null) { 26 | outSrc.set(0, 0, width, height); 27 | } 28 | 29 | if (outDest != null) { 30 | if (width <= frameWidth && height <= frameHeight) { 31 | outDest.left = (frameWidth - width) / 2; 32 | outDest.top = (frameHeight - height) / 2; 33 | outDest.right = outDest.left + width; 34 | outDest.bottom = outDest.top + height; 35 | } else { 36 | int targetWidth; 37 | int targetHeight = AspectRatioCalculator.getHeight(width, height, frameWidth); 38 | if (targetHeight <= frameHeight) { 39 | targetWidth = frameWidth; 40 | } else { 41 | targetWidth = AspectRatioCalculator.getWidth(width, height, frameHeight); 42 | targetHeight = frameHeight; 43 | } 44 | 45 | outDest.left = (frameWidth - targetWidth) / 2; 46 | outDest.top = (frameHeight - targetHeight) / 2; 47 | outDest.right = outDest.left + targetWidth; 48 | outDest.bottom = outDest.top + targetHeight; 49 | } 50 | } 51 | } 52 | 53 | @Override 54 | public FramedDecoder fork() { 55 | return new CenterInsideFramedDecoder(this); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/frame/FitGravityFramedDecoder.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.frame; 2 | 3 | import android.graphics.Rect; 4 | import android.support.annotation.Nullable; 5 | 6 | import rapid.decoder.BitmapDecoder; 7 | import rapid.decoder.BitmapMeta; 8 | 9 | @SuppressWarnings("UnusedDeclaration") 10 | class FitGravityFramedDecoder extends FramedDecoder { 11 | public static final int GRAVITY_START = 0; 12 | public static final int GRAVITY_CENTER = 1; 13 | public static final int GRAVITY_END = 2; 14 | 15 | private int mGravity; 16 | 17 | public FitGravityFramedDecoder(BitmapDecoder decoder, int frameWidth, int frameHeight, 18 | int gravity) { 19 | 20 | super(decoder, frameWidth, frameHeight); 21 | mGravity = gravity; 22 | } 23 | 24 | protected FitGravityFramedDecoder(FitGravityFramedDecoder other) { 25 | super(other); 26 | } 27 | 28 | @Override 29 | protected void getBounds(BitmapMeta meta, int frameWidth, int frameHeight, 30 | @Nullable Rect outSrc, @Nullable Rect outDest) { 31 | 32 | int width = meta.width(); 33 | int height = meta.height(); 34 | if (outSrc != null) { 35 | outSrc.set(0, 0, width, height); 36 | } 37 | if (outDest != null) { 38 | int targetWidth; 39 | int targetHeight = AspectRatioCalculator.getHeight(width, height, frameWidth); 40 | if (targetHeight <= frameHeight) { 41 | targetWidth = frameWidth; 42 | } else { 43 | targetWidth = AspectRatioCalculator.getWidth(width, height, frameHeight); 44 | targetHeight = frameHeight; 45 | } 46 | switch (mGravity) { 47 | case GRAVITY_START: 48 | default: 49 | outDest.set(0, 0, targetWidth, targetHeight); 50 | break; 51 | 52 | case GRAVITY_CENTER: 53 | outDest.left = (frameWidth - targetWidth) / 2; 54 | outDest.top = (frameHeight - targetHeight) / 2; 55 | outDest.right = outDest.left + targetWidth; 56 | outDest.bottom = outDest.top + targetHeight; 57 | break; 58 | 59 | case GRAVITY_END: 60 | outDest.right = frameWidth; 61 | outDest.bottom = frameHeight; 62 | outDest.left = outDest.right - targetWidth; 63 | outDest.top = outDest.bottom - targetHeight; 64 | break; 65 | } 66 | } 67 | } 68 | 69 | @Override 70 | public FramedDecoder fork() { 71 | return new FitGravityFramedDecoder(this); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/frame/FitXYFramedDecoder.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.frame; 2 | 3 | import android.graphics.Rect; 4 | import android.support.annotation.Nullable; 5 | 6 | import rapid.decoder.BitmapDecoder; 7 | import rapid.decoder.BitmapMeta; 8 | 9 | @SuppressWarnings("UnusedDeclaration") 10 | class FitXYFramedDecoder extends FramedDecoder { 11 | public FitXYFramedDecoder(BitmapDecoder decoder, int frameWidth, int frameHeight) { 12 | super(decoder, frameWidth, frameHeight); 13 | } 14 | 15 | protected FitXYFramedDecoder(FitXYFramedDecoder other) { 16 | super(other); 17 | } 18 | 19 | @Override 20 | protected void getBounds(BitmapMeta meta, int frameWidth, int frameHeight, 21 | @Nullable Rect outSrc, @Nullable Rect outDest) { 22 | if (outSrc != null) { 23 | outSrc.set(0, 0, meta.width(), meta.height()); 24 | } 25 | if (outDest != null) { 26 | outDest.set(0, 0, frameWidth, frameHeight); 27 | } 28 | } 29 | 30 | @Override 31 | public FramedDecoder fork() { 32 | return new FitXYFramedDecoder(this); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/frame/FramedDecoder.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.frame; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Canvas; 5 | import android.graphics.Rect; 6 | import android.graphics.drawable.Drawable; 7 | import android.support.annotation.Nullable; 8 | import android.widget.ImageView; 9 | 10 | import rapid.decoder.BitmapDecoder; 11 | import rapid.decoder.BitmapMeta; 12 | import rapid.decoder.Decodable; 13 | import rapid.decoder.cache.CacheSource; 14 | 15 | import static rapid.decoder.cache.ResourcePool.*; 16 | 17 | public abstract class FramedDecoder extends Decodable { 18 | private BitmapDecoder mDecoder; 19 | protected Drawable background; 20 | protected int frameWidth; 21 | protected int frameHeight; 22 | protected CacheSource mCacheSource; 23 | 24 | public FramedDecoder(BitmapDecoder decoder, int frameWidth, int frameHeight) { 25 | mDecoder = decoder; 26 | this.frameWidth = frameWidth; 27 | this.frameHeight = frameHeight; 28 | } 29 | 30 | protected FramedDecoder(FramedDecoder other) { 31 | background = other.background; 32 | frameWidth = other.frameWidth; 33 | frameHeight = other.frameHeight; 34 | } 35 | 36 | public FramedDecoder background(Drawable d) { 37 | this.background = d; 38 | return this; 39 | } 40 | 41 | public abstract FramedDecoder fork(); 42 | 43 | protected abstract void getBounds(BitmapMeta meta, int frameWidth, int frameHeight, 44 | @Nullable Rect outSrc, @Nullable Rect outDest); 45 | 46 | private BitmapDecoder setRegion(BitmapDecoder decoder, BitmapMeta meta, int frameWidth, 47 | int frameHeight, Rect destRegion) { 48 | Rect region = RECT.obtainNotReset(); 49 | getBounds(meta, frameWidth, frameHeight, region, destRegion); 50 | if (!(region.left == 0 && region.top == 0 && region.right == meta.width() && region 51 | .bottom == meta.height())) { 52 | 53 | decoder = decoder.fork().region(region); 54 | } 55 | RECT.recycle(region); 56 | return decoder; 57 | } 58 | 59 | @Override 60 | public void draw(Canvas cv, Rect bounds) { 61 | setRegion(mDecoder, mDecoder, bounds.width(), bounds.height(), null).draw(cv, bounds); 62 | } 63 | 64 | @Override 65 | public Bitmap decode() { 66 | return decode(false); 67 | } 68 | 69 | private Bitmap decode(boolean fromCache) { 70 | Rect rectDest = RECT.obtainNotReset(); 71 | BitmapDecoder decoder = null; 72 | Bitmap bitmap = null; 73 | if (fromCache) { 74 | BitmapMeta meta = mDecoder.getCachedMeta(); 75 | if (meta != null) { 76 | decoder = setRegion(mDecoder, meta, frameWidth, frameHeight, rectDest); 77 | bitmap = decoder.getCachedBitmap(); 78 | } 79 | } else { 80 | decoder = setRegion(mDecoder, mDecoder, frameWidth, frameHeight, rectDest); 81 | bitmap = decoder.createAndDraw(frameWidth, frameHeight, rectDest, background); 82 | } 83 | RECT.recycle(rectDest); 84 | if (decoder != null) { 85 | mCacheSource = decoder.cacheSource(); 86 | } 87 | return bitmap; 88 | } 89 | 90 | @Override 91 | public Bitmap getCachedBitmap() { 92 | return decode(true); 93 | } 94 | 95 | @Override 96 | public boolean isMemoryCacheEnabled() { 97 | return mDecoder.isMemoryCacheEnabled(); 98 | } 99 | 100 | @Override 101 | public void cancel() { 102 | mDecoder.cancel(); 103 | } 104 | 105 | @Override 106 | public boolean isCancelled() { 107 | return mDecoder.isCancelled(); 108 | } 109 | 110 | @Override 111 | public int width() { 112 | return frameWidth; 113 | } 114 | 115 | @Override 116 | public int height() { 117 | return frameHeight; 118 | } 119 | 120 | @Override 121 | public CacheSource cacheSource() { 122 | return mCacheSource; 123 | } 124 | 125 | public static FramedDecoder newInstance(BitmapDecoder decoder, int frameWidth, int frameHeight, 126 | ImageView.ScaleType scaleType) { 127 | if (ImageView.ScaleType.MATRIX.equals(scaleType)) { 128 | return new MatrixFramedDecoder(decoder, frameWidth, frameHeight); 129 | } else if (ImageView.ScaleType.FIT_XY.equals(scaleType)) { 130 | return new FitXYFramedDecoder(decoder, frameWidth, frameHeight); 131 | } else if (ImageView.ScaleType.FIT_START.equals(scaleType)) { 132 | return new FitGravityFramedDecoder(decoder, frameWidth, frameHeight, 133 | FitGravityFramedDecoder.GRAVITY_START); 134 | } else if (ImageView.ScaleType.FIT_CENTER.equals(scaleType)) { 135 | return new FitGravityFramedDecoder(decoder, frameWidth, frameHeight, 136 | FitGravityFramedDecoder.GRAVITY_CENTER); 137 | } else if (ImageView.ScaleType.FIT_END.equals(scaleType)) { 138 | return new FitGravityFramedDecoder(decoder, frameWidth, frameHeight, 139 | FitGravityFramedDecoder.GRAVITY_END); 140 | } else if (ImageView.ScaleType.CENTER.equals(scaleType)) { 141 | return new CenterFramedDecoder(decoder, frameWidth, frameHeight); 142 | } else if (ImageView.ScaleType.CENTER_CROP.equals(scaleType)) { 143 | return new CenterCropFramedDecoder(decoder, frameWidth, frameHeight); 144 | } else if (ImageView.ScaleType.CENTER_INSIDE.equals(scaleType)) { 145 | return new CenterInsideFramedDecoder(decoder, frameWidth, frameHeight); 146 | } else { 147 | throw new IllegalArgumentException("scaleType"); 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/frame/FramingMethod.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.frame; 2 | 3 | import rapid.decoder.BitmapDecoder; 4 | 5 | public abstract class FramingMethod { 6 | public abstract FramedDecoder createFramedDecoder(BitmapDecoder decoder, int frameWidth, 7 | int frameHeight); 8 | } 9 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/frame/MatrixFramedDecoder.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.frame; 2 | 3 | import android.graphics.Rect; 4 | import android.support.annotation.Nullable; 5 | 6 | import rapid.decoder.BitmapDecoder; 7 | import rapid.decoder.BitmapMeta; 8 | 9 | @SuppressWarnings("UnusedDeclaration") 10 | class MatrixFramedDecoder extends FramedDecoder { 11 | public MatrixFramedDecoder(BitmapDecoder decoder, int frameWidth, int frameHeight) { 12 | super(decoder, frameWidth, frameHeight); 13 | } 14 | 15 | protected MatrixFramedDecoder(MatrixFramedDecoder other) { 16 | super(other); 17 | } 18 | 19 | @Override 20 | protected void getBounds(BitmapMeta meta, int frameWidth, int frameHeight, 21 | @Nullable Rect outSrc, @Nullable Rect outDest) { 22 | int width = Math.min(meta.width(), frameWidth); 23 | int height = Math.min(meta.height(), frameHeight); 24 | if (outSrc != null) { 25 | outSrc.set(0, 0, width, height); 26 | } 27 | if (outDest != null) { 28 | outDest.set(0, 0, width, height); 29 | } 30 | } 31 | 32 | @Override 33 | public FramedDecoder fork() { 34 | return new MatrixFramedDecoder(this); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /library/src/main/java/rapid/decoder/frame/ScaleTypeFraming.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.frame; 2 | 3 | import android.widget.ImageView; 4 | 5 | import rapid.decoder.BitmapDecoder; 6 | 7 | public class ScaleTypeFraming extends FramingMethod { 8 | private ImageView.ScaleType mScaleType; 9 | 10 | public ScaleTypeFraming(ImageView.ScaleType scaleType) { 11 | mScaleType = scaleType; 12 | } 13 | 14 | @Override 15 | public FramedDecoder createFramedDecoder(BitmapDecoder decoder, int frameWidth, int frameHeight) { 16 | return FramedDecoder.newInstance(decoder, frameWidth, frameHeight, mScaleType); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /png-decoder/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /png-decoder/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 21 5 | buildToolsVersion "21.1.2" 6 | 7 | sourceSets.main { 8 | jni.srcDirs += ['../builtin-decoder-common'] 9 | } 10 | defaultConfig { 11 | ndk { 12 | abiFilters "armeabi", "armeabi-v7a", "x86" 13 | moduleName "png-decoder" 14 | ldLibs "z", "jnigraphics" 15 | cFlags "-ffunction-sections -fdata-sections -fvisibility=hidden -Wl,--gc-sections " + 16 | "-Ibuiltin-decoder-common" 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | } 23 | 24 | apply from: '../gradle-mvn-push.gradle' -------------------------------------------------------------------------------- /png-decoder/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_NAME=RapidDecoder png decoder 2 | POM_ARTIFACT_ID=png-decoder 3 | POM_PACKAGING=aar -------------------------------------------------------------------------------- /png-decoder/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /opt/android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /png-decoder/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /png-decoder/src/main/jni/libpng/pngrio.c: -------------------------------------------------------------------------------- 1 | 2 | /* pngrio.c - functions for data input 3 | * 4 | * Last changed in libpng 1.6.0 [February 14, 2013] 5 | * Copyright (c) 1998-2013 Glenn Randers-Pehrson 6 | * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) 7 | * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) 8 | * 9 | * This code is released under the libpng license. 10 | * For conditions of distribution and use, see the disclaimer 11 | * and license in png.h 12 | * 13 | * This file provides a location for all input. Users who need 14 | * special handling are expected to write a function that has the same 15 | * arguments as this and performs a similar function, but that possibly 16 | * has a different input method. Note that you shouldn't change this 17 | * function, but rather write a replacement function and then make 18 | * libpng use it at run time with png_set_read_fn(...). 19 | */ 20 | 21 | #include "pngpriv.h" 22 | 23 | #ifdef PNG_READ_SUPPORTED 24 | 25 | /* Read the data from whatever input you are using. The default routine 26 | * reads from a file pointer. Note that this routine sometimes gets called 27 | * with very small lengths, so you should implement some kind of simple 28 | * buffering if you are using unbuffered reads. This should never be asked 29 | * to read more then 64K on a 16 bit machine. 30 | */ 31 | void /* PRIVATE */ 32 | png_read_data(png_structrp png_ptr, png_bytep data, png_size_t length) 33 | { 34 | png_debug1(4, "reading %d bytes", (int)length); 35 | 36 | if (png_ptr->read_data_fn != NULL) 37 | (*(png_ptr->read_data_fn))(png_ptr, data, length); 38 | 39 | else 40 | png_error(png_ptr, "Call to NULL read function"); 41 | } 42 | 43 | #ifdef PNG_STDIO_SUPPORTED 44 | /* This is the function that does the actual reading of data. If you are 45 | * not reading from a standard C stream, you should create a replacement 46 | * read_data function and use it at run time with png_set_read_fn(), rather 47 | * than changing the library. 48 | */ 49 | void PNGCBAPI 50 | png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) 51 | { 52 | png_size_t check; 53 | 54 | if (png_ptr == NULL) 55 | return; 56 | 57 | /* fread() returns 0 on error, so it is OK to store this in a png_size_t 58 | * instead of an int, which is what fread() actually returns. 59 | */ 60 | check = fread(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr)); 61 | 62 | if (check != length) 63 | png_error(png_ptr, "Read Error"); 64 | } 65 | #endif 66 | 67 | /* This function allows the application to supply a new input function 68 | * for libpng if standard C streams aren't being used. 69 | * 70 | * This function takes as its arguments: 71 | * 72 | * png_ptr - pointer to a png input data structure 73 | * 74 | * io_ptr - pointer to user supplied structure containing info about 75 | * the input functions. May be NULL. 76 | * 77 | * read_data_fn - pointer to a new input function that takes as its 78 | * arguments a pointer to a png_struct, a pointer to 79 | * a location where input data can be stored, and a 32-bit 80 | * unsigned int that is the number of bytes to be read. 81 | * To exit and output any fatal error messages the new write 82 | * function should call png_error(png_ptr, "Error msg"). 83 | * May be NULL, in which case libpng's default function will 84 | * be used. 85 | */ 86 | void PNGAPI 87 | png_set_read_fn(png_structrp png_ptr, png_voidp io_ptr, 88 | png_rw_ptr read_data_fn) 89 | { 90 | if (png_ptr == NULL) 91 | return; 92 | 93 | png_ptr->io_ptr = io_ptr; 94 | 95 | #ifdef PNG_STDIO_SUPPORTED 96 | if (read_data_fn != NULL) 97 | png_ptr->read_data_fn = read_data_fn; 98 | 99 | else 100 | png_ptr->read_data_fn = png_default_read_data; 101 | #else 102 | png_ptr->read_data_fn = read_data_fn; 103 | #endif 104 | 105 | /* It is an error to write to a read device */ 106 | if (png_ptr->write_data_fn != NULL) 107 | { 108 | png_ptr->write_data_fn = NULL; 109 | png_warning(png_ptr, 110 | "Can't set both read_data_fn and write_data_fn in the" 111 | " same structure"); 112 | } 113 | 114 | #ifdef PNG_WRITE_FLUSH_SUPPORTED 115 | png_ptr->output_flush_fn = NULL; 116 | #endif 117 | } 118 | #endif /* PNG_READ_SUPPORTED */ 119 | -------------------------------------------------------------------------------- /png-decoder/src/main/jni/pngdecoder.h: -------------------------------------------------------------------------------- 1 | #ifndef PNGDECODER_H 2 | #define PNGDECODER_H 3 | 4 | #include 5 | 6 | #include "pixelcomposer.h" 7 | #include "libpng/png.h" 8 | 9 | namespace agu 10 | { 11 | class png_decoder 12 | { 13 | public: 14 | png_decoder(JNIEnv* env, jobject in); 15 | ~png_decoder(); 16 | 17 | bool begin(); 18 | void set_pixel_format(const pixel_format& format); 19 | bool read_row(unsigned char* out); 20 | 21 | inline uint get_bytes_per_row() const { return m_rowbytes; } 22 | inline uint get_width() const { return m_width; } 23 | inline uint get_height() const { return m_height; } 24 | inline bool has_alpha() const { return (m_color_type & PNG_COLOR_MASK_ALPHA); } 25 | 26 | inline void slice(unsigned int col_offset, int col_length) 27 | { 28 | m_col_offset = col_offset; 29 | m_col_length = col_length; 30 | } 31 | 32 | private: 33 | JNIEnv* m_env; 34 | jmethodID InputStream_read1; 35 | 36 | jobject m_in; 37 | jbyteArray m_in_buf; 38 | png_structp m_png; 39 | png_infop m_info; 40 | pixel_format m_format; 41 | 42 | png_uint_32 m_width; 43 | png_uint_32 m_height; 44 | png_uint_32 m_color_type; 45 | png_uint_32 m_rowbytes; 46 | uint m_interlace_type; 47 | bool m_interlace_loaded; 48 | unsigned char* m_scanline_buffer; 49 | unsigned int m_col_offset; 50 | int m_col_length; 51 | 52 | static void input_stream_reader(png_structp png, png_bytep data, png_size_t length); 53 | 54 | unsigned char* get_scanline_buffer(); 55 | }; 56 | } 57 | 58 | #endif // PNGDECODER_H -------------------------------------------------------------------------------- /repository/rapid/decoder/jpeg-decoder/0.3.0/jpeg-decoder-0.3.0-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/repository/rapid/decoder/jpeg-decoder/0.3.0/jpeg-decoder-0.3.0-sources.jar -------------------------------------------------------------------------------- /repository/rapid/decoder/jpeg-decoder/0.3.0/jpeg-decoder-0.3.0-sources.jar.md5: -------------------------------------------------------------------------------- 1 | 0b51060aecd365a51cd378036450cc79 -------------------------------------------------------------------------------- /repository/rapid/decoder/jpeg-decoder/0.3.0/jpeg-decoder-0.3.0-sources.jar.sha1: -------------------------------------------------------------------------------- 1 | 84fc5c865f3f58c738c0542ebfae0fedba06f26c -------------------------------------------------------------------------------- /repository/rapid/decoder/jpeg-decoder/0.3.0/jpeg-decoder-0.3.0.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/repository/rapid/decoder/jpeg-decoder/0.3.0/jpeg-decoder-0.3.0.aar -------------------------------------------------------------------------------- /repository/rapid/decoder/jpeg-decoder/0.3.0/jpeg-decoder-0.3.0.aar.md5: -------------------------------------------------------------------------------- 1 | f2a02628d70be3896cb6087edefc9a05 -------------------------------------------------------------------------------- /repository/rapid/decoder/jpeg-decoder/0.3.0/jpeg-decoder-0.3.0.aar.sha1: -------------------------------------------------------------------------------- 1 | f8a2cbe9593c76e53e06601a0345fad72913b37a -------------------------------------------------------------------------------- /repository/rapid/decoder/jpeg-decoder/0.3.0/jpeg-decoder-0.3.0.pom: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | rapid.decoder 6 | jpeg-decoder 7 | 0.3.0 8 | aar 9 | RapidDecoder jpeg decoder 10 | 11 | https://github.com/suckgamony/RapidDecoder 12 | 13 | 14 | The Apache Software License, Version 2.0 15 | http://www.apache.org/licenses/LICENSE-2.0.txt 16 | repo 17 | 18 | 19 | 20 | 21 | suckgamony 22 | suckgamony 23 | 24 | 25 | 26 | scm:git@github.com:suckgamony/RapidDecoder.git 27 | scm:git@github.com:suckgamony/RapidDecoder.git 28 | https://github.com/suckgamony/RapidDecoder 29 | 30 | 31 | -------------------------------------------------------------------------------- /repository/rapid/decoder/jpeg-decoder/0.3.0/jpeg-decoder-0.3.0.pom.md5: -------------------------------------------------------------------------------- 1 | 99f72b8265bcb2ee505bde3ef2670f52 -------------------------------------------------------------------------------- /repository/rapid/decoder/jpeg-decoder/0.3.0/jpeg-decoder-0.3.0.pom.sha1: -------------------------------------------------------------------------------- 1 | 6663f729cbfd754fab2860e3b5783e535965f050 -------------------------------------------------------------------------------- /repository/rapid/decoder/jpeg-decoder/maven-metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | rapid.decoder 4 | jpeg-decoder 5 | 0.3.0 6 | 7 | 8 | 0.3.0 9 | 10 | 20150112052238 11 | 12 | 13 | -------------------------------------------------------------------------------- /repository/rapid/decoder/jpeg-decoder/maven-metadata.xml.md5: -------------------------------------------------------------------------------- 1 | cfcf2914bd09d116b4d0ad335e02187f -------------------------------------------------------------------------------- /repository/rapid/decoder/jpeg-decoder/maven-metadata.xml.sha1: -------------------------------------------------------------------------------- 1 | c1a28a1369ecd3e5ad048e7bfffbff67e170d976 -------------------------------------------------------------------------------- /repository/rapid/decoder/library/0.3.0/library-0.3.0-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/repository/rapid/decoder/library/0.3.0/library-0.3.0-sources.jar -------------------------------------------------------------------------------- /repository/rapid/decoder/library/0.3.0/library-0.3.0-sources.jar.md5: -------------------------------------------------------------------------------- 1 | d1d407607b28a5e54d0ddb10b0927cd1 -------------------------------------------------------------------------------- /repository/rapid/decoder/library/0.3.0/library-0.3.0-sources.jar.sha1: -------------------------------------------------------------------------------- 1 | 691b867b4bd5b1b2a3aef0f67c17a0cca008c9ce -------------------------------------------------------------------------------- /repository/rapid/decoder/library/0.3.0/library-0.3.0.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/repository/rapid/decoder/library/0.3.0/library-0.3.0.aar -------------------------------------------------------------------------------- /repository/rapid/decoder/library/0.3.0/library-0.3.0.aar.md5: -------------------------------------------------------------------------------- 1 | f7017db27385a01c868f74c0147cf15e -------------------------------------------------------------------------------- /repository/rapid/decoder/library/0.3.0/library-0.3.0.aar.sha1: -------------------------------------------------------------------------------- 1 | 311258077a0deaaa09f6b44ef66e9e3afa8ef31c -------------------------------------------------------------------------------- /repository/rapid/decoder/library/0.3.0/library-0.3.0.pom: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | rapid.decoder 6 | library 7 | 0.3.0 8 | aar 9 | RapidDecoder library 10 | 11 | https://github.com/suckgamony/RapidDecoder 12 | 13 | 14 | The Apache Software License, Version 2.0 15 | http://www.apache.org/licenses/LICENSE-2.0.txt 16 | repo 17 | 18 | 19 | 20 | 21 | suckgamony 22 | suckgamony 23 | 24 | 25 | 26 | scm:git@github.com:suckgamony/RapidDecoder.git 27 | scm:git@github.com:suckgamony/RapidDecoder.git 28 | https://github.com/suckgamony/RapidDecoder 29 | 30 | 31 | 32 | com.android.support 33 | support-annotations 34 | + 35 | compile 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /repository/rapid/decoder/library/0.3.0/library-0.3.0.pom.md5: -------------------------------------------------------------------------------- 1 | 3ca7d61652d580cf40470d3c455a789a -------------------------------------------------------------------------------- /repository/rapid/decoder/library/0.3.0/library-0.3.0.pom.sha1: -------------------------------------------------------------------------------- 1 | 11f2b87ffe1690112de70cf4c43f45e94d336bc8 -------------------------------------------------------------------------------- /repository/rapid/decoder/library/maven-metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | rapid.decoder 4 | library 5 | 0.3.0 6 | 7 | 8 | 0.3.0 9 | 10 | 20150112052238 11 | 12 | 13 | -------------------------------------------------------------------------------- /repository/rapid/decoder/library/maven-metadata.xml.md5: -------------------------------------------------------------------------------- 1 | fd93730e1d808fb2dbfc472e8c844fe7 -------------------------------------------------------------------------------- /repository/rapid/decoder/library/maven-metadata.xml.sha1: -------------------------------------------------------------------------------- 1 | 89fc18aea6d2310759f21c2f7956670b73359afd -------------------------------------------------------------------------------- /repository/rapid/decoder/png-decoder/0.3.0/png-decoder-0.3.0-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/repository/rapid/decoder/png-decoder/0.3.0/png-decoder-0.3.0-sources.jar -------------------------------------------------------------------------------- /repository/rapid/decoder/png-decoder/0.3.0/png-decoder-0.3.0-sources.jar.md5: -------------------------------------------------------------------------------- 1 | 0b51060aecd365a51cd378036450cc79 -------------------------------------------------------------------------------- /repository/rapid/decoder/png-decoder/0.3.0/png-decoder-0.3.0-sources.jar.sha1: -------------------------------------------------------------------------------- 1 | 84fc5c865f3f58c738c0542ebfae0fedba06f26c -------------------------------------------------------------------------------- /repository/rapid/decoder/png-decoder/0.3.0/png-decoder-0.3.0.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/repository/rapid/decoder/png-decoder/0.3.0/png-decoder-0.3.0.aar -------------------------------------------------------------------------------- /repository/rapid/decoder/png-decoder/0.3.0/png-decoder-0.3.0.aar.md5: -------------------------------------------------------------------------------- 1 | a7429ea6314e5e0d18acf4e5d67a1a95 -------------------------------------------------------------------------------- /repository/rapid/decoder/png-decoder/0.3.0/png-decoder-0.3.0.aar.sha1: -------------------------------------------------------------------------------- 1 | 93c0bda8f5f74a0ca07f30510acf4d1d79a19f6a -------------------------------------------------------------------------------- /repository/rapid/decoder/png-decoder/0.3.0/png-decoder-0.3.0.pom: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | rapid.decoder 6 | png-decoder 7 | 0.3.0 8 | aar 9 | RapidDecoder png decoder 10 | 11 | https://github.com/suckgamony/RapidDecoder 12 | 13 | 14 | The Apache Software License, Version 2.0 15 | http://www.apache.org/licenses/LICENSE-2.0.txt 16 | repo 17 | 18 | 19 | 20 | 21 | suckgamony 22 | suckgamony 23 | 24 | 25 | 26 | scm:git@github.com:suckgamony/RapidDecoder.git 27 | scm:git@github.com:suckgamony/RapidDecoder.git 28 | https://github.com/suckgamony/RapidDecoder 29 | 30 | 31 | -------------------------------------------------------------------------------- /repository/rapid/decoder/png-decoder/0.3.0/png-decoder-0.3.0.pom.md5: -------------------------------------------------------------------------------- 1 | b4f1a6f956006ee6e2c31c2960df92bf -------------------------------------------------------------------------------- /repository/rapid/decoder/png-decoder/0.3.0/png-decoder-0.3.0.pom.sha1: -------------------------------------------------------------------------------- 1 | 378b23b1ab0b99c3d7b221cf632a8dcd98944911 -------------------------------------------------------------------------------- /repository/rapid/decoder/png-decoder/maven-metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | rapid.decoder 4 | png-decoder 5 | 0.3.0 6 | 7 | 8 | 0.3.0 9 | 10 | 20150112052238 11 | 12 | 13 | -------------------------------------------------------------------------------- /repository/rapid/decoder/png-decoder/maven-metadata.xml.md5: -------------------------------------------------------------------------------- 1 | 8c8af549af5315c2c73ac43dfe028541 -------------------------------------------------------------------------------- /repository/rapid/decoder/png-decoder/maven-metadata.xml.sha1: -------------------------------------------------------------------------------- 1 | 7c92edbfaf1956f186d744969dc1579cf62656a9 -------------------------------------------------------------------------------- /sample/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /sample/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 21 5 | buildToolsVersion "21.1.2" 6 | 7 | defaultConfig { 8 | applicationId "rapid.decoder.sample" 9 | minSdkVersion 8 10 | targetSdkVersion 21 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | } 16 | } 17 | 18 | dependencies { 19 | compile project(':library') 20 | compile project(':jpeg-decoder') 21 | compile project(':png-decoder') 22 | compile fileTree(dir: 'libs', include: ['*.jar']) 23 | compile 'com.android.support:appcompat-v7:20.0.0' 24 | } 25 | -------------------------------------------------------------------------------- /sample/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /opt/android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /sample/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 13 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /sample/src/main/assets/squirrel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/sample/src/main/assets/squirrel.jpg -------------------------------------------------------------------------------- /sample/src/main/java/rapid/decoder/sample/FrameFragment.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.sample; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.drawable.Drawable; 5 | import android.os.Bundle; 6 | import android.support.annotation.Nullable; 7 | import android.support.v4.app.Fragment; 8 | import android.view.Display; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.widget.ImageView; 13 | 14 | import rapid.decoder.BitmapDecoder; 15 | import rapid.decoder.compat.DisplayCompat; 16 | import rapid.decoder.frame.FramedDecoder; 17 | 18 | public class FrameFragment extends Fragment { 19 | @Override 20 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 21 | Bundle savedInstanceState) { 22 | 23 | return inflater.inflate(R.layout.fragment_frame, container, false); 24 | } 25 | 26 | @SuppressWarnings("SuspiciousNameCombination") 27 | @Override 28 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 29 | super.onViewCreated(view, savedInstanceState); 30 | 31 | Display display = getActivity().getWindowManager().getDefaultDisplay(); 32 | int width = DisplayCompat.getWidth(display); 33 | 34 | int imageWidth = width / 5; 35 | 36 | ImageView imageMatrix = (ImageView) view.findViewById(R.id.image_matrix); 37 | ImageView imageFitXY = (ImageView) view.findViewById(R.id.image_fit_xy); 38 | ImageView imageFitStart = (ImageView) view.findViewById(R.id.image_fit_start); 39 | ImageView imageFitCenter = (ImageView) view.findViewById(R.id.image_fit_center); 40 | ImageView imageFitEnd = (ImageView) view.findViewById(R.id.image_fit_end); 41 | ImageView imageCenter = (ImageView) view.findViewById(R.id.image_center); 42 | ImageView imageCenterCrop = (ImageView) view.findViewById(R.id.image_center_crop); 43 | ImageView imageCenterInside = (ImageView) view.findViewById(R.id.image_center_inside); 44 | 45 | Drawable transparentBackground = getResources().getDrawable(R.drawable 46 | .transparent_background); 47 | 48 | BitmapDecoder amanda = BitmapDecoder.from(getResources(), R.drawable.amanda).scaleBy(0.5f); 49 | Bitmap bitmap; 50 | 51 | bitmap = FramedDecoder.newInstance(amanda, imageWidth, imageWidth, 52 | ImageView.ScaleType.MATRIX) 53 | .background(transparentBackground) 54 | .decode(); 55 | imageMatrix.setImageBitmap(bitmap); 56 | 57 | bitmap = FramedDecoder.newInstance(amanda, imageWidth, imageWidth, 58 | ImageView.ScaleType.FIT_XY) 59 | .background(transparentBackground) 60 | .decode(); 61 | imageFitXY.setImageBitmap(bitmap); 62 | 63 | bitmap = FramedDecoder.newInstance(amanda, imageWidth, imageWidth, 64 | ImageView.ScaleType.FIT_START) 65 | .background(transparentBackground) 66 | .decode(); 67 | imageFitStart.setImageBitmap(bitmap); 68 | 69 | bitmap = FramedDecoder.newInstance(amanda, imageWidth, imageWidth, 70 | ImageView.ScaleType.FIT_CENTER) 71 | .background(transparentBackground) 72 | .decode(); 73 | imageFitCenter.setImageBitmap(bitmap); 74 | 75 | bitmap = FramedDecoder.newInstance(amanda, imageWidth, imageWidth, 76 | ImageView.ScaleType.FIT_END) 77 | .background(transparentBackground) 78 | .decode(); 79 | imageFitEnd.setImageBitmap(bitmap); 80 | 81 | bitmap = FramedDecoder.newInstance(amanda, imageWidth, imageWidth, 82 | ImageView.ScaleType.CENTER) 83 | .background(transparentBackground) 84 | .decode(); 85 | imageCenter.setImageBitmap(bitmap); 86 | 87 | bitmap = FramedDecoder.newInstance(amanda, imageWidth, imageWidth, 88 | ImageView.ScaleType.CENTER_CROP) 89 | .background(transparentBackground) 90 | .decode(); 91 | imageCenterCrop.setImageBitmap(bitmap); 92 | 93 | bitmap = FramedDecoder.newInstance(amanda, imageWidth, imageWidth, 94 | ImageView.ScaleType.CENTER_INSIDE) 95 | .background(transparentBackground) 96 | .decode(); 97 | imageCenterInside.setImageBitmap(bitmap); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /sample/src/main/java/rapid/decoder/sample/GalleryFragment.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.sample; 2 | 3 | import android.content.Context; 4 | import android.database.Cursor; 5 | import android.graphics.drawable.ColorDrawable; 6 | import android.os.Bundle; 7 | import android.provider.MediaStore; 8 | import android.support.annotation.Nullable; 9 | import android.support.v4.app.Fragment; 10 | import android.support.v4.app.LoaderManager; 11 | import android.support.v4.content.CursorLoader; 12 | import android.support.v4.content.Loader; 13 | import android.view.LayoutInflater; 14 | import android.view.View; 15 | import android.view.ViewGroup; 16 | import android.widget.CursorAdapter; 17 | import android.widget.GridView; 18 | import android.widget.ImageView; 19 | 20 | import rapid.decoder.BitmapDecoder; 21 | import rapid.decoder.binder.ImageViewBinder; 22 | import rapid.decoder.binder.ViewBinder; 23 | 24 | public class GalleryFragment extends Fragment implements LoaderManager.LoaderCallbacks { 25 | private GalleryAdapter mAdapter; 26 | 27 | @Override 28 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, 29 | @Nullable Bundle savedInstanceState) { 30 | return inflater.inflate(R.layout.fragment_gallery, container, false); 31 | } 32 | 33 | @Override 34 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 35 | super.onViewCreated(view, savedInstanceState); 36 | GridView grid = (GridView) view.findViewById(R.id.grid); 37 | mAdapter = new GalleryAdapter(view.getContext()); 38 | grid.setAdapter(mAdapter); 39 | getLoaderManager().initLoader(0, null, this); 40 | } 41 | 42 | @Override 43 | public Loader onCreateLoader(int i, Bundle bundle) { 44 | return new CursorLoader(getActivity(), 45 | MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, 46 | new String[]{ 47 | MediaStore.Images.Thumbnails._ID, 48 | MediaStore.Images.Thumbnails.DATA, 49 | MediaStore.Images.Thumbnails.IMAGE_ID 50 | }, 51 | null, null, null 52 | ); 53 | } 54 | 55 | @Override 56 | public void onLoadFinished(Loader cursorLoader, Cursor cursor) { 57 | mAdapter.changeCursor(cursor); 58 | } 59 | 60 | @Override 61 | public void onLoaderReset(Loader cursorLoader) { 62 | mAdapter.changeCursor(null); 63 | } 64 | 65 | private static class GalleryAdapter extends CursorAdapter { 66 | public GalleryAdapter(Context context) { 67 | super(context, null, false); 68 | } 69 | 70 | @Override 71 | public View newView(Context context, Cursor cursor, ViewGroup parent) { 72 | return LayoutInflater.from(context).inflate(R.layout.item_gallery, parent, false); 73 | } 74 | 75 | @Override 76 | public void bindView(View view, Context context, Cursor cursor) { 77 | ImageView imageView = (ImageView) view; 78 | ViewBinder binder = ImageViewBinder.obtain(imageView) 79 | .scaleType(ImageView.ScaleType.CENTER_CROP) 80 | .placeholder(new ColorDrawable(0xffcccccc)); 81 | 82 | String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Thumbnails 83 | .DATA)); 84 | BitmapDecoder.from(path).into(binder); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /sample/src/main/java/rapid/decoder/sample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.sample; 2 | 3 | import android.content.res.Configuration; 4 | import android.os.Bundle; 5 | import android.support.v4.app.ActionBarDrawerToggle; 6 | import android.support.v4.app.Fragment; 7 | import android.support.v4.widget.DrawerLayout; 8 | import android.support.v7.app.ActionBar; 9 | import android.support.v7.app.ActionBarActivity; 10 | import android.view.Gravity; 11 | import android.view.KeyEvent; 12 | import android.view.MenuItem; 13 | import android.view.View; 14 | import android.widget.AdapterView; 15 | import android.widget.AdapterView.OnItemClickListener; 16 | import android.widget.ArrayAdapter; 17 | import android.widget.ListView; 18 | 19 | import rapid.decoder.BitmapDecoder; 20 | 21 | public class MainActivity extends ActionBarActivity { 22 | public static final boolean TEST_BUILT_IN_DECODER = true; 23 | 24 | private ActionBarDrawerToggle mDrawerToggle; 25 | private DrawerLayout mDrawer; 26 | private ArrayAdapter mAdapterDrawerMenu; 27 | private int nextContent = -1; 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | setContentView(R.layout.activity_main); 33 | 34 | BitmapDecoder.initDiskCache(this); 35 | BitmapDecoder.initMemoryCache(this); 36 | 37 | mDrawer = (DrawerLayout) findViewById(R.id.drawer); 38 | ListView listDrawerMenu = (ListView) findViewById(R.id.list_drawer_menu); 39 | 40 | ActionBar actionBar = getSupportActionBar(); 41 | actionBar.setDisplayHomeAsUpEnabled(true); 42 | actionBar.setHomeButtonEnabled(true); 43 | mDrawerToggle = new ActionBarDrawerToggle(this, mDrawer, R.drawable.ic_navigation_drawer, 44 | R.string.drawer_open, R.string.drawer_close) { 45 | 46 | @Override 47 | public void onDrawerClosed(View v) { 48 | super.onDrawerClosed(v); 49 | if (nextContent >= 0) { 50 | loadContent(nextContent); 51 | nextContent = -1; 52 | } 53 | } 54 | }; 55 | 56 | mAdapterDrawerMenu = new ArrayAdapter<>(this, 57 | android.R.layout.simple_list_item_1, getResources().getStringArray(R.array 58 | .drawer_menu_items)); 59 | listDrawerMenu.setAdapter(mAdapterDrawerMenu); 60 | 61 | listDrawerMenu.setOnItemClickListener(new OnItemClickListener() { 62 | @Override 63 | public void onItemClick(AdapterView arg0, View arg1, int position, 64 | long arg3) { 65 | nextContent = position; 66 | mDrawer.closeDrawers(); 67 | } 68 | }); 69 | 70 | mDrawer.setDrawerListener(mDrawerToggle); 71 | supportInvalidateOptionsMenu(); 72 | loadContent(0); 73 | } 74 | 75 | @Override 76 | protected void onPostCreate(Bundle savedInstanceState) { 77 | super.onPostCreate(savedInstanceState); 78 | mDrawerToggle.syncState(); 79 | } 80 | 81 | private void loadContent(int index) { 82 | Fragment fragment; 83 | 84 | switch (index) { 85 | case 0: 86 | fragment = new ScaledDecodingFragment(); 87 | break; 88 | case 1: 89 | fragment = new RegionalDecodingFragment(); 90 | break; 91 | case 2: 92 | fragment = new MutableDecodingFragment(); 93 | break; 94 | case 3: 95 | fragment = new FrameFragment(); 96 | break; 97 | case 4: 98 | fragment = new GalleryFragment(); 99 | break; 100 | case 5: 101 | fragment = new ContactsFragment(); 102 | break; 103 | case 6: 104 | fragment = new WrapContentFragment(); 105 | break; 106 | case 7: 107 | fragment = new ResetFragment(); 108 | break; 109 | default: 110 | return; 111 | } 112 | 113 | setTitle(mAdapterDrawerMenu.getItem(index)); 114 | getSupportFragmentManager().beginTransaction().replace(R.id.content, fragment).commit(); 115 | 116 | mDrawer.closeDrawers(); 117 | } 118 | 119 | @Override 120 | public boolean onKeyDown(int keyCode, KeyEvent event) { 121 | if (keyCode == KeyEvent.KEYCODE_MENU) { 122 | mDrawer.openDrawer(Gravity.LEFT); 123 | return true; 124 | } else { 125 | return super.onKeyDown(keyCode, event); 126 | } 127 | } 128 | 129 | @Override 130 | public void onConfigurationChanged(Configuration newConfig) { 131 | super.onConfigurationChanged(newConfig); 132 | mDrawerToggle.onConfigurationChanged(newConfig); 133 | } 134 | 135 | @Override 136 | public boolean onOptionsItemSelected(MenuItem item) { 137 | return mDrawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /sample/src/main/java/rapid/decoder/sample/MutableDecodingFragment.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.sample; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Canvas; 5 | import android.os.Bundle; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.ImageView; 11 | 12 | import rapid.decoder.BitmapDecoder; 13 | 14 | public class MutableDecodingFragment extends Fragment { 15 | @Override 16 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 17 | Bundle savedInstanceState) { 18 | 19 | return inflater.inflate(R.layout.fragment_mutable_decoding, container, false); 20 | } 21 | 22 | @Override 23 | public void onActivityCreated(Bundle savedInstanceState) { 24 | super.onActivityCreated(savedInstanceState); 25 | 26 | ImageView imageView = (ImageView) getView().findViewById(R.id.image_view); 27 | 28 | int imageWidth = getResources().getDimensionPixelOffset(R.dimen.scaled_decoding_width); 29 | int imageHeight = getResources().getDimensionPixelOffset(R.dimen.scaled_decoding_height); 30 | 31 | Bitmap bitmap = BitmapDecoder.from(getResources(), R.drawable.amanda) 32 | .scale(imageWidth, imageHeight).mutable().decode(); 33 | Canvas cv = new Canvas(bitmap); 34 | 35 | int ribbonLeft = getResources().getDimensionPixelOffset(R.dimen.ribbon_x); 36 | int ribbonTop = getResources().getDimensionPixelOffset(R.dimen.ribbon_y); 37 | int ribbonWidth = getResources().getDimensionPixelSize(R.dimen.ribbon_width); 38 | int ribbonHeight = getResources().getDimensionPixelSize(R.dimen.ribbon_width); 39 | 40 | BitmapDecoder.from(getResources(), R.drawable.ribbon) 41 | .scale(ribbonWidth, ribbonHeight) 42 | .draw(cv, ribbonLeft, ribbonTop); 43 | 44 | imageView.setImageBitmap(bitmap); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /sample/src/main/java/rapid/decoder/sample/RegionalDecodingFragment.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.sample; 2 | 3 | import android.graphics.Bitmap; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.ImageView; 11 | 12 | import rapid.decoder.BitmapDecoder; 13 | 14 | public class RegionalDecodingFragment extends Fragment { 15 | @Override 16 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 17 | Bundle savedInstanceState) { 18 | 19 | return inflater.inflate(R.layout.fragment_scaled_decoding, container, false); 20 | } 21 | 22 | @Override 23 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 24 | super.onViewCreated(view, savedInstanceState); 25 | 26 | ImageView imageJpeg = (ImageView) view.findViewById(R.id.image_jpeg); 27 | ImageView imagePng = (ImageView) view.findViewById(R.id.image_png); 28 | 29 | // Jpeg 30 | 31 | Bitmap bitmap = BitmapDecoder.from(getResources(), R.drawable.amanda) 32 | .region(140, 22, 1010, 1111) 33 | .scaleBy(0.5f) 34 | .useBuiltInDecoder(MainActivity.TEST_BUILT_IN_DECODER) 35 | .decode(); 36 | imageJpeg.setImageBitmap(bitmap); 37 | 38 | // Png 39 | 40 | bitmap = BitmapDecoder.from(getResources(), R.drawable.amanda2) 41 | .region(204, 0, 900, 773) 42 | .scaleBy(0.5f) 43 | .useBuiltInDecoder(MainActivity.TEST_BUILT_IN_DECODER) 44 | .decode(); 45 | imagePng.setImageBitmap(bitmap); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /sample/src/main/java/rapid/decoder/sample/ResetFragment.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.sample; 2 | 3 | import android.graphics.Bitmap; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.ImageView; 11 | 12 | import rapid.decoder.BitmapDecoder; 13 | import rapid.decoder.BitmapLoader; 14 | 15 | public class ResetFragment extends Fragment { 16 | @Override 17 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, 18 | @Nullable Bundle savedInstanceState) { 19 | return inflater.inflate(R.layout.fragment_reset, container, false); 20 | } 21 | 22 | @Override 23 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 24 | super.onViewCreated(view, savedInstanceState); 25 | 26 | ImageView imageView1 = (ImageView) view.findViewById(R.id.image1); 27 | ImageView imageView2 = (ImageView) view.findViewById(R.id.image2); 28 | 29 | BitmapLoader loader = BitmapDecoder.from(getActivity(), "file:///android_asset/squirrel.jpg"); 30 | Bitmap bitmap = loader.region(140, 22, 1010, 1111) 31 | .scale(300, 400) 32 | .useBuiltInDecoder(MainActivity.TEST_BUILT_IN_DECODER) 33 | .decode(); 34 | imageView1.setImageBitmap(bitmap); 35 | 36 | bitmap = loader.reset() 37 | .scale(500, 500) 38 | .useBuiltInDecoder(MainActivity.TEST_BUILT_IN_DECODER) 39 | .decode(); 40 | imageView2.setImageBitmap(bitmap); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /sample/src/main/java/rapid/decoder/sample/ScaledDecodingFragment.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.sample; 2 | 3 | import android.graphics.Bitmap; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.ImageView; 11 | import android.widget.TextView; 12 | 13 | import rapid.decoder.BitmapDecoder; 14 | 15 | public class ScaledDecodingFragment extends Fragment { 16 | @Override 17 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 18 | Bundle savedInstanceState) { 19 | 20 | return inflater.inflate(R.layout.fragment_scaled_decoding, container, false); 21 | } 22 | 23 | @Override 24 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 25 | super.onViewCreated(view, savedInstanceState); 26 | 27 | ImageView imageJpeg = (ImageView) view.findViewById(R.id.image_jpeg); 28 | ImageView imagePng = (ImageView) view.findViewById(R.id.image_png); 29 | TextView textJpegInfo = (TextView) view.findViewById(R.id.text_jpeg_info); 30 | TextView textPngInfo = (TextView) view.findViewById(R.id.text_png_info); 31 | 32 | int width = getResources().getDimensionPixelSize(R.dimen.scaled_decoding_width); 33 | int height = getResources().getDimensionPixelSize(R.dimen.scaled_decoding_height); 34 | 35 | BitmapDecoder decoder; 36 | Bitmap bitmap; 37 | int sourceWidth; 38 | int sourceHeight; 39 | 40 | // Jpeg 41 | 42 | decoder = BitmapDecoder.from(getResources(), R.drawable.amanda); 43 | sourceWidth = decoder.width(); 44 | sourceHeight = decoder.height(); 45 | 46 | bitmap = decoder 47 | .scale(width, height) 48 | .useBuiltInDecoder(MainActivity.TEST_BUILT_IN_DECODER) 49 | .decode(); 50 | imageJpeg.setImageBitmap(bitmap); 51 | 52 | //noinspection ConstantConditions 53 | textJpegInfo.setText("Source width = " + sourceWidth + ", Source height = " + sourceHeight + "\n" + 54 | "Bitmap width = " + bitmap.getWidth() + ", Bitmap height = " + bitmap.getHeight()); 55 | 56 | // Png 57 | 58 | decoder = BitmapDecoder.from(getResources(), R.drawable.amanda2); 59 | sourceWidth = decoder.width(); 60 | sourceHeight = decoder.height(); 61 | 62 | bitmap = decoder 63 | .scale(width, height) 64 | .useBuiltInDecoder(MainActivity.TEST_BUILT_IN_DECODER) 65 | .decode(); 66 | imagePng.setImageBitmap(bitmap); 67 | 68 | //noinspection ConstantConditions 69 | textPngInfo.setText("Source width = " + sourceWidth + ", Source height = " + sourceHeight + "\n" + 70 | "Bitmap width = " + bitmap.getWidth() + ", Bitmap height = " + bitmap.getHeight()); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /sample/src/main/java/rapid/decoder/sample/WrapContentFragment.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.sample; 2 | 3 | import android.content.res.Resources; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.ImageView; 11 | 12 | import rapid.decoder.BitmapDecoder; 13 | 14 | public class WrapContentFragment extends Fragment { 15 | @Override 16 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, 17 | @Nullable Bundle savedInstanceState) { 18 | return inflater.inflate(R.layout.fragment_wrap_content, container, false); 19 | } 20 | 21 | @Override 22 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 23 | super.onViewCreated(view, savedInstanceState); 24 | 25 | ImageView pic1 = (ImageView) view.findViewById(R.id.pic1); 26 | View pic2 = view.findViewById(R.id.pic2); 27 | ImageView pic3 = (ImageView) view.findViewById(R.id.pic3); 28 | View pic4 = view.findViewById(R.id.pic4); 29 | 30 | Resources res = getResources(); 31 | 32 | BitmapDecoder.from(res, R.drawable.horizontal_reflex_848).into(pic1); 33 | BitmapDecoder.from(res, R.drawable.vertical_panorama02).into(pic2); 34 | BitmapDecoder.from(res, R.drawable.horizontal_reflex_848).into(pic3); 35 | BitmapDecoder.from(res, R.drawable.vertical_panorama02).into(pic4); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /sample/src/main/java/rapid/decoder/sample/widget/SquaredImageView.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder.sample.widget; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.widget.ImageView; 6 | 7 | public class SquaredImageView extends ImageView { 8 | public SquaredImageView(Context context) { 9 | super(context); 10 | } 11 | 12 | public SquaredImageView(Context context, AttributeSet attrs) { 13 | super(context, attrs); 14 | } 15 | 16 | public SquaredImageView(Context context, AttributeSet attrs, int defStyle) { 17 | super(context, attrs, defStyle); 18 | } 19 | 20 | @Override 21 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 22 | // heightMeasureSpec = MeasureSpec.makeMeasureSpec( 23 | // MeasureSpec.getSize(widthMeasureSpec), 24 | // MeasureSpec.getMode(heightMeasureSpec) 25 | // ); 26 | super.onMeasure(widthMeasureSpec, widthMeasureSpec); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/sample/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-hdpi/ic_navigation_drawer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/sample/src/main/res/drawable-hdpi/ic_navigation_drawer.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/sample/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-mdpi/ic_navigation_drawer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/sample/src/main/res/drawable-mdpi/ic_navigation_drawer.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-mdpi/transparent_background_base.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/sample/src/main/res/drawable-mdpi/transparent_background_base.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-nodpi/amanda.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/sample/src/main/res/drawable-nodpi/amanda.jpg -------------------------------------------------------------------------------- /sample/src/main/res/drawable-nodpi/amanda2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/sample/src/main/res/drawable-nodpi/amanda2.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-nodpi/horizontal_reflex_848.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/sample/src/main/res/drawable-nodpi/horizontal_reflex_848.jpg -------------------------------------------------------------------------------- /sample/src/main/res/drawable-nodpi/ribbon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/sample/src/main/res/drawable-nodpi/ribbon.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-nodpi/vertical_panorama02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/sample/src/main/res/drawable-nodpi/vertical_panorama02.jpg -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/sample/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_navigation_drawer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/sample/src/main/res/drawable-xhdpi/ic_navigation_drawer.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xxhdpi/ic_navigation_drawer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/sample/src/main/res/drawable-xxhdpi/ic_navigation_drawer.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable/contacts_profile_image_placeholder.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable/transparent_background.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 12 | 13 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/fragment_contacts.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/fragment_gallery.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 14 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/fragment_mutable_decoding.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 16 | 17 | 21 | 22 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/fragment_regional_decoding.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 16 | 17 | 22 | 23 | 28 | 29 | 35 | 36 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/fragment_reset.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 13 | 14 | 19 | 20 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/fragment_scaled_decoding.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 16 | 17 | 22 | 23 | 28 | 29 | 32 | 33 | 39 | 40 | 45 | 46 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/fragment_wrap_content.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 13 | 14 | 19 | 20 | 24 | 25 | 29 | 30 | 35 | 36 | 42 | 43 | 44 | 45 | 46 | 47 | 53 | 54 | 58 | 59 | 63 | 64 | 69 | 70 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/item_contacts.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/item_gallery.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /sample/src/main/res/values/arrays.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Scaled decoding sample 6 | Regional decoding sample 7 | Mutable decoding sample 8 | FramedDecoder sample 9 | Gallery sample 10 | Contacts sample 11 | Wrap content sample 12 | Reset sample 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /sample/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | 270dp 7 | 360dp 8 | 9 | 150dp 10 | 11 | 40dp 12 | 20dp 13 | 68dp 14 | 54dp 15 | 16 | 32dp 17 | 18 | 19 | -------------------------------------------------------------------------------- /sample/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | RapidDecoder sample 5 | 6 | Jpeg 7 | Png 8 | Ribbon has been added right on the decoded image. 9 | Center 10 | Matrix 11 | FitXY 12 | FitStart 13 | FitCenter 14 | FitEnd 15 | CenterCrop 16 | CenterInside 17 | Open drawer 18 | Close drawer 19 | Fixed height and wrapped width 20 | Fixed width and wrapped height 21 | 22 | 23 | -------------------------------------------------------------------------------- /sample/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':library', ':sample', ':test', ':png-decoder', ':jpeg-decoder' 2 | -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /test/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 21 5 | buildToolsVersion '21.1.2' 6 | 7 | defaultConfig { 8 | applicationId "rapid.decoder.test" 9 | minSdkVersion 8 10 | targetSdkVersion 21 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | } 16 | } 17 | 18 | dependencies { 19 | compile fileTree(dir: 'libs', include: ['*.jar']) 20 | compile project(':library') 21 | compile project(':png-decoder') 22 | compile project(':jpeg-decoder') 23 | } 24 | -------------------------------------------------------------------------------- /test/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /opt/android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /test/src/androidTest/java/rapid/decoder/BasicUnitTest.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.content.res.Resources; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.graphics.Rect; 7 | import android.test.AndroidTestCase; 8 | 9 | import rapid.decoder.test.R; 10 | 11 | public class BasicUnitTest extends AndroidTestCase { 12 | private Resources res; 13 | 14 | @SuppressWarnings("unused") 15 | private static void assertEquals(Rect rect, int left, int top, int right, int bottom) { 16 | assertEquals(left, rect.left); 17 | assertEquals(top, rect.top); 18 | assertEquals(right, rect.right); 19 | assertEquals(bottom, rect.bottom); 20 | } 21 | 22 | @Override 23 | protected void setUp() throws Exception { 24 | res = getContext().getResources(); 25 | } 26 | 27 | public void testDecoding() { 28 | decodingTest(R.drawable.android); 29 | decodingTest(R.drawable.pond); 30 | } 31 | 32 | private void decodingTest(int id) { 33 | Bitmap bitmap = BitmapFactory.decodeResource(res, id); 34 | Bitmap bitmap2; 35 | 36 | BitmapDecoder d; 37 | int w, h; 38 | 39 | d = BitmapDecoder.from(res, id); 40 | w = d.width(); 41 | h = d.height(); 42 | bitmap2 = d.decode(); 43 | assertNotNull(bitmap2); 44 | assertEquals(bitmap.getWidth(), bitmap2.getWidth()); 45 | assertEquals(bitmap.getHeight(), bitmap2.getHeight()); 46 | assertEquals(bitmap2.getWidth(), w); 47 | assertEquals(bitmap2.getHeight(), h); 48 | bitmap2.recycle(); 49 | 50 | d = BitmapDecoder.from(res, id).useBuiltInDecoder(); 51 | w = d.width(); 52 | h = d.height(); 53 | bitmap2 = d.decode(); 54 | assertNotNull(bitmap2); 55 | assertEquals(bitmap.getWidth(), bitmap2.getWidth()); 56 | assertEquals(bitmap.getHeight(), bitmap2.getHeight()); 57 | assertEquals(bitmap2.getWidth(), w); 58 | assertEquals(bitmap2.getHeight(), h); 59 | bitmap2.recycle(); 60 | 61 | d = BitmapDecoder.from(res, id).region(10, 10, 100, 90); 62 | w = d.width(); 63 | h = d.height(); 64 | bitmap2 = d.decode(); 65 | assertNotNull(bitmap2); 66 | assertEquals(90, bitmap2.getWidth()); 67 | assertEquals(80, bitmap2.getHeight()); 68 | assertEquals(bitmap2.getWidth(), w); 69 | assertEquals(bitmap2.getHeight(), h); 70 | bitmap2.recycle(); 71 | 72 | d = BitmapDecoder.from(res, id).region(10, 10, 100, 90).scaleBy(0.7f, 0.8f); 73 | w = d.width(); 74 | h = d.height(); 75 | bitmap2 = d.decode(); 76 | assertNotNull(bitmap2); 77 | assertEquals(63, bitmap2.getWidth()); 78 | assertEquals(64, bitmap2.getHeight()); 79 | assertEquals(bitmap2.getWidth(), w); 80 | assertEquals(bitmap2.getHeight(), h); 81 | bitmap2.recycle(); 82 | 83 | d = BitmapDecoder.from(res, id).region(10, 10, 100, 90).useBuiltInDecoder(); 84 | w = d.width(); 85 | h = d.height(); 86 | bitmap2 = d.decode(); 87 | assertNotNull(bitmap2); 88 | assertEquals(90, bitmap2.getWidth()); 89 | assertEquals(80, bitmap2.getHeight()); 90 | assertEquals(bitmap2.getWidth(), w); 91 | assertEquals(bitmap2.getHeight(), h); 92 | bitmap2.recycle(); 93 | 94 | d = BitmapDecoder.from(res, id).region(10, 10, 100, 90).scaleBy(0.7f, 0.8f).useBuiltInDecoder(); 95 | w = d.width(); 96 | h = d.height(); 97 | bitmap2 = d.decode(); 98 | assertNotNull(bitmap2); 99 | assertEquals(63, bitmap2.getWidth()); 100 | assertEquals(64, bitmap2.getHeight()); 101 | assertEquals(bitmap2.getWidth(), w); 102 | assertEquals(bitmap2.getHeight(), h); 103 | bitmap2.recycle(); 104 | 105 | d = BitmapDecoder.from(res, id).scale(210, 220); 106 | w = d.width(); 107 | h = d.height(); 108 | bitmap2 = d.decode(); 109 | assertNotNull(bitmap2); 110 | assertEquals(210, bitmap2.getWidth()); 111 | assertEquals(220, bitmap2.getHeight()); 112 | assertEquals(bitmap2.getWidth(), w); 113 | assertEquals(bitmap2.getHeight(), h); 114 | bitmap2.recycle(); 115 | 116 | final float SCALE_FACTOR = 0.5f; 117 | 118 | d = BitmapDecoder.from(res, id).scaleBy(SCALE_FACTOR); 119 | w = d.width(); 120 | h = d.height(); 121 | bitmap2 = d.decode(); 122 | assertNotNull(bitmap2); 123 | assertEquals((int) Math.ceil(bitmap.getWidth() * SCALE_FACTOR), bitmap2.getWidth()); 124 | assertEquals((int) Math.ceil(bitmap.getHeight() * SCALE_FACTOR), bitmap2.getHeight()); 125 | assertEquals(bitmap2.getWidth(), w); 126 | assertEquals(bitmap2.getHeight(), h); 127 | bitmap2.recycle(); 128 | 129 | d = BitmapDecoder.from(res, id).scaleBy(SCALE_FACTOR).useBuiltInDecoder(); 130 | w = d.width(); 131 | h = d.height(); 132 | bitmap2 = d.decode(); 133 | assertNotNull(bitmap2); 134 | assertEquals((int) Math.ceil(bitmap.getWidth() * SCALE_FACTOR), bitmap2.getWidth()); 135 | assertEquals((int) Math.ceil(bitmap.getHeight() * SCALE_FACTOR), bitmap2.getHeight()); 136 | assertEquals(bitmap2.getWidth(), w); 137 | assertEquals(bitmap2.getHeight(), h); 138 | bitmap2.recycle(); 139 | 140 | // region after scale 141 | 142 | final float SCALE_FACTOR_AFTER_REGION = 0.7f; 143 | 144 | d = BitmapDecoder.from(res, id).scaleBy(SCALE_FACTOR_AFTER_REGION).region(10, 10, 30, 30).mutable(); 145 | w = d.width(); 146 | h = d.height(); 147 | bitmap2 = d.decode(); 148 | assertNotNull(bitmap2); 149 | assertEquals(bitmap2.getWidth(), w); 150 | assertEquals(bitmap2.getHeight(), h); 151 | 152 | bitmap2.recycle(); 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /test/src/androidTest/java/rapid/decoder/DecodeFromUriTest.java: -------------------------------------------------------------------------------- 1 | package rapid.decoder; 2 | 3 | import android.graphics.Bitmap; 4 | import android.test.AndroidTestCase; 5 | 6 | public class DecodeFromUriTest extends AndroidTestCase { 7 | public void testInvalidUri() { 8 | Bitmap bitmap = BitmapDecoder.from(getContext(), "android.resource://a.b.c/12345").decode(); 9 | assertNull(bitmap); 10 | 11 | bitmap = BitmapDecoder.from(getContext(), "://a.b.c/12345").decode(); 12 | assertNull(bitmap); 13 | } 14 | 15 | public void testValidUri() { 16 | Bitmap bitmap = BitmapDecoder.from(getContext(), "android.resource://rapid.decoder" + 17 | ".test/drawable/android").decode(); 18 | assertNotNull(bitmap); 19 | 20 | bitmap = BitmapDecoder.from(getContext(), "android.resource://rapid.decoder" + 21 | ".test/2130837504").decode(); 22 | assertNotNull(bitmap); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /test/src/main/res/drawable-nodpi/android.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/test/src/main/res/drawable-nodpi/android.jpg -------------------------------------------------------------------------------- /test/src/main/res/drawable-xhdpi/pond.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skgmn/RapidDecoder/7cdfca47fa976c3f5f47a7091702cdf1462480be/test/src/main/res/drawable-xhdpi/pond.jpg --------------------------------------------------------------------------------