Convert Figma logo to code with AI

Piasy logoBigImageViewer

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! 🍻

3,977
400
3,977
35

Top Related Projects

34,576

An image loading and caching library for Android focused on smooth scrolling

18,705

A powerful image downloading and caching library for Android

17,071

An Android library for managing images and the memory they use.

Powerful and flexible library for loading, caching and displaying images on Android.

18,764

Implementation of ImageView for Android that supports zooming, by various touch gestures.

Android library (AAR). Highly configurable, easily extendable deep zoom view for displaying huge images without loss of detail. Perfect for photo galleries, maps, building plans etc.

Quick Overview

BigImageViewer is an Android library for viewing large images efficiently. It supports zooming, panning, and displaying various image formats including JPEG, PNG, GIF, and even long images. The library is designed to handle large images smoothly without causing out-of-memory errors.

Pros

  • Efficient memory usage, preventing out-of-memory errors
  • Supports multiple image formats, including long images
  • Smooth zooming and panning capabilities
  • Easy integration with popular image loading libraries like Glide and Fresco

Cons

  • Limited to Android platform
  • May require additional setup for certain image formats
  • Documentation could be more comprehensive
  • Some advanced features may require additional configuration

Code Examples

Loading an image with BigImageViewer:

BigImageViewer.initialize(GlideImageLoader.with(context))

val bigImageView = findViewById<BigImageView>(R.id.big_image_view)
bigImageView.showImage(Uri.parse("https://example.com/large_image.jpg"))

Configuring image loading options:

val bigImageView = findViewById<BigImageView>(R.id.big_image_view)
bigImageView.setInitScaleType(ScaleType.CENTER_CROP)
bigImageView.setOptimizeDisplay(true)
bigImageView.showImage(Uri.parse("https://example.com/large_image.jpg"))

Adding a custom progress indicator:

val bigImageView = findViewById<BigImageView>(R.id.big_image_view)
bigImageView.setProgressIndicator(ProgressPieIndicator())
bigImageView.showImage(Uri.parse("https://example.com/large_image.jpg"))

Getting Started

  1. Add the dependency to your app's build.gradle:
dependencies {
    implementation 'com.github.piasy:BigImageViewer:1.8.1'
    implementation 'com.github.piasy:GlideImageLoader:1.8.1'
}
  1. Initialize BigImageViewer in your Application class:
class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        BigImageViewer.initialize(GlideImageLoader.with(this))
    }
}
  1. Use BigImageView in your layout:
<com.github.piasy.biv.view.BigImageView
    android:id="@+id/big_image_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
  1. Load an image in your Activity or Fragment:
val bigImageView = findViewById<BigImageView>(R.id.big_image_view)
bigImageView.showImage(Uri.parse("https://example.com/large_image.jpg"))

Competitor Comparisons

34,576

An image loading and caching library for Android focused on smooth scrolling

Pros of Glide

  • More comprehensive image loading library with support for various sources (network, local, etc.)
  • Extensive caching mechanisms for improved performance
  • Wider adoption and larger community support

Cons of Glide

  • Larger library size, which may impact app size
  • Steeper learning curve due to more features and configuration options

Code Comparison

BigImageViewer:

BigImageView bigImageView = findViewById(R.id.big_image_view);
bigImageView.showImage(Uri.parse("https://example.com/image.jpg"));

Glide:

ImageView imageView = findViewById(R.id.image_view);
Glide.with(this)
    .load("https://example.com/image.jpg")
    .into(imageView);

Key Differences

  • BigImageViewer focuses specifically on large image viewing and zooming
  • Glide is a more general-purpose image loading and caching library
  • BigImageViewer uses a custom view (BigImageView) while Glide works with standard ImageViews
  • Glide offers more advanced features like transformations and placeholders

Use Cases

  • Choose BigImageViewer for apps primarily dealing with large, zoomable images
  • Opt for Glide for general image loading needs and apps requiring extensive image manipulation
18,705

A powerful image downloading and caching library for Android

Pros of Picasso

  • Widely adopted and battle-tested in many production apps
  • Extensive caching mechanisms for improved performance
  • Supports image transformations and filters out of the box

Cons of Picasso

  • Limited support for very large images
  • Lacks built-in zooming and panning capabilities
  • Memory management can be challenging for extremely large images

Code Comparison

BigImageViewer:

BigImageView bigImageView = findViewById(R.id.bigImageView);
bigImageView.showImage(Uri.parse("https://example.com/large-image.jpg"));

Picasso:

ImageView imageView = findViewById(R.id.imageView);
Picasso.get().load("https://example.com/image.jpg").into(imageView);

Key Differences

  • BigImageViewer is specifically designed for handling large images efficiently, while Picasso is a general-purpose image loading library.
  • BigImageViewer provides built-in zooming and panning capabilities, which Picasso lacks.
  • Picasso offers more extensive image transformation options out of the box.
  • BigImageViewer uses a tile-based approach for loading large images, which can be more memory-efficient for very large images compared to Picasso's approach.

Use Cases

  • Choose BigImageViewer when working with extremely large images or when zooming and panning are crucial features.
  • Opt for Picasso for general image loading tasks, especially when dealing with standard-sized images and when extensive caching and transformation options are needed.
17,071

An Android library for managing images and the memory they use.

Pros of Fresco

  • More comprehensive image loading library with broader feature set
  • Better performance optimization for memory usage and caching
  • Larger community and ongoing support from Facebook

Cons of Fresco

  • Steeper learning curve due to complexity
  • Larger library size, which may impact app size
  • More dependencies and potential for conflicts

Code Comparison

BigImageViewer:

BigImageView bigImageView = findViewById(R.id.mBigImage);
bigImageView.showImage(Uri.parse("https://example.com/image.jpg"));

Fresco:

SimpleDraweeView draweeView = findViewById(R.id.my_image_view);
draweeView.setImageURI("https://example.com/image.jpg");

Key Differences

  • BigImageViewer focuses specifically on large image viewing, while Fresco is a more general-purpose image loading library
  • BigImageViewer has a simpler API for basic use cases, making it easier to implement for large image viewing
  • Fresco offers more advanced features like image processing, animated GIF support, and progressive JPEG loading

Use Case Recommendations

  • Choose BigImageViewer for projects primarily focused on displaying large images with minimal setup
  • Opt for Fresco in larger applications requiring extensive image handling capabilities and willing to invest time in setup and optimization

Powerful and flexible library for loading, caching and displaying images on Android.

Pros of Android-Universal-Image-Loader

  • More mature and widely adopted library with extensive documentation
  • Supports a broader range of image sources, including file system, assets, and content providers
  • Offers more customization options for caching, display, and decoding

Cons of Android-Universal-Image-Loader

  • No longer actively maintained, with the last update in 2016
  • Lacks support for modern Android features and optimizations
  • Heavier library size compared to more focused alternatives

Code Comparison

Android-Universal-Image-Loader:

ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.displayImage(imageUri, imageView, options);

BigImageViewer:

BigImageView bigImageView = findViewById(R.id.big_image_view);
bigImageView.showImage(Uri.parse(imageUri));

Summary

Android-Universal-Image-Loader is a comprehensive and well-established library with extensive features, but it lacks recent updates and modern optimizations. BigImageViewer, on the other hand, is more focused on handling large images efficiently and supports modern Android features. While Android-Universal-Image-Loader offers more customization options, BigImageViewer provides a simpler API for displaying large images with better performance. The choice between the two depends on specific project requirements, with Android-Universal-Image-Loader being suitable for projects needing broad image handling capabilities, and BigImageViewer excelling in scenarios involving large image display and manipulation.

18,764

Implementation of ImageView for Android that supports zooming, by various touch gestures.

Pros of PhotoView

  • More mature and widely adopted project with a larger community
  • Supports zooming and panning with smooth animations out of the box
  • Simpler integration for basic image viewing needs

Cons of PhotoView

  • Limited support for very large images, which can lead to out-of-memory errors
  • Lacks built-in support for progressive loading or tiling of large images
  • Less flexibility for customizing the image loading process

Code Comparison

PhotoView implementation:

PhotoView photoView = findViewById(R.id.photo_view);
Glide.with(this).load(imageUrl).into(photoView);

BigImageViewer implementation:

BigImageView bigImageView = findViewById(R.id.big_image_view);
bigImageView.showImage(Uri.parse(imageUrl));

Both libraries offer simple APIs for basic image viewing, but BigImageViewer provides more advanced features for handling large images efficiently.

Android library (AAR). Highly configurable, easily extendable deep zoom view for displaying huge images without loss of detail. Perfect for photo galleries, maps, building plans etc.

Pros of subsampling-scale-image-view

  • Simpler implementation, easier to integrate for basic image viewing needs
  • Supports custom tile loading for advanced use cases
  • Efficient memory usage through subsampling and tiling

Cons of subsampling-scale-image-view

  • Limited file format support compared to BigImageViewer
  • Lacks built-in support for GIF animations
  • Less actively maintained, with fewer recent updates

Code Comparison

subsampling-scale-image-view:

SubsamplingScaleImageView imageView = new SubsamplingScaleImageView(context);
imageView.setImage(ImageSource.uri("/sdcard/image.jpg"));

BigImageViewer:

BigImageView bigImageView = findViewById(R.id.big_image_view);
bigImageView.showImage(Uri.parse("file:///sdcard/image.jpg"));

Both libraries offer simple APIs for loading and displaying large images, but BigImageViewer provides a more modern and flexible approach with support for multiple image loading engines.

BigImageViewer offers a wider range of features, including support for various image formats (JPEG, PNG, GIF, WebP) and integration with popular image loading libraries like Glide and Fresco. It also provides better performance for large images and animated GIFs.

subsampling-scale-image-view, while more focused in scope, excels in memory efficiency and custom tile loading capabilities. It's a solid choice for projects with specific requirements around large static images.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

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 zoomgif support
demogif 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);
valueeffect
centerCenter the image in the view, but perform no scaling.
centerCropScale 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.
centerInsideScale 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.
fitCenterScales 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.
fitEndScales 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.
fitStartScales 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.
fitXYScales width and height independently, so that the image matches the parent exactly. This may change the aspect ratio of the image.
customScale 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.
startScale 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:

-PhotoDraweeViewFrescoImageViewerBigImageViewer
4135*513480MB80MB2~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.