• Stars
    star
    3,980
  • Rank 10,959 (Top 0.3 %)
  • Language
    Java
  • License
    MIT License
  • Created about 8 years ago
  • Updated about 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Big image viewer supporting pan and zoom, with very little memory usage and full featured image loading choices. Powered by Subsampling Scale Image View, Fresco, Glide, and Picasso. Even with gif and webp support! 🍻

BigImageViewer

Big image viewer supporting pan and zoom, with very little memory usage and full featured image loading choices. Powered by Subsampling Scale Image View, Fresco, Glide, and Picasso. Even with gif and webp support!

Demo

memory usage

pan and zoom gif support
demo gif support

Getting started

Add the dependencies

Note: please put this download url at the first of your repositories part, otherwise, gradle may search in wrong place.

allprojects {
    repositories {
        mavenCentral()
    }
}

implementation 'com.github.piasy:BigImageViewer:1.8.1'

// load with fresco
implementation 'com.github.piasy:FrescoImageLoader:1.8.1'

// load with glide
implementation 'com.github.piasy:GlideImageLoader:1.8.1'

// progress pie indicator
implementation 'com.github.piasy:ProgressPieIndicator:1.8.1'

// support thumbnail, gif and webp with Fresco
implementation 'com.github.piasy:FrescoImageViewFactory:1.8.1'

// support thumbnail and gif with Glide
implementation 'com.github.piasy:GlideImageViewFactory:1.8.1'

Initialize

// MUST use app context to avoid memory leak!
// load with fresco
BigImageViewer.initialize(FrescoImageLoader.with(appContext));

// or load with glide
BigImageViewer.initialize(GlideImageLoader.with(appContext));

// or load with glide custom component
BigImageViewer.initialize(GlideCustomImageLoader.with(appContext, CustomComponentModel.class));

Note that if you've already used Fresco in your project, please change Fresco.initialize into BigImageViewer.initialize.

Add the BigImageView to your layout

<com.github.piasy.biv.view.BigImageView
        android:id="@+id/mBigImage"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:failureImage="@drawable/failure_image"
        app:failureImageInitScaleType="center"
        app:optimizeDisplay="true"
        />

You can disable display optimization using optimizeDisplay attribute, or BigImageView.setOptimizeDisplay(false), which will disable animation for long image, and the switch between thumbnail and origin image.

Show the image

BigImageView bigImageView = (BigImageView) findViewById(R.id.mBigImage);
bigImageView.showImage(Uri.parse(url));

Usage

Animated image support

Since 1.5.0, BIV support display animated image, e.g. gif and animated webp, to achieve that, you need set a custom ImageViewFactory via biv.setImageViewFactory:

// FrescoImageViewFactory is a prebuilt factory, which use Fresco's SimpleDraweeView
// to display animated image, both gif and webp are supported.
biv.setImageViewFactory(new FrescoImageViewFactory());

// GlideImageViewFactory is another prebuilt factory, which use ImageView to display gif,
// animated webp is not supported (although it will be displayed with ImageView,
// but it won't animate).
biv.setImageViewFactory(new GlideImageViewFactory());

Node: if the image is not gif or animated webp, then it will be displayed by SSIV, the image type is not determined by its file extension, but by its file header magic code.

Thumbnail support

To show a thumbnail before the big image is loaded, you can call below version of showImage:

bigImageView.showImage(Uri.parse(thumbnail), Uri.parse(url));

Note: make sure that you have already called setImageViewFactory.

Shared element transition support (experimental)

Since 1.6.0, BIV has experimental support for shared element transition, but it has following known issues:

  • The shared image may flicker during enter transition, or become white after return transition, when using Fresco, see Fresco issue #1445;
  • The shared image may flicker after return transition, especially after you zoomed SSIV;

You can play with the demo app to evaluate the shared element transition support.

Download progress indicator

bigImageView.setProgressIndicator(new ProgressPieIndicator());

There is one built-in indicator, ProgressPieIndicator, you can implement your own indicator easily, learn by example.

Prefetch

You can prefetch images in advance, so it could be shown immediately when user want to see it.

BigImageViewer.prefetch(uris);

Save image into gallery

bigImageView.setImageSaveCallback(new ImageSaveCallback() {
    @Override
    public void onSuccess(String uri) {
        Toast.makeText(LongImageActivity.this,
                "Success",
                Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onFail(Throwable t) {
        t.printStackTrace();
        Toast.makeText(LongImageActivity.this,
                "Fail",
                Toast.LENGTH_SHORT).show();
    }
});

// should be called on worker/IO thread
bigImageView.saveImageIntoGallery();

Get current image file

// only valid when image file is downloaded.
File path = bigImageView.getCurrentImageFile();

Image init scale type

You can set the normal image scale type using initScaleType attribute, or setInitScaleType.

mBigImageView.setInitScaleType(BigImageView.INIT_SCALE_TYPE_CENTER_CROP);
value effect
center Center the image in the view, but perform no scaling.
centerCrop Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions (width and height) of the image will be equal to or larger than the corresponding dimension of the view (minus padding). The image is then centered in the view.
centerInside Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions (width and height) of the image will be equal to or less than the corresponding dimension of the view (minus padding). The image is then centered in the view.
fitCenter Scales the image so that it fits entirely inside the parent. At least one dimension (width or height) will fit exactly. Aspect ratio is preserved. Image is centered within the parent's bounds.
fitEnd Scales the image so that it fits entirely inside the parent. At least one dimension (width or height) will fit exactly. Aspect ratio is preserved. Image is aligned to the bottom-right corner of the parent.
fitStart Scales the image so that it fits entirely inside the parent. At least one dimension (width or height) will fit exactly. Aspect ratio is preserved. Image is aligned to the top-left corner of the parent.
fitXY Scales width and height independently, so that the image matches the parent exactly. This may change the aspect ratio of the image.
custom Scale the image so that both dimensions of the image will be equal to or less than the maxScale and equal to or larger than minScale. The image is then centered in the view.
start Scale the image so that both dimensions of the image will be equal to or larger than the corresponding dimension of the view. The top left is shown.

Note: SSIV only support centerCrop, centerInside, custom and start, other scale types are treated as centerInside, while other scale types may be used by animated image types.

Failure image

You can set a local failure image using failureImage attribute, or setFailureImage.

It will displayed using an ImageView when the image network request fails. If not specified, nothing is displayed when the request fails.

Failure image init scale type

You can set the failure image scale type using failureImageInitScaleType attribute, or setFailureImageInitScaleType.

Any value of ImageView.ScaleType is valid. Default value is ImageView.ScaleType.FIT_CENTER. It will be ignored if there is no failure image set.

Tap to retry

When failure image is specified, you can tap the failure image then it will retry automatically. That's the default behavior, you can change it using tapToRetry attribute, or setTapToRetry.

Image load callback

You can handle the image load response by creating a new ImageLoader.Callback and overriding the key callbacks

ImageLoader.Callback myImageLoaderCallback = new ImageLoader.Callback() {
    @Override
    public void onCacheHit(int imageType, File image) {
      // Image was found in the cache
    }

    @Override
    public void onCacheMiss(int imageType, File image) {
      // Image was downloaded from the network
    }

    @Override
    public void onStart() {
      // Image download has started
    }

    @Override
    public void onProgress(int progress) {
      // Image download progress has changed
    }

    @Override
    public void onFinish() {
      // Image download has finished
    }

    @Override
    public void onSuccess(File image) {
      // Image was retrieved successfully (either from cache or network)
    }

    @Override
    public void onFail(Exception error) {
      // Image download failed
    }
}

Then setting it as the image load callback

mBigImageView.setImageLoaderCallback(myImageLoaderCallback);

The onSuccess(File image) is always called after the image was retrieved successfully whether from the cache or the network.

For an example, see ImageLoaderCallbackActivity.java

Cancel image loading

BIV will cancel image loading automatically when detach from window, you can also call cancel to cancel it manually.

You can also call BigImageViewer.imageLoader().cancelAll(); in an appropriate time, e.g. Activity/Fragment's onDestroy callback, to cancel all flying requests, avoiding memory leak.

Full customization

You can get the SSIV instance through the method below:

public SubsamplingScaleImageView getSSIV() {
    return mImageView;
}

Then you can do anything you can imagine about SSIV :)

Note: you should test whether SSIV is null, because the image could be a gif, then it won't be displayed by SSIV.

Custom SSIV support

You can even use your own custom SSIV, by calling biv.setImageViewFactory(), passing in a factory that override createStillImageView, and return your custom SSIV.

Custom Glide components support

You can use your custom Glide's components. If you have customized your Glide's configuration, you are able to apply that configuration to BIV too, to do that you only have to initialize BIV in this way:

BigImageViewer.initialize(GlideCustomImageLoader.with(appContext, CustomComponentModel.class));

Where CustomComponentModel.class is the Glide's model component. That's it!

For more detailed example, please refer to the example project.

Caveats

  • Handle permission when you want to save image into gallery.

  • When you want load local image file, you can create the Uri via Uri.fromFile, but the path will be url encoded, and may cause the image loader fail to load it, consider using Uri.parse("file://" + file.getAbsolutePath()).

  • When using with RecyclerView or ViewPager, the recycled BIV doesn't know it should clear the loaded image or reload the image, so you need manually notify it in some way, see issue 107, and issue 177.

  • Crash on Android 4.x device? You could force gradle to use a specific version of OkHttp (some version earlier than 3.13.0), by adding this block to your module's build.gradle, please note that it should be added at the top level, not inside any other block:

    configurations {
      all {
        resolutionStrategy {
          eachDependency { DependencyResolveDetails details ->
            if (details.requested.group == 'com.squareup.okhttp3' &&
                details.requested.name ==
                'okhttp') {
              // OkHttp drops support before 5.0 since 3.13.0
              details.useVersion '3.12.6'
            }
          }
        }
      }
    }

Why another big image viewer?

There are several big image viewer libraries, PhotoDraweeView, FrescoImageViewer, and Subsampling Scale Image View.

They both support pan and zoom. PhotoDraweeView and FrescoImageViewer both use Fresco to load image, which will cause extremely large memory usage when showing big images. Subsampling Scale Image View uses very little memory, but it can only show local image file.

This library show big image with Subsampling Scale Image View, so it only uses very little memory. And this library support using different image load libraries, so it's full featured!

If you are interested in how does this library work, you can refer to this issue, and Subsampling Scale Image View.

Performance

Memory usage of different libraries:

- PhotoDraweeView FrescoImageViewer BigImageViewer
4135*5134 80MB 80MB 2~20 MB

Todo

  • GlideImageLoader
  • Save image file to gallery
  • Optimize long image showing effect, thanks for razerdp
  • Optimize "double tap to zoom" effect, thanks for razerdp
  • Loading animation
  • Downloading progress
  • Thumbnail support
  • Component to display image list, with memory optimization
  • Fail image
  • Retry when fail
  • PicassoImageLoader, track this issue

Those features are offered by image load libraries, and they should be easy to implement, but I don't have enough time currently. So your contributions are welcome!

When you submit PR, please conform the code style of this project, which is customized from Square Android style.

More Repositories

1

RxAndroidAudio

Maybe the most robust Android Audio encapsulation library, with partial Rx support.
Java
1,570
star
2

AndroidTDDBootStrap

A bootstrap project for TDD Android.
HTML
877
star
3

SafelyAndroid

Build safely Android app, no more Activity not found, Activity state loss and NPE during fragment transaction!
Java
400
star
4

notes

tech notes
GCC Machine Description
395
star
5

RxScreenshotDetector

Android screenshot detector with ContentObserver and Rx.
Java
241
star
6

AudioMixer

A cross-platform audio mixer, supports Android, iOS, macOS and Windows. Powered by WebRTC, FFmpeg and Djinni.
C++
188
star
7

FridaAndroidTracer

A runnable jar that generate Javascript hook script to hook Android classes.
Java
134
star
8

WebRTC-Docker

Out-of-the-box docker images for AppRTC dev/test purpose.
Shell
132
star
9

AdvancedRxJava

Advanced RxJava http://akarnokd.blogspot.com/ 系列博客的中文翻译,已征得作者授权。
CSS
127
star
10

HackWebRTC

Let's hack into WebRTC :)
C++
125
star
11

AndroidPlayground

An Android project that try new things, new ideas, research purpose... Just a playground.
Java
104
star
12

YaMvp

Yet another Mvp library. Super simple, but with enough functionality.
Java
96
star
13

HandyWidgets

Handy Android widgets.
Java
89
star
14

RxComboDetector

Android view click combo detector with Rx.
Java
80
star
15

VideoCRE

A component for Video Capture, Render and Encode, extracted from WebRTC.
Java
71
star
16

ShapedDraweeView

Fresco custom view with mask shape.
Java
68
star
17

FlutterWebRTCDataChannel

A Flutter plugin allowing apps to use WebRTC DataChannel to establish P2P connection and exchange text messages.
Objective-C
66
star
18

AndroidCodeQualityConfig

Code quality config for android project, including lint, pmd, findbugs, checkstyle, jacoco code coverage. Serve as a submodule for repo AndroidTDDBootStrap
66
star
19

LearnOpenGL

OpenGL learning tutorial, following https://learnopengl.com/
Java
46
star
20

CameraCompat

Create a camera preview app with beautify and camera api compatibility!
Java
46
star
21

UltraGpuImage

The ultimate 2D image rendering engine, inspired from cats-oss/android-gpuimage, reinventing the wheel as my first OpenGL project after walking through the Learn OpenGL tutorial.
Java
43
star
22

RxQrCode

When QrCode meets RxJava...
Java
40
star
23

InsideCodec

Random walks around codec stuff, H.264, H.265, MediaCodec, VideoToolbox, etc.
C++
35
star
24

decaf-mind-compiler

The principle of compiler course project
Java
32
star
25

Piasy.github.io

Dev blog
HTML
31
star
26

ChatRecyclerView

Implement your user friendly chat RecyclerView in one line!
Java
26
star
27

VulkanTutorial-Android

Step by step tutorial of Vulkan on Android, follow https://vulkan-tutorial.com.
C++
17
star
28

Graduate

Graduate design project
HTML
16
star
29

double-tf-android

[Deprecated, checkout https://bintray.com/google/tensorflow/tensorflow-android] A pure Gradle port of the TensorFlow library for Android!
Shell
14
star
30

GradleScripts

My common used gradle scripts.
Java
12
star
31

Xrash

Xrash is a CMake based cross-platform project for C++ sources, and also illustrate crash symbolicate within them.
C++
11
star
32

JavaUniverse

A demo project that showcase how to use Java to conquer the universe, with the help of J2ObjC and GWT :)
Java
9
star
33

GitHubAndroidOAuth

OAuth for GitHub in Android.
Java
9
star
34

Udacity-DLND

Udacity Nanodegree Deep Learning Foundations
HTML
8
star
35

AndroidTDDBootStrap-base

Base part of AndroidTDDBootStrap
Java
8
star
36

CppUniverse

A demo project that showcase how to use C++ to conquer the universe, with the help of Djinni and WebAssembly :)
C++
7
star
37

LoveStory

Love story pages, include counting, 2048, and timeline.
JavaScript
7
star
38

THCO-MIPS-CPU

Computer Organization course project:THCO-MIPS CPU
VHDL
6
star
39

KmppBootstrap

Bootstrap project for multiplatform development with Kotlin multiplatform.
Objective-C
6
star
40

DialogFragmentAnywhere

Anchor your dialog fragment to anywhere!
Java
5
star
41

live-template

AndroidStudio and Idea live templates.
Shell
5
star
42

ghrc

Github rank China, by dashboard repo stars.
Go
5
star
43

OurBar

Kotlin
5
star
44

VideoCodecAnatomy

Anatomy of video codec.
C++
4
star
45

talks

Slides of public talks.
3
star
46

tcp_ip_illustrated

A playground of the TCP/IP Illustrated book.
Go
2
star
47

pcapanalyse

a pcap trace analyser
Java
2
star
48

resume

My resume under version control.
HTML
2
star
49

searchengine

The course project of search engine.
Java
1
star
50

code2png

Render source code in image with syntax highlight
Go
1
star
51

scripts

my dotfiles and useful scripts
Vim Script
1
star
52

modp_b64

C
1
star
53

QQTang

The software engineer course project, a android platform network game.
Java
1
star
54

BeegoTDDBootStrap

bootstrap repo for api server develop based on beego framework
JavaScript
1
star
55

AndroidTDDBootStrap-testbase

TestBase part of AndroidTDDBootStrap
Java
1
star