{"id":15130539,"url":"https://github.com/piasy/bigimageviewer","last_synced_at":"2025-05-14T04:07:47.966Z","repository":{"id":38239211,"uuid":"72979537","full_name":"Piasy/BigImageViewer","owner":"Piasy","description":"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! 🍻","archived":false,"fork":false,"pushed_at":"2022-12-12T00:31:21.000Z","size":55900,"stargazers_count":3990,"open_issues_count":38,"forks_count":405,"subscribers_count":72,"default_branch":"master","last_synced_at":"2025-05-12T15:31:27.467Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Piasy.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-11-06T09:55:02.000Z","updated_at":"2025-05-05T12:38:26.000Z","dependencies_parsed_at":"2023-01-27T09:45:59.345Z","dependency_job_id":null,"html_url":"https://github.com/Piasy/BigImageViewer","commit_stats":null,"previous_names":[],"tags_count":46,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Piasy%2FBigImageViewer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Piasy%2FBigImageViewer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Piasy%2FBigImageViewer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Piasy%2FBigImageViewer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Piasy","download_url":"https://codeload.github.com/Piasy/BigImageViewer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254069577,"owners_count":22009558,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-09-26T03:01:57.640Z","updated_at":"2025-05-14T04:07:42.938Z","avatar_url":"https://github.com/Piasy.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# BigImageViewer\n\n\u003cimg src=\"art/Logotype_primary.png\" width=\"70%\" height=\"70%\"/\u003e\n\nBig image viewer supporting pan and zoom, with very little memory usage and full\nfeatured image loading choices. Powered by [Subsampling Scale Image\nView](https://github.com/davemorrissey/subsampling-scale-image-view),\n[Fresco](https://github.com/facebook/fresco),\n[Glide](https://github.com/bumptech/glide), and\n[Picasso](https://github.com/square/picasso). Even with gif and webp support!\n\n## Demo\n\n![memory usage](art/android_studio_memory_monitor.png)\n\npan and zoom               |  gif support\n:-------------------------:|:-------------------------:\n![demo](art/fresco_big_image_viewer_demo.gif)  |  ![gif support](art/biv_gif_support.gif)\n\n## Getting started\n\n### Add the dependencies\n\n**Note: please put this download url at the first of your `repositories` part, otherwise, gradle may search in wrong place.**\n\n``` gradle\nallprojects {\n    repositories {\n        mavenCentral()\n    }\n}\n\nimplementation 'com.github.piasy:BigImageViewer:1.8.1'\n\n// load with fresco\nimplementation 'com.github.piasy:FrescoImageLoader:1.8.1'\n\n// load with glide\nimplementation 'com.github.piasy:GlideImageLoader:1.8.1'\n\n// progress pie indicator\nimplementation 'com.github.piasy:ProgressPieIndicator:1.8.1'\n\n// support thumbnail, gif and webp with Fresco\nimplementation 'com.github.piasy:FrescoImageViewFactory:1.8.1'\n\n// support thumbnail and gif with Glide\nimplementation 'com.github.piasy:GlideImageViewFactory:1.8.1'\n```\n\n### Initialize\n\n``` java\n// MUST use app context to avoid memory leak!\n// load with fresco\nBigImageViewer.initialize(FrescoImageLoader.with(appContext));\n\n// or load with glide\nBigImageViewer.initialize(GlideImageLoader.with(appContext));\n\n// or load with glide custom component\nBigImageViewer.initialize(GlideCustomImageLoader.with(appContext, CustomComponentModel.class));\n```\n\n**Note that** if you've already used Fresco in your project, please change\n`Fresco.initialize` into `BigImageViewer.initialize`.\n\n### Add the BigImageView to your layout\n\n``` xml\n\u003ccom.github.piasy.biv.view.BigImageView\n        android:id=\"@+id/mBigImage\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:failureImage=\"@drawable/failure_image\"\n        app:failureImageInitScaleType=\"center\"\n        app:optimizeDisplay=\"true\"\n        /\u003e\n```\n\nYou can disable display optimization using `optimizeDisplay` attribute, or\n`BigImageView.setOptimizeDisplay(false)`, which will disable animation for long\nimage, and the switch between thumbnail and origin image.\n\n### Show the image\n\n``` java\nBigImageView bigImageView = (BigImageView) findViewById(R.id.mBigImage);\nbigImageView.showImage(Uri.parse(url));\n```\n\n## Usage\n\n### Animated image support\n\nSince 1.5.0, BIV support display animated image, e.g. gif and animated webp, to achieve that,\nyou need set a custom `ImageViewFactory` via `biv.setImageViewFactory`:\n\n``` java\n// FrescoImageViewFactory is a prebuilt factory, which use Fresco's SimpleDraweeView\n// to display animated image, both gif and webp are supported.\nbiv.setImageViewFactory(new FrescoImageViewFactory());\n\n// GlideImageViewFactory is another prebuilt factory, which use ImageView to display gif,\n// animated webp is not supported (although it will be displayed with ImageView,\n// but it won't animate).\nbiv.setImageViewFactory(new GlideImageViewFactory());\n```\n\nNode: if the image is not gif or animated webp, then it will be displayed by SSIV,\nthe image type is not determined by its file extension, but by its file header magic code.\n\n### Thumbnail support\n\nTo show a thumbnail before the big image is loaded, you can call below version of `showImage`:\n\n``` java\nbigImageView.showImage(Uri.parse(thumbnail), Uri.parse(url));\n```\n\nNote: make sure that you have already called `setImageViewFactory`.\n\n### Shared element transition support (experimental)\n\nSince 1.6.0, BIV has experimental support for shared element transition,\nbut it has following known issues:\n\n+ The shared image may flicker during enter transition, or become white after return transition,\nwhen using Fresco, see [Fresco issue #1445](https://github.com/facebook/fresco/issues/1445);\n+ The shared image may flicker after return transition, especially after you zoomed SSIV;\n\nYou can play with the demo app to evaluate the shared element transition support.\n\n### Download progress indicator\n\n``` java\nbigImageView.setProgressIndicator(new ProgressPieIndicator());\n```\n\nThere is one built-in indicator, `ProgressPieIndicator`, you can implement your\nown indicator easily, [learn by example](/ProgressPieIndicator).\n\n### Prefetch\n\nYou can prefetch images in advance, so it could be shown immediately when user\nwant to see it.\n\n``` java\nBigImageViewer.prefetch(uris);\n```\n\n### Save image into gallery\n\n``` java\nbigImageView.setImageSaveCallback(new ImageSaveCallback() {\n    @Override\n    public void onSuccess(String uri) {\n        Toast.makeText(LongImageActivity.this,\n                \"Success\",\n                Toast.LENGTH_SHORT).show();\n    }\n\n    @Override\n    public void onFail(Throwable t) {\n        t.printStackTrace();\n        Toast.makeText(LongImageActivity.this,\n                \"Fail\",\n                Toast.LENGTH_SHORT).show();\n    }\n});\n\n// should be called on worker/IO thread\nbigImageView.saveImageIntoGallery();\n```\n\n### Get current image file\n\n``` java\n// only valid when image file is downloaded.\nFile path = bigImageView.getCurrentImageFile();\n```\n\n### Image init scale type\n\nYou can set the normal image scale type using `initScaleType` attribute, or `setInitScaleType`.\n\n``` java\nmBigImageView.setInitScaleType(BigImageView.INIT_SCALE_TYPE_CENTER_CROP);\n```\n\n| value | effect |\n| ------| ------ |\n| center | Center the image in the view, but perform no scaling. |\n| 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. |\n| 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. |\n| 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. |\n| 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. |\n| 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. |\n| fitXY | Scales width and height independently, so that the image matches the parent exactly. This may change the aspect ratio of the image. |\n| 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. |\n| 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. |\n\nNote: SSIV only support centerCrop, centerInside, custom and start, other scale types are\ntreated as centerInside, while other scale types may be used by animated image types.\n\n### Failure image\n\nYou can set a local failure image using `failureImage` attribute, or `setFailureImage`.\n\nIt will displayed using an `ImageView` when the image network request fails. If not specified,\nnothing is displayed when the request fails.\n\n#### Failure image init scale type\n\nYou can set the failure image scale type using `failureImageInitScaleType` attribute,\nor `setFailureImageInitScaleType`.\n\nAny value of [ImageView.ScaleType](https://developer.android.com/reference/android/widget/ImageView.ScaleType.html)\nis valid. Default value is `ImageView.ScaleType.FIT_CENTER`. It will be ignored if there is\nno failure image set.\n\n#### Tap to retry\n\nWhen failure image is specified, you can tap the failure image then it will retry automatically.\nThat's the default behavior, you can change it using `tapToRetry` attribute, or `setTapToRetry`.\n\n### Image load callback\n\nYou can handle the image load response by creating a new `ImageLoader.Callback`\nand overriding the key callbacks\n\n```java\nImageLoader.Callback myImageLoaderCallback = new ImageLoader.Callback() {\n    @Override\n    public void onCacheHit(int imageType, File image) {\n      // Image was found in the cache\n    }\n\n    @Override\n    public void onCacheMiss(int imageType, File image) {\n      // Image was downloaded from the network\n    }\n\n    @Override\n    public void onStart() {\n      // Image download has started\n    }\n\n    @Override\n    public void onProgress(int progress) {\n      // Image download progress has changed\n    }\n\n    @Override\n    public void onFinish() {\n      // Image download has finished\n    }\n\n    @Override\n    public void onSuccess(File image) {\n      // Image was retrieved successfully (either from cache or network)\n    }\n\n    @Override\n    public void onFail(Exception error) {\n      // Image download failed\n    }\n}\n```\n\nThen setting it as the image load callback\n\n```java\nmBigImageView.setImageLoaderCallback(myImageLoaderCallback);\n```\n\nThe `onSuccess(File image)` is always called after the image was retrieved\nsuccessfully whether from the cache or the network.\n\nFor an example, see ImageLoaderCallbackActivity.java\n\n### Cancel image loading\n\nBIV will cancel image loading automatically when detach from window, you can also call `cancel`\nto cancel it manually.\n\nYou can also call `BigImageViewer.imageLoader().cancelAll();` in an appropriate time,\ne.g. Activity/Fragment's `onDestroy` callback, to cancel all flying requests, avoiding memory leak.\n\n### Full customization\n\nYou can get the SSIV instance through the method below:\n\n``` java\npublic SubsamplingScaleImageView getSSIV() {\n    return mImageView;\n}\n```\n\nThen you can do anything you can imagine about SSIV :)\n\nNote: you should test whether SSIV is null, because the image could be a gif,\nthen it won't be displayed by SSIV.\n\n### Custom SSIV support\n\nYou can even use your own custom SSIV, by calling `biv.setImageViewFactory()`,\npassing in a factory that override `createStillImageView`, and return your custom SSIV.\n\n### Custom Glide components support\n\nYou can use your custom Glide's [components](https://bumptech.github.io/glide/doc/configuration.html#registering-components).\nIf 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:\n\n```java\nBigImageViewer.initialize(GlideCustomImageLoader.with(appContext, CustomComponentModel.class));\n```\n\nWhere `CustomComponentModel.class` is the Glide's model component. That's it!\n\nFor more detailed example, please refer to [the example project](https://github.com/Piasy/BigImageViewer/tree/master/app/src/main/java/com/github/piasy/biv/example/glide).\n\n## Caveats\n\n+ Handle permission when you want to save image into gallery.\n+ When you want load local image file, you can create the Uri via\n`Uri.fromFile`, but the path will be url encoded, and may cause the image loader\nfail to load it, consider using `Uri.parse(\"file://\" + file.getAbsolutePath())`.\n+ When using with RecyclerView or ViewPager, the recycled BIV doesn't know\nit should clear the loaded image or reload the image,\nso you need manually notify it in some way,\nsee [issue 107](https://github.com/Piasy/BigImageViewer/issues/107),\nand [issue 177](https://github.com/Piasy/BigImageViewer/issues/177).\n+ 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:\n\n    ```gradle\n\n    configurations {\n      all {\n        resolutionStrategy {\n          eachDependency { DependencyResolveDetails details -\u003e\n            if (details.requested.group == 'com.squareup.okhttp3' \u0026\u0026\n                details.requested.name ==\n                'okhttp') {\n              // OkHttp drops support before 5.0 since 3.13.0\n              details.useVersion '3.12.6'\n            }\n          }\n        }\n      }\n    }\n    ```\n\n## Why another big image viewer?\n\nThere are several big image viewer libraries,\n[PhotoDraweeView](https://github.com/ongakuer/PhotoDraweeView),\n[FrescoImageViewer](https://github.com/stfalcon-studio/FrescoImageViewer), and\n[Subsampling Scale Image\nView](https://github.com/davemorrissey/subsampling-scale-image-view).\n\nThey both support pan and zoom. PhotoDraweeView and FrescoImageViewer both use\nFresco to load image, which will cause extremely large memory usage when showing\nbig images. Subsampling Scale Image View uses very little memory, but it can\nonly show local image file.\n\nThis library show big image with Subsampling Scale Image View, so it only uses\nvery little memory. And this library support using different image load\nlibraries, so it's full featured!\n\nIf you are interested in how does this library work, you can refer to [this\nissue](https://github.com/Piasy/BigImageViewer/issues/8), and [Subsampling Scale\nImage View](https://github.com/davemorrissey/subsampling-scale-image-view).\n\n## Performance\n\nMemory usage of different libraries:\n\n| \\- | PhotoDraweeView | FrescoImageViewer | BigImageViewer |\n| ------| ------ | ------ | ------ |\n| 4135\\*5134 | 80MB | 80MB | 2~20 MB |\n\n## Todo\n\n+ [x] GlideImageLoader\n+ [x] Save image file to gallery\n+ [x] Optimize long image showing effect, thanks for [razerdp](https://github.com/razerdp)\n+ [x] Optimize \"double tap to zoom\" effect, thanks for [razerdp](https://github.com/razerdp)\n+ [x] Loading animation\n+ [x] Downloading progress\n+ [x] Thumbnail support\n+ [ ] Component to display image list, with memory optimization\n+ [x] Fail image\n+ [x] Retry when fail\n+ [ ] PicassoImageLoader, track [this issue](https://github.com/square/picasso/issues/506)\n\nThose features are offered by image load libraries, and they should be easy to\nimplement, but I don't have enough time currently. So your contributions are\nwelcome!\n\nWhen you submit PR, please conform the [code style of this project](https://github.com/Piasy/java-code-styles),\nwhich is customized from Square Android style.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiasy%2Fbigimageviewer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpiasy%2Fbigimageviewer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiasy%2Fbigimageviewer/lists"}